Merge pull request #154 from yanesca/iotcrypt-789-update-tls-prf-to-multipart

Update TLS 1.2 PRF to multipart API
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 78bf131..1321074 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -458,6 +458,12 @@
 #error "MBEDTLS_PSA_CRYPTO_SPM defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C) &&    \
+    ! ( defined(MBEDTLS_PSA_CRYPTO_C) && \
+        defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) )
+#error "MBEDTLS_PSA_CRYPTO_SE_C defined, but not all prerequisites"
+#endif
+
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) &&            \
     ! defined(MBEDTLS_PSA_CRYPTO_C)
 #error "MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites"
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 56ad01c..0e8d755 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -1710,6 +1710,19 @@
 #define MBEDTLS_PSA_CRYPTO_C
 
 /**
+ * \def MBEDTLS_PSA_CRYPTO_SE_C
+ *
+ * Enable secure element support in the Platform Security Architecture
+ * cryptography API.
+ *
+ * Module:  library/psa_crypto_se.c
+ *
+ * Requires: MBEDTLS_PSA_CRYPTO_C, MBEDTLS_PSA_CRYPTO_STORAGE_C
+ *
+ */
+#define MBEDTLS_PSA_CRYPTO_SE_C
+
+/**
  * \def MBEDTLS_PSA_CRYPTO_STORAGE_C
  *
  * Enable the Platform Security Architecture persistent key storage.
diff --git a/include/psa/crypto_se_driver.h b/include/psa/crypto_se_driver.h
index 9f54947..8524705 100644
--- a/include/psa/crypto_se_driver.h
+++ b/include/psa/crypto_se_driver.h
@@ -8,11 +8,11 @@
  * space in which the PSA Crypto implementation runs, typically secure
  * elements (SEs).
  *
- * This file is part of the PSA Crypto Driver Model, containing functions for
- * driver developers to implement to enable hardware to be called in a
- * standardized way by a PSA Cryptographic API implementation. The functions
- * comprising the driver model, which driver authors implement, are not
- * intended to be called by application developers.
+ * This file is part of the PSA Crypto Driver HAL (hardware abstraction layer),
+ * containing functions for driver developers to implement to enable hardware
+ * to be called in a standardized way by a PSA Cryptography API
+ * implementation. The functions comprising the driver HAL, which driver
+ * authors implement, are not intended to be called by application developers.
  */
 
 /*
@@ -726,7 +726,7 @@
  * \retval #PSA_SUCCESS
  *         The slot's content, if any, has been erased.
  */
-typedef psa_status_t (*psa_drv_se_destroy_key_t)(psa_key_slot_number_t key);
+typedef psa_status_t (*psa_drv_se_destroy_key_t)(psa_key_slot_number_t key_slot);
 
 /**
  * \brief A function that exports a secure element key in binary format
@@ -878,7 +878,7 @@
  * \param[in,out] p_context A hardware-specific structure containing any
  *                          context information for the implementation
  * \param[in] kdf_alg       The algorithm to be used for the key derivation
- * \param[in] souce_key     The key to be used as the source material for the
+ * \param[in] source_key    The key to be used as the source material for the
  *                          key derivation
  *
  * \retval PSA_SUCCESS
@@ -961,6 +961,90 @@
 
 /**@}*/
 
