Merge pull request #4092 from ronald-cron-arm/psa-crypto-client

Psa crypto client
diff --git a/ChangeLog.d/psa-crypto-client.txt b/ChangeLog.d/psa-crypto-client.txt
new file mode 100644
index 0000000..3070ee9
--- /dev/null
+++ b/ChangeLog.d/psa-crypto-client.txt
@@ -0,0 +1,4 @@
+Changes
+   * A new library C file psa_crypto_client.c has been created to contain
+     the PSA code needed by a PSA crypto client when the PSA crypto
+     implementation is not included into the library.
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 251d4f0..c3132a5 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -1338,6 +1338,22 @@
  */
 #define MBEDTLS_PKCS1_V21
 
+/** \def MBEDTLS_PSA_CRYPTO_CLIENT
+ *
+ * Enable support for PSA crypto client.
+ *
+ * \note This option allows to include the code necessary for a PSA
+ *       crypto client when the PSA crypto implementation is not included in
+ *       the library (MBEDTLS_PSA_CRYPTO_C disabled). The code included is the
+ *       code to set and get PSA key attributes.
+ *       The development of PSA drivers partially relying on the library to
+ *       fulfill the hardware gaps is another possible usage of this option.
+ *
+ * \warning This interface is experimental and may change or be removed
+ * without notice.
+ */
+//#define MBEDTLS_PSA_CRYPTO_CLIENT
+
 /** \def MBEDTLS_PSA_CRYPTO_DRIVERS
  *
  * Enable support for the experimental PSA crypto driver interface.
diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h
index 9804881..386c7d7 100644
--- a/include/psa/crypto_types.h
+++ b/include/psa/crypto_types.h
@@ -35,6 +35,13 @@
 
 #include "crypto_platform.h"
 
+/* If MBEDTLS_PSA_CRYPTO_C is defined, make sure MBEDTLS_PSA_CRYPTO_CLIENT
+ * is defined as well to include all PSA code.
+ */
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+#define MBEDTLS_PSA_CRYPTO_CLIENT
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
 #include <stdint.h>
 
 /** \defgroup error Error codes
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 3ecbf9a..9c252a8 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -61,6 +61,7 @@
     platform_util.c
     poly1305.c
     psa_crypto.c
+    psa_crypto_client.c
     psa_crypto_driver_wrappers.c
     psa_crypto_ecp.c
     psa_crypto_rsa.c
diff --git a/library/Makefile b/library/Makefile
index 5ef2923..903dc0d 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -118,6 +118,7 @@
 	     platform_util.o \
 	     poly1305.o \
 	     psa_crypto.o \
+	     psa_crypto_client.o \
 	     psa_crypto_driver_wrappers.o \
 	     psa_crypto_ecp.o \
 	     psa_crypto_rsa.o \
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 82407c3..7f12bcb 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -990,55 +990,6 @@
     return( overall_status );
 }
 
-void psa_reset_key_attributes( psa_key_attributes_t *attributes )
-{
-    mbedtls_free( attributes->domain_parameters );
-    memset( attributes, 0, sizeof( *attributes ) );
-}
-
-psa_status_t psa_set_key_domain_parameters( psa_key_attributes_t *attributes,
-                                            psa_key_type_t type,
-                                            const uint8_t *data,
-                                            size_t data_length )
-{
-    uint8_t *copy = NULL;
-
-    if( data_length != 0 )
-    {
-        copy = mbedtls_calloc( 1, data_length );
-        if( copy == NULL )
-            return( PSA_ERROR_INSUFFICIENT_MEMORY );
-        memcpy( copy, data, data_length );
-    }
-    /* After this point, this function is guaranteed to succeed, so it
-     * can start modifying `*attributes`. */
-
-    if( attributes->domain_parameters != NULL )
-    {
-        mbedtls_free( attributes->domain_parameters );
-        attributes->domain_parameters = NULL;
-        attributes->domain_parameters_size = 0;
-    }
-
-    attributes->domain_parameters = copy;
-    attributes->domain_parameters_size = data_length;
-    attributes->core.type = type;
-    return( PSA_SUCCESS );
-}
-
-psa_status_t psa_get_key_domain_parameters(
-    const psa_key_attributes_t *attributes,
-    uint8_t *data, size_t data_size, size_t *data_length )
-{
-    if( attributes->domain_parameters_size > data_size )
-        return( PSA_ERROR_BUFFER_TOO_SMALL );
-    *data_length = attributes->domain_parameters_size;
-    if( attributes->domain_parameters_size != 0 )
-        memcpy( data, attributes->domain_parameters,
-                attributes->domain_parameters_size );
-    return( PSA_SUCCESS );
-}
-
 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
 static psa_status_t psa_get_rsa_public_exponent(
diff --git a/library/psa_crypto_client.c b/library/psa_crypto_client.c
new file mode 100644
index 0000000..e84cf30
--- /dev/null
+++ b/library/psa_crypto_client.c
@@ -0,0 +1,83 @@
+/*
+ *  PSA crypto client code
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  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.
+ */
+
+#include "common.h"
+#include "psa_crypto_service_integration.h"
+#include "psa/crypto.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+
+#include <string.h>
+#include "mbedtls/platform.h"
+#if !defined(MBEDTLS_PLATFORM_C)
+#define mbedtls_calloc calloc
+#define mbedtls_free   free
+#endif
+
+void psa_reset_key_attributes( psa_key_attributes_t *attributes )
+{
+    mbedtls_free( attributes->domain_parameters );
+    memset( attributes, 0, sizeof( *attributes ) );
+}
+
+psa_status_t psa_set_key_domain_parameters( psa_key_attributes_t *attributes,
+                                            psa_key_type_t type,
+                                            const uint8_t *data,
+                                            size_t data_length )
+{
+    uint8_t *copy = NULL;
+
+    if( data_length != 0 )
+    {
+        copy = mbedtls_calloc( 1, data_length );
+        if( copy == NULL )
+            return( PSA_ERROR_INSUFFICIENT_MEMORY );
+        memcpy( copy, data, data_length );
+    }
+    /* After this point, this function is guaranteed to succeed, so it
+     * can start modifying `*attributes`. */
+
+    if( attributes->domain_parameters != NULL )
+    {
+        mbedtls_free( attributes->domain_parameters );
+        attributes->domain_parameters = NULL;
+        attributes->domain_parameters_size = 0;
+    }
+
+    attributes->domain_parameters = copy;
+    attributes->domain_parameters_size = data_length;
+    attributes->core.type = type;
+    return( PSA_SUCCESS );
+}
+
+psa_status_t psa_get_key_domain_parameters(
+    const psa_key_attributes_t *attributes,
+    uint8_t *data, size_t data_size, size_t *data_length )
+{
+    if( attributes->domain_parameters_size > data_size )
+        return( PSA_ERROR_BUFFER_TOO_SMALL );
+    *data_length = attributes->domain_parameters_size;
+    if( attributes->domain_parameters_size != 0 )
+        memcpy( data, attributes->domain_parameters,
+                attributes->domain_parameters_size );
+    return( PSA_SUCCESS );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
diff --git a/library/version_features.c b/library/version_features.c
index c6f46d9..9332987 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -438,6 +438,9 @@
 #if defined(MBEDTLS_PKCS1_V21)
     "MBEDTLS_PKCS1_V21",
 #endif /* MBEDTLS_PKCS1_V21 */
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+    "MBEDTLS_PSA_CRYPTO_CLIENT",
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
 #if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
     "MBEDTLS_PSA_CRYPTO_DRIVERS",
 #endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
diff --git a/programs/test/query_config.c b/programs/test/query_config.c
index 0dc06c0..6962adf 100644
--- a/programs/test/query_config.c
+++ b/programs/test/query_config.c
@@ -1226,6 +1226,14 @@
     }
 #endif /* MBEDTLS_PKCS1_V21 */
 
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+    if( strcmp( "MBEDTLS_PSA_CRYPTO_CLIENT", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_CRYPTO_CLIENT );
+        return( 0 );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
+
 #if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
     if( strcmp( "MBEDTLS_PSA_CRYPTO_DRIVERS", config ) == 0 )
     {
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f8ce925..6873dad 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -141,6 +141,7 @@
 add_test_suite(pkwrite)
 add_test_suite(poly1305)
 add_test_suite(psa_crypto)
+add_test_suite(psa_crypto_attributes)
 add_test_suite(psa_crypto_entropy)
 add_test_suite(psa_crypto_hash)
 add_test_suite(psa_crypto_init)
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index a4c7a74..e9d15e4 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -798,6 +798,17 @@
     make test
 }
 
+component_test_psa_crypto_client () {
+    msg "build: default config - PSA_CRYPTO_C + PSA_CRYPTO_CLIENT, make"
+    scripts/config.py unset MBEDTLS_PSA_CRYPTO_C
+    scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CLIENT
+    make
+
+    msg "test: default config - PSA_CRYPTO_C + PSA_CRYPTO_CLIENT, make"
+    make test
+}
+
 component_test_zlib_make() {
     msg "build: zlib enabled, make"
     scripts/config.py set MBEDTLS_ZLIB_SUPPORT
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 50972a2..c37bdce 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -1,33 +1,6 @@
 PSA compile-time sanity checks
 static_checks:
 
-PSA key attributes structure
-attributes_set_get:0xffff1234:0x6963:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:128
-
-PSA key attributes: id only
-persistence_attributes:0x1234:0x5678:-1:-1:0:0x1234:0x5678:PSA_KEY_LIFETIME_PERSISTENT
-
-PSA key attributes: lifetime=3 only
-persistence_attributes:-1:0:3:-1:0:0:0:3
-
-PSA key attributes: id then back to volatile
-persistence_attributes:0x1234:0x5678:PSA_KEY_LIFETIME_VOLATILE:-1:0:0:0x5678:PSA_KEY_LIFETIME_VOLATILE
-
-PSA key attributes: id then back to non local volatile
-persistence_attributes:0x1234:0x5678:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE,1):-1:0:0:0x5678:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE,1)
-
-PSA key attributes: id then lifetime
-persistence_attributes:0x1234:0x5678:3:-1:0:0x1234:0x5678:3
-
-PSA key attributes: lifetime then id
-persistence_attributes:0x1234:0x5678:3:0x1235:0x5679:0x1235:0x5679:3
-
-PSA key attributes: non local volatile lifetime then id
-persistence_attributes:0x1234:0x5678:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE,3):0x1235:0x5679:0x1235:0x5679:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_PERSISTENT,3)
-
-PSA key attributes: slot number
-slot_number_attribute:
-
 PSA import/export raw: 1 bytes
 import_export:"2a":PSA_KEY_TYPE_RAW_DATA:PSA_KEY_USAGE_EXPORT:0:8:0:PSA_SUCCESS:1
 
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 66446a8..18c9dc3 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -1364,127 +1364,6 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void attributes_set_get( int owner_id_arg, int id_arg, int lifetime_arg,
-                         int usage_flags_arg, int alg_arg,
-                         int type_arg, int bits_arg )
-{
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( owner_id_arg, id_arg );
-    psa_key_lifetime_t lifetime = lifetime_arg;
-    psa_key_usage_t usage_flags = usage_flags_arg;
-    psa_algorithm_t alg = alg_arg;
-    psa_key_type_t type = type_arg;
-    size_t bits = bits_arg;
-
-    TEST_EQUAL(
-        MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psa_get_key_id( &attributes ) ), 0 );
-    TEST_EQUAL(
-        MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( psa_get_key_id( &attributes ) ), 0 );
-    TEST_EQUAL( psa_get_key_lifetime( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_type( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_bits( &attributes ), 0 );
-
-    psa_set_key_id( &attributes, id );
-    psa_set_key_lifetime( &attributes, lifetime );
-    psa_set_key_usage_flags( &attributes, usage_flags );
-    psa_set_key_algorithm( &attributes, alg );
-    psa_set_key_type( &attributes, type );
-    psa_set_key_bits( &attributes, bits );
-
-    TEST_ASSERT( mbedtls_svc_key_id_equal(
-                     psa_get_key_id( &attributes ), id ) );
-    TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
-    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
-    TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
-    TEST_EQUAL( psa_get_key_type( &attributes ), type );
-    TEST_EQUAL( psa_get_key_bits( &attributes ), bits );
-
-    psa_reset_key_attributes( &attributes );
-
-    TEST_EQUAL(
-        MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psa_get_key_id( &attributes ) ), 0 );
-    TEST_EQUAL(
-        MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( psa_get_key_id( &attributes ) ), 0 );
-    TEST_EQUAL( psa_get_key_lifetime( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_type( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_bits( &attributes ), 0 );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void persistence_attributes( int id1_arg, int owner_id1_arg, int lifetime_arg,
-                             int id2_arg, int owner_id2_arg,
-                             int expected_id_arg, int expected_owner_id_arg,
-                             int expected_lifetime_arg )
-{
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    mbedtls_svc_key_id_t id1 =
-        mbedtls_svc_key_id_make( owner_id1_arg, id1_arg );
-    psa_key_lifetime_t lifetime = lifetime_arg;
-    mbedtls_svc_key_id_t id2 =
-        mbedtls_svc_key_id_make( owner_id2_arg, id2_arg );
-    mbedtls_svc_key_id_t expected_id =
-        mbedtls_svc_key_id_make( expected_owner_id_arg, expected_id_arg );
-    psa_key_lifetime_t expected_lifetime = expected_lifetime_arg;
-
-    if( id1_arg != -1 )
-        psa_set_key_id( &attributes, id1 );
-    if( lifetime_arg != -1 )
-        psa_set_key_lifetime( &attributes, lifetime );
-    if( id2_arg != -1 )
-        psa_set_key_id( &attributes, id2 );
-
-    TEST_ASSERT( mbedtls_svc_key_id_equal(
-                     psa_get_key_id( &attributes ), expected_id ) );
-    TEST_EQUAL( psa_get_key_lifetime( &attributes ), expected_lifetime );
-}
-/* END_CASE */
-
-/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_SE_C */
-void slot_number_attribute( )
-{
-    psa_key_slot_number_t slot_number = 0xdeadbeef;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-
-    /* Initially, there is no slot number. */
-    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
-                PSA_ERROR_INVALID_ARGUMENT );
-
-    /* Test setting a slot number. */
-    psa_set_key_slot_number( &attributes, 0 );
-    PSA_ASSERT( psa_get_key_slot_number( &attributes, &slot_number ) );
-    TEST_EQUAL( slot_number, 0 );
-
-    /* Test changing the slot number. */
-    psa_set_key_slot_number( &attributes, 42 );
-    PSA_ASSERT( psa_get_key_slot_number( &attributes, &slot_number ) );
-    TEST_EQUAL( slot_number, 42 );
-
-    /* Test clearing the slot number. */
-    psa_clear_key_slot_number( &attributes );
-    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
-                PSA_ERROR_INVALID_ARGUMENT );
-
-    /* Clearing again should have no effect. */
-    psa_clear_key_slot_number( &attributes );
-    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
-                PSA_ERROR_INVALID_ARGUMENT );
-
-    /* Test that reset clears the slot number. */
-    psa_set_key_slot_number( &attributes, 42 );
-    PSA_ASSERT( psa_get_key_slot_number( &attributes, &slot_number ) );
-    TEST_EQUAL( slot_number, 42 );
-    psa_reset_key_attributes( &attributes );
-    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
-                PSA_ERROR_INVALID_ARGUMENT );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
 void import_with_policy( int type_arg,
                          int usage_arg, int alg_arg,
                          int expected_status_arg )
