diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 0bd9c03ebf..63f119dc01 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -8,11 +8,27 @@ #include "crypto_platform.h" +#include + #ifdef __DOXYGEN_ONLY__ /** \defgroup platform Implementation-specific definitions * @{ */ +/** \brief Key slot number. + * + * This type represents key slots. It must be an unsigned integral + * type.* The choice of type is implementation-dependent. + * 0 is not a valid key slot number. The meaning of other values is + * implementation dependent. + * + * At any given point in time, each key slot either contains a + * cryptographic object, or is empty. Key slots are persistent: + * once set, the cryptographic object remains in the key slot until + * explicitly destroyed. + */ +typedef _unsigned_integral_type_ psa_key_slot_t; + /**@}*/ #endif @@ -89,6 +105,103 @@ psa_status_t psa_crypto_init(void); /**@}*/ +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +typedef uint32_t psa_key_type_t; + +#define PSA_KEY_TYPE_NONE 0x00000000 +#define PSA_KEY_TYPE_RAW_DATA 0x00000001 +#define PSA_KEY_TYPE_RSA 0x40000001 +#define PSA_KEY_TYPE_ECC_BASE 0x40010000 + +#define PSA_KEY_TYPE_VENDOR_FLAG 0x80000000 +#define PSA_KEY_TYPE_ASYMMETRIC_FLAG 0x40000000 +#define PSA_KEY_TYPE_ECC_TEST_MASK 0x7fff0000 +#define PSA_KEY_TYPE_ECC_TEST_VALUE 0x40010000 + +#define PSA_KEY_TYPE_IS_VENDOR(type) \ + (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0) +#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \ + (((type) & PSA_KEY_TYPE_ASYMMETRIC_FLAG) != 0) +#define PSA_KEY_TYPE_IS_ECC(type) \ + (((type) & PSA_KEY_TYPE_ECC_TEST_MASK) == PSA_KEY_TYPE_ECC_TEST_VALUE) + +typedef uint32_t psa_algorithm_type_t; + +/**@}*/ + +/** \defgroup key_management Key management + * @{ + */ + +/** + * \brief Import a key in binary format. + * + * This function supports any output from psa_export_key(). + * + * \return * \c PSA_SUCCESS: success. + * * \c PSA_ERROR_NOT_SUPPORTED + * * \c PSA_ERROR_INVALID_ARGUMENT + * * \c PSA_ERROR_INSUFFICIENT_MEMORY + * * \c PSA_ERROR_COMMUNICATION_FAILURE + * * \c PSA_ERROR_HARDWARE_FAILURE + * * \c PSA_ERROR_TAMPERING_DETECTED + */ +psa_status_t psa_import_key(psa_key_slot_t key, + psa_key_type_t type, + const uint8_t *data, + size_t data_length); + +/** + * \brief Destroy a key. + * + * \return * \c PSA_SUCCESS: success. + * * \c PSA_ERROR_EMPTY_SLOT + * * \c PSA_ERROR_COMMUNICATION_FAILURE + * * \c PSA_ERROR_HARDWARE_FAILURE + * * \c PSA_ERROR_TAMPERING_DETECTED + */ +psa_status_t psa_destroy_key(psa_key_slot_t key); + +/** + * \brief Get basic metadata about a key. + * + * \return * \c PSA_SUCCESS: success. + * * \c PSA_ERROR_EMPTY_SLOT + * * \c PSA_ERROR_COMMUNICATION_FAILURE + * * \c PSA_ERROR_HARDWARE_FAILURE + * * \c PSA_ERROR_TAMPERING_DETECTED + */ +psa_status_t psa_get_key_information(psa_key_slot_t key, + psa_key_type_t *type, + size_t *bits); + +/** + * \brief Export a key in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an equivalent object. + * + * If a key is created with psa_import_key() and then exported with + * this function, it is not guaranteed that the resulting data is + * identical: the implementation may choose a different representation + * of the same key. + * + * \return * \c PSA_SUCCESS: success. + * * \c PSA_ERROR_EMPTY_SLOT + * * \c PSA_ERROR_COMMUNICATION_FAILURE + * * \c PSA_ERROR_HARDWARE_FAILURE + * * \c PSA_ERROR_TAMPERING_DETECTED + */ +psa_status_t psa_export_key(psa_key_slot_t key, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/**@}*/ + #ifdef __cplusplus } #endif diff --git a/include/psa/crypto_platform.h b/include/psa/crypto_platform.h index eafc0b3ea2..7aabd1bc07 100644 --- a/include/psa/crypto_platform.h +++ b/include/psa/crypto_platform.h @@ -36,4 +36,7 @@ /* PSA requires several types which C99 provides in stdint.h. */ #include +/* Integral type representing a key slot number. */ +typedef uint16_t psa_key_slot_t; + #endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/library/psa_crypto.c b/library/psa_crypto.c index ca25bb487d..31dd0d640c 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -29,8 +29,18 @@ #include "psa/crypto.h" +#include +#include +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + #include "mbedtls/ctr_drbg.h" #include "mbedtls/entropy.h" +#include "mbedtls/pk.h" /* Implementation that should never be optimized out by the compiler */ @@ -39,10 +49,32 @@ static void mbedtls_zeroize( void *v, size_t n ) volatile unsigned char *p = v; while( n-- ) *p++ = 0; } +/****************************************************************/ +/* Global data, support functions and library management */ +/****************************************************************/ + +/* Number of key slots (plus one because 0 is not used). + * The value is a compile-time constant for now, for simplicity. */ +#define MBEDTLS_PSA_KEY_SLOT_COUNT 32 + +typedef struct { + psa_key_type_t type; + union { + struct raw_data { + uint8_t *data; + size_t bytes; + } raw; +#if defined(MBEDTLS_PK_C) + mbedtls_pk_context pk; +#endif /* MBEDTLS_PK_C */ + } data; +} key_slot_t; + typedef struct { int initialized; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; + key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT]; } psa_global_data_t; static psa_global_data_t global_data; @@ -57,13 +89,210 @@ static psa_status_t mbedtls_to_psa_error( int ret ) case MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE: case MBEDTLS_ERR_ENTROPY_SOURCE_FAILED: return( PSA_ERROR_INSUFFICIENT_ENTROPY ); + case MBEDTLS_ERR_PK_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_PK_TYPE_MISMATCH: + case MBEDTLS_ERR_PK_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_PK_FILE_IO_ERROR: + return( PSA_ERROR_TAMPERING_DETECTED ); + case MBEDTLS_ERR_PK_KEY_INVALID_VERSION: + case MBEDTLS_ERR_PK_KEY_INVALID_FORMAT: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_PK_UNKNOWN_PK_ALG: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_PK_PASSWORD_REQUIRED: + case MBEDTLS_ERR_PK_PASSWORD_MISMATCH: + return( PSA_ERROR_NOT_PERMITTED ); + case MBEDTLS_ERR_PK_INVALID_PUBKEY: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_PK_INVALID_ALG: + case MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE: + case MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_PK_SIG_LEN_MISMATCH: + return( PSA_ERROR_INVALID_SIGNATURE ); default: return( PSA_ERROR_UNKNOWN_ERROR ); } } + + +/****************************************************************/ +/* Key management */ +/****************************************************************/ + +psa_status_t psa_import_key(psa_key_slot_t key, + psa_key_type_t type, + const uint8_t *data, + size_t data_length) +{ + key_slot_t *slot; + + if( key == 0 || key > MBEDTLS_PSA_KEY_SLOT_COUNT ) + return( PSA_ERROR_INVALID_ARGUMENT ); + slot = &global_data.key_slots[key]; + if( slot->type != PSA_KEY_TYPE_NONE ) + return( PSA_ERROR_OCCUPIED_SLOT ); + + if( type == PSA_KEY_TYPE_RAW_DATA ) + { + if( data_length > SIZE_MAX / 8 ) + return( PSA_ERROR_NOT_SUPPORTED ); + slot->data.raw.data = mbedtls_calloc( 1, data_length ); + if( slot->data.raw.data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + memcpy( slot->data.raw.data, data, data_length ); + slot->data.raw.bytes = data_length; + } + else +#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_PARSE_C) + if( type == PSA_KEY_TYPE_RSA || PSA_KEY_TYPE_IS_ECC( type ) ) + { + int ret; + mbedtls_pk_init( &slot->data.pk ); + ret = mbedtls_pk_parse_key( &slot->data.pk, + data, data_length, + NULL, 0 ); + if( ret != 0 ) + return( mbedtls_to_psa_error( ret ) ); + } + else +#endif /* defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_PARSE_C) */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + slot->type = type; + return( PSA_SUCCESS ); +} + +psa_status_t psa_destroy_key(psa_key_slot_t key) +{ + key_slot_t *slot; + + if( key == 0 || key > MBEDTLS_PSA_KEY_SLOT_COUNT ) + return( PSA_ERROR_INVALID_ARGUMENT ); + slot = &global_data.key_slots[key]; + if( slot->type == PSA_KEY_TYPE_NONE ) + return( PSA_ERROR_EMPTY_SLOT ); + + if( slot->type == PSA_KEY_TYPE_RAW_DATA ) + { + mbedtls_free( slot->data.raw.data ); + } + else +#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_PARSE_C) + if( slot->type == PSA_KEY_TYPE_RSA || + PSA_KEY_TYPE_IS_ECC( slot->type ) ) + { + mbedtls_pk_free( &slot->data.pk ); + } + else +#endif /* defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_PARSE_C) */ + { + /* Shouldn't happen: the key type is not any type that we + * put it. */ + return( PSA_ERROR_TAMPERING_DETECTED ); + } + + mbedtls_zeroize( slot, sizeof( *slot ) ); + return( PSA_SUCCESS ); +} + +psa_status_t psa_get_key_information(psa_key_slot_t key, + psa_key_type_t *type, + size_t *bits) +{ + key_slot_t *slot; + + if( key == 0 || key > MBEDTLS_PSA_KEY_SLOT_COUNT ) + return( PSA_ERROR_INVALID_ARGUMENT ); + slot = &global_data.key_slots[key]; + if( type != NULL ) + *type = slot->type; + if( bits != NULL ) + *bits = 0; + if( slot->type == PSA_KEY_TYPE_NONE ) + return( PSA_ERROR_EMPTY_SLOT ); + + if( slot->type == PSA_KEY_TYPE_RAW_DATA ) + { + if( bits != NULL ) + *bits = slot->data.raw.bytes * 8; + } + else +#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_PARSE_C) + if( slot->type == PSA_KEY_TYPE_RSA || + PSA_KEY_TYPE_IS_ECC( slot->type ) ) + { + if( bits != NULL ) + *bits = mbedtls_pk_get_bitlen( &slot->data.pk ); + } + else +#endif /* defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_PARSE_C) */ + { + /* Shouldn't happen: the key type is not any type that we + * put it. */ + return( PSA_ERROR_TAMPERING_DETECTED ); + } + + return( PSA_SUCCESS ); +} + +psa_status_t psa_export_key(psa_key_slot_t key, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + key_slot_t *slot; + + if( key == 0 || key > MBEDTLS_PSA_KEY_SLOT_COUNT ) + return( PSA_ERROR_INVALID_ARGUMENT ); + slot = &global_data.key_slots[key]; + if( slot->type == PSA_KEY_TYPE_NONE ) + return( PSA_ERROR_EMPTY_SLOT ); + + if( slot->type == PSA_KEY_TYPE_RAW_DATA ) + { + if( slot->data.raw.bytes > data_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + memcpy( data, slot->data.raw.data, slot->data.raw.bytes ); + *data_length = slot->data.raw.bytes; + return( PSA_SUCCESS ); + } + else +#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_PARSE_C) + if( slot->type == PSA_KEY_TYPE_RSA || + PSA_KEY_TYPE_IS_ECC( slot->type ) ) + { + int ret; + ret = mbedtls_pk_write_key_der( &slot->data.pk, + data, data_size ); + if( ret < 0 ) + return( mbedtls_to_psa_error( ret ) ); + *data_length = ret; + return( PSA_SUCCESS ); + } + else +#endif /* defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_PARSE_C) */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + + + +/****************************************************************/ +/* Module setup */ +/****************************************************************/ + void mbedtls_psa_crypto_free( void ) { + size_t key; + for( key = 1; key < MBEDTLS_PSA_KEY_SLOT_COUNT; key++ ) + psa_destroy_key( key ); mbedtls_ctr_drbg_free( &global_data.ctr_drbg ); mbedtls_entropy_free( &global_data.entropy ); mbedtls_zeroize( &global_data, sizeof( global_data ) ); diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 3d7689bd25..d9149cacfd 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -1,2 +1,30 @@ PSA init/deinit init_deinit: + +PSA import/export raw: 0 bytes +import_export:"":PSA_KEY_TYPE_RAW_DATA:0:0:PSA_SUCCESS:1 + +PSA import/export raw: 1 bytes +import_export:"2a":PSA_KEY_TYPE_RAW_DATA:8:0:PSA_SUCCESS:1 + +PSA import/export raw: 1 bytes, larger buffer +import_export:"2a":PSA_KEY_TYPE_RAW_DATA:8:1:PSA_SUCCESS:1 + +PSA import/export raw: 2 bytes, buffer too small +import_export:"2a2b":PSA_KEY_TYPE_RAW_DATA:16:-1:PSA_ERROR_BUFFER_TOO_SMALL:1 + +PSA import/export RSA: good +depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C +import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA:1024:0:PSA_SUCCESS:1 + +PSA import/export RSA: trailing garbage ignored +depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C +import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b2400":PSA_KEY_TYPE_RSA:1024:-1:PSA_SUCCESS:0 + +PSA import RSA: truncated +depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C +import:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b":PSA_KEY_TYPE_RSA:PSA_ERROR_INVALID_ARGUMENT + +#PSA import/export EC secp256r1: good +#depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +#import_export:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_NISTP256R1:256:0:PSA_SUCCESS:1 diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 9d9eee47bf..6fa10dd96b 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -10,15 +10,125 @@ /* BEGIN_CASE */ void init_deinit() { - psa_status_t ret; + psa_status_t status; int i; for( i = 0; i <= 1; i++ ) { - ret = psa_crypto_init( ); - TEST_ASSERT( ret == PSA_SUCCESS ); - ret = psa_crypto_init( ); - TEST_ASSERT( ret == PSA_SUCCESS ); + status = psa_crypto_init( ); + TEST_ASSERT( status == PSA_SUCCESS ); + status = psa_crypto_init( ); + TEST_ASSERT( status == PSA_SUCCESS ); mbedtls_psa_crypto_free( ); } } /* END_CASE */ + +/* BEGIN_CASE */ +void import( char *hex, int type, int expected_status ) +{ + int slot = 1; + psa_status_t status; + unsigned char *data = NULL; + size_t data_size; + + data_size = strlen( hex ) / 2; + data = mbedtls_calloc( 1, data_size ); + TEST_ASSERT( data != NULL ); + data_size = unhexify( data, hex ); + TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + + status = psa_import_key( slot, type, data, data_size ); + TEST_ASSERT( status == (psa_status_t) expected_status ); + if( status == PSA_SUCCESS ) + TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS ); + +exit: + mbedtls_free( data ); + mbedtls_psa_crypto_free( ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void import_export( char *hex, int type_arg, + int expected_bits, + int export_size_delta, + int expected_export_status, + int canonical_input ) +{ + int slot = 1; + int slot2 = slot + 1; + psa_key_type_t type = type_arg; + psa_status_t status; + unsigned char *data = NULL; + unsigned char *exported = NULL; + unsigned char *reexported = NULL; + size_t data_size; + size_t export_size; + size_t exported_length; + size_t reexported_length; + psa_key_type_t got_type; + size_t got_bits; + + data_size = strlen( hex ) / 2; + data = mbedtls_calloc( 1, data_size ); + TEST_ASSERT( data != NULL ); + data_size = unhexify( data, hex ); + export_size = (ssize_t) data_size + export_size_delta; + exported = mbedtls_calloc( 1, export_size ); + TEST_ASSERT( exported != NULL ); + if( ! canonical_input ) + { + reexported = mbedtls_calloc( 1, export_size ); + TEST_ASSERT( reexported != NULL ); + } + TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + + /* Import the key */ + TEST_ASSERT( psa_import_key( slot, type, + data, data_size ) == PSA_SUCCESS ); + + /* Test the key information */ + TEST_ASSERT( psa_get_key_information( slot, + &got_type, &got_bits ) == + PSA_SUCCESS ); + TEST_ASSERT( got_type == type ); + TEST_ASSERT( got_bits == (size_t) expected_bits ); + + /* Export the key */ + status = psa_export_key( slot, + exported, export_size, + &exported_length ); + TEST_ASSERT( status == (psa_status_t) expected_export_status ); + if( status != PSA_SUCCESS ) + goto destroy; + + if( canonical_input ) + { + TEST_ASSERT( exported_length == data_size ); + TEST_ASSERT( memcmp( exported, data, data_size ) == 0 ); + } + else + { + TEST_ASSERT( psa_import_key( slot2, type, + exported, export_size ) == + PSA_SUCCESS ); + TEST_ASSERT( psa_export_key( slot2, + reexported, export_size, + &reexported_length ) == + PSA_SUCCESS ); + TEST_ASSERT( reexported_length == exported_length ); + TEST_ASSERT( memcmp( reexported, exported, + exported_length ) == 0 ); + } + +destroy: + /* Destroy the key */ + TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS ); + TEST_ASSERT( psa_get_key_information( + slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT ); + +exit: + mbedtls_free( data ); + mbedtls_psa_crypto_free( ); +} +/* END_CASE */