+/** \defgroup se_registration Secure element driver registration
+ */
+/**@{*/
+
+/** A structure containing pointers to all the entry points of a
+ * secure element driver.
+ *
+ * Future versions of this specification may add extra substructures at
+ * the end of this structure.
+ */
+typedef struct {
+    /** The version of the driver HAL that this driver implements.
+     * This is a protection against loading driver binaries built against
+     * a different version of this specification.
+     * Use #PSA_DRV_SE_HAL_VERSION.
+     */
+    uint32_t hal_version;
+    psa_drv_se_key_management_t key_management;
+    psa_drv_se_mac_t mac;
+    psa_drv_se_cipher_t cipher;
+    psa_drv_se_aead_t aead;
+    psa_drv_se_asymmetric_t asymmetric;
+    psa_drv_se_key_derivation_t derivation;
+} psa_drv_se_t;
+
+/** The current version of the secure element driver HAL.
+ */
+/* 0.0.0 patchlevel 5 */
+#define PSA_DRV_SE_HAL_VERSION 0x00000005
+
+/** Register an external cryptoprocessor (secure element) driver.
+ *
+ * This function is only intended to be used by driver code, not by
+ * application code. In implementations with separation between the
+ * PSA cryptography module and applications, this function should
+ * only be available to callers that run in the same memory space as
+ * the cryptography module, and should not be exposed to applications
+ * running in a different memory space.
+ *
+ * This function may be called before psa_crypto_init(). It is
+ * implementation-defined whether this function may be called
+ * after psa_crypto_init().
+ *
+ * \note Implementations store metadata about keys including the lifetime
+ *       value. Therefore, from one instantiation of the PSA Cryptography
+ *       library to the next one, if there is a key in storage with a certain
+ *       lifetime value, you must always register the same driver (or an
+ *       updated version that communicates with the same secure element)
+ *       with the same lifetime value.
+ *
+ * \param lifetime      The lifetime value through which this driver will
+ *                      be exposed to applications.
+ *                      The values #PSA_KEY_LIFETIME_VOLATILE and
+ *                      #PSA_KEY_LIFETIME_PERSISTENT are reserved and
+ *                      may not be used for drivers. Implementations
+ *                      may reserve other values.
+ * \param[in] methods   The method table of the driver. This structure must
+ *                      remain valid for as long as the cryptography
+ *                      module keeps running. It is typically a global
+ *                      constant.
+ *
+ * \return PSA_SUCCESS
+ *         The driver was successfully registered. Applications can now
+ *         use \p lifetime to access keys through the methods passed to
+ *         this function.
+ * \return PSA_ERROR_BAD_STATE
+ *         This function was called after the initialization of the
+ *         cryptography module, and this implementation does not support
+ *         driver registration at this stage.
+ * \return PSA_ERROR_ALREADY_EXISTS
+ *         There is already a registered driver for this value of \p lifetime.
+ * \return PSA_ERROR_INVALID_ARGUMENT
+ *         \p lifetime is a reserved value.
+ * \return PSA_ERROR_NOT_SUPPORTED
+ *         `methods->hal_version` is not supported by this implementation.
+ * \return PSA_ERROR_INSUFFICIENT_MEMORY
+ * \return PSA_ERROR_NOT_PERMITTED
+ */
+psa_status_t psa_register_se_driver(
+    psa_key_lifetime_t lifetime,
+    const psa_drv_se_t *methods);
+
+/**@}*/
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 61bc13d..78c233a 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -53,6 +53,7 @@
     platform_util.c
     poly1305.c
     psa_crypto.c
+    psa_crypto_se.c
     psa_crypto_slot_management.c
     psa_crypto_storage.c
     psa_its_file.c
diff --git a/library/Makefile b/library/Makefile
index 921b68e..2b979b4 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -80,7 +80,7 @@
 		pk.o		pk_wrap.o	pkcs12.o	\
 		pkcs5.o		pkparse.o	pkwrite.o	\
 		platform.o	platform_util.o	poly1305.o	\
-		psa_crypto.o					\
+		psa_crypto.o	psa_crypto_se.o			\
 		psa_crypto_slot_management.o			\
 		psa_crypto_storage.o				\
 		psa_its_file.o					\
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index a47f956..2285694 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -32,6 +32,9 @@
 
 #include "psa_crypto_core.h"
 #include "psa_crypto_invasive.h"
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+#include "psa_crypto_se.h"
+#endif
 #include "psa_crypto_slot_management.h"
 /* Include internal declarations that are useful for implementing persistently
  * stored keys. */