diff --git a/tests/suites/test_suite_psa_crypto_attributes.data b/tests/suites/test_suite_psa_crypto_attributes.data
new file mode 100644
index 0000000..15ff325
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_attributes.data
@@ -0,0 +1,26 @@
+PSA key attributes structure
+attributes_set_get:0xffff1234:0x6963:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:128
+
+PSA key attributes: id only
+persistence_attributes:0x1234:0x5678:-1:-1:0:0x1234:0x5678:PSA_KEY_LIFETIME_PERSISTENT
+
+PSA key attributes: lifetime=3 only
+persistence_attributes:-1:0:3:-1:0:0:0:3
+
+PSA key attributes: id then back to volatile
+persistence_attributes:0x1234:0x5678:PSA_KEY_LIFETIME_VOLATILE:-1:0:0:0x5678:PSA_KEY_LIFETIME_VOLATILE
+
+PSA key attributes: id then back to non local volatile
+persistence_attributes:0x1234:0x5678:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE,1):-1:0:0:0x5678:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE,1)
+
+PSA key attributes: id then lifetime
+persistence_attributes:0x1234:0x5678:3:-1:0:0x1234:0x5678:3
+
+PSA key attributes: lifetime then id
+persistence_attributes:0x1234:0x5678:3:0x1235:0x5679:0x1235:0x5679:3
+
+PSA key attributes: non local volatile lifetime then id
+persistence_attributes:0x1234:0x5678:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE,3):0x1235:0x5679:0x1235:0x5679:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_PERSISTENT,3)
+
+PSA key attributes: slot number
+slot_number_attribute:
diff --git a/tests/suites/test_suite_psa_crypto_attributes.function b/tests/suites/test_suite_psa_crypto_attributes.function
new file mode 100644
index 0000000..ce34fae
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_attributes.function
@@ -0,0 +1,129 @@
+/* BEGIN_HEADER */
+#include "psa/crypto.h"
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_PSA_CRYPTO_CLIENT
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void attributes_set_get( int owner_id_arg, int id_arg, int lifetime_arg,
+                         int usage_flags_arg, int alg_arg,
+                         int type_arg, int bits_arg )
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( owner_id_arg, id_arg );
+    psa_key_lifetime_t lifetime = lifetime_arg;
+    psa_key_usage_t usage_flags = usage_flags_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_key_type_t type = type_arg;
+    size_t bits = bits_arg;
+
+    TEST_EQUAL(
+        MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psa_get_key_id( &attributes ) ), 0 );
+    TEST_EQUAL(
+        MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( psa_get_key_id( &attributes ) ), 0 );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_type( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_bits( &attributes ), 0 );
+
+    psa_set_key_id( &attributes, id );
+    psa_set_key_lifetime( &attributes, lifetime );
+    psa_set_key_usage_flags( &attributes, usage_flags );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, type );
+    psa_set_key_bits( &attributes, bits );
+
+    TEST_ASSERT( mbedtls_svc_key_id_equal(
+                     psa_get_key_id( &attributes ), id ) );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
+    TEST_EQUAL( psa_get_key_type( &attributes ), type );
+    TEST_EQUAL( psa_get_key_bits( &attributes ), bits );
+
+    psa_reset_key_attributes( &attributes );
+
+    TEST_EQUAL(
+        MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psa_get_key_id( &attributes ) ), 0 );
+    TEST_EQUAL(
+        MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( psa_get_key_id( &attributes ) ), 0 );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_type( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_bits( &attributes ), 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void persistence_attributes( int id1_arg, int owner_id1_arg, int lifetime_arg,
+                             int id2_arg, int owner_id2_arg,
+                             int expected_id_arg, int expected_owner_id_arg,
+                             int expected_lifetime_arg )
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t id1 =
+        mbedtls_svc_key_id_make( owner_id1_arg, id1_arg );
+    psa_key_lifetime_t lifetime = lifetime_arg;
+    mbedtls_svc_key_id_t id2 =
+        mbedtls_svc_key_id_make( owner_id2_arg, id2_arg );
+    mbedtls_svc_key_id_t expected_id =
+        mbedtls_svc_key_id_make( expected_owner_id_arg, expected_id_arg );
+    psa_key_lifetime_t expected_lifetime = expected_lifetime_arg;
+
+    if( id1_arg != -1 )
+        psa_set_key_id( &attributes, id1 );
+    if( lifetime_arg != -1 )
+        psa_set_key_lifetime( &attributes, lifetime );
+    if( id2_arg != -1 )
+        psa_set_key_id( &attributes, id2 );
+
+    TEST_ASSERT( mbedtls_svc_key_id_equal(
+                     psa_get_key_id( &attributes ), expected_id ) );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ), expected_lifetime );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_SE_C */
+void slot_number_attribute( )
+{
+    psa_key_slot_number_t slot_number = 0xdeadbeef;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    /* Initially, there is no slot number. */
+    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
+                PSA_ERROR_INVALID_ARGUMENT );
+
+    /* Test setting a slot number. */
+    psa_set_key_slot_number( &attributes, 0 );
+    PSA_ASSERT( psa_get_key_slot_number( &attributes, &slot_number ) );
+    TEST_EQUAL( slot_number, 0 );
+
+    /* Test changing the slot number. */
+    psa_set_key_slot_number( &attributes, 42 );
+    PSA_ASSERT( psa_get_key_slot_number( &attributes, &slot_number ) );
+    TEST_EQUAL( slot_number, 42 );
+
+    /* Test clearing the slot number. */
+    psa_clear_key_slot_number( &attributes );
+    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
+                PSA_ERROR_INVALID_ARGUMENT );
+
+    /* Clearing again should have no effect. */
+    psa_clear_key_slot_number( &attributes );
+    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
+                PSA_ERROR_INVALID_ARGUMENT );
+
+    /* Test that reset clears the slot number. */
+    psa_set_key_slot_number( &attributes, 42 );
+    PSA_ASSERT( psa_get_key_slot_number( &attributes, &slot_number ) );
+    TEST_EQUAL( slot_number, 42 );
+    psa_reset_key_attributes( &attributes );
+    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
+                PSA_ERROR_INVALID_ARGUMENT );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_psa_crypto_metadata.function b/tests/suites/test_suite_psa_crypto_metadata.function
index 2d5b0f0..4b55da1 100644
--- a/tests/suites/test_suite_psa_crypto_metadata.function
+++ b/tests/suites/test_suite_psa_crypto_metadata.function
@@ -184,7 +184,7 @@
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
- * depends_on:MBEDTLS_PSA_CRYPTO_C
+ * depends_on:MBEDTLS_PSA_CRYPTO_CLIENT
  * END_DEPENDENCIES
  */
 
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index 42cca89..e6d6532 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -319,6 +319,7 @@
     <ClCompile Include="..\..\library\platform_util.c" />

     <ClCompile Include="..\..\library\poly1305.c" />

     <ClCompile Include="..\..\library\psa_crypto.c" />

+    <ClCompile Include="..\..\library\psa_crypto_client.c" />

     <ClCompile Include="..\..\library\psa_crypto_driver_wrappers.c" />

     <ClCompile Include="..\..\library\psa_crypto_ecp.c" />

     <ClCompile Include="..\..\library\psa_crypto_rsa.c" />