From 37941cb5e16da18dd6182100fa2a69b589341143 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Tue, 28 Jul 2020 18:49:51 +0200 Subject: [PATCH 01/22] Add initial pass on a multi-part test driver Signed-off-by: Steven Cooreman --- include/psa/crypto_struct.h | 6 + library/psa_crypto.c | 17 + library/psa_crypto_driver_wrappers.c | 524 +++++++++++++++++++++++ library/psa_crypto_driver_wrappers.h | 62 +++ tests/include/test/drivers/cipher.h | 168 ++++++++ tests/include/test/drivers/test_driver.h | 1 + tests/src/drivers/cipher.c | 348 +++++++++++++++ 7 files changed, 1126 insertions(+) create mode 100644 tests/include/test/drivers/cipher.h create mode 100644 tests/src/drivers/cipher.c diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 67c53db92..0ea8073ec 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -164,6 +164,12 @@ struct psa_cipher_operation_s { unsigned dummy; /* Enable easier initializing of the union. */ mbedtls_cipher_context_t cipher; +#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) + struct { + unsigned int id; + void* ctx; + } driver; +#endif } ctx; }; diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 04ef28b0c..6acf49850 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -4079,6 +4079,23 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT ); + status = psa_get_key_from_slot( handle, &slot, usage, alg ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Try doing this through a driver before using software fallback */ + if( cipher_operation == MBEDTLS_ENCRYPT ) + status = psa_driver_wrapper_cipher_encrypt_setup( operation, + slot, + alg ); + else + status = psa_driver_wrapper_cipher_decrypt_setup( operation, + slot, + alg ); + + if( status != PSA_ERROR_NOT_SUPPORTED ) + goto exit; + /* A context must be freshly initialized before it can be set up. */ if( operation->alg != 0 ) { diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index cc51e2450..140c3d4b8 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -38,6 +38,11 @@ /* Repeat above block for each JSON-declared driver during autogeneration */ +/* Auto-generated values depending on which drivers are registered */ +#if defined(PSA_CRYPTO_DRIVER_TEST) +#define PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID (1) +#define PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID (2) +#endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */ /* Support the 'old' SE interface when asked to */ @@ -370,4 +375,523 @@ psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attrib #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } +/* + * Cipher functions + */ +psa_status_t psa_driver_wrapper_cipher_encrypt( + psa_key_slot_t *slot, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + 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_DRIVER_TEST) + status = test_transparent_cipher_encrypt( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + input, + input_length, + output, + output_size, + output_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return status; +#endif /* PSA_CRYPTO_DRIVER_TEST */ + /* Fell through, meaning no accelerator supports this operation */ + return PSA_ERROR_NOT_SUPPORTED; + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + return( test_opaque_cipher_encrypt( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + input, + input_length, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is declared with a lifetime not known to us */ + return status; + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void) slot; + (void) alg; + (void) input; + (void) input_length; + (void) output; + (void) output_size; + (void) output_length; + + return PSA_ERROR_NOT_SUPPORTED; +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_decrypt( + psa_key_slot_t *slot, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + 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_DRIVER_TEST) + status = test_transparent_cipher_decrypt( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + input, + input_length, + output, + output_size, + output_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return status; +#endif /* PSA_CRYPTO_DRIVER_TEST */ + /* Fell through, meaning no accelerator supports this operation */ + return PSA_ERROR_NOT_SUPPORTED; + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + return( test_opaque_cipher_decrypt( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + input, + input_length, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is declared with a lifetime not known to us */ + return status; + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void) slot; + (void) alg; + (void) input; + (void) input_length; + (void) output; + (void) output_size; + (void) output_length; + + return PSA_ERROR_NOT_SUPPORTED; +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_encrypt_setup( + psa_cipher_operation_t *operation, + psa_key_slot_t *slot, + psa_algorithm_t alg ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + /* Check for operation already allocated */ + if( operation->ctx.driver.ctx != NULL ) + return PSA_ERROR_BAD_STATE; + + 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_DRIVER_TEST) + operation->ctx.driver.ctx = mbedtls_calloc( 1, sizeof(test_transparent_cipher_operation_t) ); + if( operation->ctx.driver.ctx == NULL ) + return PSA_ERROR_INSUFFICIENT_MEMORY; + + status = test_transparent_cipher_encrypt_setup( operation->ctx.driver.ctx, + &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + { + if( status == PSA_SUCCESS ) + operation->ctx.driver.id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; + else + { + mbedtls_free( operation->ctx.driver.ctx ); + operation->ctx.driver.ctx = NULL; + } + + return status; + } + else + { + mbedtls_free( operation->ctx.driver.ctx ); + operation->ctx.driver.ctx = NULL; + } +#endif /* PSA_CRYPTO_DRIVER_TEST */ + /* Fell through, meaning no accelerator supports this operation */ + return PSA_ERROR_NOT_SUPPORTED; + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + operation->ctx.driver.ctx = mbedtls_calloc( 1, sizeof(test_opaque_cipher_operation_t) ); + if( operation->ctx.driver.ctx == NULL ) + return PSA_ERROR_INSUFFICIENT_MEMORY; + + status = test_opaque_cipher_encrypt_setup( operation->ctx.driver.ctx, + &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg ); + if( status == PSA_SUCCESS ) + operation->ctx.driver.id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; + else + { + mbedtls_free( operation->ctx.driver.ctx ); + operation->ctx.driver.ctx = NULL; + } + + return status; +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is declared with a lifetime not known to us */ + return PSA_ERROR_BAD_STATE; + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void)slot; + (void)alg; + (void)operation; + + return PSA_ERROR_NOT_SUPPORTED; +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_decrypt_setup( + psa_cipher_operation_t *operation, + psa_key_slot_t *slot, + psa_algorithm_t alg ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + /* Check for operation already allocated */ + if( operation->ctx.driver.ctx != NULL ) + return PSA_ERROR_BAD_STATE; + + 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_DRIVER_TEST) + operation->ctx.driver.ctx = mbedtls_calloc( 1, sizeof(test_transparent_cipher_operation_t) ); + if( operation->ctx.driver.ctx == NULL ) + return PSA_ERROR_INSUFFICIENT_MEMORY; + + status = test_transparent_cipher_decrypt_setup( operation->ctx.driver.ctx, + &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + { + if( status == PSA_SUCCESS ) + operation->ctx.driver.id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; + else + { + mbedtls_free( operation->ctx.driver.ctx ); + operation->ctx.driver.ctx = NULL; + } + + return status; + } + else + { + mbedtls_free( operation->ctx.driver.ctx ); + operation->ctx.driver.ctx = NULL; + } +#endif /* PSA_CRYPTO_DRIVER_TEST */ + /* Fell through, meaning no accelerator supports this operation */ + return PSA_ERROR_NOT_SUPPORTED; + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + operation->ctx.driver.ctx = mbedtls_calloc( 1, sizeof(test_opaque_cipher_operation_t) ); + if( operation->ctx.driver.ctx == NULL ) + return PSA_ERROR_INSUFFICIENT_MEMORY; + + status = test_opaque_cipher_decrypt_setup( operation->ctx.driver.ctx, + &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg ); + if( status == PSA_SUCCESS ) + operation->ctx.driver.id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; + else + { + mbedtls_free( operation->ctx.driver.ctx ); + operation->ctx.driver.ctx = NULL; + } + + return status; +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is declared with a lifetime not known to us */ + return PSA_ERROR_BAD_STATE; + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void)slot; + (void)alg; + (void)operation; + + return PSA_ERROR_NOT_SUPPORTED; +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_generate_iv( + psa_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + /* Check for operation already allocated */ + if( operation->ctx.driver.ctx == NULL ) + return PSA_ERROR_INVALID_ARGUMENT; + + switch( operation->ctx.driver.id ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( test_transparent_cipher_generate_iv( operation->ctx.driver.ctx, + iv, + iv_size, + iv_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( test_opaque_cipher_generate_iv( operation->ctx.driver.ctx, + iv, + iv_size, + iv_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is attached to a driver not known to us */ + return PSA_ERROR_BAD_STATE; + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void) operation; + (void) iv; + (void) iv_size; + (void) iv_length; + + return PSA_ERROR_NOT_SUPPORTED; +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_set_iv( + psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + /* Check for operation already allocated */ + if( operation->ctx.driver.ctx == NULL ) + return PSA_ERROR_INVALID_ARGUMENT; + + switch( operation->ctx.driver.id ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( test_transparent_cipher_set_iv( operation->ctx.driver.ctx, + iv, + iv_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( test_opaque_cipher_set_iv( operation->ctx.driver.ctx, + iv, + iv_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is attached to a driver not known to us */ + return PSA_ERROR_BAD_STATE; + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void) operation; + (void) iv; + (void) iv_length; + + return PSA_ERROR_NOT_SUPPORTED; +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_update( + psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + /* Check for operation already allocated */ + if( operation->ctx.driver.ctx == NULL ) + return PSA_ERROR_INVALID_ARGUMENT; + + switch( operation->ctx.driver.id ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( test_transparent_cipher_update( operation->ctx.driver.ctx, + input, + input_length, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( test_opaque_cipher_update( operation->ctx.driver.ctx, + input, + input_length, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is attached to a driver not known to us */ + return PSA_ERROR_BAD_STATE; + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void) operation; + (void) input; + (void) input_length; + (void) output; + (void) output_length; + (void) output_size; + + return PSA_ERROR_NOT_SUPPORTED; +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_finish( + psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + /* Check for operation already allocated */ + if( operation->ctx.driver.ctx == NULL ) + return PSA_ERROR_INVALID_ARGUMENT; + + switch( operation->ctx.driver.id ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( test_transparent_cipher_finish( operation->ctx.driver.ctx, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( test_opaque_cipher_finish( operation->ctx.driver.ctx, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is attached to a driver not known to us */ + return PSA_ERROR_BAD_STATE; + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void) operation; + (void) output; + (void) output_size; + (void) output_length; + + return PSA_ERROR_NOT_SUPPORTED; +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_abort( + psa_cipher_operation_t *operation ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + /* Check for operation already allocated */ + if( operation->ctx.driver.ctx == NULL ) + return PSA_ERROR_INVALID_ARGUMENT; + + switch( operation->ctx.driver.id ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + status = test_transparent_cipher_abort( operation->ctx.driver.ctx ); + + mbedtls_free( operation->ctx.driver.ctx ); + operation->ctx.driver.ctx = NULL; + operation->ctx.driver.id = 0; + + return status; +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + status = test_opaque_cipher_abort( operation->ctx.driver.ctx ); + mbedtls_free( operation->ctx.driver.ctx ); + operation->ctx.driver.ctx = NULL; + + return status; +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Operation is attached to a driver not known to us */ + return PSA_ERROR_BAD_STATE; + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void)operation; + + return PSA_ERROR_NOT_SUPPORTED; +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + /* End of automatically generated file. */ diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h index 42993792a..a2096048d 100644 --- a/library/psa_crypto_driver_wrappers.h +++ b/library/psa_crypto_driver_wrappers.h @@ -25,6 +25,9 @@ #include "psa/crypto.h" #include "psa/crypto_driver_common.h" +/* + * Signature functions + */ psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot, psa_algorithm_t alg, const uint8_t *hash, @@ -43,6 +46,65 @@ psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot, psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes, psa_key_slot_t *slot ); +/* + * Cipher functions + */ +psa_status_t psa_driver_wrapper_cipher_encrypt( + psa_key_slot_t *slot, + psa_algorithm_t alg, + 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_cipher_decrypt( + psa_key_slot_t *slot, + psa_algorithm_t alg, + 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_cipher_encrypt_setup( + psa_cipher_operation_t *operation, + psa_key_slot_t *slot, + psa_algorithm_t alg ); + +psa_status_t psa_driver_wrapper_cipher_decrypt_setup( + psa_cipher_operation_t *operation, + psa_key_slot_t *slot, + psa_algorithm_t alg ); + +psa_status_t psa_driver_wrapper_cipher_generate_iv( + psa_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length ); + +psa_status_t psa_driver_wrapper_cipher_set_iv( + psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length ); + +psa_status_t psa_driver_wrapper_cipher_update( + psa_cipher_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_cipher_finish( + psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length ); + +psa_status_t psa_driver_wrapper_cipher_abort( + psa_cipher_operation_t *operation ); + #endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */ /* End of automatically generated file. */ diff --git a/tests/include/test/drivers/cipher.h b/tests/include/test/drivers/cipher.h new file mode 100644 index 000000000..c58a92691 --- /dev/null +++ b/tests/include/test/drivers/cipher.h @@ -0,0 +1,168 @@ +/* + * Test driver for cipher functions + */ +/* Copyright (C) 2020, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_TEST_DRIVERS_CIPHER_H +#define PSA_CRYPTO_TEST_DRIVERS_CIPHER_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(PSA_CRYPTO_DRIVER_TEST) +#include + +#include "mbedtls/cipher.h" +typedef struct { + psa_algorithm_t alg; + unsigned int key_set : 1; + unsigned int iv_required : 1; + unsigned int iv_set : 1; + uint8_t iv_size; + uint8_t block_size; + mbedtls_cipher_context_t cipher; +} test_transparent_cipher_operation_t; + +typedef struct{ + unsigned int initialised : 1; + test_transparent_cipher_operation_t ctx; +} test_opaque_cipher_operation_t; + +extern void *test_driver_cipher_forced_output; +extern size_t test_driver_cipher_forced_output_length; + +extern psa_status_t test_transparent_cipher_status; +extern unsigned long test_transparent_cipher_hit; + +psa_status_t test_transparent_cipher_encrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, size_t *output_length); + +psa_status_t test_transparent_cipher_decrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, size_t *output_length); + +psa_status_t test_transparent_cipher_encrypt_setup( + test_transparent_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg); + +psa_status_t test_transparent_cipher_decrypt_setup( + test_transparent_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg); + +psa_status_t test_transparent_cipher_abort( + test_transparent_cipher_operation_t *operation); + +psa_status_t test_transparent_cipher_generate_iv( + test_transparent_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length); + +psa_status_t test_transparent_cipher_set_iv( + test_transparent_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length); + +psa_status_t test_transparent_cipher_update( + test_transparent_cipher_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 test_transparent_cipher_finish( + test_transparent_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/* + * opaque versions + */ +psa_status_t test_opaque_cipher_encrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, size_t *output_length); + +psa_status_t test_opaque_cipher_decrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, size_t *output_length); + +psa_status_t test_opaque_cipher_encrypt_setup( + test_opaque_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg); + +psa_status_t test_opaque_cipher_decrypt_setup( + test_opaque_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg); + +psa_status_t test_opaque_cipher_abort( + test_opaque_cipher_operation_t *operation); + +psa_status_t test_opaque_cipher_generate_iv( + test_opaque_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length); + +psa_status_t test_opaque_cipher_set_iv( + test_opaque_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length); + +psa_status_t test_opaque_cipher_update( + test_opaque_cipher_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 test_opaque_cipher_finish( + test_opaque_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length); + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_TEST_DRIVERS_CIPHER_H */ diff --git a/tests/include/test/drivers/test_driver.h b/tests/include/test/drivers/test_driver.h index 75135e0f4..7ee8e5eea 100644 --- a/tests/include/test/drivers/test_driver.h +++ b/tests/include/test/drivers/test_driver.h @@ -24,5 +24,6 @@ #include "test/drivers/signature.h" #include "test/drivers/keygen.h" +#include "test/drivers/cipher.h" #endif /* PSA_CRYPTO_TEST_DRIVER_H */ diff --git a/tests/src/drivers/cipher.c b/tests/src/drivers/cipher.c new file mode 100644 index 000000000..0f059a08d --- /dev/null +++ b/tests/src/drivers/cipher.c @@ -0,0 +1,348 @@ +/* + * Test driver for cipher functions. + * Currently only supports multi-part operations using AES-CTR. + */ +/* Copyright (C) 2020, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST) +#include "psa/crypto.h" +#include "mbedtls/cipher.h" + +#include "drivers/cipher.h" + +#include "test/random.h" + +#include + +/* If non-null, on success, copy this to the output. */ +void *test_driver_cipher_forced_output = NULL; +size_t test_driver_cipher_forced_output_length = 0; + +psa_status_t test_transparent_cipher_status = PSA_ERROR_NOT_SUPPORTED; +unsigned long test_transparent_cipher_hit = 0; + +psa_status_t test_transparent_cipher_encrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, size_t *output_length) +{ + (void) attributes; + (void) key; + (void) key_length; + (void) alg; + (void) input; + (void) input_length; + test_transparent_cipher_hit++; + + if( test_transparent_cipher_status != PSA_SUCCESS ) + return test_transparent_cipher_status; + if( output_size < test_driver_cipher_forced_output_length ) + return PSA_ERROR_BUFFER_TOO_SMALL; + + memcpy(output, test_driver_cipher_forced_output, test_driver_cipher_forced_output_length); + *output_length = test_driver_cipher_forced_output_length; + + return test_transparent_cipher_status; +} + +psa_status_t test_transparent_cipher_decrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, size_t *output_length) +{ + (void) attributes; + (void) key; + (void) key_length; + (void) alg; + (void) input; + (void) input_length; + test_transparent_cipher_hit++; + + if( test_transparent_cipher_status != PSA_SUCCESS ) + return test_transparent_cipher_status; + if( output_size < test_driver_cipher_forced_output_length ) + return PSA_ERROR_BUFFER_TOO_SMALL; + + memcpy(output, test_driver_cipher_forced_output, test_driver_cipher_forced_output_length); + *output_length = test_driver_cipher_forced_output_length; + + return test_transparent_cipher_status; +} + +psa_status_t test_transparent_cipher_encrypt_setup( + test_transparent_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg) +{ + (void) attributes; + (void) key; + (void) key_length; + (void) alg; + + /* write our struct, this will trigger memory corruption failures + * in test when we go outside of bounds. */ + memset(operation, 0, sizeof(test_transparent_cipher_operation_t)); + + test_transparent_cipher_hit++; + return test_transparent_cipher_status; +} + +psa_status_t test_transparent_cipher_decrypt_setup( + test_transparent_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg) +{ + (void) attributes; + (void) key; + (void) key_length; + (void) alg; + + /* write our struct, this will trigger memory corruption failures + * in test when we go outside of bounds. */ + memset(operation, 0, sizeof(test_transparent_cipher_operation_t)); + + test_transparent_cipher_hit++; + return test_transparent_cipher_status; +} + +psa_status_t test_transparent_cipher_abort( + test_transparent_cipher_operation_t *operation) +{ + /* write our struct, this will trigger memory corruption failures + * in test when we go outside of bounds. */ + memset(operation, 0, sizeof(test_transparent_cipher_operation_t)); + + test_transparent_cipher_hit++; + return test_transparent_cipher_status; +} + +psa_status_t test_transparent_cipher_generate_iv( + test_transparent_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length) +{ + (void) operation; + (void) iv; + (void) iv_size; + (void) iv_length; + + test_transparent_cipher_hit++; + return test_transparent_cipher_status; +} + +psa_status_t test_transparent_cipher_set_iv( + test_transparent_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length) +{ + (void) operation; + (void) iv; + (void) iv_length; + + test_transparent_cipher_hit++; + return test_transparent_cipher_status; +} + +psa_status_t test_transparent_cipher_update( + test_transparent_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + (void) operation; + (void) input; + (void) input_length; + test_transparent_cipher_hit++; + + if( test_transparent_cipher_status != PSA_SUCCESS ) + return test_transparent_cipher_status; + if( output_size < test_driver_cipher_forced_output_length ) + return PSA_ERROR_BUFFER_TOO_SMALL; + + memcpy(output, test_driver_cipher_forced_output, test_driver_cipher_forced_output_length); + *output_length = test_driver_cipher_forced_output_length; + + return test_transparent_cipher_status; +} + +psa_status_t test_transparent_cipher_finish( + test_transparent_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + (void) operation; + test_transparent_cipher_hit++; + + if( test_transparent_cipher_status != PSA_SUCCESS ) + return test_transparent_cipher_status; + if( output_size < test_driver_cipher_forced_output_length ) + return PSA_ERROR_BUFFER_TOO_SMALL; + + memcpy(output, test_driver_cipher_forced_output, test_driver_cipher_forced_output_length); + *output_length = test_driver_cipher_forced_output_length; + + return test_transparent_cipher_status; +} + +/* + * opaque versions, to do + */ +psa_status_t test_opaque_cipher_encrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, size_t *output_length) +{ + (void) attributes; + (void) key; + (void) key_length; + (void) alg; + (void) input; + (void) input_length; + (void) output; + (void) output_size; + (void) output_length; + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t test_opaque_cipher_decrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, size_t *output_length) +{ + (void) attributes; + (void) key; + (void) key_length; + (void) alg; + (void) input; + (void) input_length; + (void) output; + (void) output_size; + (void) output_length; + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t test_opaque_cipher_encrypt_setup( + test_opaque_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg) +{ + (void) operation; + (void) attributes; + (void) key; + (void) key_length; + (void) alg; + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t test_opaque_cipher_decrypt_setup( + test_opaque_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg) +{ + (void) operation; + (void) attributes; + (void) key; + (void) key_length; + (void) alg; + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t test_opaque_cipher_abort( + test_opaque_cipher_operation_t *operation) +{ + (void) operation; + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t test_opaque_cipher_generate_iv( + test_opaque_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length) +{ + (void) operation; + (void) iv; + (void) iv_size; + (void) iv_length; + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t test_opaque_cipher_set_iv( + test_opaque_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length) +{ + (void) operation; + (void) iv; + (void) iv_length; + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t test_opaque_cipher_update( + test_opaque_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + (void) operation; + (void) input; + (void) input_length; + (void) output; + (void) output_size; + (void) output_length; + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t test_opaque_cipher_finish( + test_opaque_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + (void) operation; + (void) output; + (void) output_size; + (void) output_length; + return PSA_ERROR_NOT_SUPPORTED; +} +#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */ From d3feccd3a5364a7ac99097672954a1c8aa9d45cf Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Tue, 1 Sep 2020 15:56:14 +0200 Subject: [PATCH 02/22] Restructure cipher context object to contain driver switch Once an operation has been 'accepted' by a driver, the remainder is bound to the same driver, since driver-specific context structs cannot be shared. This provides a pretty good gate mechanism for the fallback logic, too. Signed-off-by: Steven Cooreman --- include/psa/crypto_struct.h | 3 +- library/psa_crypto.c | 68 +++++++++++++++++++++++++++++-------- tests/src/drivers/cipher.c | 2 ++ 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 0ea8073ec..3ff3f93ef 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -158,6 +158,7 @@ struct psa_cipher_operation_s unsigned int key_set : 1; unsigned int iv_required : 1; unsigned int iv_set : 1; + unsigned int accelerator_set : 1; uint8_t iv_size; uint8_t block_size; union @@ -173,7 +174,7 @@ struct psa_cipher_operation_s } ctx; }; -#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, 0, 0, {0}} +#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, 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 6acf49850..7eb956835 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -4059,9 +4059,9 @@ static psa_status_t psa_cipher_init( psa_cipher_operation_t *operation, { operation->iv_required = 1; } + operation->accelerator_set = 0; operation->iv_size = 0; operation->block_size = 0; - mbedtls_cipher_init( &operation->ctx.cipher ); return( PSA_SUCCESS ); } @@ -4083,6 +4083,14 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, if( status != PSA_SUCCESS ) goto exit; + /* A context must be freshly initialized before it can be set up. */ + if( operation->alg != 0 ) + return( PSA_ERROR_BAD_STATE ); + + status = psa_cipher_init( operation, alg ); + if( status != PSA_SUCCESS ) + return( status ); + /* Try doing this through a driver before using software fallback */ if( cipher_operation == MBEDTLS_ENCRYPT ) status = psa_driver_wrapper_cipher_encrypt_setup( operation, @@ -4093,18 +4101,19 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, slot, alg ); - if( status != PSA_ERROR_NOT_SUPPORTED ) - goto exit; - - /* A context must be freshly initialized before it can be set up. */ - if( operation->alg != 0 ) + if( status == PSA_SUCCESS ) { - return( PSA_ERROR_BAD_STATE ); + operation->accelerator_set = 1; + operation->key_set = 1; } - status = psa_cipher_init( operation, alg ); - if( status != PSA_SUCCESS ) - return( status ); + if( status != PSA_ERROR_NOT_SUPPORTED || + psa_key_lifetime_is_external( slot->attr.lifetime ) ) + goto exit; + + /* Proceed with initializing mbed TLS cipher context if no accelerator is + * available for the given algorithm & key. */ + mbedtls_cipher_init( &operation->ctx.cipher ); status = psa_get_transparent_key( handle, &slot, usage, alg); if( status != PSA_SUCCESS ) @@ -4206,7 +4215,14 @@ psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, { psa_status_t status; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( operation->iv_set || ! operation->iv_required ) + + if( operation->accelerator_set == 1 ) + return( psa_driver_wrapper_cipher_generate_iv( operation, + iv, + iv_size, + iv_length ) ); + + if( operation->iv_set || ! operation->iv_required || ! operation->key_set ) { return( PSA_ERROR_BAD_STATE ); } @@ -4238,7 +4254,13 @@ psa_status_t psa_cipher_set_iv( psa_cipher_operation_t *operation, { psa_status_t status; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( operation->iv_set || ! operation->iv_required ) + + if( operation->accelerator_set == 1 ) + return( psa_driver_wrapper_cipher_set_iv( operation, + iv, + iv_length ) ); + + if( operation->iv_set || ! operation->iv_required || ! operation->key_set ) { return( PSA_ERROR_BAD_STATE ); } @@ -4355,7 +4377,15 @@ psa_status_t psa_cipher_update( psa_cipher_operation_t *operation, psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t expected_output_size; - if( operation->alg == 0 ) + if( operation->accelerator_set == 1 ) + return( psa_driver_wrapper_cipher_update( operation, + input, + input_length, + output, + output_size, + output_length ) ); + + if( operation->alg == 0 || ! operation->key_set ) { return( PSA_ERROR_BAD_STATE ); } @@ -4414,6 +4444,12 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, int cipher_ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; + if( operation->accelerator_set == 1 ) + return( psa_driver_wrapper_cipher_finish( operation, + output, + output_size, + output_length ) ); + if( ! operation->key_set ) { return( PSA_ERROR_BAD_STATE ); @@ -4483,11 +4519,15 @@ psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) if( ! PSA_ALG_IS_CIPHER( operation->alg ) ) return( PSA_ERROR_BAD_STATE ); - mbedtls_cipher_free( &operation->ctx.cipher ); + if( operation->accelerator_set == 1 ) + psa_driver_wrapper_cipher_abort( operation ); + else + mbedtls_cipher_free( &operation->ctx.cipher ); operation->alg = 0; operation->key_set = 0; operation->iv_set = 0; + operation->accelerator_set = 0; operation->iv_size = 0; operation->block_size = 0; operation->iv_required = 0; diff --git a/tests/src/drivers/cipher.c b/tests/src/drivers/cipher.c index 0f059a08d..9db506151 100644 --- a/tests/src/drivers/cipher.c +++ b/tests/src/drivers/cipher.c @@ -40,6 +40,8 @@ void *test_driver_cipher_forced_output = NULL; size_t test_driver_cipher_forced_output_length = 0; +/* Test driver, if not explicitly setup, returns 'PSA_ERROR_NOT_SUPPORTED' by default, + * causing regular test suites to pass since the core will go into fallback mode. */ psa_status_t test_transparent_cipher_status = PSA_ERROR_NOT_SUPPORTED; unsigned long test_transparent_cipher_hit = 0; From 3ec4018e2bdcd187604f8280ecb14e00b698fed1 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Wed, 2 Sep 2020 16:27:46 +0200 Subject: [PATCH 03/22] Update license texts Signed-off-by: Steven Cooreman --- tests/include/test/drivers/cipher.h | 4 +--- tests/src/drivers/cipher.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/include/test/drivers/cipher.h b/tests/include/test/drivers/cipher.h index c58a92691..a697054fe 100644 --- a/tests/include/test/drivers/cipher.h +++ b/tests/include/test/drivers/cipher.h @@ -1,7 +1,7 @@ /* * Test driver for cipher functions */ -/* Copyright (C) 2020, ARM Limited, All Rights Reserved +/* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -15,8 +15,6 @@ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef PSA_CRYPTO_TEST_DRIVERS_CIPHER_H diff --git a/tests/src/drivers/cipher.c b/tests/src/drivers/cipher.c index 9db506151..95dc2b6bc 100644 --- a/tests/src/drivers/cipher.c +++ b/tests/src/drivers/cipher.c @@ -2,7 +2,7 @@ * Test driver for cipher functions. * Currently only supports multi-part operations using AES-CTR. */ -/* Copyright (C) 2020, ARM Limited, All Rights Reserved +/* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -16,8 +16,6 @@ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) From 8b12225717833eacc24f72a222abcf9de0b20f50 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Thu, 3 Sep 2020 15:30:32 +0200 Subject: [PATCH 04/22] Add a working implementation of a multipart AES-CTR test driver Signed-off-by: Steven Cooreman --- library/psa_crypto.c | 50 ++++--- tests/src/drivers/cipher.c | 258 ++++++++++++++++++++++++++++++------- 2 files changed, 246 insertions(+), 62 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 7eb956835..cdae05ec4 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -4217,10 +4217,13 @@ psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if( operation->accelerator_set == 1 ) - return( psa_driver_wrapper_cipher_generate_iv( operation, - iv, - iv_size, - iv_length ) ); + { + status = psa_driver_wrapper_cipher_generate_iv( operation, + iv, + iv_size, + iv_length ); + goto exit; + } if( operation->iv_set || ! operation->iv_required || ! operation->key_set ) { @@ -4256,9 +4259,12 @@ psa_status_t psa_cipher_set_iv( psa_cipher_operation_t *operation, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if( operation->accelerator_set == 1 ) - return( psa_driver_wrapper_cipher_set_iv( operation, - iv, - iv_length ) ); + { + status = psa_driver_wrapper_cipher_set_iv( operation, + iv, + iv_length ); + goto exit; + } if( operation->iv_set || ! operation->iv_required || ! operation->key_set ) { @@ -4378,12 +4384,15 @@ psa_status_t psa_cipher_update( psa_cipher_operation_t *operation, size_t expected_output_size; if( operation->accelerator_set == 1 ) - return( psa_driver_wrapper_cipher_update( operation, - input, - input_length, - output, - output_size, - output_length ) ); + { + status = psa_driver_wrapper_cipher_update( operation, + input, + input_length, + output, + output_size, + output_length ); + goto exit; + } if( operation->alg == 0 || ! operation->key_set ) { @@ -4445,10 +4454,17 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; if( operation->accelerator_set == 1 ) - return( psa_driver_wrapper_cipher_finish( operation, - output, - output_size, - output_length ) ); + { + status = psa_driver_wrapper_cipher_finish( operation, + output, + output_size, + output_length ); + if( status != PSA_SUCCESS ) + goto error; + + (void) psa_cipher_abort( operation ); + return( status ); + } if( ! operation->key_set ) { diff --git a/tests/src/drivers/cipher.c b/tests/src/drivers/cipher.c index 95dc2b6bc..278e42899 100644 --- a/tests/src/drivers/cipher.c +++ b/tests/src/drivers/cipher.c @@ -38,9 +38,12 @@ void *test_driver_cipher_forced_output = NULL; size_t test_driver_cipher_forced_output_length = 0; -/* Test driver, if not explicitly setup, returns 'PSA_ERROR_NOT_SUPPORTED' by default, - * causing regular test suites to pass since the core will go into fallback mode. */ -psa_status_t test_transparent_cipher_status = PSA_ERROR_NOT_SUPPORTED; +/* Test driver implements AES-CTR by default when it's status is not overridden. + * Set test_transparent_cipher_status to PSA_ERROR_NOT_SUPPORTED to use fallback + * even for AES-CTR. + * Keep in mind this code is only exercised during the crypto drivers test target, + * meaning the other test runs will still test only the non-driver implementation. */ +psa_status_t test_transparent_cipher_status = PSA_SUCCESS; unsigned long test_transparent_cipher_hit = 0; psa_status_t test_transparent_cipher_encrypt( @@ -101,16 +104,57 @@ psa_status_t test_transparent_cipher_encrypt_setup( const uint8_t *key, size_t key_length, psa_algorithm_t alg) { - (void) attributes; - (void) key; - (void) key_length; - (void) alg; - - /* write our struct, this will trigger memory corruption failures - * in test when we go outside of bounds. */ - memset(operation, 0, sizeof(test_transparent_cipher_operation_t)); + const mbedtls_cipher_info_t *cipher_info = NULL; + int ret = 0; test_transparent_cipher_hit++; + + if( operation->alg != 0 ) + return PSA_ERROR_BAD_STATE; + + /* write our struct, this will trigger memory corruption failures + * in test when we go outside of bounds, or when the function is called + * without first destroying the context object. */ + memset(operation, 0, sizeof(test_transparent_cipher_operation_t)); + + /* Test driver supports AES-CTR only, to verify operation calls. */ + if( alg != PSA_ALG_CTR || psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES ) + return PSA_ERROR_NOT_SUPPORTED; + + operation->alg = alg; + operation->iv_size = 16; + operation->block_size = 16; + + cipher_info = mbedtls_cipher_info_from_values( MBEDTLS_CIPHER_ID_AES, + key_length * 8, + MBEDTLS_MODE_CTR ); + if( cipher_info == NULL ) + return PSA_ERROR_NOT_SUPPORTED; + + mbedtls_cipher_init( &operation->cipher ); + + ret = mbedtls_cipher_setup( &operation->cipher, cipher_info ); + if( ret != 0 ) { + mbedtls_cipher_free( &operation->cipher ); + return mbedtls_to_psa_error( ret ); + } + + ret = mbedtls_cipher_setkey( &operation->cipher, + key, + key_length * 8, MBEDTLS_ENCRYPT ); + if( ret != 0 ) { + mbedtls_cipher_free( &operation->cipher ); + return mbedtls_to_psa_error( ret ); + } + + operation->iv_set = 0; + operation->iv_required = 1; + operation->key_set = 1; + + /* Allow overriding return value for testing purposes */ + if( test_transparent_cipher_status != PSA_SUCCESS ) + mbedtls_cipher_free( &operation->cipher ); + return test_transparent_cipher_status; } @@ -120,28 +164,72 @@ psa_status_t test_transparent_cipher_decrypt_setup( const uint8_t *key, size_t key_length, psa_algorithm_t alg) { - (void) attributes; - (void) key; - (void) key_length; - (void) alg; - - /* write our struct, this will trigger memory corruption failures - * in test when we go outside of bounds. */ - memset(operation, 0, sizeof(test_transparent_cipher_operation_t)); +const mbedtls_cipher_info_t *cipher_info = NULL; + int ret = 0; test_transparent_cipher_hit++; + + if( operation->alg != 0 ) + return PSA_ERROR_BAD_STATE; + + /* write our struct, this will trigger memory corruption failures + * in test when we go outside of bounds, or when the function is called + * without first destroying the context object. */ + memset(operation, 0, sizeof(test_transparent_cipher_operation_t)); + + /* Test driver supports AES-CTR only, to verify operation calls. */ + if( alg != PSA_ALG_CTR || psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES ) + return PSA_ERROR_NOT_SUPPORTED; + + operation->alg = alg; + operation->iv_size = 16; + operation->block_size = 16; + + mbedtls_cipher_init( &operation->cipher ); + + cipher_info = mbedtls_cipher_info_from_values( MBEDTLS_CIPHER_ID_AES, + key_length * 8, + MBEDTLS_MODE_CTR ); + if( cipher_info == NULL ) + return PSA_ERROR_NOT_SUPPORTED; + + ret = mbedtls_cipher_setup( &operation->cipher, cipher_info ); + if( ret != 0 ) + return mbedtls_to_psa_error( ret ); + + ret = mbedtls_cipher_setkey( &operation->cipher, + key, + key_length * 8, MBEDTLS_DECRYPT ); + if( ret != 0 ) + return mbedtls_to_psa_error( ret ); + + operation->iv_set = 0; + operation->iv_required = 1; + operation->key_set = 1; + + /* Allow overriding return value for testing purposes */ + if( test_transparent_cipher_status != PSA_SUCCESS ) + mbedtls_cipher_free( &operation->cipher ); + return test_transparent_cipher_status; } psa_status_t test_transparent_cipher_abort( test_transparent_cipher_operation_t *operation) { + if( operation->alg == 0 ) + return( PSA_SUCCESS ); + if( operation->alg != PSA_ALG_CTR ) + return( PSA_ERROR_BAD_STATE ); + + mbedtls_cipher_free( &operation->cipher ); + /* write our struct, this will trigger memory corruption failures * in test when we go outside of bounds. */ memset(operation, 0, sizeof(test_transparent_cipher_operation_t)); test_transparent_cipher_hit++; - return test_transparent_cipher_status; + return PSA_SUCCESS; } psa_status_t test_transparent_cipher_generate_iv( @@ -150,13 +238,32 @@ psa_status_t test_transparent_cipher_generate_iv( size_t iv_size, size_t *iv_length) { - (void) operation; - (void) iv; - (void) iv_size; - (void) iv_length; + psa_status_t status; + mbedtls_test_rnd_pseudo_info rnd_info; + memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) ); test_transparent_cipher_hit++; - return test_transparent_cipher_status; + + if( operation->alg != PSA_ALG_CTR ) + return( PSA_ERROR_BAD_STATE ); + + if( operation->iv_set || ! operation->iv_required ) + return( PSA_ERROR_BAD_STATE ); + + if( iv_size < operation->iv_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + status = mbedtls_to_psa_error( + mbedtls_test_rnd_pseudo_rand( &rnd_info, + iv, + operation->iv_size ) ); + if( status != PSA_SUCCESS ) + return status; + + *iv_length = operation->iv_size; + status = test_transparent_cipher_set_iv( operation, iv, *iv_length ); + + return status; } psa_status_t test_transparent_cipher_set_iv( @@ -164,12 +271,26 @@ psa_status_t test_transparent_cipher_set_iv( const uint8_t *iv, size_t iv_length) { - (void) operation; - (void) iv; - (void) iv_length; + psa_status_t status; test_transparent_cipher_hit++; - return test_transparent_cipher_status; + + if( operation->alg != PSA_ALG_CTR ) + return PSA_ERROR_BAD_STATE; + + if( operation->iv_set || ! operation->iv_required ) + return( PSA_ERROR_BAD_STATE ); + + if( iv_length != operation->iv_size ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = mbedtls_to_psa_error( + mbedtls_cipher_set_iv( &operation->cipher, iv, iv_length ) ); + + if( status == PSA_SUCCESS ) + operation->iv_set = 1; + + return status; } psa_status_t test_transparent_cipher_update( @@ -180,18 +301,35 @@ psa_status_t test_transparent_cipher_update( size_t output_size, size_t *output_length) { - (void) operation; - (void) input; - (void) input_length; + size_t expected_output_size; + psa_status_t status; + test_transparent_cipher_hit++; - if( test_transparent_cipher_status != PSA_SUCCESS ) - return test_transparent_cipher_status; - if( output_size < test_driver_cipher_forced_output_length ) - return PSA_ERROR_BUFFER_TOO_SMALL; + if( operation->alg != PSA_ALG_CTR ) + return( PSA_ERROR_BAD_STATE ); - memcpy(output, test_driver_cipher_forced_output, test_driver_cipher_forced_output_length); - *output_length = test_driver_cipher_forced_output_length; + expected_output_size = ( operation->cipher.unprocessed_len + input_length ) + / operation->block_size * operation->block_size; + + if( output_size < expected_output_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + status = mbedtls_to_psa_error( + mbedtls_cipher_update( &operation->cipher, input, + input_length, output, output_length ) ); + + if( status != PSA_SUCCESS ) + return status; + + if( test_driver_cipher_forced_output != NULL ) + { + if( output_size < test_driver_cipher_forced_output_length ) + return PSA_ERROR_BUFFER_TOO_SMALL; + + memcpy(output, test_driver_cipher_forced_output, test_driver_cipher_forced_output_length); + *output_length = test_driver_cipher_forced_output_length; + } return test_transparent_cipher_status; } @@ -202,16 +340,46 @@ psa_status_t test_transparent_cipher_finish( size_t output_size, size_t *output_length) { - (void) operation; + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; + test_transparent_cipher_hit++; - if( test_transparent_cipher_status != PSA_SUCCESS ) - return test_transparent_cipher_status; - if( output_size < test_driver_cipher_forced_output_length ) - return PSA_ERROR_BUFFER_TOO_SMALL; + if( operation->alg != PSA_ALG_CTR ) + return( PSA_ERROR_BAD_STATE ); - memcpy(output, test_driver_cipher_forced_output, test_driver_cipher_forced_output_length); - *output_length = test_driver_cipher_forced_output_length; + if( ! operation->key_set ) + return( PSA_ERROR_BAD_STATE ); + + if( operation->iv_required && ! operation->iv_set ) + return( PSA_ERROR_BAD_STATE ); + + status = mbedtls_to_psa_error( + mbedtls_cipher_finish( &operation->cipher, + temp_output_buffer, + output_length ) ); + + mbedtls_cipher_free( &operation->cipher ); + + if( status != PSA_SUCCESS ) + return( status ); + + if( *output_length == 0 ) + ; /* Nothing to copy. Note that output may be NULL in this case. */ + else if( output_size >= *output_length ) + memcpy( output, temp_output_buffer, *output_length ); + else + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + + if( test_driver_cipher_forced_output != NULL ) + { + if( output_size < test_driver_cipher_forced_output_length ) + return PSA_ERROR_BUFFER_TOO_SMALL; + + memcpy(output, test_driver_cipher_forced_output, test_driver_cipher_forced_output_length); + *output_length = test_driver_cipher_forced_output_length; + } return test_transparent_cipher_status; } From d53c1bf6f27f6a52c548d517c27c7a92e7431ed4 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Thu, 3 Sep 2020 15:31:04 +0200 Subject: [PATCH 05/22] Exercise the AES-CTR multipart driver and check it gets called Signed-off-by: Steven Cooreman --- ...test_suite_psa_crypto_driver_wrappers.data | 84 +++++ ..._suite_psa_crypto_driver_wrappers.function | 319 ++++++++++++++++++ 2 files changed, 403 insertions(+) diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data index 74e61723f..b864daff5 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.data +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data @@ -39,3 +39,87 @@ generate_key:PSA_ERROR_NOT_SUPPORTED:"":PSA_SUCCESS generate_key through transparent driver: error generate_key:PSA_ERROR_GENERIC_ERROR:"":PSA_ERROR_GENERIC_ERROR + +PSA symmetric encrypt: AES-CTR, 16 bytes, good +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_SUCCESS + +PSA symmetric encrypt: AES-CTR, 15 bytes, good +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":PSA_SUCCESS + +PSA symmetric decrypt: AES-CTR, 16 bytes, good +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR +cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":PSA_SUCCESS + +PSA symmetric encryption multipart: AES-CTR, 11+5 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:11:5:"8f9408fe80a81d3e813da3c7b0b2bd32" + +PSA symmetric encryption multipart: AES-CTR, 16+16 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587" + +PSA symmetric encryption multipart: AES-CTR, 12+20 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:12:20:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587" + +PSA symmetric encryption multipart: AES-CTR, 20+12 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:20:12:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587" + +PSA symmetric encryption multipart: AES-CTR, 12+10 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597":12:12:10:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7b" + +PSA symmetric encryption multipart: AES-CTR, 0+15 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":0:0:15:"8f9408fe80a81d3e813da3c7b0b2bd" + +PSA symmetric encryption multipart: AES-CTR, 15+0 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd" + +PSA symmetric encryption multipart: AES-CTR, 0+16 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":0:0:16:"8f9408fe80a81d3e813da3c7b0b2bd32" + +PSA symmetric encryption multipart: AES-CTR, 16+0 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32" + +PSA symmetric decryption multipart: AES-CTR, 11+5 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:11:5:"8f9408fe80a81d3e813da3c7b0b2bd32" + +PSA symmetric decryption multipart: AES-CTR, 16+16 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587" + +PSA symmetric decryption multipart: AES-CTR, 12+20 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:12:20:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587" + +PSA symmetric decryption multipart: AES-CTR, 20+12 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:20:12:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587" + +PSA symmetric decryption multipart: AES-CTR, 12+10 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597":12:12:10:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7b" + +PSA symmetric decryption multipart: AES-CTR, 0+15 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":0:0:15:"8f9408fe80a81d3e813da3c7b0b2bd" + +PSA symmetric decryption multipart: AES-CTR, 15+0 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd" + +PSA symmetric decryption multipart: AES-CTR, 0+16 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":0:0:16:"8f9408fe80a81d3e813da3c7b0b2bd32" + +PSA symmetric decryption multipart: AES-CTR, 16+0 bytes +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32" diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function index 917798237..0e009911e 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function @@ -183,3 +183,322 @@ exit: test_driver_keygen_hooks = test_driver_keygen_hooks_init(); } /* END_CASE */ + +/* BEGIN_CASE */ +void cipher_encrypt( int alg_arg, int key_type_arg, + data_t *key, data_t *iv, + data_t *input, data_t *expected_output, + int expected_status_arg ) +{ + psa_key_handle_t handle = 0; + psa_status_t status; + psa_key_type_t key_type = key_type_arg; + psa_algorithm_t alg = alg_arg; + psa_status_t expected_status = expected_status_arg; + unsigned char *output = NULL; + size_t output_buffer_size = 0; + size_t function_output_length = 0; + size_t total_output_length = 0; + psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + test_transparent_cipher_hit = 0; + + PSA_ASSERT( psa_crypto_init( ) ); + + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT ); + psa_set_key_algorithm( &attributes, alg ); + psa_set_key_type( &attributes, key_type ); + + PSA_ASSERT( psa_import_key( &attributes, key->x, key->len, &handle ) ); + + PSA_ASSERT( psa_cipher_encrypt_setup( &operation, + handle, alg ) ); + TEST_EQUAL( test_transparent_cipher_hit, 1); + test_transparent_cipher_hit = 0; + + PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) ); + TEST_EQUAL( test_transparent_cipher_hit, 1); + test_transparent_cipher_hit = 0; + + output_buffer_size = ( (size_t) input->len + + PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) ); + ASSERT_ALLOC( output, output_buffer_size ); + + PSA_ASSERT( psa_cipher_update( &operation, + input->x, input->len, + output, output_buffer_size, + &function_output_length ) ); + TEST_EQUAL( test_transparent_cipher_hit, 1); + test_transparent_cipher_hit = 0; + + total_output_length += function_output_length; + status = psa_cipher_finish( &operation, + output + total_output_length, + output_buffer_size - total_output_length, + &function_output_length ); + TEST_EQUAL( test_transparent_cipher_hit, 2); + test_transparent_cipher_hit = 0; + + total_output_length += function_output_length; + + TEST_EQUAL( status, expected_status ); + if( expected_status == PSA_SUCCESS ) + { + PSA_ASSERT( psa_cipher_abort( &operation ) ); + // driver function should've been called as part of the finish() core routine + TEST_EQUAL( test_transparent_cipher_hit, 0); + test_transparent_cipher_hit = 0; + ASSERT_COMPARE( expected_output->x, expected_output->len, + output, total_output_length ); + } + +exit: + psa_cipher_abort( &operation ); + mbedtls_free( output ); + psa_destroy_key( handle ); + PSA_DONE( ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void cipher_encrypt_multipart( int alg_arg, int key_type_arg, + data_t *key, data_t *iv, + data_t *input, + int first_part_size_arg, + int output1_length_arg, int output2_length_arg, + data_t *expected_output ) +{ + psa_key_handle_t handle = 0; + psa_key_type_t key_type = key_type_arg; + psa_algorithm_t alg = alg_arg; + size_t first_part_size = first_part_size_arg; + size_t output1_length = output1_length_arg; + size_t output2_length = output2_length_arg; + unsigned char *output = NULL; + size_t output_buffer_size = 0; + size_t function_output_length = 0; + size_t total_output_length = 0; + psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + test_transparent_cipher_hit = 0; + + PSA_ASSERT( psa_crypto_init( ) ); + + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT ); + psa_set_key_algorithm( &attributes, alg ); + psa_set_key_type( &attributes, key_type ); + + PSA_ASSERT( psa_import_key( &attributes, key->x, key->len, &handle ) ); + + PSA_ASSERT( psa_cipher_encrypt_setup( &operation, + handle, alg ) ); + TEST_EQUAL( test_transparent_cipher_hit, 1); + test_transparent_cipher_hit = 0; + + PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) ); + TEST_EQUAL( test_transparent_cipher_hit, 1); + test_transparent_cipher_hit = 0; + + output_buffer_size = ( (size_t) input->len + + PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) ); + ASSERT_ALLOC( output, output_buffer_size ); + + TEST_ASSERT( first_part_size <= input->len ); + PSA_ASSERT( psa_cipher_update( &operation, input->x, first_part_size, + output, output_buffer_size, + &function_output_length ) ); + TEST_EQUAL( test_transparent_cipher_hit, 1); + test_transparent_cipher_hit = 0; + + TEST_ASSERT( function_output_length == output1_length ); + total_output_length += function_output_length; + PSA_ASSERT( psa_cipher_update( &operation, + input->x + first_part_size, + input->len - first_part_size, + output + total_output_length, + output_buffer_size - total_output_length, + &function_output_length ) ); + TEST_EQUAL( test_transparent_cipher_hit, 1); + test_transparent_cipher_hit = 0; + TEST_ASSERT( function_output_length == output2_length ); + total_output_length += function_output_length; + PSA_ASSERT( psa_cipher_finish( &operation, + output + total_output_length, + output_buffer_size - total_output_length, + &function_output_length ) ); + TEST_EQUAL( test_transparent_cipher_hit, 2); + test_transparent_cipher_hit = 0; + total_output_length += function_output_length; + PSA_ASSERT( psa_cipher_abort( &operation ) ); + TEST_EQUAL( test_transparent_cipher_hit, 0); + + ASSERT_COMPARE( expected_output->x, expected_output->len, + output, total_output_length ); + +exit: + psa_cipher_abort( &operation ); + mbedtls_free( output ); + psa_destroy_key( handle ); + PSA_DONE( ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void cipher_decrypt_multipart( int alg_arg, int key_type_arg, + data_t *key, data_t *iv, + data_t *input, + int first_part_size_arg, + int output1_length_arg, int output2_length_arg, + data_t *expected_output ) +{ + psa_key_handle_t handle = 0; + + psa_key_type_t key_type = key_type_arg; + psa_algorithm_t alg = alg_arg; + size_t first_part_size = first_part_size_arg; + size_t output1_length = output1_length_arg; + size_t output2_length = output2_length_arg; + unsigned char *output = NULL; + size_t output_buffer_size = 0; + size_t function_output_length = 0; + size_t total_output_length = 0; + psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + test_transparent_cipher_hit = 0; + + PSA_ASSERT( psa_crypto_init( ) ); + + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT ); + psa_set_key_algorithm( &attributes, alg ); + psa_set_key_type( &attributes, key_type ); + + PSA_ASSERT( psa_import_key( &attributes, key->x, key->len, &handle ) ); + + PSA_ASSERT( psa_cipher_decrypt_setup( &operation, + handle, alg ) ); + TEST_EQUAL( test_transparent_cipher_hit, 1); + test_transparent_cipher_hit = 0; + + PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) ); + TEST_EQUAL( test_transparent_cipher_hit, 1); + test_transparent_cipher_hit = 0; + + output_buffer_size = ( (size_t) input->len + + PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) ); + ASSERT_ALLOC( output, output_buffer_size ); + + TEST_ASSERT( first_part_size <= input->len ); + PSA_ASSERT( psa_cipher_update( &operation, + input->x, first_part_size, + output, output_buffer_size, + &function_output_length ) ); + TEST_EQUAL( test_transparent_cipher_hit, 1); + test_transparent_cipher_hit = 0; + + TEST_ASSERT( function_output_length == output1_length ); + total_output_length += function_output_length; + PSA_ASSERT( psa_cipher_update( &operation, + input->x + first_part_size, + input->len - first_part_size, + output + total_output_length, + output_buffer_size - total_output_length, + &function_output_length ) ); + TEST_EQUAL( test_transparent_cipher_hit, 1); + test_transparent_cipher_hit = 0; + + TEST_ASSERT( function_output_length == output2_length ); + total_output_length += function_output_length; + PSA_ASSERT( psa_cipher_finish( &operation, + output + total_output_length, + output_buffer_size - total_output_length, + &function_output_length ) ); + TEST_EQUAL( test_transparent_cipher_hit, 2); + test_transparent_cipher_hit = 0; + total_output_length += function_output_length; + PSA_ASSERT( psa_cipher_abort( &operation ) ); + TEST_EQUAL( test_transparent_cipher_hit, 0); + + ASSERT_COMPARE( expected_output->x, expected_output->len, + output, total_output_length ); + +exit: + psa_cipher_abort( &operation ); + mbedtls_free( output ); + psa_destroy_key( handle ); + PSA_DONE( ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void cipher_decrypt( int alg_arg, int key_type_arg, + data_t *key, data_t *iv, + data_t *input, data_t *expected_output, + int expected_status_arg ) +{ + psa_key_handle_t handle = 0; + psa_status_t status; + psa_key_type_t key_type = key_type_arg; + psa_algorithm_t alg = alg_arg; + psa_status_t expected_status = expected_status_arg; + unsigned char *output = NULL; + size_t output_buffer_size = 0; + size_t function_output_length = 0; + size_t total_output_length = 0; + psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + test_transparent_cipher_hit = 0; + + PSA_ASSERT( psa_crypto_init( ) ); + + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT ); + psa_set_key_algorithm( &attributes, alg ); + psa_set_key_type( &attributes, key_type ); + + PSA_ASSERT( psa_import_key( &attributes, key->x, key->len, &handle ) ); + + PSA_ASSERT( psa_cipher_decrypt_setup( &operation, + handle, alg ) ); + TEST_EQUAL( test_transparent_cipher_hit, 1); + test_transparent_cipher_hit = 0; + + PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) ); + TEST_EQUAL( test_transparent_cipher_hit, 1); + test_transparent_cipher_hit = 0; + + output_buffer_size = ( (size_t) input->len + + PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) ); + ASSERT_ALLOC( output, output_buffer_size ); + + PSA_ASSERT( psa_cipher_update( &operation, + input->x, input->len, + output, output_buffer_size, + &function_output_length ) ); + TEST_EQUAL( test_transparent_cipher_hit, 1); + test_transparent_cipher_hit = 0; + + total_output_length += function_output_length; + status = psa_cipher_finish( &operation, + output + total_output_length, + output_buffer_size - total_output_length, + &function_output_length ); + TEST_EQUAL( test_transparent_cipher_hit, 2); + test_transparent_cipher_hit = 0; + + total_output_length += function_output_length; + TEST_EQUAL( status, expected_status ); + + if( expected_status == PSA_SUCCESS ) + { + PSA_ASSERT( psa_cipher_abort( &operation ) ); + TEST_EQUAL( test_transparent_cipher_hit, 0); + ASSERT_COMPARE( expected_output->x, expected_output->len, + output, total_output_length ); + } + +exit: + psa_cipher_abort( &operation ); + mbedtls_free( output ); + psa_destroy_key( handle ); + PSA_DONE( ); +} +/* END_CASE */ From a32193fae8a2d1adc8d91fab062a6d7b48b0ea3a Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Thu, 3 Sep 2020 16:25:36 +0200 Subject: [PATCH 06/22] Add changelog entry Signed-off-by: Steven Cooreman --- ChangeLog.d/add_cipher_transparent_driver.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ChangeLog.d/add_cipher_transparent_driver.txt diff --git a/ChangeLog.d/add_cipher_transparent_driver.txt b/ChangeLog.d/add_cipher_transparent_driver.txt new file mode 100644 index 000000000..ce6f33d0d --- /dev/null +++ b/ChangeLog.d/add_cipher_transparent_driver.txt @@ -0,0 +1,4 @@ +Features + * Partial implementation of the new PSA Crypto accelerator APIs for + enabling symmetric cipher acceleration through crypto accelerators. + Contributed by Steven Cooreman in #3644. From 435beeaef34c2943ba1829f9d0e256430086618c Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Thu, 3 Sep 2020 16:37:54 +0200 Subject: [PATCH 07/22] Add new files to IDE project Signed-off-by: Steven Cooreman --- visualc/VS2010/mbedTLS.vcxproj | 1 + 1 file changed, 1 insertion(+) diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj index 9d7929839..db8ec3389 100644 --- a/visualc/VS2010/mbedTLS.vcxproj +++ b/visualc/VS2010/mbedTLS.vcxproj @@ -238,6 +238,7 @@ + From acb5a100a7280aec99218455b3e9ba7be7ae8895 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Tue, 8 Sep 2020 14:06:57 +0200 Subject: [PATCH 08/22] Structify cipher test driver hook variables Signed-off-by: Steven Cooreman --- tests/include/test/drivers/cipher.h | 22 ++- tests/src/drivers/cipher.c | 155 +++++++++--------- ..._suite_psa_crypto_driver_wrappers.function | 93 ++++++----- 3 files changed, 146 insertions(+), 124 deletions(-) diff --git a/tests/include/test/drivers/cipher.h b/tests/include/test/drivers/cipher.h index a697054fe..96ab29556 100644 --- a/tests/include/test/drivers/cipher.h +++ b/tests/include/test/drivers/cipher.h @@ -45,11 +45,25 @@ typedef struct{ test_transparent_cipher_operation_t ctx; } test_opaque_cipher_operation_t; -extern void *test_driver_cipher_forced_output; -extern size_t test_driver_cipher_forced_output_length; +typedef struct { + /* If non-null, on success, copy this to the output. */ + void *forced_output; + size_t forced_output_length; + /* If not PSA_SUCCESS, return this error code instead of processing the + * function call. */ + psa_status_t forced_status; + /* Count the amount of times one of the keygen driver functions is called. */ + unsigned long hits; +} test_driver_cipher_hooks_t; -extern psa_status_t test_transparent_cipher_status; -extern unsigned long test_transparent_cipher_hit; +#define TEST_DRIVER_CIPHER_INIT { NULL, 0, PSA_SUCCESS, 0 } +static inline test_driver_cipher_hooks_t test_driver_cipher_hooks_init( void ) +{ + const test_driver_cipher_hooks_t v = TEST_DRIVER_CIPHER_INIT; + return( v ); +} + +extern test_driver_cipher_hooks_t test_driver_cipher_hooks; psa_status_t test_transparent_cipher_encrypt( const psa_key_attributes_t *attributes, diff --git a/tests/src/drivers/cipher.c b/tests/src/drivers/cipher.c index 278e42899..0a4a347dd 100644 --- a/tests/src/drivers/cipher.c +++ b/tests/src/drivers/cipher.c @@ -26,25 +26,21 @@ #if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST) #include "psa/crypto.h" +#include "psa_crypto_core.h" #include "mbedtls/cipher.h" -#include "drivers/cipher.h" +#include "test/drivers/cipher.h" #include "test/random.h" #include -/* If non-null, on success, copy this to the output. */ -void *test_driver_cipher_forced_output = NULL; -size_t test_driver_cipher_forced_output_length = 0; - /* Test driver implements AES-CTR by default when it's status is not overridden. - * Set test_transparent_cipher_status to PSA_ERROR_NOT_SUPPORTED to use fallback - * even for AES-CTR. - * Keep in mind this code is only exercised during the crypto drivers test target, - * meaning the other test runs will still test only the non-driver implementation. */ -psa_status_t test_transparent_cipher_status = PSA_SUCCESS; -unsigned long test_transparent_cipher_hit = 0; + * Set test_driver_cipher_hooks.forced_status to PSA_ERROR_NOT_SUPPORTED to use + * fallback even for AES-CTR. + * Keep in mind this code is only exercised with the crypto drivers test target, + * meaning the other test runs will only test the non-driver implementation. */ +test_driver_cipher_hooks_t test_driver_cipher_hooks = TEST_DRIVER_CIPHER_INIT; psa_status_t test_transparent_cipher_encrypt( const psa_key_attributes_t *attributes, @@ -59,17 +55,19 @@ psa_status_t test_transparent_cipher_encrypt( (void) alg; (void) input; (void) input_length; - test_transparent_cipher_hit++; + test_driver_cipher_hooks.hits++; - if( test_transparent_cipher_status != PSA_SUCCESS ) - return test_transparent_cipher_status; - if( output_size < test_driver_cipher_forced_output_length ) - return PSA_ERROR_BUFFER_TOO_SMALL; + if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS ) + return( test_driver_cipher_hooks.forced_status ); + if( output_size < test_driver_cipher_hooks.forced_output_length ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); - memcpy(output, test_driver_cipher_forced_output, test_driver_cipher_forced_output_length); - *output_length = test_driver_cipher_forced_output_length; + memcpy( output, + test_driver_cipher_hooks.forced_output, + test_driver_cipher_hooks.forced_output_length ); + *output_length = test_driver_cipher_hooks.forced_output_length; - return test_transparent_cipher_status; + return( test_driver_cipher_hooks.forced_status ); } psa_status_t test_transparent_cipher_decrypt( @@ -85,17 +83,19 @@ psa_status_t test_transparent_cipher_decrypt( (void) alg; (void) input; (void) input_length; - test_transparent_cipher_hit++; + test_driver_cipher_hooks.hits++; - if( test_transparent_cipher_status != PSA_SUCCESS ) - return test_transparent_cipher_status; - if( output_size < test_driver_cipher_forced_output_length ) - return PSA_ERROR_BUFFER_TOO_SMALL; + if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS ) + return( test_driver_cipher_hooks.forced_status ); + if( output_size < test_driver_cipher_hooks.forced_output_length ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); - memcpy(output, test_driver_cipher_forced_output, test_driver_cipher_forced_output_length); - *output_length = test_driver_cipher_forced_output_length; + memcpy( output, + test_driver_cipher_hooks.forced_output, + test_driver_cipher_hooks.forced_output_length ); + *output_length = test_driver_cipher_hooks.forced_output_length; - return test_transparent_cipher_status; + return( test_driver_cipher_hooks.forced_status ); } psa_status_t test_transparent_cipher_encrypt_setup( @@ -107,19 +107,20 @@ psa_status_t test_transparent_cipher_encrypt_setup( const mbedtls_cipher_info_t *cipher_info = NULL; int ret = 0; - test_transparent_cipher_hit++; + test_driver_cipher_hooks.hits++; if( operation->alg != 0 ) - return PSA_ERROR_BAD_STATE; + return( PSA_ERROR_BAD_STATE ); /* write our struct, this will trigger memory corruption failures * in test when we go outside of bounds, or when the function is called * without first destroying the context object. */ - memset(operation, 0, sizeof(test_transparent_cipher_operation_t)); + memset( operation, 0, sizeof( test_transparent_cipher_operation_t ) ); /* Test driver supports AES-CTR only, to verify operation calls. */ - if( alg != PSA_ALG_CTR || psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES ) - return PSA_ERROR_NOT_SUPPORTED; + if( alg != PSA_ALG_CTR || + psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES ) + return( PSA_ERROR_NOT_SUPPORTED ); operation->alg = alg; operation->iv_size = 16; @@ -129,14 +130,14 @@ psa_status_t test_transparent_cipher_encrypt_setup( key_length * 8, MBEDTLS_MODE_CTR ); if( cipher_info == NULL ) - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); mbedtls_cipher_init( &operation->cipher ); ret = mbedtls_cipher_setup( &operation->cipher, cipher_info ); if( ret != 0 ) { mbedtls_cipher_free( &operation->cipher ); - return mbedtls_to_psa_error( ret ); + return( mbedtls_to_psa_error( ret ) ); } ret = mbedtls_cipher_setkey( &operation->cipher, @@ -144,7 +145,7 @@ psa_status_t test_transparent_cipher_encrypt_setup( key_length * 8, MBEDTLS_ENCRYPT ); if( ret != 0 ) { mbedtls_cipher_free( &operation->cipher ); - return mbedtls_to_psa_error( ret ); + return( mbedtls_to_psa_error( ret ) ); } operation->iv_set = 0; @@ -152,10 +153,10 @@ psa_status_t test_transparent_cipher_encrypt_setup( operation->key_set = 1; /* Allow overriding return value for testing purposes */ - if( test_transparent_cipher_status != PSA_SUCCESS ) + if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS ) mbedtls_cipher_free( &operation->cipher ); - return test_transparent_cipher_status; + return( test_driver_cipher_hooks.forced_status ); } psa_status_t test_transparent_cipher_decrypt_setup( @@ -164,18 +165,18 @@ psa_status_t test_transparent_cipher_decrypt_setup( const uint8_t *key, size_t key_length, psa_algorithm_t alg) { -const mbedtls_cipher_info_t *cipher_info = NULL; + const mbedtls_cipher_info_t *cipher_info = NULL; int ret = 0; - test_transparent_cipher_hit++; + test_driver_cipher_hooks.hits++; if( operation->alg != 0 ) - return PSA_ERROR_BAD_STATE; + return( PSA_ERROR_BAD_STATE ); /* write our struct, this will trigger memory corruption failures * in test when we go outside of bounds, or when the function is called * without first destroying the context object. */ - memset(operation, 0, sizeof(test_transparent_cipher_operation_t)); + memset( operation, 0, sizeof( test_transparent_cipher_operation_t ) ); /* Test driver supports AES-CTR only, to verify operation calls. */ if( alg != PSA_ALG_CTR || psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES ) @@ -195,23 +196,23 @@ const mbedtls_cipher_info_t *cipher_info = NULL; ret = mbedtls_cipher_setup( &operation->cipher, cipher_info ); if( ret != 0 ) - return mbedtls_to_psa_error( ret ); + return( mbedtls_to_psa_error( ret ) ); ret = mbedtls_cipher_setkey( &operation->cipher, key, key_length * 8, MBEDTLS_DECRYPT ); if( ret != 0 ) - return mbedtls_to_psa_error( ret ); + return( mbedtls_to_psa_error( ret ) ); operation->iv_set = 0; operation->iv_required = 1; operation->key_set = 1; /* Allow overriding return value for testing purposes */ - if( test_transparent_cipher_status != PSA_SUCCESS ) + if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS ) mbedtls_cipher_free( &operation->cipher ); - return test_transparent_cipher_status; + return( test_driver_cipher_hooks.forced_status ); } psa_status_t test_transparent_cipher_abort( @@ -226,10 +227,10 @@ psa_status_t test_transparent_cipher_abort( /* write our struct, this will trigger memory corruption failures * in test when we go outside of bounds. */ - memset(operation, 0, sizeof(test_transparent_cipher_operation_t)); + memset( operation, 0, sizeof( test_transparent_cipher_operation_t ) ); - test_transparent_cipher_hit++; - return PSA_SUCCESS; + test_driver_cipher_hooks.hits++; + return( PSA_SUCCESS ); } psa_status_t test_transparent_cipher_generate_iv( @@ -242,7 +243,7 @@ psa_status_t test_transparent_cipher_generate_iv( mbedtls_test_rnd_pseudo_info rnd_info; memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) ); - test_transparent_cipher_hit++; + test_driver_cipher_hooks.hits++; if( operation->alg != PSA_ALG_CTR ) return( PSA_ERROR_BAD_STATE ); @@ -258,12 +259,12 @@ psa_status_t test_transparent_cipher_generate_iv( iv, operation->iv_size ) ); if( status != PSA_SUCCESS ) - return status; + return( status ); *iv_length = operation->iv_size; status = test_transparent_cipher_set_iv( operation, iv, *iv_length ); - return status; + return( status ); } psa_status_t test_transparent_cipher_set_iv( @@ -273,10 +274,10 @@ psa_status_t test_transparent_cipher_set_iv( { psa_status_t status; - test_transparent_cipher_hit++; + test_driver_cipher_hooks.hits++; if( operation->alg != PSA_ALG_CTR ) - return PSA_ERROR_BAD_STATE; + return( PSA_ERROR_BAD_STATE ); if( operation->iv_set || ! operation->iv_required ) return( PSA_ERROR_BAD_STATE ); @@ -290,7 +291,7 @@ psa_status_t test_transparent_cipher_set_iv( if( status == PSA_SUCCESS ) operation->iv_set = 1; - return status; + return( status ); } psa_status_t test_transparent_cipher_update( @@ -304,7 +305,7 @@ psa_status_t test_transparent_cipher_update( size_t expected_output_size; psa_status_t status; - test_transparent_cipher_hit++; + test_driver_cipher_hooks.hits++; if( operation->alg != PSA_ALG_CTR ) return( PSA_ERROR_BAD_STATE ); @@ -322,16 +323,18 @@ psa_status_t test_transparent_cipher_update( if( status != PSA_SUCCESS ) return status; - if( test_driver_cipher_forced_output != NULL ) + if( test_driver_cipher_hooks.forced_output != NULL ) { - if( output_size < test_driver_cipher_forced_output_length ) + if( output_size < test_driver_cipher_hooks.forced_output_length ) return PSA_ERROR_BUFFER_TOO_SMALL; - memcpy(output, test_driver_cipher_forced_output, test_driver_cipher_forced_output_length); - *output_length = test_driver_cipher_forced_output_length; + memcpy( output, + test_driver_cipher_hooks.forced_output, + test_driver_cipher_hooks.forced_output_length ); + *output_length = test_driver_cipher_hooks.forced_output_length; } - return test_transparent_cipher_status; + return( test_driver_cipher_hooks.forced_status ); } psa_status_t test_transparent_cipher_finish( @@ -343,7 +346,7 @@ psa_status_t test_transparent_cipher_finish( psa_status_t status = PSA_ERROR_GENERIC_ERROR; uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; - test_transparent_cipher_hit++; + test_driver_cipher_hooks.hits++; if( operation->alg != PSA_ALG_CTR ) return( PSA_ERROR_BAD_STATE ); @@ -372,16 +375,18 @@ psa_status_t test_transparent_cipher_finish( return( PSA_ERROR_BUFFER_TOO_SMALL ); - if( test_driver_cipher_forced_output != NULL ) + if( test_driver_cipher_hooks.forced_output != NULL ) { - if( output_size < test_driver_cipher_forced_output_length ) + if( output_size < test_driver_cipher_hooks.forced_output_length ) return PSA_ERROR_BUFFER_TOO_SMALL; - memcpy(output, test_driver_cipher_forced_output, test_driver_cipher_forced_output_length); - *output_length = test_driver_cipher_forced_output_length; + memcpy( output, + test_driver_cipher_hooks.forced_output, + test_driver_cipher_hooks.forced_output_length ); + *output_length = test_driver_cipher_hooks.forced_output_length; } - return test_transparent_cipher_status; + return( test_driver_cipher_hooks.forced_status ); } /* @@ -403,7 +408,7 @@ psa_status_t test_opaque_cipher_encrypt( (void) output; (void) output_size; (void) output_length; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); } psa_status_t test_opaque_cipher_decrypt( @@ -422,7 +427,7 @@ psa_status_t test_opaque_cipher_decrypt( (void) output; (void) output_size; (void) output_length; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); } psa_status_t test_opaque_cipher_encrypt_setup( @@ -436,7 +441,7 @@ psa_status_t test_opaque_cipher_encrypt_setup( (void) key; (void) key_length; (void) alg; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); } psa_status_t test_opaque_cipher_decrypt_setup( @@ -450,14 +455,14 @@ psa_status_t test_opaque_cipher_decrypt_setup( (void) key; (void) key_length; (void) alg; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); } psa_status_t test_opaque_cipher_abort( test_opaque_cipher_operation_t *operation) { (void) operation; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); } psa_status_t test_opaque_cipher_generate_iv( @@ -470,7 +475,7 @@ psa_status_t test_opaque_cipher_generate_iv( (void) iv; (void) iv_size; (void) iv_length; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); } psa_status_t test_opaque_cipher_set_iv( @@ -481,7 +486,7 @@ psa_status_t test_opaque_cipher_set_iv( (void) operation; (void) iv; (void) iv_length; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); } psa_status_t test_opaque_cipher_update( @@ -498,7 +503,7 @@ psa_status_t test_opaque_cipher_update( (void) output; (void) output_size; (void) output_length; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); } psa_status_t test_opaque_cipher_finish( @@ -511,6 +516,6 @@ psa_status_t test_opaque_cipher_finish( (void) output; (void) output_size; (void) output_length; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); } #endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */ diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function index 0e009911e..1daf9bb3f 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function @@ -201,7 +201,7 @@ void cipher_encrypt( int alg_arg, int key_type_arg, size_t total_output_length = 0; psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - test_transparent_cipher_hit = 0; + test_driver_cipher_hooks = test_driver_cipher_hooks_init(); PSA_ASSERT( psa_crypto_init( ) ); @@ -213,12 +213,12 @@ void cipher_encrypt( int alg_arg, int key_type_arg, PSA_ASSERT( psa_cipher_encrypt_setup( &operation, handle, alg ) ); - TEST_EQUAL( test_transparent_cipher_hit, 1); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + test_driver_cipher_hooks.hits = 0; PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) ); - TEST_EQUAL( test_transparent_cipher_hit, 1); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + test_driver_cipher_hooks.hits = 0; output_buffer_size = ( (size_t) input->len + PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) ); @@ -228,16 +228,16 @@ void cipher_encrypt( int alg_arg, int key_type_arg, input->x, input->len, output, output_buffer_size, &function_output_length ) ); - TEST_EQUAL( test_transparent_cipher_hit, 1); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + test_driver_cipher_hooks.hits = 0; total_output_length += function_output_length; status = psa_cipher_finish( &operation, output + total_output_length, output_buffer_size - total_output_length, &function_output_length ); - TEST_EQUAL( test_transparent_cipher_hit, 2); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); + test_driver_cipher_hooks.hits = 0; total_output_length += function_output_length; @@ -246,8 +246,7 @@ void cipher_encrypt( int alg_arg, int key_type_arg, { PSA_ASSERT( psa_cipher_abort( &operation ) ); // driver function should've been called as part of the finish() core routine - TEST_EQUAL( test_transparent_cipher_hit, 0); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 0 ); ASSERT_COMPARE( expected_output->x, expected_output->len, output, total_output_length ); } @@ -257,6 +256,7 @@ exit: mbedtls_free( output ); psa_destroy_key( handle ); PSA_DONE( ); + test_driver_cipher_hooks = test_driver_cipher_hooks_init(); } /* END_CASE */ @@ -280,7 +280,7 @@ void cipher_encrypt_multipart( int alg_arg, int key_type_arg, size_t total_output_length = 0; psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - test_transparent_cipher_hit = 0; + test_driver_cipher_hooks = test_driver_cipher_hooks_init(); PSA_ASSERT( psa_crypto_init( ) ); @@ -292,12 +292,12 @@ void cipher_encrypt_multipart( int alg_arg, int key_type_arg, PSA_ASSERT( psa_cipher_encrypt_setup( &operation, handle, alg ) ); - TEST_EQUAL( test_transparent_cipher_hit, 1); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + test_driver_cipher_hooks.hits = 0; PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) ); - TEST_EQUAL( test_transparent_cipher_hit, 1); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + test_driver_cipher_hooks.hits = 0; output_buffer_size = ( (size_t) input->len + PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) ); @@ -307,8 +307,8 @@ void cipher_encrypt_multipart( int alg_arg, int key_type_arg, PSA_ASSERT( psa_cipher_update( &operation, input->x, first_part_size, output, output_buffer_size, &function_output_length ) ); - TEST_EQUAL( test_transparent_cipher_hit, 1); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + test_driver_cipher_hooks.hits = 0; TEST_ASSERT( function_output_length == output1_length ); total_output_length += function_output_length; @@ -318,19 +318,19 @@ void cipher_encrypt_multipart( int alg_arg, int key_type_arg, output + total_output_length, output_buffer_size - total_output_length, &function_output_length ) ); - TEST_EQUAL( test_transparent_cipher_hit, 1); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + test_driver_cipher_hooks.hits = 0; TEST_ASSERT( function_output_length == output2_length ); total_output_length += function_output_length; PSA_ASSERT( psa_cipher_finish( &operation, output + total_output_length, output_buffer_size - total_output_length, &function_output_length ) ); - TEST_EQUAL( test_transparent_cipher_hit, 2); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); + test_driver_cipher_hooks.hits = 0 ; total_output_length += function_output_length; PSA_ASSERT( psa_cipher_abort( &operation ) ); - TEST_EQUAL( test_transparent_cipher_hit, 0); + TEST_EQUAL( test_driver_cipher_hooks.hits, 0 ); ASSERT_COMPARE( expected_output->x, expected_output->len, output, total_output_length ); @@ -340,6 +340,7 @@ exit: mbedtls_free( output ); psa_destroy_key( handle ); PSA_DONE( ); + test_driver_cipher_hooks = test_driver_cipher_hooks_init(); } /* END_CASE */ @@ -364,7 +365,7 @@ void cipher_decrypt_multipart( int alg_arg, int key_type_arg, size_t total_output_length = 0; psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - test_transparent_cipher_hit = 0; + test_driver_cipher_hooks = test_driver_cipher_hooks_init(); PSA_ASSERT( psa_crypto_init( ) ); @@ -376,12 +377,12 @@ void cipher_decrypt_multipart( int alg_arg, int key_type_arg, PSA_ASSERT( psa_cipher_decrypt_setup( &operation, handle, alg ) ); - TEST_EQUAL( test_transparent_cipher_hit, 1); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + test_driver_cipher_hooks.hits = 0; PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) ); - TEST_EQUAL( test_transparent_cipher_hit, 1); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + test_driver_cipher_hooks.hits = 0; output_buffer_size = ( (size_t) input->len + PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) ); @@ -392,8 +393,8 @@ void cipher_decrypt_multipart( int alg_arg, int key_type_arg, input->x, first_part_size, output, output_buffer_size, &function_output_length ) ); - TEST_EQUAL( test_transparent_cipher_hit, 1); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + test_driver_cipher_hooks.hits = 0; TEST_ASSERT( function_output_length == output1_length ); total_output_length += function_output_length; @@ -403,8 +404,8 @@ void cipher_decrypt_multipart( int alg_arg, int key_type_arg, output + total_output_length, output_buffer_size - total_output_length, &function_output_length ) ); - TEST_EQUAL( test_transparent_cipher_hit, 1); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + test_driver_cipher_hooks.hits = 0; TEST_ASSERT( function_output_length == output2_length ); total_output_length += function_output_length; @@ -412,11 +413,11 @@ void cipher_decrypt_multipart( int alg_arg, int key_type_arg, output + total_output_length, output_buffer_size - total_output_length, &function_output_length ) ); - TEST_EQUAL( test_transparent_cipher_hit, 2); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); + test_driver_cipher_hooks.hits = 0; total_output_length += function_output_length; PSA_ASSERT( psa_cipher_abort( &operation ) ); - TEST_EQUAL( test_transparent_cipher_hit, 0); + TEST_EQUAL( test_driver_cipher_hooks.hits, 0 ); ASSERT_COMPARE( expected_output->x, expected_output->len, output, total_output_length ); @@ -426,6 +427,7 @@ exit: mbedtls_free( output ); psa_destroy_key( handle ); PSA_DONE( ); + test_driver_cipher_hooks = test_driver_cipher_hooks_init(); } /* END_CASE */ @@ -446,7 +448,7 @@ void cipher_decrypt( int alg_arg, int key_type_arg, size_t total_output_length = 0; psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - test_transparent_cipher_hit = 0; + test_driver_cipher_hooks = test_driver_cipher_hooks_init(); PSA_ASSERT( psa_crypto_init( ) ); @@ -458,12 +460,12 @@ void cipher_decrypt( int alg_arg, int key_type_arg, PSA_ASSERT( psa_cipher_decrypt_setup( &operation, handle, alg ) ); - TEST_EQUAL( test_transparent_cipher_hit, 1); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + test_driver_cipher_hooks.hits = 0; PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) ); - TEST_EQUAL( test_transparent_cipher_hit, 1); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + test_driver_cipher_hooks.hits = 0; output_buffer_size = ( (size_t) input->len + PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) ); @@ -473,16 +475,16 @@ void cipher_decrypt( int alg_arg, int key_type_arg, input->x, input->len, output, output_buffer_size, &function_output_length ) ); - TEST_EQUAL( test_transparent_cipher_hit, 1); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + test_driver_cipher_hooks.hits = 0; total_output_length += function_output_length; status = psa_cipher_finish( &operation, output + total_output_length, output_buffer_size - total_output_length, &function_output_length ); - TEST_EQUAL( test_transparent_cipher_hit, 2); - test_transparent_cipher_hit = 0; + TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); + test_driver_cipher_hooks.hits = 0; total_output_length += function_output_length; TEST_EQUAL( status, expected_status ); @@ -490,7 +492,7 @@ void cipher_decrypt( int alg_arg, int key_type_arg, if( expected_status == PSA_SUCCESS ) { PSA_ASSERT( psa_cipher_abort( &operation ) ); - TEST_EQUAL( test_transparent_cipher_hit, 0); + TEST_EQUAL( test_driver_cipher_hooks.hits, 0 ); ASSERT_COMPARE( expected_output->x, expected_output->len, output, total_output_length ); } @@ -500,5 +502,6 @@ exit: mbedtls_free( output ); psa_destroy_key( handle ); PSA_DONE( ); + test_driver_cipher_hooks = test_driver_cipher_hooks_init(); } /* END_CASE */ From 5240e8b519a95501b84d3724d3274c09e7bf46f2 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Wed, 9 Sep 2020 11:51:45 +0200 Subject: [PATCH 09/22] Style and language fixes from review Signed-off-by: Steven Cooreman --- include/psa/crypto_struct.h | 2 +- library/psa_crypto.c | 14 ++-- library/psa_crypto_driver_wrappers.c | 78 +++++++++---------- tests/include/test/drivers/cipher.h | 2 +- tests/src/drivers/cipher.c | 34 ++++---- ..._suite_psa_crypto_driver_wrappers.function | 4 + 6 files changed, 71 insertions(+), 63 deletions(-) diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 3ff3f93ef..5ac187504 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -158,7 +158,7 @@ struct psa_cipher_operation_s unsigned int key_set : 1; unsigned int iv_required : 1; unsigned int iv_set : 1; - unsigned int accelerator_set : 1; + unsigned int accelerator_set : 1; /* Indicates a driver is used instead of software fallback. */ uint8_t iv_size; uint8_t block_size; union diff --git a/library/psa_crypto.c b/library/psa_crypto.c index cdae05ec4..4ba9baffe 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -4225,7 +4225,7 @@ psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, goto exit; } - if( operation->iv_set || ! operation->iv_required || ! operation->key_set ) + if( operation->iv_set || ! operation->iv_required ) { return( PSA_ERROR_BAD_STATE ); } @@ -4266,7 +4266,7 @@ psa_status_t psa_cipher_set_iv( psa_cipher_operation_t *operation, goto exit; } - if( operation->iv_set || ! operation->iv_required || ! operation->key_set ) + if( operation->iv_set || ! operation->iv_required ) { return( PSA_ERROR_BAD_STATE ); } @@ -4394,7 +4394,11 @@ psa_status_t psa_cipher_update( psa_cipher_operation_t *operation, goto exit; } - if( operation->alg == 0 || ! operation->key_set ) + if( operation->alg == 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + if( operation->iv_required && ! operation->iv_set ) { return( PSA_ERROR_BAD_STATE ); } @@ -4466,10 +4470,6 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, return( status ); } - if( ! operation->key_set ) - { - return( PSA_ERROR_BAD_STATE ); - } if( operation->iv_required && ! operation->iv_set ) { return( PSA_ERROR_BAD_STATE ); diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index 140c3d4b8..11aeef830 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -411,10 +411,10 @@ psa_status_t psa_driver_wrapper_cipher_encrypt( output_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) - return status; + return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ /* Fell through, meaning no accelerator supports this operation */ - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: @@ -430,7 +430,7 @@ psa_status_t psa_driver_wrapper_cipher_encrypt( #endif /* PSA_CRYPTO_DRIVER_TEST */ default: /* Key is declared with a lifetime not known to us */ - return status; + return( status ); } #else /* PSA_CRYPTO_DRIVER_PRESENT */ (void) slot; @@ -441,7 +441,7 @@ psa_status_t psa_driver_wrapper_cipher_encrypt( (void) output_size; (void) output_length; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } @@ -478,10 +478,10 @@ psa_status_t psa_driver_wrapper_cipher_decrypt( output_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) - return status; + return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ /* Fell through, meaning no accelerator supports this operation */ - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: @@ -497,7 +497,7 @@ psa_status_t psa_driver_wrapper_cipher_decrypt( #endif /* PSA_CRYPTO_DRIVER_TEST */ default: /* Key is declared with a lifetime not known to us */ - return status; + return( status ); } #else /* PSA_CRYPTO_DRIVER_PRESENT */ (void) slot; @@ -508,7 +508,7 @@ psa_status_t psa_driver_wrapper_cipher_decrypt( (void) output_size; (void) output_length; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } @@ -526,7 +526,7 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( /* Check for operation already allocated */ if( operation->ctx.driver.ctx != NULL ) - return PSA_ERROR_BAD_STATE; + return( PSA_ERROR_BAD_STATE ); switch( location ) { @@ -554,7 +554,7 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( operation->ctx.driver.ctx = NULL; } - return status; + return( status ); } else { @@ -563,13 +563,13 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( } #endif /* PSA_CRYPTO_DRIVER_TEST */ /* Fell through, meaning no accelerator supports this operation */ - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: operation->ctx.driver.ctx = mbedtls_calloc( 1, sizeof(test_opaque_cipher_operation_t) ); if( operation->ctx.driver.ctx == NULL ) - return PSA_ERROR_INSUFFICIENT_MEMORY; + return( PSA_ERROR_INSUFFICIENT_MEMORY ); status = test_opaque_cipher_encrypt_setup( operation->ctx.driver.ctx, &attributes, @@ -584,18 +584,18 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( operation->ctx.driver.ctx = NULL; } - return status; + return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ default: /* Key is declared with a lifetime not known to us */ - return PSA_ERROR_BAD_STATE; + return( PSA_ERROR_BAD_STATE ); } #else /* PSA_CRYPTO_DRIVER_PRESENT */ (void)slot; (void)alg; (void)operation; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } @@ -613,7 +613,7 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( /* Check for operation already allocated */ if( operation->ctx.driver.ctx != NULL ) - return PSA_ERROR_BAD_STATE; + return( PSA_ERROR_BAD_STATE ); switch( location ) { @@ -623,7 +623,7 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( #if defined(PSA_CRYPTO_DRIVER_TEST) operation->ctx.driver.ctx = mbedtls_calloc( 1, sizeof(test_transparent_cipher_operation_t) ); if( operation->ctx.driver.ctx == NULL ) - return PSA_ERROR_INSUFFICIENT_MEMORY; + return( PSA_ERROR_INSUFFICIENT_MEMORY ); status = test_transparent_cipher_decrypt_setup( operation->ctx.driver.ctx, &attributes, @@ -641,7 +641,7 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( operation->ctx.driver.ctx = NULL; } - return status; + return( status ); } else { @@ -650,7 +650,7 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( } #endif /* PSA_CRYPTO_DRIVER_TEST */ /* Fell through, meaning no accelerator supports this operation */ - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: @@ -671,18 +671,18 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( operation->ctx.driver.ctx = NULL; } - return status; + return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ default: /* Key is declared with a lifetime not known to us */ - return PSA_ERROR_BAD_STATE; + return( PSA_ERROR_BAD_STATE ); } #else /* PSA_CRYPTO_DRIVER_PRESENT */ (void)slot; (void)alg; (void)operation; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } @@ -695,7 +695,7 @@ psa_status_t psa_driver_wrapper_cipher_generate_iv( #if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) /* Check for operation already allocated */ if( operation->ctx.driver.ctx == NULL ) - return PSA_ERROR_INVALID_ARGUMENT; + return( PSA_ERROR_INVALID_ARGUMENT ); switch( operation->ctx.driver.id ) { @@ -715,7 +715,7 @@ psa_status_t psa_driver_wrapper_cipher_generate_iv( #endif /* PSA_CRYPTO_DRIVER_TEST */ default: /* Key is attached to a driver not known to us */ - return PSA_ERROR_BAD_STATE; + return( PSA_ERROR_BAD_STATE ); } #else /* PSA_CRYPTO_DRIVER_PRESENT */ (void) operation; @@ -723,7 +723,7 @@ psa_status_t psa_driver_wrapper_cipher_generate_iv( (void) iv_size; (void) iv_length; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } @@ -735,7 +735,7 @@ psa_status_t psa_driver_wrapper_cipher_set_iv( #if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) /* Check for operation already allocated */ if( operation->ctx.driver.ctx == NULL ) - return PSA_ERROR_INVALID_ARGUMENT; + return( PSA_ERROR_INVALID_ARGUMENT ); switch( operation->ctx.driver.id ) { @@ -753,14 +753,14 @@ psa_status_t psa_driver_wrapper_cipher_set_iv( #endif /* PSA_CRYPTO_DRIVER_TEST */ default: /* Key is attached to a driver not known to us */ - return PSA_ERROR_BAD_STATE; + return( PSA_ERROR_BAD_STATE ); } #else /* PSA_CRYPTO_DRIVER_PRESENT */ (void) operation; (void) iv; (void) iv_length; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } @@ -775,7 +775,7 @@ psa_status_t psa_driver_wrapper_cipher_update( #if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) /* Check for operation already allocated */ if( operation->ctx.driver.ctx == NULL ) - return PSA_ERROR_INVALID_ARGUMENT; + return( PSA_ERROR_INVALID_ARGUMENT ); switch( operation->ctx.driver.id ) { @@ -799,7 +799,7 @@ psa_status_t psa_driver_wrapper_cipher_update( #endif /* PSA_CRYPTO_DRIVER_TEST */ default: /* Key is attached to a driver not known to us */ - return PSA_ERROR_BAD_STATE; + return( PSA_ERROR_BAD_STATE ); } #else /* PSA_CRYPTO_DRIVER_PRESENT */ (void) operation; @@ -809,7 +809,7 @@ psa_status_t psa_driver_wrapper_cipher_update( (void) output_length; (void) output_size; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } @@ -822,7 +822,7 @@ psa_status_t psa_driver_wrapper_cipher_finish( #if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) /* Check for operation already allocated */ if( operation->ctx.driver.ctx == NULL ) - return PSA_ERROR_INVALID_ARGUMENT; + return( PSA_ERROR_INVALID_ARGUMENT ); switch( operation->ctx.driver.id ) { @@ -842,7 +842,7 @@ psa_status_t psa_driver_wrapper_cipher_finish( #endif /* PSA_CRYPTO_DRIVER_TEST */ default: /* Key is attached to a driver not known to us */ - return PSA_ERROR_BAD_STATE; + return( PSA_ERROR_BAD_STATE ); } #else /* PSA_CRYPTO_DRIVER_PRESENT */ (void) operation; @@ -850,7 +850,7 @@ psa_status_t psa_driver_wrapper_cipher_finish( (void) output_size; (void) output_length; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } @@ -861,7 +861,7 @@ psa_status_t psa_driver_wrapper_cipher_abort( psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; /* Check for operation already allocated */ if( operation->ctx.driver.ctx == NULL ) - return PSA_ERROR_INVALID_ARGUMENT; + return( PSA_ERROR_INVALID_ARGUMENT ); switch( operation->ctx.driver.id ) { @@ -873,7 +873,7 @@ psa_status_t psa_driver_wrapper_cipher_abort( operation->ctx.driver.ctx = NULL; operation->ctx.driver.id = 0; - return status; + return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: @@ -881,16 +881,16 @@ psa_status_t psa_driver_wrapper_cipher_abort( mbedtls_free( operation->ctx.driver.ctx ); operation->ctx.driver.ctx = NULL; - return status; + return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ default: /* Operation is attached to a driver not known to us */ - return PSA_ERROR_BAD_STATE; + return( PSA_ERROR_BAD_STATE ); } #else /* PSA_CRYPTO_DRIVER_PRESENT */ (void)operation; - return PSA_ERROR_NOT_SUPPORTED; + return( PSA_ERROR_NOT_SUPPORTED ); #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } diff --git a/tests/include/test/drivers/cipher.h b/tests/include/test/drivers/cipher.h index 96ab29556..ef787f794 100644 --- a/tests/include/test/drivers/cipher.h +++ b/tests/include/test/drivers/cipher.h @@ -52,7 +52,7 @@ typedef struct { /* If not PSA_SUCCESS, return this error code instead of processing the * function call. */ psa_status_t forced_status; - /* Count the amount of times one of the keygen driver functions is called. */ + /* Count the amount of times one of the cipher driver functions is called. */ unsigned long hits; } test_driver_cipher_hooks_t; diff --git a/tests/src/drivers/cipher.c b/tests/src/drivers/cipher.c index 0a4a347dd..c8eb1d350 100644 --- a/tests/src/drivers/cipher.c +++ b/tests/src/drivers/cipher.c @@ -35,11 +35,11 @@ #include -/* Test driver implements AES-CTR by default when it's status is not overridden. +/* Test driver implements AES-CTR only. Its default behaviour (when its return + * status is not overridden through the hooks) is to take care of all AES-CTR + * operations, and return PSA_ERROR_NOT_SUPPORTED for all others. * Set test_driver_cipher_hooks.forced_status to PSA_ERROR_NOT_SUPPORTED to use - * fallback even for AES-CTR. - * Keep in mind this code is only exercised with the crypto drivers test target, - * meaning the other test runs will only test the non-driver implementation. */ + * fallback even for AES-CTR. */ test_driver_cipher_hooks_t test_driver_cipher_hooks = TEST_DRIVER_CIPHER_INIT; psa_status_t test_transparent_cipher_encrypt( @@ -112,10 +112,11 @@ psa_status_t test_transparent_cipher_encrypt_setup( if( operation->alg != 0 ) return( PSA_ERROR_BAD_STATE ); - /* write our struct, this will trigger memory corruption failures - * in test when we go outside of bounds, or when the function is called - * without first destroying the context object. */ - memset( operation, 0, sizeof( test_transparent_cipher_operation_t ) ); + /* Wiping the entire struct here, instead of member-by-member. This is useful + * for the test suite, since it gives a chance of catching memory corruption + * errors should the core not have allocated (enough) memory for our context + * struct. */ + memset( operation, 0, sizeof( *operation ) ); /* Test driver supports AES-CTR only, to verify operation calls. */ if( alg != PSA_ALG_CTR || @@ -173,10 +174,11 @@ psa_status_t test_transparent_cipher_decrypt_setup( if( operation->alg != 0 ) return( PSA_ERROR_BAD_STATE ); - /* write our struct, this will trigger memory corruption failures - * in test when we go outside of bounds, or when the function is called - * without first destroying the context object. */ - memset( operation, 0, sizeof( test_transparent_cipher_operation_t ) ); + /* Wiping the entire struct here, instead of member-by-member. This is useful + * for the test suite, since it gives a chance of catching memory corruption + * errors should the core not have allocated (enough) memory for our context + * struct. */ + memset( operation, 0, sizeof( *operation ) ); /* Test driver supports AES-CTR only, to verify operation calls. */ if( alg != PSA_ALG_CTR || psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES ) @@ -225,9 +227,11 @@ psa_status_t test_transparent_cipher_abort( mbedtls_cipher_free( &operation->cipher ); - /* write our struct, this will trigger memory corruption failures - * in test when we go outside of bounds. */ - memset( operation, 0, sizeof( test_transparent_cipher_operation_t ) ); + /* Wiping the entire struct here, instead of member-by-member. This is useful + * for the test suite, since it gives a chance of catching memory corruption + * errors should the core not have allocated (enough) memory for our context + * struct. */ + memset( operation, 0, sizeof( *operation ) ); test_driver_cipher_hooks.hits++; return( PSA_SUCCESS ); diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function index 1daf9bb3f..470c43864 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function @@ -236,6 +236,7 @@ void cipher_encrypt( int alg_arg, int key_type_arg, output + total_output_length, output_buffer_size - total_output_length, &function_output_length ); + /* Finish will have called abort as well, so expecting two hits here */ TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); test_driver_cipher_hooks.hits = 0; @@ -326,6 +327,7 @@ void cipher_encrypt_multipart( int alg_arg, int key_type_arg, output + total_output_length, output_buffer_size - total_output_length, &function_output_length ) ); + /* Finish will have called abort as well, so expecting two hits here */ TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); test_driver_cipher_hooks.hits = 0 ; total_output_length += function_output_length; @@ -413,6 +415,7 @@ void cipher_decrypt_multipart( int alg_arg, int key_type_arg, output + total_output_length, output_buffer_size - total_output_length, &function_output_length ) ); + /* Finish will have called abort as well, so expecting two hits here */ TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); test_driver_cipher_hooks.hits = 0; total_output_length += function_output_length; @@ -483,6 +486,7 @@ void cipher_decrypt( int alg_arg, int key_type_arg, output + total_output_length, output_buffer_size - total_output_length, &function_output_length ); + /* Finish will have called abort as well, so expecting two hits here */ TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); test_driver_cipher_hooks.hits = 0; From fb81aa588983f7b338db853af914e17bfdc30561 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Wed, 9 Sep 2020 12:01:43 +0200 Subject: [PATCH 10/22] Only pass the driver-relevant portion of the context struct Signed-off-by: Steven Cooreman --- include/psa/crypto_struct.h | 17 ++-- library/psa_crypto.c | 14 +-- library/psa_crypto_driver_wrappers.c | 127 ++++++++++++++------------- library/psa_crypto_driver_wrappers.h | 14 +-- 4 files changed, 89 insertions(+), 83 deletions(-) diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 5ac187504..b26588fc5 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -77,6 +77,16 @@ extern "C" { #include "mbedtls/sha256.h" #include "mbedtls/sha512.h" +typedef struct { + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_driver_wrappers.h */ + unsigned int id; + /** Context structure for the assigned driver, when id is not zero. */ + void* ctx; +} psa_operation_driver_context_t; + struct psa_hash_operation_s { psa_algorithm_t alg; @@ -165,12 +175,7 @@ struct psa_cipher_operation_s { unsigned dummy; /* Enable easier initializing of the union. */ mbedtls_cipher_context_t cipher; -#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) - struct { - unsigned int id; - void* ctx; - } driver; -#endif + psa_operation_driver_context_t driver; } ctx; }; diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 4ba9baffe..6575ec472 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -4093,11 +4093,11 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, /* Try doing this through a driver before using software fallback */ if( cipher_operation == MBEDTLS_ENCRYPT ) - status = psa_driver_wrapper_cipher_encrypt_setup( operation, + status = psa_driver_wrapper_cipher_encrypt_setup( &operation->ctx.driver, slot, alg ); else - status = psa_driver_wrapper_cipher_decrypt_setup( operation, + status = psa_driver_wrapper_cipher_decrypt_setup( &operation->ctx.driver, slot, alg ); @@ -4218,7 +4218,7 @@ psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, if( operation->accelerator_set == 1 ) { - status = psa_driver_wrapper_cipher_generate_iv( operation, + status = psa_driver_wrapper_cipher_generate_iv( &operation->ctx.driver, iv, iv_size, iv_length ); @@ -4260,7 +4260,7 @@ psa_status_t psa_cipher_set_iv( psa_cipher_operation_t *operation, if( operation->accelerator_set == 1 ) { - status = psa_driver_wrapper_cipher_set_iv( operation, + status = psa_driver_wrapper_cipher_set_iv( &operation->ctx.driver, iv, iv_length ); goto exit; @@ -4385,7 +4385,7 @@ psa_status_t psa_cipher_update( psa_cipher_operation_t *operation, if( operation->accelerator_set == 1 ) { - status = psa_driver_wrapper_cipher_update( operation, + status = psa_driver_wrapper_cipher_update( &operation->ctx.driver, input, input_length, output, @@ -4459,7 +4459,7 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, if( operation->accelerator_set == 1 ) { - status = psa_driver_wrapper_cipher_finish( operation, + status = psa_driver_wrapper_cipher_finish( &operation->ctx.driver, output, output_size, output_length ); @@ -4536,7 +4536,7 @@ psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) return( PSA_ERROR_BAD_STATE ); if( operation->accelerator_set == 1 ) - psa_driver_wrapper_cipher_abort( operation ); + psa_driver_wrapper_cipher_abort( &operation->ctx.driver ); else mbedtls_cipher_free( &operation->ctx.cipher ); diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index 11aeef830..dea9cb588 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -38,7 +38,8 @@ /* Repeat above block for each JSON-declared driver during autogeneration */ -/* Auto-generated values depending on which drivers are registered */ +/* Auto-generated values depending on which drivers are registered. ID 0 is + * reserved for unallocated operations. */ #if defined(PSA_CRYPTO_DRIVER_TEST) #define PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID (1) #define PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID (2) @@ -513,7 +514,7 @@ psa_status_t psa_driver_wrapper_cipher_decrypt( } psa_status_t psa_driver_wrapper_cipher_encrypt_setup( - psa_cipher_operation_t *operation, + psa_operation_driver_context_t *operation, psa_key_slot_t *slot, psa_algorithm_t alg ) { @@ -525,7 +526,7 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( }; /* Check for operation already allocated */ - if( operation->ctx.driver.ctx != NULL ) + if( operation->ctx != NULL || operation->id != 0 ) return( PSA_ERROR_BAD_STATE ); switch( location ) @@ -534,11 +535,11 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_DRIVER_TEST) - operation->ctx.driver.ctx = mbedtls_calloc( 1, sizeof(test_transparent_cipher_operation_t) ); - if( operation->ctx.driver.ctx == NULL ) + operation->ctx = mbedtls_calloc( 1, sizeof(test_transparent_cipher_operation_t) ); + if( operation->ctx == NULL ) return PSA_ERROR_INSUFFICIENT_MEMORY; - status = test_transparent_cipher_encrypt_setup( operation->ctx.driver.ctx, + status = test_transparent_cipher_encrypt_setup( operation->ctx, &attributes, slot->data.key.data, slot->data.key.bytes, @@ -547,19 +548,19 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( if( status != PSA_ERROR_NOT_SUPPORTED ) { if( status == PSA_SUCCESS ) - operation->ctx.driver.id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; + operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; else { - mbedtls_free( operation->ctx.driver.ctx ); - operation->ctx.driver.ctx = NULL; + mbedtls_free( operation->ctx ); + operation->ctx = NULL; } return( status ); } else { - mbedtls_free( operation->ctx.driver.ctx ); - operation->ctx.driver.ctx = NULL; + mbedtls_free( operation->ctx ); + operation->ctx = NULL; } #endif /* PSA_CRYPTO_DRIVER_TEST */ /* Fell through, meaning no accelerator supports this operation */ @@ -567,21 +568,21 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: - operation->ctx.driver.ctx = mbedtls_calloc( 1, sizeof(test_opaque_cipher_operation_t) ); - if( operation->ctx.driver.ctx == NULL ) + operation->ctx = mbedtls_calloc( 1, sizeof(test_opaque_cipher_operation_t) ); + if( operation->ctx == NULL ) return( PSA_ERROR_INSUFFICIENT_MEMORY ); - status = test_opaque_cipher_encrypt_setup( operation->ctx.driver.ctx, + status = test_opaque_cipher_encrypt_setup( operation->ctx, &attributes, slot->data.key.data, slot->data.key.bytes, alg ); if( status == PSA_SUCCESS ) - operation->ctx.driver.id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; + operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; else { - mbedtls_free( operation->ctx.driver.ctx ); - operation->ctx.driver.ctx = NULL; + mbedtls_free( operation->ctx ); + operation->ctx = NULL; } return( status ); @@ -600,7 +601,7 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( } psa_status_t psa_driver_wrapper_cipher_decrypt_setup( - psa_cipher_operation_t *operation, + psa_operation_driver_context_t *operation, psa_key_slot_t *slot, psa_algorithm_t alg ) { @@ -612,7 +613,7 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( }; /* Check for operation already allocated */ - if( operation->ctx.driver.ctx != NULL ) + if( operation->ctx != NULL ) return( PSA_ERROR_BAD_STATE ); switch( location ) @@ -621,11 +622,11 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_DRIVER_TEST) - operation->ctx.driver.ctx = mbedtls_calloc( 1, sizeof(test_transparent_cipher_operation_t) ); - if( operation->ctx.driver.ctx == NULL ) + operation->ctx = mbedtls_calloc( 1, sizeof(test_transparent_cipher_operation_t) ); + if( operation->ctx == NULL ) return( PSA_ERROR_INSUFFICIENT_MEMORY ); - status = test_transparent_cipher_decrypt_setup( operation->ctx.driver.ctx, + status = test_transparent_cipher_decrypt_setup( operation->ctx, &attributes, slot->data.key.data, slot->data.key.bytes, @@ -634,19 +635,19 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( if( status != PSA_ERROR_NOT_SUPPORTED ) { if( status == PSA_SUCCESS ) - operation->ctx.driver.id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; + operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; else { - mbedtls_free( operation->ctx.driver.ctx ); - operation->ctx.driver.ctx = NULL; + mbedtls_free( operation->ctx ); + operation->ctx = NULL; } return( status ); } else { - mbedtls_free( operation->ctx.driver.ctx ); - operation->ctx.driver.ctx = NULL; + mbedtls_free( operation->ctx ); + operation->ctx = NULL; } #endif /* PSA_CRYPTO_DRIVER_TEST */ /* Fell through, meaning no accelerator supports this operation */ @@ -654,21 +655,21 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: - operation->ctx.driver.ctx = mbedtls_calloc( 1, sizeof(test_opaque_cipher_operation_t) ); - if( operation->ctx.driver.ctx == NULL ) + operation->ctx = mbedtls_calloc( 1, sizeof(test_opaque_cipher_operation_t) ); + if( operation->ctx == NULL ) return PSA_ERROR_INSUFFICIENT_MEMORY; - status = test_opaque_cipher_decrypt_setup( operation->ctx.driver.ctx, + status = test_opaque_cipher_decrypt_setup( operation->ctx, &attributes, slot->data.key.data, slot->data.key.bytes, alg ); if( status == PSA_SUCCESS ) - operation->ctx.driver.id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; + operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; else { - mbedtls_free( operation->ctx.driver.ctx ); - operation->ctx.driver.ctx = NULL; + mbedtls_free( operation->ctx ); + operation->ctx = NULL; } return( status ); @@ -687,28 +688,28 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( } psa_status_t psa_driver_wrapper_cipher_generate_iv( - psa_cipher_operation_t *operation, + psa_operation_driver_context_t *operation, uint8_t *iv, size_t iv_size, size_t *iv_length ) { #if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) /* Check for operation already allocated */ - if( operation->ctx.driver.ctx == NULL ) + if( operation->ctx == NULL ) return( PSA_ERROR_INVALID_ARGUMENT ); - switch( operation->ctx.driver.id ) + switch( operation->id ) { #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - return( test_transparent_cipher_generate_iv( operation->ctx.driver.ctx, + return( test_transparent_cipher_generate_iv( operation->ctx, iv, iv_size, iv_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: - return( test_opaque_cipher_generate_iv( operation->ctx.driver.ctx, + return( test_opaque_cipher_generate_iv( operation->ctx, iv, iv_size, iv_length ) ); @@ -728,26 +729,26 @@ psa_status_t psa_driver_wrapper_cipher_generate_iv( } psa_status_t psa_driver_wrapper_cipher_set_iv( - psa_cipher_operation_t *operation, + psa_operation_driver_context_t *operation, const uint8_t *iv, size_t iv_length ) { #if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) /* Check for operation already allocated */ - if( operation->ctx.driver.ctx == NULL ) + if( operation->ctx == NULL ) return( PSA_ERROR_INVALID_ARGUMENT ); - switch( operation->ctx.driver.id ) + switch( operation->id ) { #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - return( test_transparent_cipher_set_iv( operation->ctx.driver.ctx, + return( test_transparent_cipher_set_iv( operation->ctx, iv, iv_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: - return( test_opaque_cipher_set_iv( operation->ctx.driver.ctx, + return( test_opaque_cipher_set_iv( operation->ctx, iv, iv_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ @@ -765,7 +766,7 @@ psa_status_t psa_driver_wrapper_cipher_set_iv( } psa_status_t psa_driver_wrapper_cipher_update( - psa_cipher_operation_t *operation, + psa_operation_driver_context_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, @@ -774,14 +775,14 @@ psa_status_t psa_driver_wrapper_cipher_update( { #if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) /* Check for operation already allocated */ - if( operation->ctx.driver.ctx == NULL ) + if( operation->ctx == NULL ) return( PSA_ERROR_INVALID_ARGUMENT ); - switch( operation->ctx.driver.id ) + switch( operation->id ) { #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - return( test_transparent_cipher_update( operation->ctx.driver.ctx, + return( test_transparent_cipher_update( operation->ctx, input, input_length, output, @@ -790,7 +791,7 @@ psa_status_t psa_driver_wrapper_cipher_update( #endif /* PSA_CRYPTO_DRIVER_TEST */ #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: - return( test_opaque_cipher_update( operation->ctx.driver.ctx, + return( test_opaque_cipher_update( operation->ctx, input, input_length, output, @@ -814,28 +815,28 @@ psa_status_t psa_driver_wrapper_cipher_update( } psa_status_t psa_driver_wrapper_cipher_finish( - psa_cipher_operation_t *operation, + psa_operation_driver_context_t *operation, uint8_t *output, size_t output_size, size_t *output_length ) { #if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) /* Check for operation already allocated */ - if( operation->ctx.driver.ctx == NULL ) + if( operation->ctx == NULL ) return( PSA_ERROR_INVALID_ARGUMENT ); - switch( operation->ctx.driver.id ) + switch( operation->id ) { #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - return( test_transparent_cipher_finish( operation->ctx.driver.ctx, + return( test_transparent_cipher_finish( operation->ctx, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: - return( test_opaque_cipher_finish( operation->ctx.driver.ctx, + return( test_opaque_cipher_finish( operation->ctx, output, output_size, output_length ) ); @@ -855,31 +856,31 @@ psa_status_t psa_driver_wrapper_cipher_finish( } psa_status_t psa_driver_wrapper_cipher_abort( - psa_cipher_operation_t *operation ) + psa_operation_driver_context_t *operation ) { #if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; /* Check for operation already allocated */ - if( operation->ctx.driver.ctx == NULL ) + if( operation->ctx == NULL ) return( PSA_ERROR_INVALID_ARGUMENT ); - switch( operation->ctx.driver.id ) + switch( operation->id ) { #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: - status = test_transparent_cipher_abort( operation->ctx.driver.ctx ); + status = test_transparent_cipher_abort( operation->ctx ); - mbedtls_free( operation->ctx.driver.ctx ); - operation->ctx.driver.ctx = NULL; - operation->ctx.driver.id = 0; + mbedtls_free( operation->ctx ); + operation->ctx = NULL; + operation->id = 0; return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: - status = test_opaque_cipher_abort( operation->ctx.driver.ctx ); - mbedtls_free( operation->ctx.driver.ctx ); - operation->ctx.driver.ctx = NULL; + status = test_opaque_cipher_abort( operation->ctx ); + mbedtls_free( operation->ctx ); + operation->ctx = NULL; return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h index a2096048d..0db15d6c3 100644 --- a/library/psa_crypto_driver_wrappers.h +++ b/library/psa_crypto_driver_wrappers.h @@ -68,28 +68,28 @@ psa_status_t psa_driver_wrapper_cipher_decrypt( size_t *output_length ); psa_status_t psa_driver_wrapper_cipher_encrypt_setup( - psa_cipher_operation_t *operation, + psa_operation_driver_context_t *operation, psa_key_slot_t *slot, psa_algorithm_t alg ); psa_status_t psa_driver_wrapper_cipher_decrypt_setup( - psa_cipher_operation_t *operation, + psa_operation_driver_context_t *operation, psa_key_slot_t *slot, psa_algorithm_t alg ); psa_status_t psa_driver_wrapper_cipher_generate_iv( - psa_cipher_operation_t *operation, + psa_operation_driver_context_t *operation, uint8_t *iv, size_t iv_size, size_t *iv_length ); psa_status_t psa_driver_wrapper_cipher_set_iv( - psa_cipher_operation_t *operation, + psa_operation_driver_context_t *operation, const uint8_t *iv, size_t iv_length ); psa_status_t psa_driver_wrapper_cipher_update( - psa_cipher_operation_t *operation, + psa_operation_driver_context_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, @@ -97,13 +97,13 @@ psa_status_t psa_driver_wrapper_cipher_update( size_t *output_length ); psa_status_t psa_driver_wrapper_cipher_finish( - psa_cipher_operation_t *operation, + psa_operation_driver_context_t *operation, uint8_t *output, size_t output_size, size_t *output_length ); psa_status_t psa_driver_wrapper_cipher_abort( - psa_cipher_operation_t *operation ); + psa_operation_driver_context_t *operation ); #endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */ From 150c99b8842877e00bcc247739688e4f19d01069 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Wed, 9 Sep 2020 14:32:44 +0200 Subject: [PATCH 11/22] Simplify cipher setup wrapper body Signed-off-by: Steven Cooreman --- library/psa_crypto_driver_wrappers.c | 32 +++++++--------------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index dea9cb588..268b47c62 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -545,23 +545,15 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( slot->data.key.bytes, alg ); /* Declared with fallback == true */ - if( status != PSA_ERROR_NOT_SUPPORTED ) - { - if( status == PSA_SUCCESS ) - operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; - else - { - mbedtls_free( operation->ctx ); - operation->ctx = NULL; - } - - return( status ); - } + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; else { mbedtls_free( operation->ctx ); operation->ctx = NULL; } + + return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ /* Fell through, meaning no accelerator supports this operation */ return( PSA_ERROR_NOT_SUPPORTED ); @@ -632,23 +624,15 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( slot->data.key.bytes, alg ); /* Declared with fallback == true */ - if( status != PSA_ERROR_NOT_SUPPORTED ) - { - if( status == PSA_SUCCESS ) - operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; - else - { - mbedtls_free( operation->ctx ); - operation->ctx = NULL; - } - - return( status ); - } + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; else { mbedtls_free( operation->ctx ); operation->ctx = NULL; } + + return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ /* Fell through, meaning no accelerator supports this operation */ return( PSA_ERROR_NOT_SUPPORTED ); From cfeea8fa1e52cfc011031532daec710d1e0eca2a Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Wed, 9 Sep 2020 15:09:18 +0200 Subject: [PATCH 12/22] Unify driver context struct handling Added zeroization of the wrapper context on failure/abort, and reliance on the crypto core to not call an uninitialised wrapper. Signed-off-by: Steven Cooreman --- library/psa_crypto_driver_wrappers.c | 52 +++++++++++++--------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index 268b47c62..d41209bbf 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -525,10 +525,6 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( .core = slot->attr }; - /* Check for operation already allocated */ - if( operation->ctx != NULL || operation->id != 0 ) - return( PSA_ERROR_BAD_STATE ); - switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: @@ -549,6 +545,9 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; else { + mbedtls_platform_zeroize( + operation->ctx, + sizeof( test_transparent_cipher_operation_t ) ); mbedtls_free( operation->ctx ); operation->ctx = NULL; } @@ -573,6 +572,9 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; else { + mbedtls_platform_zeroize( + operation->ctx, + sizeof( test_opaque_cipher_operation_t ) ); mbedtls_free( operation->ctx ); operation->ctx = NULL; } @@ -604,10 +606,6 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( .core = slot->attr }; - /* Check for operation already allocated */ - if( operation->ctx != NULL ) - return( PSA_ERROR_BAD_STATE ); - switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: @@ -628,6 +626,9 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; else { + mbedtls_platform_zeroize( + operation->ctx, + sizeof( test_transparent_cipher_operation_t ) ); mbedtls_free( operation->ctx ); operation->ctx = NULL; } @@ -652,6 +653,9 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; else { + mbedtls_platform_zeroize( + operation->ctx, + sizeof( test_opaque_cipher_operation_t ) ); mbedtls_free( operation->ctx ); operation->ctx = NULL; } @@ -678,10 +682,6 @@ psa_status_t psa_driver_wrapper_cipher_generate_iv( size_t *iv_length ) { #if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) - /* Check for operation already allocated */ - if( operation->ctx == NULL ) - return( PSA_ERROR_INVALID_ARGUMENT ); - switch( operation->id ) { #if defined(PSA_CRYPTO_DRIVER_TEST) @@ -718,10 +718,6 @@ psa_status_t psa_driver_wrapper_cipher_set_iv( size_t iv_length ) { #if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) - /* Check for operation already allocated */ - if( operation->ctx == NULL ) - return( PSA_ERROR_INVALID_ARGUMENT ); - switch( operation->id ) { #if defined(PSA_CRYPTO_DRIVER_TEST) @@ -758,10 +754,6 @@ psa_status_t psa_driver_wrapper_cipher_update( size_t *output_length ) { #if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) - /* Check for operation already allocated */ - if( operation->ctx == NULL ) - return( PSA_ERROR_INVALID_ARGUMENT ); - switch( operation->id ) { #if defined(PSA_CRYPTO_DRIVER_TEST) @@ -805,10 +797,6 @@ psa_status_t psa_driver_wrapper_cipher_finish( size_t *output_length ) { #if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) - /* Check for operation already allocated */ - if( operation->ctx == NULL ) - return( PSA_ERROR_INVALID_ARGUMENT ); - switch( operation->id ) { #if defined(PSA_CRYPTO_DRIVER_TEST) @@ -844,16 +832,20 @@ psa_status_t psa_driver_wrapper_cipher_abort( { #if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; - /* Check for operation already allocated */ - if( operation->ctx == NULL ) - return( PSA_ERROR_INVALID_ARGUMENT ); + + /* The object has (apparently) been initialized but it is not in use. It's + * ok to call abort on such an object, and there's nothing to do. */ + if( operation->ctx == NULL && operation->id == 0 ) + return( PSA_SUCCESS ); switch( operation->id ) { #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: status = test_transparent_cipher_abort( operation->ctx ); - + mbedtls_platform_zeroize( + operation->ctx, + sizeof( test_transparent_cipher_operation_t ) ); mbedtls_free( operation->ctx ); operation->ctx = NULL; operation->id = 0; @@ -863,8 +855,12 @@ psa_status_t psa_driver_wrapper_cipher_abort( #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: status = test_opaque_cipher_abort( operation->ctx ); + mbedtls_platform_zeroize( + operation->ctx, + sizeof( test_opaque_cipher_operation_t ) ); mbedtls_free( operation->ctx ); operation->ctx = NULL; + operation->id = 0; return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ From 7df0292f5a62572a92dbdb954c0de8a6265ad4af Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Wed, 9 Sep 2020 15:28:49 +0200 Subject: [PATCH 13/22] Check & set operation flags for both driver and software in the core Signed-off-by: Steven Cooreman --- library/psa_crypto.c | 65 ++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 6575ec472..eb760d438 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -4102,10 +4102,7 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, alg ); if( status == PSA_SUCCESS ) - { operation->accelerator_set = 1; - operation->key_set = 1; - } if( status != PSA_ERROR_NOT_SUPPORTED || psa_key_lifetime_is_external( slot->attr.lifetime ) ) @@ -4172,7 +4169,6 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, goto exit; #endif //MBEDTLS_CIPHER_MODE_WITH_PADDING - operation->key_set = 1; operation->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 : PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type ) ); if( ( alg & PSA_ALG_CIPHER_FROM_BLOCK_FLAG ) != 0 && @@ -4186,10 +4182,17 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, operation->iv_size = 12; #endif + status = PSA_SUCCESS; + exit: - if( status == 0 ) + if( ret != 0 ) status = mbedtls_to_psa_error( ret ); - if( status != 0 ) + if( status == PSA_SUCCESS ) + { + /* Update operation flags for both driver and software implementations */ + operation->key_set = 1; + } + else psa_cipher_abort( operation ); return( status ); } @@ -4215,6 +4218,10 @@ psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, { psa_status_t status; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if( operation->iv_set || ! operation->iv_required ) + { + return( PSA_ERROR_BAD_STATE ); + } if( operation->accelerator_set == 1 ) { @@ -4225,10 +4232,6 @@ psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, goto exit; } - if( operation->iv_set || ! operation->iv_required ) - { - return( PSA_ERROR_BAD_STATE ); - } if( iv_size < operation->iv_size ) { status = PSA_ERROR_BUFFER_TOO_SMALL; @@ -4246,7 +4249,9 @@ psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, status = psa_cipher_set_iv( operation, iv, *iv_length ); exit: - if( status != PSA_SUCCESS ) + if( status == PSA_SUCCESS ) + operation->iv_set = 1; + else psa_cipher_abort( operation ); return( status ); } @@ -4257,6 +4262,10 @@ psa_status_t psa_cipher_set_iv( psa_cipher_operation_t *operation, { psa_status_t status; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if( operation->iv_set || ! operation->iv_required ) + { + return( PSA_ERROR_BAD_STATE ); + } if( operation->accelerator_set == 1 ) { @@ -4266,10 +4275,6 @@ psa_status_t psa_cipher_set_iv( psa_cipher_operation_t *operation, goto exit; } - if( operation->iv_set || ! operation->iv_required ) - { - return( PSA_ERROR_BAD_STATE ); - } if( iv_length != operation->iv_size ) { status = PSA_ERROR_INVALID_ARGUMENT; @@ -4382,6 +4387,14 @@ psa_status_t psa_cipher_update( psa_cipher_operation_t *operation, { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t expected_output_size; + if( operation->alg == 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + if( operation->iv_required && ! operation->iv_set ) + { + return( PSA_ERROR_BAD_STATE ); + } if( operation->accelerator_set == 1 ) { @@ -4394,15 +4407,6 @@ psa_status_t psa_cipher_update( psa_cipher_operation_t *operation, goto exit; } - if( operation->alg == 0 ) - { - return( PSA_ERROR_BAD_STATE ); - } - if( operation->iv_required && ! operation->iv_set ) - { - return( PSA_ERROR_BAD_STATE ); - } - if( ! PSA_ALG_IS_STREAM_CIPHER( operation->alg ) ) { /* Take the unprocessed partial block left over from previous @@ -4456,6 +4460,14 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, psa_status_t status = PSA_ERROR_GENERIC_ERROR; int cipher_ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; + if( operation->alg == 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + if( operation->iv_required && ! operation->iv_set ) + { + return( PSA_ERROR_BAD_STATE ); + } if( operation->accelerator_set == 1 ) { @@ -4470,11 +4482,6 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, return( status ); } - if( operation->iv_required && ! operation->iv_set ) - { - return( PSA_ERROR_BAD_STATE ); - } - if( operation->ctx.cipher.unprocessed_len != 0 ) { if( operation->alg == PSA_ALG_ECB_NO_PADDING || From 16afd3d9b48da2b03fc89af44d2913d6e0b956e7 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Wed, 9 Sep 2020 15:36:39 +0200 Subject: [PATCH 14/22] Unify cipher setup function inside test driver Signed-off-by: Steven Cooreman --- tests/src/drivers/cipher.c | 83 ++++++++++++-------------------------- 1 file changed, 25 insertions(+), 58 deletions(-) diff --git a/tests/src/drivers/cipher.c b/tests/src/drivers/cipher.c index c8eb1d350..e04fd898c 100644 --- a/tests/src/drivers/cipher.c +++ b/tests/src/drivers/cipher.c @@ -98,7 +98,8 @@ psa_status_t test_transparent_cipher_decrypt( return( test_driver_cipher_hooks.forced_status ); } -psa_status_t test_transparent_cipher_encrypt_setup( +static psa_status_t test_transparent_cipher_setup( + mbedtls_operation_t direction, test_transparent_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key, size_t key_length, @@ -125,7 +126,6 @@ psa_status_t test_transparent_cipher_encrypt_setup( operation->alg = alg; operation->iv_size = 16; - operation->block_size = 16; cipher_info = mbedtls_cipher_info_from_values( MBEDTLS_CIPHER_ID_AES, key_length * 8, @@ -134,7 +134,6 @@ psa_status_t test_transparent_cipher_encrypt_setup( return( PSA_ERROR_NOT_SUPPORTED ); mbedtls_cipher_init( &operation->cipher ); - ret = mbedtls_cipher_setup( &operation->cipher, cipher_info ); if( ret != 0 ) { mbedtls_cipher_free( &operation->cipher ); @@ -143,7 +142,7 @@ psa_status_t test_transparent_cipher_encrypt_setup( ret = mbedtls_cipher_setkey( &operation->cipher, key, - key_length * 8, MBEDTLS_ENCRYPT ); + key_length * 8, direction ); if( ret != 0 ) { mbedtls_cipher_free( &operation->cipher ); return( mbedtls_to_psa_error( ret ) ); @@ -160,61 +159,32 @@ psa_status_t test_transparent_cipher_encrypt_setup( return( test_driver_cipher_hooks.forced_status ); } +psa_status_t test_transparent_cipher_encrypt_setup( + test_transparent_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg) +{ + return ( test_transparent_cipher_setup( MBEDTLS_ENCRYPT, + operation, + attributes, + key, + key_length, + alg ) ); +} + psa_status_t test_transparent_cipher_decrypt_setup( test_transparent_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key, size_t key_length, psa_algorithm_t alg) { - const mbedtls_cipher_info_t *cipher_info = NULL; - int ret = 0; - - test_driver_cipher_hooks.hits++; - - if( operation->alg != 0 ) - return( PSA_ERROR_BAD_STATE ); - - /* Wiping the entire struct here, instead of member-by-member. This is useful - * for the test suite, since it gives a chance of catching memory corruption - * errors should the core not have allocated (enough) memory for our context - * struct. */ - memset( operation, 0, sizeof( *operation ) ); - - /* Test driver supports AES-CTR only, to verify operation calls. */ - if( alg != PSA_ALG_CTR || psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES ) - return PSA_ERROR_NOT_SUPPORTED; - - operation->alg = alg; - operation->iv_size = 16; - operation->block_size = 16; - - mbedtls_cipher_init( &operation->cipher ); - - cipher_info = mbedtls_cipher_info_from_values( MBEDTLS_CIPHER_ID_AES, - key_length * 8, - MBEDTLS_MODE_CTR ); - if( cipher_info == NULL ) - return PSA_ERROR_NOT_SUPPORTED; - - ret = mbedtls_cipher_setup( &operation->cipher, cipher_info ); - if( ret != 0 ) - return( mbedtls_to_psa_error( ret ) ); - - ret = mbedtls_cipher_setkey( &operation->cipher, - key, - key_length * 8, MBEDTLS_DECRYPT ); - if( ret != 0 ) - return( mbedtls_to_psa_error( ret ) ); - - operation->iv_set = 0; - operation->iv_required = 1; - operation->key_set = 1; - - /* Allow overriding return value for testing purposes */ - if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS ) - mbedtls_cipher_free( &operation->cipher ); - - return( test_driver_cipher_hooks.forced_status ); + return ( test_transparent_cipher_setup( MBEDTLS_DECRYPT, + operation, + attributes, + key, + key_length, + alg ) ); } psa_status_t test_transparent_cipher_abort( @@ -306,7 +276,6 @@ psa_status_t test_transparent_cipher_update( size_t output_size, size_t *output_length) { - size_t expected_output_size; psa_status_t status; test_driver_cipher_hooks.hits++; @@ -314,10 +283,8 @@ psa_status_t test_transparent_cipher_update( if( operation->alg != PSA_ALG_CTR ) return( PSA_ERROR_BAD_STATE ); - expected_output_size = ( operation->cipher.unprocessed_len + input_length ) - / operation->block_size * operation->block_size; - - if( output_size < expected_output_size ) + /* CTR is a stream cipher, so data in and out are always the same size */ + if( output_size < input_length ) return( PSA_ERROR_BUFFER_TOO_SMALL ); status = mbedtls_to_psa_error( From b5e52f2e31dcb0a232d9868569ab73eea14c2b4e Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Wed, 9 Sep 2020 16:19:34 +0200 Subject: [PATCH 15/22] Remove superfluous call in PSA cipher setup As pointed out by Ronald. The key slot is populated using get_key_from_slot, and after calling the driver the slot is validated to not contain an external key, so calling get_transparent_key is superfluous. Signed-off-by: Steven Cooreman --- library/psa_crypto.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index eb760d438..d8c6c1e6d 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -4112,11 +4112,7 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, * available for the given algorithm & key. */ mbedtls_cipher_init( &operation->ctx.cipher ); - status = psa_get_transparent_key( handle, &slot, usage, alg); - if( status != PSA_SUCCESS ) - goto exit; key_bits = psa_get_key_slot_bits( slot ); - cipher_info = mbedtls_cipher_info_from_psa( alg, slot->attr.type, key_bits, NULL ); if( cipher_info == NULL ) { From e55f3e8de4cdb9e2d5580114d303ede28b0af9b3 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Wed, 9 Sep 2020 18:41:07 +0200 Subject: [PATCH 16/22] Make sure to not call mbedtls_cipher_free on an uninitialised context As pointed out by Gilles Signed-off-by: Steven Cooreman --- library/psa_crypto.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index d8c6c1e6d..647ca6286 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -4101,12 +4101,18 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, slot, alg ); - if( status == PSA_SUCCESS ) - operation->accelerator_set = 1; - if( status != PSA_ERROR_NOT_SUPPORTED || psa_key_lifetime_is_external( slot->attr.lifetime ) ) + { + /* Indicate this operation is bound to an accelerator. When the driver + * setup succeeded, this indicates to the core to not call any mbedtls_ + * functions for this operation (contexts are not interoperable). + * In case the drivers couldn't setup and there's no way to fallback, + * indicate to the core to not call mbedtls_cipher_free on an + * uninitialised mbed TLS cipher context. */ + operation->accelerator_set = 1; goto exit; + } /* Proceed with initializing mbed TLS cipher context if no accelerator is * available for the given algorithm & key. */ From fe0ab55c615a3471444ac58d137dc0fa8d6a02dd Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Thu, 10 Sep 2020 13:07:02 +0200 Subject: [PATCH 17/22] Implement one-shot cipher in test driver Signed-off-by: Steven Cooreman --- tests/src/drivers/cipher.c | 182 +++++++++++++++++++++++++++++-------- 1 file changed, 144 insertions(+), 38 deletions(-) diff --git a/tests/src/drivers/cipher.c b/tests/src/drivers/cipher.c index e04fd898c..2915fba68 100644 --- a/tests/src/drivers/cipher.c +++ b/tests/src/drivers/cipher.c @@ -42,6 +42,134 @@ * fallback even for AES-CTR. */ test_driver_cipher_hooks_t test_driver_cipher_hooks = TEST_DRIVER_CIPHER_INIT; +static psa_status_t test_transparent_cipher_oneshot( + mbedtls_operation_t direction, + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, size_t *output_length) +{ + test_driver_cipher_hooks.hits++; + + /* Test driver supports AES-CTR only, to verify operation calls. */ + if( alg != PSA_ALG_CTR || + psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES ) + return( PSA_ERROR_NOT_SUPPORTED ); + + /* If test driver response code is not SUCCESS, we can return early */ + if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS ) + return( test_driver_cipher_hooks.forced_status ); + + /* If test driver output is overridden, we don't need to do actual crypto */ + if( test_driver_cipher_hooks.forced_output != NULL ) + { + if( output_size < test_driver_cipher_hooks.forced_output_length ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + memcpy( output, + test_driver_cipher_hooks.forced_output, + test_driver_cipher_hooks.forced_output_length ); + *output_length = test_driver_cipher_hooks.forced_output_length; + + return( test_driver_cipher_hooks.forced_status ); + } + + /* Run AES-CTR using the cipher module */ + { + mbedtls_test_rnd_pseudo_info rnd_info; + memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) ); + + const mbedtls_cipher_info_t *cipher_info = + mbedtls_cipher_info_from_values( MBEDTLS_CIPHER_ID_AES, + key_length * 8, + MBEDTLS_MODE_CTR ); + mbedtls_cipher_context_t cipher; + int ret = 0; + uint8_t temp_output_buffer[16] = {0}; + size_t temp_output_length = 0; + + if( direction == MBEDTLS_ENCRYPT ) + { + /* Oneshot encrypt needs to prepend the IV to the output */ + if( output_size < ( input_length + 16 ) ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + } + else + { + /* Oneshot decrypt has the IV prepended to the input */ + if( output_size < ( input_length - 16 ) ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + } + + if( cipher_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + + mbedtls_cipher_init( &cipher ); + ret = mbedtls_cipher_setup( &cipher, cipher_info ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_setkey( &cipher, + key, + key_length * 8, direction ); + if( ret != 0 ) + goto exit; + + if( direction == MBEDTLS_ENCRYPT ) + { + mbedtls_test_rnd_pseudo_info rnd_info; + memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) ); + + ret = mbedtls_test_rnd_pseudo_rand( &rnd_info, + temp_output_buffer, + 16 ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_set_iv( &cipher, temp_output_buffer, 16 ); + } + else + ret = mbedtls_cipher_set_iv( &cipher, input, 16 ); + + if( ret != 0 ) + goto exit; + + if( direction == MBEDTLS_ENCRYPT ) + { + ret = mbedtls_cipher_update( &cipher, + input, input_length, + &output[16], output_length ); + if( ret == 0 ) + { + memcpy( output, temp_output_buffer, 16 ); + *output_length += 16; + } + } + else + ret = mbedtls_cipher_update( &cipher, + &input[16], input_length - 16, + output, output_length ); + + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_finish( &cipher, + temp_output_buffer, + &temp_output_length ); + +exit: + if( ret != 0 ) + { + *output_length = 0; + memset(output, 0, output_size); + } + + mbedtls_cipher_free( &cipher ); + return( mbedtls_to_psa_error( ret ) ); + } +} + psa_status_t test_transparent_cipher_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key, size_t key_length, @@ -49,25 +177,14 @@ psa_status_t test_transparent_cipher_encrypt( const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length) { - (void) attributes; - (void) key; - (void) key_length; - (void) alg; - (void) input; - (void) input_length; - test_driver_cipher_hooks.hits++; - - if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS ) - return( test_driver_cipher_hooks.forced_status ); - if( output_size < test_driver_cipher_hooks.forced_output_length ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); - - memcpy( output, - test_driver_cipher_hooks.forced_output, - test_driver_cipher_hooks.forced_output_length ); - *output_length = test_driver_cipher_hooks.forced_output_length; - - return( test_driver_cipher_hooks.forced_status ); + return ( + test_transparent_cipher_oneshot( + MBEDTLS_ENCRYPT, + attributes, + key, key_length, + alg, + input, input_length, + output, output_size, output_length) ); } psa_status_t test_transparent_cipher_decrypt( @@ -77,25 +194,14 @@ psa_status_t test_transparent_cipher_decrypt( const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length) { - (void) attributes; - (void) key; - (void) key_length; - (void) alg; - (void) input; - (void) input_length; - test_driver_cipher_hooks.hits++; - - if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS ) - return( test_driver_cipher_hooks.forced_status ); - if( output_size < test_driver_cipher_hooks.forced_output_length ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); - - memcpy( output, - test_driver_cipher_hooks.forced_output, - test_driver_cipher_hooks.forced_output_length ); - *output_length = test_driver_cipher_hooks.forced_output_length; - - return( test_driver_cipher_hooks.forced_status ); + return ( + test_transparent_cipher_oneshot( + MBEDTLS_DECRYPT, + attributes, + key, key_length, + alg, + input, input_length, + output, output_size, output_length) ); } static psa_status_t test_transparent_cipher_setup( From eca33c60f8cf46b4696ba8cd4569a4f77512194b Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Thu, 10 Sep 2020 14:32:26 +0200 Subject: [PATCH 18/22] Add testing of fallback to cipher operations Signed-off-by: Steven Cooreman --- .../test_suite_psa_crypto_driver_wrappers.data | 18 +++++++++++++++--- ...t_suite_psa_crypto_driver_wrappers.function | 18 ++++++++++++------ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data index b864daff5..9374f28be 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.data +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data @@ -42,15 +42,27 @@ generate_key:PSA_ERROR_GENERIC_ERROR:"":PSA_ERROR_GENERIC_ERROR PSA symmetric encrypt: AES-CTR, 16 bytes, good depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR -cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_SUCCESS +cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_SUCCESS:PSA_SUCCESS PSA symmetric encrypt: AES-CTR, 15 bytes, good depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR -cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":PSA_SUCCESS +cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":PSA_SUCCESS:PSA_SUCCESS + +PSA symmetric encrypt: AES-CTR, 16 bytes, fallback +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS + +PSA symmetric encrypt: AES-CTR, 15 bytes, fallback +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS PSA symmetric decrypt: AES-CTR, 16 bytes, good depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR -cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":PSA_SUCCESS +cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":PSA_SUCCESS:PSA_SUCCESS + +PSA symmetric decrypt: AES-CTR, 16 bytes, fallback +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR +cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS PSA symmetric encryption multipart: AES-CTR, 11+5 bytes depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function index 470c43864..b1a1ae389 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function @@ -188,6 +188,7 @@ exit: void cipher_encrypt( int alg_arg, int key_type_arg, data_t *key, data_t *iv, data_t *input, data_t *expected_output, + int force_status_arg, int expected_status_arg ) { psa_key_handle_t handle = 0; @@ -195,6 +196,7 @@ void cipher_encrypt( int alg_arg, int key_type_arg, psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; psa_status_t expected_status = expected_status_arg; + psa_status_t force_status = force_status_arg; unsigned char *output = NULL; size_t output_buffer_size = 0; size_t function_output_length = 0; @@ -202,6 +204,7 @@ void cipher_encrypt( int alg_arg, int key_type_arg, psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; test_driver_cipher_hooks = test_driver_cipher_hooks_init(); + test_driver_cipher_hooks.forced_status = force_status; PSA_ASSERT( psa_crypto_init( ) ); @@ -217,7 +220,7 @@ void cipher_encrypt( int alg_arg, int key_type_arg, test_driver_cipher_hooks.hits = 0; PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) ); - TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) ); test_driver_cipher_hooks.hits = 0; output_buffer_size = ( (size_t) input->len + @@ -228,7 +231,7 @@ void cipher_encrypt( int alg_arg, int key_type_arg, input->x, input->len, output, output_buffer_size, &function_output_length ) ); - TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) ); test_driver_cipher_hooks.hits = 0; total_output_length += function_output_length; @@ -237,7 +240,7 @@ void cipher_encrypt( int alg_arg, int key_type_arg, output_buffer_size - total_output_length, &function_output_length ); /* Finish will have called abort as well, so expecting two hits here */ - TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); + TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 2 : 0 ) ); test_driver_cipher_hooks.hits = 0; total_output_length += function_output_length; @@ -438,6 +441,7 @@ exit: void cipher_decrypt( int alg_arg, int key_type_arg, data_t *key, data_t *iv, data_t *input, data_t *expected_output, + int force_status_arg, int expected_status_arg ) { psa_key_handle_t handle = 0; @@ -445,6 +449,7 @@ void cipher_decrypt( int alg_arg, int key_type_arg, psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; psa_status_t expected_status = expected_status_arg; + psa_status_t force_status = force_status_arg; unsigned char *output = NULL; size_t output_buffer_size = 0; size_t function_output_length = 0; @@ -452,6 +457,7 @@ void cipher_decrypt( int alg_arg, int key_type_arg, psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; test_driver_cipher_hooks = test_driver_cipher_hooks_init(); + test_driver_cipher_hooks.forced_status = force_status; PSA_ASSERT( psa_crypto_init( ) ); @@ -467,7 +473,7 @@ void cipher_decrypt( int alg_arg, int key_type_arg, test_driver_cipher_hooks.hits = 0; PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) ); - TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) ); test_driver_cipher_hooks.hits = 0; output_buffer_size = ( (size_t) input->len + @@ -478,7 +484,7 @@ void cipher_decrypt( int alg_arg, int key_type_arg, input->x, input->len, output, output_buffer_size, &function_output_length ) ); - TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) ); test_driver_cipher_hooks.hits = 0; total_output_length += function_output_length; @@ -487,7 +493,7 @@ void cipher_decrypt( int alg_arg, int key_type_arg, output_buffer_size - total_output_length, &function_output_length ); /* Finish will have called abort as well, so expecting two hits here */ - TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); + TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 2 : 0 ) ); test_driver_cipher_hooks.hits = 0; total_output_length += function_output_length; From a07b9970c6093418b7f1cecac31f919e55df517b Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Thu, 10 Sep 2020 14:54:14 +0200 Subject: [PATCH 19/22] Update semantics around driver context use in psa_cipher_setup Signed-off-by: Steven Cooreman --- include/psa/crypto_struct.h | 2 +- library/psa_crypto.c | 93 ++++++++++++++++++------------------- 2 files changed, 47 insertions(+), 48 deletions(-) diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index b26588fc5..861850c84 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -168,7 +168,7 @@ struct psa_cipher_operation_s unsigned int key_set : 1; unsigned int iv_required : 1; unsigned int iv_set : 1; - unsigned int accelerator_set : 1; /* Indicates a driver is used instead of software fallback. */ + unsigned int driver_in_use : 1; /* Indicates a driver is used instead of software fallback. */ uint8_t iv_size; uint8_t block_size; union diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 647ca6286..6b259030b 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -4037,34 +4037,6 @@ rsa_exit: /* Symmetric cryptography */ /****************************************************************/ -/* Initialize the cipher operation structure. Once this function has been - * called, psa_cipher_abort can run and will do the right thing. */ -static psa_status_t psa_cipher_init( psa_cipher_operation_t *operation, - psa_algorithm_t alg ) -{ - if( ! PSA_ALG_IS_CIPHER( alg ) ) - { - memset( operation, 0, sizeof( *operation ) ); - return( PSA_ERROR_INVALID_ARGUMENT ); - } - - operation->alg = alg; - operation->key_set = 0; - operation->iv_set = 0; - if( alg == PSA_ALG_ECB_NO_PADDING ) - { - operation->iv_required = 0; - } - else - { - operation->iv_required = 1; - } - operation->accelerator_set = 0; - operation->iv_size = 0; - operation->block_size = 0; - return( PSA_SUCCESS ); -} - static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, psa_key_handle_t handle, psa_algorithm_t alg, @@ -4079,19 +4051,36 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT ); - status = psa_get_key_from_slot( handle, &slot, usage, alg ); - if( status != PSA_SUCCESS ) - goto exit; - /* A context must be freshly initialized before it can be set up. */ if( operation->alg != 0 ) return( PSA_ERROR_BAD_STATE ); - status = psa_cipher_init( operation, alg ); - if( status != PSA_SUCCESS ) - return( status ); + /* The requested algorithm must be one that can be processed by cipher. */ + if( ! PSA_ALG_IS_CIPHER( alg ) ) + { + memset( operation, 0, sizeof( *operation ) ); + return( PSA_ERROR_INVALID_ARGUMENT ); + } - /* Try doing this through a driver before using software fallback */ + /* Reset the operation members to their initial state, except for alg. The + * alg member is used as an indicator that psa_cipher_abort needs to free + * allocated resources, which doesn't happen until later. */ + operation->key_set = 0; + operation->iv_set = 0; + operation->driver_in_use = 0; + operation->iv_size = 0; + operation->block_size = 0; + if( alg == PSA_ALG_ECB_NO_PADDING ) + operation->iv_required = 0; + else + operation->iv_required = 1; + + /* Fetch key material from key storage. */ + status = psa_get_key_from_slot( handle, &slot, usage, alg ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Try doing the operation through a driver before using software fallback. */ if( cipher_operation == MBEDTLS_ENCRYPT ) status = psa_driver_wrapper_cipher_encrypt_setup( &operation->ctx.driver, slot, @@ -4104,20 +4093,30 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, if( status != PSA_ERROR_NOT_SUPPORTED || psa_key_lifetime_is_external( slot->attr.lifetime ) ) { - /* Indicate this operation is bound to an accelerator. When the driver - * setup succeeded, this indicates to the core to not call any mbedtls_ + /* Indicate this operation is bound to a driver. When the driver setup + * succeeded, this indicates to the core to not call any mbedtls_ * functions for this operation (contexts are not interoperable). * In case the drivers couldn't setup and there's no way to fallback, * indicate to the core to not call mbedtls_cipher_free on an * uninitialised mbed TLS cipher context. */ - operation->accelerator_set = 1; + operation->driver_in_use = 1; + + /* If the wrapper call succeeded, it allocated resources that need to be + * freed using psa_cipher_abort. Indicate this through setting alg. */ + if( status == PSA_SUCCESS ) + operation->alg = alg; + goto exit; } - /* Proceed with initializing mbed TLS cipher context if no accelerator is + /* Proceed with initializing an mbed TLS cipher context if no driver is * available for the given algorithm & key. */ mbedtls_cipher_init( &operation->ctx.cipher ); + /* Once the cipher context is initialised, it needs to be freed using + * psa_cipher_abort. Indicate this through setting alg. */ + operation->alg = alg; + key_bits = psa_get_key_slot_bits( slot ); cipher_info = mbedtls_cipher_info_from_psa( alg, slot->attr.type, key_bits, NULL ); if( cipher_info == NULL ) @@ -4225,7 +4224,7 @@ psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, return( PSA_ERROR_BAD_STATE ); } - if( operation->accelerator_set == 1 ) + if( operation->driver_in_use == 1 ) { status = psa_driver_wrapper_cipher_generate_iv( &operation->ctx.driver, iv, @@ -4269,7 +4268,7 @@ psa_status_t psa_cipher_set_iv( psa_cipher_operation_t *operation, return( PSA_ERROR_BAD_STATE ); } - if( operation->accelerator_set == 1 ) + if( operation->driver_in_use == 1 ) { status = psa_driver_wrapper_cipher_set_iv( &operation->ctx.driver, iv, @@ -4398,7 +4397,7 @@ psa_status_t psa_cipher_update( psa_cipher_operation_t *operation, return( PSA_ERROR_BAD_STATE ); } - if( operation->accelerator_set == 1 ) + if( operation->driver_in_use == 1 ) { status = psa_driver_wrapper_cipher_update( &operation->ctx.driver, input, @@ -4471,7 +4470,7 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, return( PSA_ERROR_BAD_STATE ); } - if( operation->accelerator_set == 1 ) + if( operation->driver_in_use == 1 ) { status = psa_driver_wrapper_cipher_finish( &operation->ctx.driver, output, @@ -4533,7 +4532,7 @@ psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) { if( operation->alg == 0 ) { - /* The object has (apparently) been initialized but it is not + /* 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 ); @@ -4544,7 +4543,7 @@ psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) if( ! PSA_ALG_IS_CIPHER( operation->alg ) ) return( PSA_ERROR_BAD_STATE ); - if( operation->accelerator_set == 1 ) + if( operation->driver_in_use == 1 ) psa_driver_wrapper_cipher_abort( &operation->ctx.driver ); else mbedtls_cipher_free( &operation->ctx.cipher ); @@ -4552,7 +4551,7 @@ psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) operation->alg = 0; operation->key_set = 0; operation->iv_set = 0; - operation->accelerator_set = 0; + operation->driver_in_use = 0; operation->iv_size = 0; operation->block_size = 0; operation->iv_required = 0; From 89e54f2edcb7f9c32784eb39a3daa46d50c60867 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Thu, 10 Sep 2020 18:07:57 +0200 Subject: [PATCH 20/22] Add mock and negative testing to cipher driver Signed-off-by: Steven Cooreman --- tests/src/drivers/cipher.c | 15 +- ...test_suite_psa_crypto_driver_wrappers.data | 39 +++- ..._suite_psa_crypto_driver_wrappers.function | 175 ++++++++++++++++++ 3 files changed, 222 insertions(+), 7 deletions(-) diff --git a/tests/src/drivers/cipher.c b/tests/src/drivers/cipher.c index 2915fba68..f9106d171 100644 --- a/tests/src/drivers/cipher.c +++ b/tests/src/drivers/cipher.c @@ -296,6 +296,8 @@ psa_status_t test_transparent_cipher_decrypt_setup( psa_status_t test_transparent_cipher_abort( test_transparent_cipher_operation_t *operation) { + test_driver_cipher_hooks.hits++; + if( operation->alg == 0 ) return( PSA_SUCCESS ); if( operation->alg != PSA_ALG_CTR ) @@ -309,7 +311,6 @@ psa_status_t test_transparent_cipher_abort( * struct. */ memset( operation, 0, sizeof( *operation ) ); - test_driver_cipher_hooks.hits++; return( PSA_SUCCESS ); } @@ -325,6 +326,9 @@ psa_status_t test_transparent_cipher_generate_iv( test_driver_cipher_hooks.hits++; + if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS ) + return( test_driver_cipher_hooks.forced_status ); + if( operation->alg != PSA_ALG_CTR ) return( PSA_ERROR_BAD_STATE ); @@ -356,6 +360,9 @@ psa_status_t test_transparent_cipher_set_iv( test_driver_cipher_hooks.hits++; + if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS ) + return( test_driver_cipher_hooks.forced_status ); + if( operation->alg != PSA_ALG_CTR ) return( PSA_ERROR_BAD_STATE ); @@ -386,6 +393,9 @@ psa_status_t test_transparent_cipher_update( test_driver_cipher_hooks.hits++; + if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS ) + return( test_driver_cipher_hooks.forced_status ); + if( operation->alg != PSA_ALG_CTR ) return( PSA_ERROR_BAD_STATE ); @@ -425,6 +435,9 @@ psa_status_t test_transparent_cipher_finish( test_driver_cipher_hooks.hits++; + if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS ) + return( test_driver_cipher_hooks.forced_status ); + if( operation->alg != PSA_ALG_CTR ) return( PSA_ERROR_BAD_STATE ); diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data index 9374f28be..7b5d6bd84 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.data +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data @@ -42,27 +42,51 @@ generate_key:PSA_ERROR_GENERIC_ERROR:"":PSA_ERROR_GENERIC_ERROR PSA symmetric encrypt: AES-CTR, 16 bytes, good depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR -cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_SUCCESS:PSA_SUCCESS +cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_SUCCESS:PSA_SUCCESS PSA symmetric encrypt: AES-CTR, 15 bytes, good depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR -cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":PSA_SUCCESS:PSA_SUCCESS +cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":0:PSA_SUCCESS:PSA_SUCCESS PSA symmetric encrypt: AES-CTR, 16 bytes, fallback depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR -cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS +cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS PSA symmetric encrypt: AES-CTR, 15 bytes, fallback depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR -cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS +cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":0:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS + +PSA symmetric encrypt: AES-CTR, 16 bytes, fallback w/ fake +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":1:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS + +PSA symmetric encrypt: AES-CTR, 15 bytes, fallback w/ fake +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":1:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS + +PSA symmetric encrypt: AES-CTR, 16 bytes, fake +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"d07a6a6e2687feb2":1:PSA_SUCCESS:PSA_SUCCESS + +PSA symmetric encrypt: AES-CTR, 15 bytes, fake +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR +cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"d07a6a6e2687feb2":1:PSA_SUCCESS:PSA_SUCCESS PSA symmetric decrypt: AES-CTR, 16 bytes, good depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR -cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":PSA_SUCCESS:PSA_SUCCESS +cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":0:PSA_SUCCESS:PSA_SUCCESS PSA symmetric decrypt: AES-CTR, 16 bytes, fallback depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR -cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS +cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":0:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS + +PSA symmetric decrypt: AES-CTR, 16 bytes, fallback w/ fake +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR +cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":1:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS + +PSA symmetric decrypt: AES-CTR, 16 bytes, fake +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR +cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"d07a6a6e2687feb2":1:PSA_SUCCESS:PSA_SUCCESS PSA symmetric encryption multipart: AES-CTR, 11+5 bytes depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR @@ -135,3 +159,6 @@ cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf715880 PSA symmetric decryption multipart: AES-CTR, 16+0 bytes depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32" + +Cipher driver: negative testing on all entry points +cipher_entry_points:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a" diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function index b1a1ae389..af0c7eefe 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function @@ -188,6 +188,7 @@ exit: void cipher_encrypt( int alg_arg, int key_type_arg, data_t *key, data_t *iv, data_t *input, data_t *expected_output, + int mock_output_arg, int force_status_arg, int expected_status_arg ) { @@ -227,6 +228,12 @@ void cipher_encrypt( int alg_arg, int key_type_arg, PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) ); ASSERT_ALLOC( output, output_buffer_size ); + if( mock_output_arg ) + { + test_driver_cipher_hooks.forced_output = expected_output->x; + test_driver_cipher_hooks.forced_output_length = expected_output->len; + } + PSA_ASSERT( psa_cipher_update( &operation, input->x, input->len, output, output_buffer_size, @@ -234,6 +241,12 @@ void cipher_encrypt( int alg_arg, int key_type_arg, TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) ); test_driver_cipher_hooks.hits = 0; + if( mock_output_arg ) + { + test_driver_cipher_hooks.forced_output = NULL; + test_driver_cipher_hooks.forced_output_length = 0; + } + total_output_length += function_output_length; status = psa_cipher_finish( &operation, output + total_output_length, @@ -441,6 +454,7 @@ exit: void cipher_decrypt( int alg_arg, int key_type_arg, data_t *key, data_t *iv, data_t *input, data_t *expected_output, + int mock_output_arg, int force_status_arg, int expected_status_arg ) { @@ -480,6 +494,12 @@ void cipher_decrypt( int alg_arg, int key_type_arg, PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) ); ASSERT_ALLOC( output, output_buffer_size ); + if( mock_output_arg ) + { + test_driver_cipher_hooks.forced_output = expected_output->x; + test_driver_cipher_hooks.forced_output_length = expected_output->len; + } + PSA_ASSERT( psa_cipher_update( &operation, input->x, input->len, output, output_buffer_size, @@ -487,6 +507,12 @@ void cipher_decrypt( int alg_arg, int key_type_arg, TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) ); test_driver_cipher_hooks.hits = 0; + if( mock_output_arg ) + { + test_driver_cipher_hooks.forced_output = NULL; + test_driver_cipher_hooks.forced_output_length = 0; + } + total_output_length += function_output_length; status = psa_cipher_finish( &operation, output + total_output_length, @@ -515,3 +541,152 @@ exit: test_driver_cipher_hooks = test_driver_cipher_hooks_init(); } /* END_CASE */ + +/* BEGIN_CASE */ +void cipher_entry_points( int alg_arg, int key_type_arg, + data_t *key, data_t *iv, + data_t *input ) +{ + psa_key_handle_t handle = 0; + psa_status_t status; + psa_key_type_t key_type = key_type_arg; + psa_algorithm_t alg = alg_arg; + unsigned char *output = NULL; + size_t output_buffer_size = 0; + size_t function_output_length = 0; + psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + test_driver_cipher_hooks = test_driver_cipher_hooks_init(); + + PSA_ASSERT( psa_crypto_init( ) ); + + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ); + psa_set_key_algorithm( &attributes, alg ); + psa_set_key_type( &attributes, key_type ); + + PSA_ASSERT( psa_import_key( &attributes, key->x, key->len, &handle ) ); + + /* Test setup call, encrypt */ + test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR; + status = psa_cipher_encrypt_setup( &operation, + handle, alg ); + /* When setup fails, it shouldn't call any further entry points */ + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); + test_driver_cipher_hooks.hits = 0; + + /* Test setup call failure, decrypt */ + status = psa_cipher_decrypt_setup( &operation, + handle, alg ); + /* When setup fails, it shouldn't call any further entry points */ + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); + test_driver_cipher_hooks.hits = 0; + + /* Test IV setting failure */ + test_driver_cipher_hooks.forced_status = PSA_SUCCESS; + status = psa_cipher_encrypt_setup( &operation, + handle, alg ); + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); + test_driver_cipher_hooks.hits = 0; + + test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR; + status = psa_cipher_set_iv( &operation, iv->x, iv->len ); + /* When setting the IV fails, it should call abort too */ + TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); + TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); + psa_cipher_abort( &operation ); + test_driver_cipher_hooks.hits = 0; + + /* Test IV generation failure */ + test_driver_cipher_hooks.forced_status = PSA_SUCCESS; + status = psa_cipher_encrypt_setup( &operation, + handle, alg ); + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); + test_driver_cipher_hooks.hits = 0; + + test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR; + ASSERT_ALLOC( output, 16 ); + status = psa_cipher_generate_iv( &operation, output, 16, &output_buffer_size ); + /* When setting the IV fails, it should call abort too */ + TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); + TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); + mbedtls_free( output ); + output = NULL; + psa_cipher_abort( &operation ); + test_driver_cipher_hooks.hits = 0; + + /* Test update failure */ + test_driver_cipher_hooks.forced_status = PSA_SUCCESS; + status = psa_cipher_encrypt_setup( &operation, + handle, alg ); + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); + test_driver_cipher_hooks.hits = 0; + + status = psa_cipher_set_iv( &operation, iv->x, iv->len ); + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); + test_driver_cipher_hooks.hits = 0; + + test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR; + ASSERT_ALLOC( output, input->len + 16 ); + output_buffer_size = input->len + 16; + status = psa_cipher_update( &operation, + input->x, input->len, + output, output_buffer_size, + &function_output_length ); + /* When the update call fails, it should call abort too */ + TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); + TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); + mbedtls_free( output ); + output = NULL; + psa_cipher_abort( &operation ); + test_driver_cipher_hooks.hits = 0; + + /* Test finish failure */ + test_driver_cipher_hooks.forced_status = PSA_SUCCESS; + status = psa_cipher_encrypt_setup( &operation, + handle, alg ); + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); + test_driver_cipher_hooks.hits = 0; + + status = psa_cipher_set_iv( &operation, iv->x, iv->len ); + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); + test_driver_cipher_hooks.hits = 0; + + ASSERT_ALLOC( output, input->len + 16 ); + output_buffer_size = input->len + 16; + status = psa_cipher_update( &operation, + input->x, input->len, + output, output_buffer_size, + &function_output_length ); + TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); + TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); + test_driver_cipher_hooks.hits = 0; + + test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR; + status = psa_cipher_finish( &operation, + output + function_output_length, + output_buffer_size - function_output_length, + &function_output_length ); + /* When the finish call fails, it should call abort too */ + TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); + TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); + mbedtls_free( output ); + output = NULL; + psa_cipher_abort( &operation ); + test_driver_cipher_hooks.hits = 0; + +exit: + psa_cipher_abort( &operation ); + mbedtls_free( output ); + psa_destroy_key( handle ); + PSA_DONE( ); + test_driver_cipher_hooks = test_driver_cipher_hooks_init(); +} +/* END_CASE */ From ef8575e1bff2c33a97169216170901025451014f Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Fri, 11 Sep 2020 11:44:50 +0200 Subject: [PATCH 21/22] Apply review feedback * Reworked the cipher context once again to be more robustly defined * Removed redundant memset * Unified behaviour on failure between driver and software in cipher_finish * Cipher test driver setup function now also returns early when its status is overridden, like the other test driver functions * Removed redundant test cases * Added bad-order checking to verify the driver doesn't get called where the spec says it won't. Signed-off-by: Steven Cooreman --- include/psa/crypto_struct.h | 2 +- library/psa_crypto.c | 105 ++++++++---------- tests/src/drivers/cipher.c | 8 +- ...test_suite_psa_crypto_driver_wrappers.data | 12 -- ..._suite_psa_crypto_driver_wrappers.function | 60 +++++++--- 5 files changed, 93 insertions(+), 94 deletions(-) diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 861850c84..a85a9bf4d 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -168,7 +168,7 @@ struct psa_cipher_operation_s unsigned int key_set : 1; unsigned int iv_required : 1; unsigned int iv_set : 1; - unsigned int driver_in_use : 1; /* Indicates a driver is used instead of software fallback. */ + unsigned int mbedtls_in_use : 1; /* Indicates mbed TLS is handling the operation. */ uint8_t iv_size; uint8_t block_size; union diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 6b259030b..8383eaeb2 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -4057,17 +4057,19 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, /* The requested algorithm must be one that can be processed by cipher. */ if( ! PSA_ALG_IS_CIPHER( alg ) ) - { - memset( operation, 0, sizeof( *operation ) ); return( PSA_ERROR_INVALID_ARGUMENT ); - } - /* Reset the operation members to their initial state, except for alg. The - * alg member is used as an indicator that psa_cipher_abort needs to free - * allocated resources, which doesn't happen until later. */ + /* Fetch key material from key storage. */ + status = psa_get_key_from_slot( handle, &slot, usage, alg ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Initialize the operation struct members, except for alg. The alg member + * is used to indicate to psa_cipher_abort that there are resources to free, + * so we only set it after resources have been allocated/initialized. */ operation->key_set = 0; operation->iv_set = 0; - operation->driver_in_use = 0; + operation->mbedtls_in_use = 0; operation->iv_size = 0; operation->block_size = 0; if( alg == PSA_ALG_ECB_NO_PADDING ) @@ -4075,11 +4077,6 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, else operation->iv_required = 1; - /* Fetch key material from key storage. */ - status = psa_get_key_from_slot( handle, &slot, usage, alg ); - if( status != PSA_SUCCESS ) - goto exit; - /* Try doing the operation through a driver before using software fallback. */ if( cipher_operation == MBEDTLS_ENCRYPT ) status = psa_driver_wrapper_cipher_encrypt_setup( &operation->ctx.driver, @@ -4090,32 +4087,25 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, slot, alg ); + if( status == PSA_SUCCESS ) + /* Once the driver context is initialised, it needs to be freed using + * psa_cipher_abort. Indicate this through setting alg. */ + operation->alg = alg; + if( status != PSA_ERROR_NOT_SUPPORTED || psa_key_lifetime_is_external( slot->attr.lifetime ) ) - { - /* Indicate this operation is bound to a driver. When the driver setup - * succeeded, this indicates to the core to not call any mbedtls_ - * functions for this operation (contexts are not interoperable). - * In case the drivers couldn't setup and there's no way to fallback, - * indicate to the core to not call mbedtls_cipher_free on an - * uninitialised mbed TLS cipher context. */ - operation->driver_in_use = 1; - - /* If the wrapper call succeeded, it allocated resources that need to be - * freed using psa_cipher_abort. Indicate this through setting alg. */ - if( status == PSA_SUCCESS ) - operation->alg = alg; - goto exit; - } /* Proceed with initializing an mbed TLS cipher context if no driver is * available for the given algorithm & key. */ mbedtls_cipher_init( &operation->ctx.cipher ); /* Once the cipher context is initialised, it needs to be freed using - * psa_cipher_abort. Indicate this through setting alg. */ + * psa_cipher_abort. Indicate there is something to be freed through setting + * alg, and indicate the operation is being done using mbedtls crypto through + * setting mbedtls_in_use. */ operation->alg = alg; + operation->mbedtls_in_use = 1; key_bits = psa_get_key_slot_bits( slot ); cipher_info = mbedtls_cipher_info_from_psa( alg, slot->attr.type, key_bits, NULL ); @@ -4224,7 +4214,7 @@ psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, return( PSA_ERROR_BAD_STATE ); } - if( operation->driver_in_use == 1 ) + if( operation->mbedtls_in_use == 0 ) { status = psa_driver_wrapper_cipher_generate_iv( &operation->ctx.driver, iv, @@ -4268,7 +4258,7 @@ psa_status_t psa_cipher_set_iv( psa_cipher_operation_t *operation, return( PSA_ERROR_BAD_STATE ); } - if( operation->driver_in_use == 1 ) + if( operation->mbedtls_in_use == 0 ) { status = psa_driver_wrapper_cipher_set_iv( &operation->ctx.driver, iv, @@ -4397,7 +4387,7 @@ psa_status_t psa_cipher_update( psa_cipher_operation_t *operation, return( PSA_ERROR_BAD_STATE ); } - if( operation->driver_in_use == 1 ) + if( operation->mbedtls_in_use == 0 ) { status = psa_driver_wrapper_cipher_update( &operation->ctx.driver, input, @@ -4459,7 +4449,6 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, size_t *output_length ) { psa_status_t status = PSA_ERROR_GENERIC_ERROR; - int cipher_ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; if( operation->alg == 0 ) { @@ -4470,17 +4459,13 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, return( PSA_ERROR_BAD_STATE ); } - if( operation->driver_in_use == 1 ) + if( operation->mbedtls_in_use == 0 ) { status = psa_driver_wrapper_cipher_finish( &operation->ctx.driver, output, output_size, output_length ); - if( status != PSA_SUCCESS ) - goto error; - - (void) psa_cipher_abort( operation ); - return( status ); + goto exit; } if( operation->ctx.cipher.unprocessed_len != 0 ) @@ -4490,18 +4475,16 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, operation->ctx.cipher.operation == MBEDTLS_ENCRYPT ) ) { status = PSA_ERROR_INVALID_ARGUMENT; - goto error; + goto exit; } } - cipher_ret = mbedtls_cipher_finish( &operation->ctx.cipher, - temp_output_buffer, - output_length ); - if( cipher_ret != 0 ) - { - status = mbedtls_to_psa_error( cipher_ret ); - goto error; - } + status = mbedtls_to_psa_error( + mbedtls_cipher_finish( &operation->ctx.cipher, + temp_output_buffer, + output_length ) ); + if( status != PSA_SUCCESS ) + goto exit; if( *output_length == 0 ) ; /* Nothing to copy. Note that output may be NULL in this case. */ @@ -4510,22 +4493,24 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, else { status = PSA_ERROR_BUFFER_TOO_SMALL; - goto error; + goto exit; } - mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); - status = psa_cipher_abort( operation ); +exit: + if( operation->mbedtls_in_use == 1 ) + mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); - return( status ); + if( status == PSA_SUCCESS ) + return( psa_cipher_abort( operation ) ); + else + { + *output_length = 0; -error: + mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); + (void) psa_cipher_abort( operation ); - *output_length = 0; - - mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); - (void) psa_cipher_abort( operation ); - - return( status ); + return( status ); + } } psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) @@ -4543,7 +4528,7 @@ psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) if( ! PSA_ALG_IS_CIPHER( operation->alg ) ) return( PSA_ERROR_BAD_STATE ); - if( operation->driver_in_use == 1 ) + if( operation->mbedtls_in_use == 0 ) psa_driver_wrapper_cipher_abort( &operation->ctx.driver ); else mbedtls_cipher_free( &operation->ctx.cipher ); @@ -4551,7 +4536,7 @@ psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) operation->alg = 0; operation->key_set = 0; operation->iv_set = 0; - operation->driver_in_use = 0; + operation->mbedtls_in_use = 0; operation->iv_size = 0; operation->block_size = 0; operation->iv_required = 0; diff --git a/tests/src/drivers/cipher.c b/tests/src/drivers/cipher.c index f9106d171..fa7c6a9e7 100644 --- a/tests/src/drivers/cipher.c +++ b/tests/src/drivers/cipher.c @@ -225,6 +225,10 @@ static psa_status_t test_transparent_cipher_setup( * struct. */ memset( operation, 0, sizeof( *operation ) ); + /* Allow overriding return value for testing purposes */ + if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS ) + return( test_driver_cipher_hooks.forced_status ); + /* Test driver supports AES-CTR only, to verify operation calls. */ if( alg != PSA_ALG_CTR || psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES ) @@ -258,10 +262,6 @@ static psa_status_t test_transparent_cipher_setup( operation->iv_required = 1; operation->key_set = 1; - /* Allow overriding return value for testing purposes */ - if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS ) - mbedtls_cipher_free( &operation->cipher ); - return( test_driver_cipher_hooks.forced_status ); } diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data index 7b5d6bd84..7abc25692 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.data +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data @@ -56,14 +56,6 @@ PSA symmetric encrypt: AES-CTR, 15 bytes, fallback depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":0:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS -PSA symmetric encrypt: AES-CTR, 16 bytes, fallback w/ fake -depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR -cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":1:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS - -PSA symmetric encrypt: AES-CTR, 15 bytes, fallback w/ fake -depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR -cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":1:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS - PSA symmetric encrypt: AES-CTR, 16 bytes, fake depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"d07a6a6e2687feb2":1:PSA_SUCCESS:PSA_SUCCESS @@ -80,10 +72,6 @@ PSA symmetric decrypt: AES-CTR, 16 bytes, fallback depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":0:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS -PSA symmetric decrypt: AES-CTR, 16 bytes, fallback w/ fake -depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR -cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":1:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS - PSA symmetric decrypt: AES-CTR, 16 bytes, fake depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"d07a6a6e2687feb2":1:PSA_SUCCESS:PSA_SUCCESS diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function index af0c7eefe..951670d56 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function @@ -558,6 +558,9 @@ void cipher_entry_points( int alg_arg, int key_type_arg, psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; test_driver_cipher_hooks = test_driver_cipher_hooks_init(); + ASSERT_ALLOC( output, input->len + 16 ); + output_buffer_size = input->len + 16; + PSA_ASSERT( psa_crypto_init( ) ); psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ); @@ -574,6 +577,9 @@ void cipher_entry_points( int alg_arg, int key_type_arg, TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); test_driver_cipher_hooks.hits = 0; + status = psa_cipher_set_iv( &operation, iv->x, iv->len ); + TEST_EQUAL( status, PSA_ERROR_BAD_STATE ); + TEST_EQUAL( test_driver_cipher_hooks.hits, 0 ); /* Test setup call failure, decrypt */ status = psa_cipher_decrypt_setup( &operation, @@ -582,6 +588,9 @@ void cipher_entry_points( int alg_arg, int key_type_arg, TEST_EQUAL( test_driver_cipher_hooks.hits, 1 ); TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); test_driver_cipher_hooks.hits = 0; + status = psa_cipher_set_iv( &operation, iv->x, iv->len ); + TEST_EQUAL( status, PSA_ERROR_BAD_STATE ); + TEST_EQUAL( test_driver_cipher_hooks.hits, 0 ); /* Test IV setting failure */ test_driver_cipher_hooks.forced_status = PSA_SUCCESS; @@ -596,8 +605,15 @@ void cipher_entry_points( int alg_arg, int key_type_arg, /* When setting the IV fails, it should call abort too */ TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); - psa_cipher_abort( &operation ); + /* Failure should prevent further operations from executing on the driver */ test_driver_cipher_hooks.hits = 0; + status = psa_cipher_update( &operation, + input->x, input->len, + output, output_buffer_size, + &function_output_length ); + TEST_EQUAL( status, PSA_ERROR_BAD_STATE ); + TEST_EQUAL( test_driver_cipher_hooks.hits, 0 ); + psa_cipher_abort( &operation ); /* Test IV generation failure */ test_driver_cipher_hooks.forced_status = PSA_SUCCESS; @@ -608,15 +624,19 @@ void cipher_entry_points( int alg_arg, int key_type_arg, test_driver_cipher_hooks.hits = 0; test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR; - ASSERT_ALLOC( output, 16 ); - status = psa_cipher_generate_iv( &operation, output, 16, &output_buffer_size ); - /* When setting the IV fails, it should call abort too */ + status = psa_cipher_generate_iv( &operation, output, 16, &function_output_length ); + /* When generating the IV fails, it should call abort too */ TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); - mbedtls_free( output ); - output = NULL; - psa_cipher_abort( &operation ); + /* Failure should prevent further operations from executing on the driver */ test_driver_cipher_hooks.hits = 0; + status = psa_cipher_update( &operation, + input->x, input->len, + output, output_buffer_size, + &function_output_length ); + TEST_EQUAL( status, PSA_ERROR_BAD_STATE ); + TEST_EQUAL( test_driver_cipher_hooks.hits, 0 ); + psa_cipher_abort( &operation ); /* Test update failure */ test_driver_cipher_hooks.forced_status = PSA_SUCCESS; @@ -632,8 +652,6 @@ void cipher_entry_points( int alg_arg, int key_type_arg, test_driver_cipher_hooks.hits = 0; test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR; - ASSERT_ALLOC( output, input->len + 16 ); - output_buffer_size = input->len + 16; status = psa_cipher_update( &operation, input->x, input->len, output, output_buffer_size, @@ -641,10 +659,15 @@ void cipher_entry_points( int alg_arg, int key_type_arg, /* When the update call fails, it should call abort too */ TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); - mbedtls_free( output ); - output = NULL; - psa_cipher_abort( &operation ); + /* Failure should prevent further operations from executing on the driver */ test_driver_cipher_hooks.hits = 0; + status = psa_cipher_update( &operation, + input->x, input->len, + output, output_buffer_size, + &function_output_length ); + TEST_EQUAL( status, PSA_ERROR_BAD_STATE ); + TEST_EQUAL( test_driver_cipher_hooks.hits, 0 ); + psa_cipher_abort( &operation ); /* Test finish failure */ test_driver_cipher_hooks.forced_status = PSA_SUCCESS; @@ -659,8 +682,6 @@ void cipher_entry_points( int alg_arg, int key_type_arg, TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); test_driver_cipher_hooks.hits = 0; - ASSERT_ALLOC( output, input->len + 16 ); - output_buffer_size = input->len + 16; status = psa_cipher_update( &operation, input->x, input->len, output, output_buffer_size, @@ -677,10 +698,15 @@ void cipher_entry_points( int alg_arg, int key_type_arg, /* When the finish call fails, it should call abort too */ TEST_EQUAL( test_driver_cipher_hooks.hits, 2 ); TEST_EQUAL( status, test_driver_cipher_hooks.forced_status ); - mbedtls_free( output ); - output = NULL; - psa_cipher_abort( &operation ); + /* Failure should prevent further operations from executing on the driver */ test_driver_cipher_hooks.hits = 0; + status = psa_cipher_update( &operation, + input->x, input->len, + output, output_buffer_size, + &function_output_length ); + TEST_EQUAL( status, PSA_ERROR_BAD_STATE ); + TEST_EQUAL( test_driver_cipher_hooks.hits, 0 ); + psa_cipher_abort( &operation ); exit: psa_cipher_abort( &operation ); From 6d81f7e1196faf6c0797110a272970c250fd55c6 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Mon, 14 Sep 2020 13:14:31 +0200 Subject: [PATCH 22/22] Final feedback from @ronald-cron-arm Signed-off-by: Steven Cooreman --- library/psa_crypto.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 8383eaeb2..931e2e915 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -4088,9 +4088,11 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, alg ); if( status == PSA_SUCCESS ) + { /* Once the driver context is initialised, it needs to be freed using * psa_cipher_abort. Indicate this through setting alg. */ operation->alg = alg; + } if( status != PSA_ERROR_NOT_SUPPORTED || psa_key_lifetime_is_external( slot->attr.lifetime ) ) @@ -4491,10 +4493,7 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, else if( output_size >= *output_length ) memcpy( output, temp_output_buffer, *output_length ); else - { status = PSA_ERROR_BUFFER_TOO_SMALL; - goto exit; - } exit: if( operation->mbedtls_in_use == 1 ) @@ -4505,8 +4504,6 @@ exit: else { *output_length = 0; - - mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); (void) psa_cipher_abort( operation ); return( status );