@@ -5512,6 +5515,11 @@
      * In particular, this sets all state indicator to the value
      * indicating "uninitialized". */
     mbedtls_platform_zeroize( &global_data, sizeof( global_data ) );
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    /* Unregister all secure element drivers, so that we restart from
+     * a pristine state. */
+    psa_unregister_all_se_drivers( );
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 }
 
 psa_status_t psa_crypto_init( void )
diff --git a/library/psa_crypto_se.c b/library/psa_crypto_se.c
new file mode 100644
index 0000000..688d4e7
--- /dev/null
+++ b/library/psa_crypto_se.c
@@ -0,0 +1,86 @@
+/*
+ *  PSA crypto support for secure element drivers
+ */
+/*  Copyright (C) 2019, 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_SE_C)
+
+#include <assert.h>
+#include <string.h>
+
+#include "psa_crypto_se.h"
+
+typedef struct
+{
+    psa_key_lifetime_t lifetime;
+    const psa_drv_se_t *methods;
+} method_table_entry_t;
+
+static method_table_entry_t driver_table[PSA_MAX_SE_DRIVERS];
+
+psa_status_t psa_register_se_driver(
+    psa_key_lifetime_t lifetime,
+    const psa_drv_se_t *methods)
+{
+    size_t i;
+
+    if( methods->hal_version != PSA_DRV_SE_HAL_VERSION )
+        return( PSA_ERROR_NOT_SUPPORTED );
+    /* Driver table entries are 0-initialized. 0 is not a valid driver
+     * lifetime because it means a volatile key. */
+#if defined(static_assert)
+    static_assert( PSA_KEY_LIFETIME_VOLATILE == 0,
+                   "Secure element support requires 0 to mean a volatile key" );
+#endif
+    if( lifetime == PSA_KEY_LIFETIME_VOLATILE ||
+        lifetime == PSA_KEY_LIFETIME_PERSISTENT )
+    {
+        return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+
+    for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ )
+    {
+        if( driver_table[i].lifetime == 0 )
+            break;
+        /* Check that lifetime isn't already in use up to the first free
+         * entry. Since entries are created in order and never deleted,
+         * there can't be a used entry after the first free entry. */
+        if( driver_table[i].lifetime == lifetime )
+            return( PSA_ERROR_ALREADY_EXISTS );
+    }
+    if( i == PSA_MAX_SE_DRIVERS )
+        return( PSA_ERROR_INSUFFICIENT_MEMORY );
+
+    driver_table[i].lifetime = lifetime;
+    driver_table[i].methods = methods;
+    return( PSA_SUCCESS );
+}
+
+void psa_unregister_all_se_drivers( void )
+{
+    memset( driver_table, 0, sizeof( driver_table ) );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
diff --git a/library/psa_crypto_se.h b/library/psa_crypto_se.h
new file mode 100644
index 0000000..e99bd25
--- /dev/null
+++ b/library/psa_crypto_se.h
@@ -0,0 +1,45 @@
+/*
+ *  PSA crypto support for secure element drivers
+ */
+/*  Copyright (C) 2019, 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_SE_H
+#define PSA_CRYPTO_SE_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include "psa/crypto.h"
+#include "psa/crypto_se_driver.h"
+
+/** The maximum number of registered secure element driver lifetimes. */
+#define PSA_MAX_SE_DRIVERS 4
+
+/** Unregister all secure element drivers.
+ *
+ * \warning Do not call this function while the library is in the initialized
+ *          state. This function is only intended to be called at the end
+ *          of mbedtls_psa_crypto_free().
+ */
+void psa_unregister_all_se_drivers( void );
+
+#endif /* PSA_CRYPTO_SE_H */
diff --git a/library/version_features.c b/library/version_features.c
index 4f1da6a..5701598 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -555,6 +555,9 @@
 #if defined(MBEDTLS_PSA_CRYPTO_C)
     "MBEDTLS_PSA_CRYPTO_C",
 #endif /* MBEDTLS_PSA_CRYPTO_C */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    "MBEDTLS_PSA_CRYPTO_SE_C",
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
     "MBEDTLS_PSA_CRYPTO_STORAGE_C",
 #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
diff --git a/programs/test/query_config.c b/programs/test/query_config.c
index fc25353..ee754d9 100644
--- a/programs/test/query_config.c
+++ b/programs/test/query_config.c
@@ -1509,6 +1509,14 @@
     }
 #endif /* MBEDTLS_PSA_CRYPTO_C */
 
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    if( strcmp( "MBEDTLS_PSA_CRYPTO_SE_C", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_CRYPTO_SE_C );
+        return( 0 );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
     if( strcmp( "MBEDTLS_PSA_CRYPTO_STORAGE_C", config ) == 0 )
     {
diff --git a/scripts/config.pl b/scripts/config.pl
index b667905..05cc52e 100755
--- a/scripts/config.pl
+++ b/scripts/config.pl
@@ -107,6 +107,7 @@
 MBEDTLS_MEMORY_BUFFER_ALLOC_C
 MBEDTLS_PLATFORM_TIME_ALT
 MBEDTLS_PLATFORM_FPRINTF_ALT
+MBEDTLS_PSA_CRYPTO_SE_C
 MBEDTLS_PSA_CRYPTO_STORAGE_C
 MBEDTLS_PSA_CRYPTO_STORAGE_ITS_C
 MBEDTLS_PSA_ITS_FILE_C
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 42d99d6..323ad2d 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -135,6 +135,7 @@
 add_test_suite(psa_crypto_init)
 add_test_suite(psa_crypto_metadata)
 add_test_suite(psa_crypto_persistent_key)
+add_test_suite(psa_crypto_se_driver_hal)
 add_test_suite(psa_crypto_slot_management)
 add_test_suite(psa_its)
 add_test_suite(shax)
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index b38c7d4..c1e1ffe 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -709,6 +709,7 @@
     scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
     scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
     scripts/config.pl unset MBEDTLS_FS_IO
+    scripts/config.pl unset MBEDTLS_PSA_CRYPTO_SE_C
     scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C
     scripts/config.pl unset MBEDTLS_PSA_ITS_FILE_C
     scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_ITS_C
@@ -894,6 +895,7 @@
     scripts/config.pl unset MBEDTLS_TIMING_C
     scripts/config.pl unset MBEDTLS_FS_IO
     scripts/config.pl unset MBEDTLS_PSA_ITS_FILE_C
+    scripts/config.pl unset MBEDTLS_PSA_CRYPTO_SE_C
     scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_ITS_C
     scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C
     scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
@@ -913,6 +915,7 @@
     scripts/config.pl unset MBEDTLS_TIMING_C
     scripts/config.pl unset MBEDTLS_FS_IO
     scripts/config.pl unset MBEDTLS_PSA_ITS_FILE_C
+    scripts/config.pl unset MBEDTLS_PSA_CRYPTO_SE_C
     scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_ITS_C
     scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C
     scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
@@ -935,6 +938,7 @@
     scripts/config.pl unset MBEDTLS_TIMING_C
     scripts/config.pl unset MBEDTLS_FS_IO
     scripts/config.pl unset MBEDTLS_PSA_ITS_FILE_C
+    scripts/config.pl unset MBEDTLS_PSA_CRYPTO_SE_C
     scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_ITS_C
     scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C
     scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
@@ -957,6 +961,7 @@
     scripts/config.pl unset MBEDTLS_TIMING_C
     scripts/config.pl unset MBEDTLS_FS_IO
     scripts/config.pl unset MBEDTLS_PSA_ITS_FILE_C
+    scripts/config.pl unset MBEDTLS_PSA_CRYPTO_SE_C
     scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_ITS_C
     scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C
     scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal.data b/tests/suites/test_suite_psa_crypto_se_driver_hal.data
new file mode 100644
index 0000000..c04b70d
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.data
@@ -0,0 +1,28 @@
+Register SE driver: good
+register_one:2:PSA_DRV_SE_HAL_VERSION:PSA_SUCCESS
+
+# Run this test case a second time to verify that the library deinit
+# unregistered the first driver.
+Register SE driver: good, again
+register_one:2:PSA_DRV_SE_HAL_VERSION:PSA_SUCCESS
+
+Register SE driver: invalid lifetime (0)
+register_one:0:PSA_DRV_SE_HAL_VERSION:PSA_ERROR_INVALID_ARGUMENT
+
+Register SE driver: invalid lifetime (VOLATILE)
+register_one:PSA_KEY_LIFETIME_VOLATILE:PSA_DRV_SE_HAL_VERSION:PSA_ERROR_INVALID_ARGUMENT
+
+Register SE driver: invalid lifetime (PERSISTENT)
+register_one:PSA_KEY_LIFETIME_PERSISTENT:PSA_DRV_SE_HAL_VERSION:PSA_ERROR_INVALID_ARGUMENT
+
+Register SE driver: invalid version (ancient)
+register_one:2:0x00000003:PSA_ERROR_NOT_SUPPORTED
+
+Register SE driver: invalid version (future)
+register_one:2:PSA_DRV_SE_HAL_VERSION + 1:PSA_ERROR_NOT_SUPPORTED
+
+Register SE driver: already registered
+register_twice:3
+
+Register SE driver: maximum number of drivers
+register_max:
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal.function b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
new file mode 100644
index 0000000..b9d0a1f
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
@@ -0,0 +1,80 @@
+/* BEGIN_HEADER */
+#include "psa_crypto_helpers.h"
+#include "psa/crypto_se_driver.h"
+
+#include "psa_crypto_se.h"
+
+/* The minimum valid lifetime value for a secure element driver. */
+#define MIN_DRIVER_LIFETIME 2
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_PSA_CRYPTO_SE_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void register_one( int lifetime, int version, int expected_status_arg )
+{
+    psa_status_t expected_status = expected_status_arg;
+    psa_drv_se_t driver;
+
+    memset( &driver, 0, sizeof( driver ) );
+    driver.hal_version = version;
+
+    TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
+                expected_status );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+exit:
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void register_twice( int count )
+{
+    psa_drv_se_t driver;
+    psa_key_lifetime_t lifetime;
+    psa_key_lifetime_t max = MIN_DRIVER_LIFETIME + count;
+
+    memset( &driver, 0, sizeof( driver ) );
+    driver.hal_version = PSA_DRV_SE_HAL_VERSION;
+
+    for( lifetime = MIN_DRIVER_LIFETIME; lifetime < max; lifetime++ )
+        PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+    for( lifetime = MIN_DRIVER_LIFETIME; lifetime < max; lifetime++ )
+        TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
+                    PSA_ERROR_ALREADY_EXISTS );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+exit:
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void register_max( )
+{
+    psa_drv_se_t driver;
+    psa_key_lifetime_t lifetime;
+    psa_key_lifetime_t max = MIN_DRIVER_LIFETIME + PSA_MAX_SE_DRIVERS;
+
+    memset( &driver, 0, sizeof( driver ) );
+    driver.hal_version = PSA_DRV_SE_HAL_VERSION;
+
+    for( lifetime = MIN_DRIVER_LIFETIME; lifetime < max; lifetime++ )
+        PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
+
+    TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
+                PSA_ERROR_INSUFFICIENT_MEMORY );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+exit:
+    PSA_DONE( );
+}
+/* END_CASE */
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index 07c80e8..2034a84 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -225,6 +225,7 @@
     <ClInclude Include="..\..\library/psa_crypto_core.h" />

     <ClInclude Include="..\..\library/psa_crypto_invasive.h" />

     <ClInclude Include="..\..\library/psa_crypto_its.h" />

+    <ClInclude Include="..\..\library/psa_crypto_se.h" />

     <ClInclude Include="..\..\library/psa_crypto_service_integration.h" />

     <ClInclude Include="..\..\library/psa_crypto_slot_management.h" />

     <ClInclude Include="..\..\library/psa_crypto_storage.h" />

@@ -281,6 +282,7 @@
     <ClCompile Include="..\..\library\platform_util.c" />

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

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

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

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

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

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