SE driver: call the p_init method during psa_crypto_init()
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 90158f8..e26a7ec 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -5687,6 +5687,12 @@
     if( status != PSA_SUCCESS )
         goto exit;
 
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    status = psa_init_all_se_drivers( );
+    if( status != PSA_SUCCESS )
+        goto exit;
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
 #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
     status = psa_crypto_load_transaction( );
     if( status == PSA_SUCCESS )
diff --git a/library/psa_crypto_se.c b/library/psa_crypto_se.c
index 81b3103..81f0a1a 100644
--- a/library/psa_crypto_se.c
+++ b/library/psa_crypto_se.c
@@ -272,6 +272,28 @@
     return( status == PSA_SUCCESS ? storage_status : status );
 }
 
+psa_status_t psa_init_all_se_drivers( void )
+{
+    size_t i;
+    for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ )
+    {
+        psa_se_drv_table_entry_t *driver = &driver_table[i];
+        if( driver->lifetime == 0 )
+            continue; /* skipping unused entry */
+        const psa_drv_se_t *methods = psa_get_se_driver_methods( driver );
+        if( methods->p_init != NULL )
+        {
+            psa_status_t status = methods->p_init(
+                &driver->context,
+                driver->internal.persistent_data,
+                driver->lifetime );
+            if( status != PSA_SUCCESS )
+                return( status );
+        }
+    }
+    return( PSA_SUCCESS );
+}
+
 
 
 /****************************************************************/
diff --git a/library/psa_crypto_se.h b/library/psa_crypto_se.h
index 900a72b..86bf7a7 100644
--- a/library/psa_crypto_se.h
+++ b/library/psa_crypto_se.h
@@ -66,6 +66,12 @@
  */
 void psa_unregister_all_se_drivers( void );
 
+/** Initialize all secure element drivers.
+ *
+ * Called from psa_crypto_init().
+ */
+psa_status_t psa_init_all_se_drivers( void );
+
 /** A structure that describes a registered secure element driver.
  *
  * A secure element driver table entry contains a pointer to the
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.data b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.data
index dba6875..f60bd76 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.data
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.data
@@ -1,3 +1,12 @@
+SE init mock test: success
+mock_init:2:PSA_SUCCESS:PSA_SUCCESS:PSA_SUCCESS:1
+
+SE init mock test: failure
+mock_init:2:PSA_SUCCESS:PSA_ERROR_HARDWARE_FAILURE:PSA_ERROR_HARDWARE_FAILURE:1
+
+SE init mock test: invalid lifetime
+mock_init:1:PSA_ERROR_INVALID_ARGUMENT:PSA_ERROR_BAD_STATE:PSA_SUCCESS:0
+
 SE key importing mock test
 mock_import:PSA_SUCCESS:PSA_SUCCESS:0:PSA_SUCCESS
 
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
index e6b3f7b..7088a52 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
@@ -8,6 +8,13 @@
 static struct
 {
     uint16_t called;
+    psa_key_lifetime_t lifetime;
+    psa_status_t return_value;
+} mock_init_data;
+
+static struct
+{
+    uint16_t called;
     psa_key_slot_number_t key_slot;
     psa_key_attributes_t attributes;
     size_t pubkey_size;
@@ -92,6 +99,7 @@
 
 static void mock_teardown( void )
 {
+    memset( &mock_init_data, 0, sizeof( mock_init_data ) );
     memset( &mock_import_data, 0, sizeof( mock_import_data ) );
     memset( &mock_export_data, 0, sizeof( mock_export_data ) );
     memset( &mock_export_public_data, 0, sizeof( mock_export_public_data ) );
@@ -103,6 +111,18 @@
     psa_purge_storage( );
 }
 
+static psa_status_t mock_init( psa_drv_se_context_t *drv_context,
+                               void *persistent_data,
+                               psa_key_lifetime_t lifetime )
+{
+    (void) drv_context;
+    (void) persistent_data;
+
+    mock_init_data.called++;
+    mock_init_data.lifetime = lifetime;
+    return( mock_init_data.return_value );
+}
+
 static psa_status_t mock_generate( psa_drv_se_context_t *drv_context,
                                    psa_key_slot_number_t key_slot,
                                    const psa_key_attributes_t *attributes,
@@ -259,6 +279,42 @@
  */
 
 /* BEGIN_CASE */
+void mock_init( int lifetime_arg,
+                int expected_register_status_arg,
+                int driver_status_arg,
+                int expected_psa_status_arg,
+                int expected_called )
+{
+    psa_key_lifetime_t lifetime = lifetime_arg;
+    psa_status_t expected_register_status = expected_register_status_arg;
+    psa_status_t driver_status = driver_status_arg;
+    psa_status_t expected_psa_status = expected_psa_status_arg;
+    psa_drv_se_t driver = {
+        .hal_version = PSA_DRV_SE_HAL_VERSION,
+        .p_init = mock_init,
+    };
+    int psa_crypto_init_called = 0;
+
+    mock_init_data.return_value = driver_status;
+
+    TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
+                expected_register_status );
+
+    psa_crypto_init_called = 1;
+    TEST_EQUAL( psa_crypto_init( ), expected_psa_status );
+
+    TEST_EQUAL( mock_init_data.called, expected_called );
+    if( expected_called )
+        TEST_EQUAL( mock_init_data.lifetime, lifetime );
+
+exit:
+    if( psa_crypto_init_called )
+        PSA_DONE( );
+    mock_teardown( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void mock_import( int mock_alloc_return_value,
                   int mock_import_return_value,
                   int bits,
@@ -335,6 +391,7 @@
     memset( &key_management, 0, sizeof( key_management ) );
     driver.hal_version = PSA_DRV_SE_HAL_VERSION;
     driver.key_management = &key_management;
+    driver.p_init = mock_init;
     key_management.p_import = mock_import;
     key_management.p_export = mock_export;
     key_management.p_destroy = mock_destroy;