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 */