Merge pull request #8075 from valeriosetti/issue8016

driver-only ECC: curve acceleration macros
diff --git a/.travis.yml b/.travis.yml
index d020394..3b4132e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,9 @@
 # Declare python as our language. This way we get our chosen Python version,
 # and pip is available. Gcc and clang are available anyway.
-distro: xenial
+dist: jammy
 os: linux
 language: python
-python: 3.5
+python: 3.10
 
 cache: ccache
 
@@ -11,6 +11,9 @@
   only:
     coverity_scan
 
+install:
+  - $PYTHON scripts/min_requirements.py
+
 env:
   global:
     - SEED=1
diff --git a/3rdparty/p256-m/p256-m_driver_entrypoints.c b/3rdparty/p256-m/p256-m_driver_entrypoints.c
index 7709301..61310a8 100644
--- a/3rdparty/p256-m/p256-m_driver_entrypoints.c
+++ b/3rdparty/p256-m/p256-m_driver_entrypoints.c
@@ -22,9 +22,9 @@
 #include "p256-m_driver_entrypoints.h"
 #include "p256-m/p256-m.h"
 #include "psa/crypto.h"
-#include "psa_crypto_driver_wrappers.h"
 #include <stddef.h>
 #include <string.h>
+#include "psa_crypto_driver_wrappers_no_static.h"
 
 #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)
 
diff --git a/ChangeLog.d/updated_windows_apis.txt b/ChangeLog.d/updated_windows_apis.txt
new file mode 100644
index 0000000..73b17df
--- /dev/null
+++ b/ChangeLog.d/updated_windows_apis.txt
@@ -0,0 +1,9 @@
+Requirement changes
+   * Minimum required Windows version is now Windows Vista, or
+     Windows Server 2008.
+
+Changes
+   * Update Windows code to use BCryptGenRandom and wcslen, and
+     ensure that conversions between size_t, ULONG, and int are
+     always done safely.  Original contribution by Kevin Kane #635, #730
+     followed by Simon Butcher #1453.
diff --git a/docs/architecture/psa-crypto-implementation-structure.md b/docs/architecture/psa-crypto-implementation-structure.md
index a5aac40..d7e4f9c 100644
--- a/docs/architecture/psa-crypto-implementation-structure.md
+++ b/docs/architecture/psa-crypto-implementation-structure.md
@@ -49,7 +49,7 @@
 ```
 The code of most PSA APIs is expected to match precisely the above layout. However, it is likely that the code structure of some APIs will be more complicated with several calls to the driver interface, mainly to encompass a larger variety of hardware designs. For example, to encompass hardware accelerators that are capable of verifying a MAC and those that are only capable of computing a MAC, the psa_mac_verify() API could call first psa_driver_wrapper_mac_verify() and then fallback to psa_driver_wrapper_mac_compute().
 
-The implementations of `psa_driver_wrapper_<entry_point>` functions are generated by the build system based on the JSON driver description files of the various PSA drivers making up the Mbed TLS PSA Cryptography API implementation. The implementations are generated in a psa_crypto_driver_wrappers.c C file and the function prototypes declared in a psa_crypto_driver_wrappers.h header file.
+The implementations of `psa_driver_wrapper_<entry_point>` functions are generated by the build system based on the JSON driver description files of the various PSA drivers making up the Mbed TLS PSA Cryptography API implementation. The implementations are splited into two parts. The static ones are generated in a psa_crypto_driver_wrappers.h header file, the non-static ones are generated in a psa_crypto_driver_wrappers_no_static.c C file and the function prototypes declared in a psa_crypto_driver_wrappers_no_static.h header file.
 
 The psa_driver_wrapper_<entry_point>() functions dispatch cryptographic operations to accelerator drivers, secure element drivers as well as to the software implementations of cryptographic operations.
 
@@ -139,7 +139,7 @@
 The general structure of a cryptographic operation function is:
 
 1. API function defined in `library/psa_crypto.c`. The entry point performs generic checks that don't depend on whether the mechanism is implemented in software or in a driver and looks up keys in the key store.
-2. Driver dispatch code in `scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja` or files included from there.
+2. Driver dispatch code in `scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja`, `scripts/data_files/driver_templates/psa_crypto_driver_wrappers_no_static.c.jinja` or files included from there.
 3. Built-in implementation in `library/psa_crypto_*.c` (with function declarations in the corresponding `.h` file). These files typically contain the implementation of modes of operation over basic building blocks that are defined elsewhere. For example, HMAC is implemented in `library/psa_crypto_mac.c` but the underlying hash functions are implemented in `library/sha*.c` and `library/md*.c`.
 4. Basic cryptographic building blocks in `library/*.c`.
 
diff --git a/docs/proposed/psa-driver-wrappers-codegen-migration-guide.md b/docs/proposed/psa-driver-wrappers-codegen-migration-guide.md
index 67157e5..8875921 100644
--- a/docs/proposed/psa-driver-wrappers-codegen-migration-guide.md
+++ b/docs/proposed/psa-driver-wrappers-codegen-migration-guide.md
@@ -1,7 +1,7 @@
-Migrating to an auto generated psa_crypto_driver_wrappers.c file
+Migrating to an auto generated psa_crypto_driver_wrappers.h file
 ================================================================
 
-This document describes how to migrate to the auto generated psa_crypto_driver_wrappers.c file.
+This document describes how to migrate to the auto generated psa_crypto_driver_wrappers.h file.
 It is meant to give the library user migration guidelines while the Mbed TLS project tides over multiple minor revs of version 1.0, after which this will be merged into psa-driver-interface.md.
 
 For a practical guide with a description of the current state of drivers Mbed TLS, see our [PSA Cryptoprocessor driver development examples](../psa-driver-example-and-guide.html).
@@ -27,10 +27,10 @@
 
 #### What's changed
 
-(1) psa_crypto_driver_wrappers.c will from this point on be auto generated.
-(2) The auto generation is based on the template file at **scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja**.
-(3) The driver JSONS to be used for generating the psa_crypto_driver_wrappers.c file can be found at **scripts/data_files/driver_jsons/** as their default location, this path includes the schemas against which the driver schemas will be validated (driver_opaque_schema.json, driver_transparent_schema.json) and a driverlist.json which specifies the drivers to be considered and the order in which they want to be called into. The default location for driverlist.json and driver JSONS can be overloaded by passing an argument --json-dir while running the script generate_driver_wrappers.py.
-(4) While the complete driver wrapper templating support is yet to come in, if the library user sees a need to patch psa_crypto_driver_wrappers.c file, the user will need to patch into the template file as needed (psa_crypto_driver_wrappers.c.jinja).
+(1) psa_crypto_driver_wrappers.h will from this point on be auto generated.
+(2) The auto generation is based on the template file at **scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja**.
+(3) The driver JSONS to be used for generating the psa_crypto_driver_wrappers.h file can be found at **scripts/data_files/driver_jsons/** as their default location, this path includes the schemas against which the driver schemas will be validated (driver_opaque_schema.json, driver_transparent_schema.json) and a driverlist.json which specifies the drivers to be considered and the order in which they want to be called into. The default location for driverlist.json and driver JSONS can be overloaded by passing an argument --json-dir while running the script generate_driver_wrappers.py.
+(4) While the complete driver wrapper templating support is yet to come in, if the library user sees a need to patch psa_crypto_driver_wrappers.h file, the user will need to patch into the template file as needed (psa_crypto_driver_wrappers.h.jinja).
 
 #### How to set your driver up
 
diff --git a/docs/psa-driver-example-and-guide.md b/docs/psa-driver-example-and-guide.md
index eb100d7..8bda60f 100644
--- a/docs/psa-driver-example-and-guide.md
+++ b/docs/psa-driver-example-and-guide.md
@@ -74,7 +74,7 @@
 
 
 **4. For each operation being accelerated, locate the function in the driver dispatch layer that corresponds to the entry point of that operation.** \
-The file `psa_crypto_driver_wrappers.c.jinja` contains the driver wrapper functions. For the entry points that have driver wrapper auto-generation implemented, the functions have been replaced with `jinja` templating logic. While the file has a `.jinja` extension, the driver wrapper functions for the remaining entry points are simple C functions. The names of these functions are of the form `psa_driver_wrapper` followed by the entry point name. So, for example, the function `psa_driver_wrapper_sign_hash()` corresponds to the `sign_hash` entry point.
+The file `psa_crypto_driver_wrappers.h.jinja` and `psa_crypto_driver_wrappers_no_static.c.jinja` contains the driver wrapper functions. For the entry points that have driver wrapper auto-generation implemented, the functions have been replaced with `jinja` templating logic. While the file has a `.jinja` extension, the driver wrapper functions for the remaining entry points are simple C functions. The names of these functions are of the form `psa_driver_wrapper` followed by the entry point name. So, for example, the function `psa_driver_wrapper_sign_hash()` corresponds to the `sign_hash` entry point.
 
 **5. If a driver entry point function has been provided then ensure it has the same signature as the driver wrapper function.** \
 If one has not been provided then write one. Its name should begin with the driver prefix, followed by transparent/opaque (depending on driver type), and end with the entry point name. It should have the same signature as the driver wrapper function. The purpose of the entry point function is to take arguments in PSA format for the implemented operation and return outputs/status codes in PSA format. \
@@ -153,7 +153,7 @@
 There are no entry points for `sign_message` and `verify_message`, which are not necessary for a sign-and-hash algorithm. The core still implements these functions by doing the hashes and then calling the sign/verify-hash entry points.
 The driver entry point functions can be found in `p256m_driver_entrypoints.[hc]`. These functions act as an interface between Mbed TLS and p256-m; converting between PSA and p256-m argument formats and performing sanity checks. If the driver's status codes differ from PSA's, it is recommended to implement a status code translation function. The function `p256_to_psa_error()` converts error codes returned by p256-m into PSA error codes.
 
-The driver wrapper functions in `psa_crypto_driver_wrappers.c.jinja` for all four entry points have also been modified. The code block below shows the additions made to `psa_driver_wrapper_sign_hash()`. In adherence to the defined process, all code related to the driver call is placed within a check for `MBEDTLS_PSA_P256M_DRIVER_ENABLED`. p256-m only supports non-deterministic ECDSA using keys based on NIST P256; these constraints are enforced through checks (see the `if` statement). Checks that involve accessing key attributes, (e.g. checking key type or bits) **must** be performed in the driver wrapper. This is because this information is marked private and may not be accessed outside the library. Other checks can be performed here or in the entry point function. The status returned by the driver is propagated up the call hierarchy **unless** the driver does not support the operation (i.e. return `PSA_ERROR_NOT_SUPPORTED`). In that case the next available driver/built-in implementation is called.
+The driver wrapper functions in `psa_crypto_driver_wrappers.h.jinja` for all four entry points have also been modified. The code block below shows the additions made to `psa_driver_wrapper_sign_hash()`. In adherence to the defined process, all code related to the driver call is placed within a check for `MBEDTLS_PSA_P256M_DRIVER_ENABLED`. p256-m only supports non-deterministic ECDSA using keys based on NIST P256; these constraints are enforced through checks (see the `if` statement). Checks that involve accessing key attributes, (e.g. checking key type or bits) **must** be performed in the driver wrapper. This is because this information is marked private and may not be accessed outside the library. Other checks can be performed here or in the entry point function. The status returned by the driver is propagated up the call hierarchy **unless** the driver does not support the operation (i.e. return `PSA_ERROR_NOT_SUPPORTED`). In that case the next available driver/built-in implementation is called.
 
 ```
 #if defined (MBEDTLS_PSA_P256M_DRIVER_ENABLED)
diff --git a/include/psa/crypto_driver_contexts_composites.h b/include/psa/crypto_driver_contexts_composites.h
index 068a193..d018864 100644
--- a/include/psa/crypto_driver_contexts_composites.h
+++ b/include/psa/crypto_driver_contexts_composites.h
@@ -121,7 +121,7 @@
  *
  * The union members are the driver's context structures, and the member names
  * are formatted as `'drivername'_ctx`. This allows for procedural generation
- * of both this file and the content of psa_crypto_driver_wrappers.c */
+ * of both this file and the content of psa_crypto_driver_wrappers.h */
 
 typedef union {
     unsigned dummy; /* Make sure this union is always non-empty */
diff --git a/include/psa/crypto_driver_contexts_primitives.h b/include/psa/crypto_driver_contexts_primitives.h
index 7f81f62..b27a768 100644
--- a/include/psa/crypto_driver_contexts_primitives.h
+++ b/include/psa/crypto_driver_contexts_primitives.h
@@ -94,7 +94,7 @@
  *
  * The union members are the driver's context structures, and the member names
  * are formatted as `'drivername'_ctx`. This allows for procedural generation
- * of both this file and the content of psa_crypto_driver_wrappers.c */
+ * of both this file and the content of psa_crypto_driver_wrappers.h */
 
 typedef union {
     unsigned dummy; /* Make sure this union is always non-empty */
diff --git a/library/.gitignore b/library/.gitignore
index 5a29a43..c6a39f5 100644
--- a/library/.gitignore
+++ b/library/.gitignore
@@ -6,5 +6,6 @@
 /error.c
 /version_features.c
 /ssl_debug_helpers_generated.c
-/psa_crypto_driver_wrappers.c
+/psa_crypto_driver_wrappers.h
+/psa_crypto_driver_wrappers_no_static.c
 ###END_GENERATED_FILES###
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 83204f3..65b957a 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -67,7 +67,7 @@
     psa_crypto_aead.c
     psa_crypto_cipher.c
     psa_crypto_client.c
-    psa_crypto_driver_wrappers.c
+    psa_crypto_driver_wrappers_no_static.c
     psa_crypto_ecp.c
     psa_crypto_ffdh.c
     psa_crypto_hash.c
@@ -174,14 +174,16 @@
 
     add_custom_command(
         OUTPUT
-            ${CMAKE_CURRENT_BINARY_DIR}/psa_crypto_driver_wrappers.c
+            ${CMAKE_CURRENT_BINARY_DIR}/psa_crypto_driver_wrappers.h
+            ${CMAKE_CURRENT_BINARY_DIR}/psa_crypto_driver_wrappers_no_static.c
         COMMAND
             ${MBEDTLS_PYTHON_EXECUTABLE}
                 ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_driver_wrappers.py
                 ${CMAKE_CURRENT_BINARY_DIR}
         DEPENDS
             ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_driver_wrappers.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja
+            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja
+            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files/driver_templates/psa_crypto_driver_wrappers_no_static.c.jinja
     )
 
 
@@ -189,7 +191,7 @@
     link_to_source(error.c)
     link_to_source(version_features.c)
     link_to_source(ssl_debug_helpers_generated.c)
-    link_to_source(psa_crypto_driver_wrappers.c)
+    link_to_source(psa_crypto_driver_wrappers_no_static.c)
 endif()
 
 if(CMAKE_COMPILER_IS_GNUCC)
@@ -213,7 +215,7 @@
 endif()
 
 if(WIN32)
-    set(libs ${libs} ws2_32)
+    set(libs ${libs} ws2_32 bcrypt)
 endif(WIN32)
 
 if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
diff --git a/library/Makefile b/library/Makefile
index 69ccbfd..a5b1ef0 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -39,6 +39,10 @@
 endif
 endif
 
+ifdef WINDOWS_BUILD
+LOCAL_LDFLAGS += -lbcrypt
+endif
+
 # To compile as a shared library:
 ifdef SHARED
 # all code is position-indep with mingw, avoid warning about useless flag
@@ -132,7 +136,7 @@
 	     psa_crypto_aead.o \
 	     psa_crypto_cipher.o \
 	     psa_crypto_client.o \
-	     psa_crypto_driver_wrappers.o \
+	     psa_crypto_driver_wrappers_no_static.o \
 	     psa_crypto_ecp.o \
 	     psa_crypto_ffdh.o \
 	     psa_crypto_hash.o \
@@ -312,7 +316,8 @@
 GENERATED_FILES = \
 	error.c version_features.c \
 	ssl_debug_helpers_generated.c \
-        psa_crypto_driver_wrappers.c
+	psa_crypto_driver_wrappers.h \
+	psa_crypto_driver_wrappers_no_static.c
 generated_files: $(GENERATED_FILES)
 
 # See root Makefile
@@ -348,12 +353,18 @@
 	echo "  Gen   $@"
 	$(PERL) ../scripts/generate_features.pl
 
-psa_crypto_driver_wrappers.c: $(gen_file_dep) ../scripts/generate_driver_wrappers.py
-psa_crypto_driver_wrappers.c: $(gen_file_dep) ../scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja
-psa_crypto_driver_wrappers.c:
-	echo "  Gen   $@"
+GENERATED_WRAPPER_FILES = \
+                    psa_crypto_driver_wrappers.h \
+                    psa_crypto_driver_wrappers_no_static.c
+$(GENERATED_WRAPPER_FILES): ../scripts/generate_driver_wrappers.py
+$(GENERATED_WRAPPER_FILES): ../scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja
+$(GENERATED_WRAPPER_FILES): ../scripts/data_files/driver_templates/psa_crypto_driver_wrappers_no_static.c.jinja
+$(GENERATED_WRAPPER_FILES):
+	echo "  Gen   $(GENERATED_WRAPPER_FILES)"
 	$(PYTHON) ../scripts/generate_driver_wrappers.py
 
+psa_crypto.o:psa_crypto_driver_wrappers.h
+
 clean:
 ifndef WINDOWS
 	rm -f *.o libmbed*
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
index bc71307..9d5b1e6 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
@@ -49,34 +49,35 @@
 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
 
 #include <windows.h>
-#if _WIN32_WINNT >= 0x0501 /* _WIN32_WINNT_WINXP */
-#include <wincrypt.h>
+#include <bcrypt.h>
+#include <intsafe.h>
 
 int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len,
                                   size_t *olen)
 {
-    HCRYPTPROV provider;
     ((void) data);
     *olen = 0;
 
-    if (CryptAcquireContext(&provider, NULL, NULL,
-                            PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) {
-        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
-    }
+    /*
+     * BCryptGenRandom takes ULONG for size, which is smaller than size_t on
+     * 64-bit Windows platforms. Extract entropy in chunks of len (dependent
+     * on ULONG_MAX) size.
+     */
+    while (len != 0) {
+        unsigned long ulong_bytes =
+            (len > ULONG_MAX) ? ULONG_MAX : (unsigned long) len;
 
-    if (CryptGenRandom(provider, (DWORD) len, output) == FALSE) {
-        CryptReleaseContext(provider, 0);
-        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
-    }
+        if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, output, ulong_bytes,
+                                            BCRYPT_USE_SYSTEM_PREFERRED_RNG))) {
+            return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+        }
 
-    CryptReleaseContext(provider, 0);
-    *olen = len;
+        *olen += ulong_bytes;
+        len -= ulong_bytes;
+    }
 
     return 0;
 }
-#else /* !_WIN32_WINNT_WINXP */
-#error "Entropy not available before Windows XP, use MBEDTLS_NO_PLATFORM_ENTROPY"
-#endif /* !_WIN32_WINNT_WINXP */
 #else /* _WIN32 && !EFIX64 && !EFI32 */
 
 /*
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index e6de7f9..1faf1dd 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -34,6 +34,7 @@
 #include "psa_crypto_core.h"
 #include "psa_crypto_invasive.h"
 #include "psa_crypto_driver_wrappers.h"
+#include "psa_crypto_driver_wrappers_no_static.h"
 #include "psa_crypto_ecp.h"
 #include "psa_crypto_ffdh.h"
 #include "psa_crypto_hash.h"
diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h
deleted file mode 100644
index 0d20eaa..0000000
--- a/library/psa_crypto_driver_wrappers.h
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- *  Function signatures for functionality that can be provided by
- *  cryptographic accelerators.
- */
-/*  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.
- */
-
-#ifndef PSA_CRYPTO_DRIVER_WRAPPERS_H
-#define PSA_CRYPTO_DRIVER_WRAPPERS_H
-
-#include "psa/crypto.h"
-#include "psa/crypto_driver_common.h"
-
-#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)
-#include "../3rdparty/p256-m/p256-m_driver_entrypoints.h"
-#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */
-
-/*
- * Initialization and termination functions
- */
-psa_status_t psa_driver_wrapper_init(void);
-void psa_driver_wrapper_free(void);
-
-/*
- * Signature functions
- */
-psa_status_t psa_driver_wrapper_sign_message(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer,
-    size_t key_buffer_size,
-    psa_algorithm_t alg,
-    const uint8_t *input,
-    size_t input_length,
-    uint8_t *signature,
-    size_t signature_size,
-    size_t *signature_length);
-
-psa_status_t psa_driver_wrapper_verify_message(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer,
-    size_t key_buffer_size,
-    psa_algorithm_t alg,
-    const uint8_t *input,
-    size_t input_length,
-    const uint8_t *signature,
-    size_t signature_length);
-
-psa_status_t psa_driver_wrapper_sign_hash(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer, size_t key_buffer_size,
-    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
-    uint8_t *signature, size_t signature_size, size_t *signature_length);
-
-psa_status_t psa_driver_wrapper_verify_hash(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer, size_t key_buffer_size,
-    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
-    const uint8_t *signature, size_t signature_length);
-
-/*
- * Interruptible Signature functions
- */
-
-uint32_t psa_driver_wrapper_sign_hash_get_num_ops(
-    psa_sign_hash_interruptible_operation_t *operation);
-
-uint32_t psa_driver_wrapper_verify_hash_get_num_ops(
-    psa_verify_hash_interruptible_operation_t *operation);
-
-psa_status_t psa_driver_wrapper_sign_hash_start(
-    psa_sign_hash_interruptible_operation_t *operation,
-    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
-    size_t key_buffer_size, psa_algorithm_t alg,
-    const uint8_t *hash, size_t hash_length);
-
-psa_status_t psa_driver_wrapper_sign_hash_complete(
-    psa_sign_hash_interruptible_operation_t *operation,
-    uint8_t *signature, size_t signature_size,
-    size_t *signature_length);
-
-psa_status_t psa_driver_wrapper_sign_hash_abort(
-    psa_sign_hash_interruptible_operation_t *operation);
-
-psa_status_t psa_driver_wrapper_verify_hash_start(
-    psa_verify_hash_interruptible_operation_t *operation,
-    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
-    size_t key_buffer_size, psa_algorithm_t alg,
-    const uint8_t *hash, size_t hash_length,
-    const uint8_t *signature, size_t signature_length);
-
-psa_status_t psa_driver_wrapper_verify_hash_complete(
-    psa_verify_hash_interruptible_operation_t *operation);
-
-psa_status_t psa_driver_wrapper_verify_hash_abort(
-    psa_verify_hash_interruptible_operation_t *operation);
-
-/*
- * Key handling functions
- */
-
-psa_status_t psa_driver_wrapper_import_key(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *data, size_t data_length,
-    uint8_t *key_buffer, size_t key_buffer_size,
-    size_t *key_buffer_length, size_t *bits);
-
-psa_status_t psa_driver_wrapper_export_key(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer, size_t key_buffer_size,
-    uint8_t *data, size_t data_size, size_t *data_length);
-
-psa_status_t psa_driver_wrapper_export_public_key(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer, size_t key_buffer_size,
-    uint8_t *data, size_t data_size, size_t *data_length);
-
-psa_status_t psa_driver_wrapper_get_key_buffer_size(
-    const psa_key_attributes_t *attributes,
-    size_t *key_buffer_size);
-
-psa_status_t psa_driver_wrapper_get_key_buffer_size_from_key_data(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *data,
-    size_t data_length,
-    size_t *key_buffer_size);
-
-psa_status_t psa_driver_wrapper_generate_key(
-    const psa_key_attributes_t *attributes,
-    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);
-
-psa_status_t psa_driver_wrapper_get_builtin_key(
-    psa_drv_slot_number_t slot_number,
-    psa_key_attributes_t *attributes,
-    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);
-
-psa_status_t psa_driver_wrapper_copy_key(
-    psa_key_attributes_t *attributes,
-    const uint8_t *source_key, size_t source_key_length,
-    uint8_t *target_key_buffer, size_t target_key_buffer_size,
-    size_t *target_key_buffer_length);
-/*
- * Cipher functions
- */
-psa_status_t psa_driver_wrapper_cipher_encrypt(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer,
-    size_t key_buffer_size,
-    psa_algorithm_t alg,
-    const uint8_t *iv,
-    size_t iv_length,
-    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(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer,
-    size_t key_buffer_size,
-    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,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer, size_t key_buffer_size,
-    psa_algorithm_t alg);
-
-psa_status_t psa_driver_wrapper_cipher_decrypt_setup(
-    psa_cipher_operation_t *operation,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer, size_t key_buffer_size,
-    psa_algorithm_t alg);
-
-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);
-
-/*
- * Hashing functions
- */
-psa_status_t psa_driver_wrapper_hash_compute(
-    psa_algorithm_t alg,
-    const uint8_t *input,
-    size_t input_length,
-    uint8_t *hash,
-    size_t hash_size,
-    size_t *hash_length);
-
-psa_status_t psa_driver_wrapper_hash_setup(
-    psa_hash_operation_t *operation,
-    psa_algorithm_t alg);
-
-psa_status_t psa_driver_wrapper_hash_clone(
-    const psa_hash_operation_t *source_operation,
-    psa_hash_operation_t *target_operation);
-
-psa_status_t psa_driver_wrapper_hash_update(
-    psa_hash_operation_t *operation,
-    const uint8_t *input,
-    size_t input_length);
-
-psa_status_t psa_driver_wrapper_hash_finish(
-    psa_hash_operation_t *operation,
-    uint8_t *hash,
-    size_t hash_size,
-    size_t *hash_length);
-
-psa_status_t psa_driver_wrapper_hash_abort(
-    psa_hash_operation_t *operation);
-
-/*
- * AEAD functions
- */
-
-psa_status_t psa_driver_wrapper_aead_encrypt(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer, size_t key_buffer_size,
-    psa_algorithm_t alg,
-    const uint8_t *nonce, size_t nonce_length,
-    const uint8_t *additional_data, size_t additional_data_length,
-    const uint8_t *plaintext, size_t plaintext_length,
-    uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length);
-
-psa_status_t psa_driver_wrapper_aead_decrypt(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer, size_t key_buffer_size,
-    psa_algorithm_t alg,
-    const uint8_t *nonce, size_t nonce_length,
-    const uint8_t *additional_data, size_t additional_data_length,
-    const uint8_t *ciphertext, size_t ciphertext_length,
-    uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length);
-
-psa_status_t psa_driver_wrapper_aead_encrypt_setup(
-    psa_aead_operation_t *operation,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer, size_t key_buffer_size,
-    psa_algorithm_t alg);
-
-psa_status_t psa_driver_wrapper_aead_decrypt_setup(
-    psa_aead_operation_t *operation,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer, size_t key_buffer_size,
-    psa_algorithm_t alg);
-
-psa_status_t psa_driver_wrapper_aead_set_nonce(
-    psa_aead_operation_t *operation,
-    const uint8_t *nonce,
-    size_t nonce_length);
-
-psa_status_t psa_driver_wrapper_aead_set_lengths(
-    psa_aead_operation_t *operation,
-    size_t ad_length,
-    size_t plaintext_length);
-
-psa_status_t psa_driver_wrapper_aead_update_ad(
-    psa_aead_operation_t *operation,
-    const uint8_t *input,
-    size_t input_length);
-
-psa_status_t psa_driver_wrapper_aead_update(
-    psa_aead_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_aead_finish(
-    psa_aead_operation_t *operation,
-    uint8_t *ciphertext,
-    size_t ciphertext_size,
-    size_t *ciphertext_length,
-    uint8_t *tag,
-    size_t tag_size,
-    size_t *tag_length);
-
-psa_status_t psa_driver_wrapper_aead_verify(
-    psa_aead_operation_t *operation,
-    uint8_t *plaintext,
-    size_t plaintext_size,
-    size_t *plaintext_length,
-    const uint8_t *tag,
-    size_t tag_length);
-
-psa_status_t psa_driver_wrapper_aead_abort(
-    psa_aead_operation_t *operation);
-
-/*
- * MAC functions
- */
-psa_status_t psa_driver_wrapper_mac_compute(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer,
-    size_t key_buffer_size,
-    psa_algorithm_t alg,
-    const uint8_t *input,
-    size_t input_length,
-    uint8_t *mac,
-    size_t mac_size,
-    size_t *mac_length);
-
-psa_status_t psa_driver_wrapper_mac_sign_setup(
-    psa_mac_operation_t *operation,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer,
-    size_t key_buffer_size,
-    psa_algorithm_t alg);
-
-psa_status_t psa_driver_wrapper_mac_verify_setup(
-    psa_mac_operation_t *operation,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer,
-    size_t key_buffer_size,
-    psa_algorithm_t alg);
-
-psa_status_t psa_driver_wrapper_mac_update(
-    psa_mac_operation_t *operation,
-    const uint8_t *input,
-    size_t input_length);
-
-psa_status_t psa_driver_wrapper_mac_sign_finish(
-    psa_mac_operation_t *operation,
-    uint8_t *mac,
-    size_t mac_size,
-    size_t *mac_length);
-
-psa_status_t psa_driver_wrapper_mac_verify_finish(
-    psa_mac_operation_t *operation,
-    const uint8_t *mac,
-    size_t mac_length);
-
-psa_status_t psa_driver_wrapper_mac_abort(
-    psa_mac_operation_t *operation);
-
-/*
- * Asymmetric cryptography
- */
-psa_status_t psa_driver_wrapper_asymmetric_encrypt(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer,
-    size_t key_buffer_size,
-    psa_algorithm_t alg,
-    const uint8_t *input,
-    size_t input_length,
-    const uint8_t *salt,
-    size_t salt_length,
-    uint8_t *output,
-    size_t output_size,
-    size_t *output_length);
-
-psa_status_t psa_driver_wrapper_asymmetric_decrypt(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer,
-    size_t key_buffer_size,
-    psa_algorithm_t alg,
-    const uint8_t *input,
-    size_t input_length,
-    const uint8_t *salt,
-    size_t salt_length,
-    uint8_t *output,
-    size_t output_size,
-    size_t *output_length);
-
-/*
- * Raw Key Agreement
- */
-psa_status_t psa_driver_wrapper_key_agreement(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer,
-    size_t key_buffer_size,
-    psa_algorithm_t alg,
-    const uint8_t *peer_key,
-    size_t peer_key_length,
-    uint8_t *shared_secret,
-    size_t shared_secret_size,
-    size_t *shared_secret_length);
-
-/*
- * PAKE functions.
- */
-psa_status_t psa_driver_wrapper_pake_setup(
-    psa_pake_operation_t *operation,
-    const psa_crypto_driver_pake_inputs_t *inputs);
-
-psa_status_t psa_driver_wrapper_pake_output(
-    psa_pake_operation_t *operation,
-    psa_crypto_driver_pake_step_t step,
-    uint8_t *output,
-    size_t output_size,
-    size_t *output_length);
-
-psa_status_t psa_driver_wrapper_pake_input(
-    psa_pake_operation_t *operation,
-    psa_crypto_driver_pake_step_t step,
-    const uint8_t *input,
-    size_t input_length);
-
-psa_status_t psa_driver_wrapper_pake_get_implicit_key(
-    psa_pake_operation_t *operation,
-    uint8_t *output, size_t output_size,
-    size_t *output_length);
-
-psa_status_t psa_driver_wrapper_pake_abort(
-    psa_pake_operation_t *operation);
-
-#endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */
-
-/* End of automatically generated file. */
diff --git a/library/psa_crypto_driver_wrappers_no_static.h b/library/psa_crypto_driver_wrappers_no_static.h
new file mode 100644
index 0000000..4985403
--- /dev/null
+++ b/library/psa_crypto_driver_wrappers_no_static.h
@@ -0,0 +1,43 @@
+/*
+ *  Function signatures for functionality that can be provided by
+ *  cryptographic accelerators.
+ */
+/*  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.
+ */
+
+#ifndef PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H
+#define PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H
+
+#include "psa/crypto.h"
+#include "psa/crypto_driver_common.h"
+
+psa_status_t psa_driver_wrapper_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    uint8_t *data, size_t data_size, size_t *data_length);
+
+psa_status_t psa_driver_wrapper_get_key_buffer_size(
+    const psa_key_attributes_t *attributes,
+    size_t *key_buffer_size);
+
+psa_status_t psa_driver_wrapper_get_builtin_key(
+    psa_drv_slot_number_t slot_number,
+    psa_key_attributes_t *attributes,
+    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);
+
+#endif /* PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H */
+
+/* End of automatically generated file. */
diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c
index ef285ac..92646c0 100644
--- a/library/psa_crypto_slot_management.c
+++ b/library/psa_crypto_slot_management.c
@@ -25,7 +25,7 @@
 #include "psa/crypto.h"
 
 #include "psa_crypto_core.h"
-#include "psa_crypto_driver_wrappers.h"
+#include "psa_crypto_driver_wrappers_no_static.h"
 #include "psa_crypto_slot_management.h"
 #include "psa_crypto_storage.h"
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 8d07694..e9153e7 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1535,7 +1535,6 @@
 {
     int ret = 0;
 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
-#if _WIN32_WINNT >= 0x0501 /* _WIN32_WINNT_XP */
     int w_ret;
     WCHAR szDir[MAX_PATH];
     char filename[MAX_PATH];
@@ -1556,6 +1555,11 @@
     p = filename + len;
     filename[len++] = '*';
 
+    /*
+     * Note this function uses the code page CP_ACP which is the system default
+     * ANSI codepage. The input string is always described in BYTES and the
+     * output length is described in WCHARs.
+     */
     w_ret = MultiByteToWideChar(CP_ACP, 0, filename, (int) len, szDir,
                                 MAX_PATH - 3);
     if (w_ret == 0) {
@@ -1574,11 +1578,8 @@
         if (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
             continue;
         }
-
         w_ret = WideCharToMultiByte(CP_ACP, 0, file_data.cFileName,
-                                    -1,
-                                    p, (int) len,
-                                    NULL, NULL);
+                                    -1, p, (int) len, NULL, NULL);
         if (w_ret == 0) {
             ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
             goto cleanup;
@@ -1598,9 +1599,6 @@
 
 cleanup:
     FindClose(hFind);
-#else /* !_WIN32_WINNT_XP */
-#error "mbedtls_x509_crt_parse_path not available before Windows XP"
-#endif /* !_WIN32_WINNT_XP */
 #else /* _WIN32 */
     int t_ret;
     int snp_ret;
diff --git a/programs/Makefile b/programs/Makefile
index 5f47e25..80637e9 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -45,7 +45,7 @@
 ifdef WINDOWS_BUILD
 DLEXT=dll
 EXEXT=.exe
-LOCAL_LDFLAGS += -lws2_32
+LOCAL_LDFLAGS += -lws2_32 -lbcrypt
 ifdef SHARED
 SHARED_SUFFIX=.$(DLEXT)
 endif
diff --git a/programs/fuzz/Makefile b/programs/fuzz/Makefile
index 8477aa8..b4fc76a 100644
--- a/programs/fuzz/Makefile
+++ b/programs/fuzz/Makefile
@@ -27,6 +27,10 @@
 LOCAL_LDFLAGS += -lFuzzingEngine
 endif
 
+ifdef WINDOWS_BUILD
+LOCAL_LDFLAGS += -lbcrypt
+endif
+
 # A test application is built for each suites/test_suite_*.data file.
 # Application name is same as .data file's base name and can be
 # constructed by stripping path 'suites/' and extension .data.
diff --git a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja
similarity index 92%
rename from scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja
rename to scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja
index 6354061..3d116b3 100644
--- a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja
+++ b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja
@@ -25,7 +25,7 @@
 #include "psa_crypto_aead.h"
 #include "psa_crypto_cipher.h"
 #include "psa_crypto_core.h"
-#include "psa_crypto_driver_wrappers.h"
+#include "psa_crypto_driver_wrappers_no_static.h"
 #include "psa_crypto_hash.h"
 #include "psa_crypto_mac.h"
 #include "psa_crypto_pake.h"
@@ -82,7 +82,7 @@
 #include "psa_crypto_se.h"
 #endif
 
-psa_status_t psa_driver_wrapper_init( void )
+static inline psa_status_t psa_driver_wrapper_init( void )
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
@@ -106,7 +106,7 @@
     return( PSA_SUCCESS );
 }
 
-void psa_driver_wrapper_free( void )
+static inline void psa_driver_wrapper_free( void )
 {
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
     /* Unregister all secure element drivers, so that we restart from
@@ -121,7 +121,7 @@
 }
 
 /* Start delegation functions */
-psa_status_t psa_driver_wrapper_sign_message(
+static inline psa_status_t psa_driver_wrapper_sign_message(
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer,
     size_t key_buffer_size,
@@ -196,7 +196,7 @@
                                       signature_length ) );
 }
 
-psa_status_t psa_driver_wrapper_verify_message(
+static inline psa_status_t psa_driver_wrapper_verify_message(
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer,
     size_t key_buffer_size,
@@ -267,7 +267,7 @@
                                         signature_length ) );
 }
 
-psa_status_t psa_driver_wrapper_sign_hash(
+static inline psa_status_t psa_driver_wrapper_sign_hash(
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer, size_t key_buffer_size,
     psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
@@ -371,7 +371,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_verify_hash(
+static inline psa_status_t psa_driver_wrapper_verify_hash(
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer, size_t key_buffer_size,
     psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
@@ -472,7 +472,7 @@
     }
 }
 
-uint32_t psa_driver_wrapper_sign_hash_get_num_ops(
+static inline uint32_t psa_driver_wrapper_sign_hash_get_num_ops(
     psa_sign_hash_interruptible_operation_t *operation )
 {
     switch( operation->id )
@@ -495,7 +495,7 @@
     return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-uint32_t psa_driver_wrapper_verify_hash_get_num_ops(
+static inline uint32_t psa_driver_wrapper_verify_hash_get_num_ops(
     psa_verify_hash_interruptible_operation_t *operation )
 {
     switch( operation->id )
@@ -519,7 +519,7 @@
     return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-psa_status_t psa_driver_wrapper_sign_hash_start(
+static inline psa_status_t psa_driver_wrapper_sign_hash_start(
     psa_sign_hash_interruptible_operation_t *operation,
     const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
     size_t key_buffer_size, psa_algorithm_t alg,
@@ -572,7 +572,7 @@
         return( status );
 }
 
-psa_status_t psa_driver_wrapper_sign_hash_complete(
+static inline psa_status_t psa_driver_wrapper_sign_hash_complete(
     psa_sign_hash_interruptible_operation_t *operation,
     uint8_t *signature, size_t signature_size,
     size_t *signature_length )
@@ -599,7 +599,7 @@
     return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-psa_status_t psa_driver_wrapper_sign_hash_abort(
+static inline psa_status_t psa_driver_wrapper_sign_hash_abort(
     psa_sign_hash_interruptible_operation_t *operation )
 {
     switch( operation->id )
@@ -618,7 +618,7 @@
     return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-psa_status_t psa_driver_wrapper_verify_hash_start(
+static inline psa_status_t psa_driver_wrapper_verify_hash_start(
     psa_verify_hash_interruptible_operation_t *operation,
     const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
     size_t key_buffer_size, psa_algorithm_t alg,
@@ -676,7 +676,7 @@
     return( status );
 }
 
-psa_status_t psa_driver_wrapper_verify_hash_complete(
+static inline psa_status_t psa_driver_wrapper_verify_hash_complete(
     psa_verify_hash_interruptible_operation_t *operation )
 {
     switch( operation->id )
@@ -697,7 +697,7 @@
     return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-psa_status_t psa_driver_wrapper_verify_hash_abort(
+static inline psa_status_t psa_driver_wrapper_verify_hash_abort(
     psa_verify_hash_interruptible_operation_t *operation )
 {
     switch( operation->id )
@@ -729,7 +729,7 @@
  * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
  * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
  */
-psa_status_t psa_driver_wrapper_get_key_buffer_size_from_key_data(
+static inline psa_status_t psa_driver_wrapper_get_key_buffer_size_from_key_data(
     const psa_key_attributes_t *attributes,
     const uint8_t *data,
     size_t data_length,
@@ -758,58 +758,7 @@
     }
 }
 
-/** Get the key buffer size required to store the key material of a key
- *  associated with an opaque driver.
- *
- * \param[in] attributes  The key attributes.
- * \param[out] key_buffer_size  Minimum buffer size to contain the key material
- *
- * \retval #PSA_SUCCESS
- *         The minimum size for a buffer to contain the key material has been
- *         returned successfully.
- * \retval #PSA_ERROR_NOT_SUPPORTED
- *         The type and/or the size in bits of the key or the combination of
- *         the two is not supported.
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         The key is declared with a lifetime not known to us.
- */
-psa_status_t psa_driver_wrapper_get_key_buffer_size(
-    const psa_key_attributes_t *attributes,
-    size_t *key_buffer_size )
-{
-    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
-    psa_key_type_t key_type = attributes->core.type;
-    size_t key_bits = attributes->core.bits;
-
-    *key_buffer_size = 0;
-    switch( location )
-    {
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
-#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
-            /* Emulate property 'builtin_key_size' */
-            if( psa_key_id_is_builtin(
-                    MBEDTLS_SVC_KEY_ID_GET_KEY_ID(
-                        psa_get_key_id( attributes ) ) ) )
-            {
-                *key_buffer_size = sizeof( psa_drv_slot_number_t );
-                return( PSA_SUCCESS );
-            }
-#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
-            *key_buffer_size = mbedtls_test_opaque_size_function( key_type,
-                                                                  key_bits );
-            return( ( *key_buffer_size != 0 ) ?
-                    PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_TEST */
-
-        default:
-            (void)key_type;
-            (void)key_bits;
-            return( PSA_ERROR_INVALID_ARGUMENT );
-    }
-}
-
-psa_status_t psa_driver_wrapper_generate_key(
+static inline psa_status_t psa_driver_wrapper_generate_key(
     const psa_key_attributes_t *attributes,
     uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
 {
@@ -895,7 +844,7 @@
     return( status );
 }
 
-psa_status_t psa_driver_wrapper_import_key(
+static inline psa_status_t psa_driver_wrapper_import_key(
     const psa_key_attributes_t *attributes,
     const uint8_t *data,
     size_t data_length,
@@ -976,7 +925,7 @@
 {% endwith %}
 }
 
-psa_status_t psa_driver_wrapper_export_key(
+static inline psa_status_t psa_driver_wrapper_export_key(
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer, size_t key_buffer_size,
     uint8_t *data, size_t data_size, size_t *data_length )
@@ -1038,108 +987,7 @@
 {% endwith %}
 }
 
-psa_status_t psa_driver_wrapper_export_public_key(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key_buffer, size_t key_buffer_size,
-    uint8_t *data, size_t data_size, size_t *data_length )
-
-{
-{% with entry_point = "export_public_key" -%}
-{% macro entry_point_param(driver) -%}
-attributes,
-key_buffer,
-key_buffer_size,
-data,
-data_size,
-data_length
-{% endmacro %}
-    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
-    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(
-                                      psa_get_key_lifetime( attributes ) );
-
-    /* Try dynamically-registered SE interface first */
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    const psa_drv_se_t *drv;
-    psa_drv_se_context_t *drv_context;
-
-    if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) )
-    {
-        if( ( drv->key_management == NULL ) ||
-            ( drv->key_management->p_export_public == NULL ) )
-        {
-            return( PSA_ERROR_NOT_SUPPORTED );
-        }
-
-        return( drv->key_management->p_export_public(
-                    drv_context,
-                    *( (psa_key_slot_number_t *)key_buffer ),
-                    data, data_size, data_length ) );
-    }
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
-
-    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_ACCELERATOR_DRIVER_PRESENT)
-{% with nest_indent=12 %}
-{% include "OS-template-transparent.jinja" -%}
-{% endwith -%}
-#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
-            /* Fell through, meaning no accelerator supports this operation */
-            return( psa_export_public_key_internal( attributes,
-                                                    key_buffer,
-                                                    key_buffer_size,
-                                                    data,
-                                                    data_size,
-                                                    data_length ) );
-
-        /* Add cases for opaque driver here */
-#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
-{% with nest_indent=8 %}
-{% include "OS-template-opaque.jinja" -%}
-{% endwith -%}
-#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
-        default:
-            /* Key is declared with a lifetime not known to us */
-            return( status );
-    }
-{% endwith %}
-}
-
-psa_status_t psa_driver_wrapper_get_builtin_key(
-    psa_drv_slot_number_t slot_number,
-    psa_key_attributes_t *attributes,
-    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
-{
-{% with entry_point = "get_builtin_key" -%}
-{% macro entry_point_param(driver) -%}
-slot_number,
-attributes,
-key_buffer,
-key_buffer_size,
-key_buffer_length
-{% endmacro %}
-    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
-    switch( location )
-    {
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-{% with nest_indent=8 %}
-{% include "OS-template-opaque.jinja" -%}
-{% endwith -%}
-#endif /* PSA_CRYPTO_DRIVER_TEST */
-        default:
-            (void) slot_number;
-            (void) key_buffer;
-            (void) key_buffer_size;
-            (void) key_buffer_length;
-            return( PSA_ERROR_DOES_NOT_EXIST );
-    }
-{% endwith %}
-}
-
-psa_status_t psa_driver_wrapper_copy_key(
+static inline psa_status_t psa_driver_wrapper_copy_key(
     psa_key_attributes_t *attributes,
     const uint8_t *source_key, size_t source_key_length,
     uint8_t *target_key_buffer, size_t target_key_buffer_size,
@@ -1191,7 +1039,7 @@
 /*
  * Cipher functions
  */
-psa_status_t psa_driver_wrapper_cipher_encrypt(
+static inline psa_status_t psa_driver_wrapper_cipher_encrypt(
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer,
     size_t key_buffer_size,
@@ -1283,7 +1131,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_cipher_decrypt(
+static inline psa_status_t psa_driver_wrapper_cipher_decrypt(
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer,
     size_t key_buffer_size,
@@ -1365,7 +1213,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_cipher_encrypt_setup(
+static inline psa_status_t psa_driver_wrapper_cipher_encrypt_setup(
     psa_cipher_operation_t *operation,
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer, size_t key_buffer_size,
@@ -1438,7 +1286,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_cipher_decrypt_setup(
+static inline psa_status_t psa_driver_wrapper_cipher_decrypt_setup(
     psa_cipher_operation_t *operation,
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer, size_t key_buffer_size,
@@ -1511,7 +1359,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_cipher_set_iv(
+static inline psa_status_t psa_driver_wrapper_cipher_set_iv(
     psa_cipher_operation_t *operation,
     const uint8_t *iv,
     size_t iv_length )
@@ -1546,7 +1394,7 @@
     return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-psa_status_t psa_driver_wrapper_cipher_update(
+static inline psa_status_t psa_driver_wrapper_cipher_update(
     psa_cipher_operation_t *operation,
     const uint8_t *input,
     size_t input_length,
@@ -1592,7 +1440,7 @@
     return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-psa_status_t psa_driver_wrapper_cipher_finish(
+static inline psa_status_t psa_driver_wrapper_cipher_finish(
     psa_cipher_operation_t *operation,
     uint8_t *output,
     size_t output_size,
@@ -1630,7 +1478,7 @@
     return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-psa_status_t psa_driver_wrapper_cipher_abort(
+static inline psa_status_t psa_driver_wrapper_cipher_abort(
     psa_cipher_operation_t *operation )
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
@@ -1670,7 +1518,7 @@
 /*
  * Hashing functions
  */
-psa_status_t psa_driver_wrapper_hash_compute(
+static inline psa_status_t psa_driver_wrapper_hash_compute(
     psa_algorithm_t alg,
     const uint8_t *input,
     size_t input_length,
@@ -1706,7 +1554,7 @@
     return( PSA_ERROR_NOT_SUPPORTED );
 }
 
-psa_status_t psa_driver_wrapper_hash_setup(
+static inline psa_status_t psa_driver_wrapper_hash_setup(
     psa_hash_operation_t *operation,
     psa_algorithm_t alg )
 {
@@ -1739,7 +1587,7 @@
     return( PSA_ERROR_NOT_SUPPORTED );
 }
 
-psa_status_t psa_driver_wrapper_hash_clone(
+static inline psa_status_t psa_driver_wrapper_hash_clone(
     const psa_hash_operation_t *source_operation,
     psa_hash_operation_t *target_operation )
 {
@@ -1764,7 +1612,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_hash_update(
+static inline psa_status_t psa_driver_wrapper_hash_update(
     psa_hash_operation_t *operation,
     const uint8_t *input,
     size_t input_length )
@@ -1789,7 +1637,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_hash_finish(
+static inline psa_status_t psa_driver_wrapper_hash_finish(
     psa_hash_operation_t *operation,
     uint8_t *hash,
     size_t hash_size,
@@ -1816,7 +1664,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_hash_abort(
+static inline psa_status_t psa_driver_wrapper_hash_abort(
     psa_hash_operation_t *operation )
 {
     switch( operation->id )
@@ -1835,7 +1683,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_aead_encrypt(
+static inline psa_status_t psa_driver_wrapper_aead_encrypt(
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer, size_t key_buffer_size,
     psa_algorithm_t alg,
@@ -1887,7 +1735,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_aead_decrypt(
+static inline psa_status_t psa_driver_wrapper_aead_decrypt(
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer, size_t key_buffer_size,
     psa_algorithm_t alg,
@@ -1939,7 +1787,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_aead_encrypt_setup(
+static inline psa_status_t psa_driver_wrapper_aead_encrypt_setup(
    psa_aead_operation_t *operation,
    const psa_key_attributes_t *attributes,
    const uint8_t *key_buffer, size_t key_buffer_size,
@@ -1987,7 +1835,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_aead_decrypt_setup(
+static inline psa_status_t psa_driver_wrapper_aead_decrypt_setup(
    psa_aead_operation_t *operation,
    const psa_key_attributes_t *attributes,
    const uint8_t *key_buffer, size_t key_buffer_size,
@@ -2037,7 +1885,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_aead_set_nonce(
+static inline psa_status_t psa_driver_wrapper_aead_set_nonce(
    psa_aead_operation_t *operation,
    const uint8_t *nonce,
    size_t nonce_length )
@@ -2071,7 +1919,7 @@
     return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-psa_status_t psa_driver_wrapper_aead_set_lengths(
+static inline psa_status_t psa_driver_wrapper_aead_set_lengths(
    psa_aead_operation_t *operation,
    size_t ad_length,
    size_t plaintext_length )
@@ -2105,7 +1953,7 @@
     return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-psa_status_t psa_driver_wrapper_aead_update_ad(
+static inline psa_status_t psa_driver_wrapper_aead_update_ad(
    psa_aead_operation_t *operation,
    const uint8_t *input,
    size_t input_length )
@@ -2139,7 +1987,7 @@
     return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-psa_status_t psa_driver_wrapper_aead_update(
+static inline psa_status_t psa_driver_wrapper_aead_update(
    psa_aead_operation_t *operation,
    const uint8_t *input,
    size_t input_length,
@@ -2181,7 +2029,7 @@
     return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-psa_status_t psa_driver_wrapper_aead_finish(
+static inline psa_status_t psa_driver_wrapper_aead_finish(
    psa_aead_operation_t *operation,
    uint8_t *ciphertext,
    size_t ciphertext_size,
@@ -2226,7 +2074,7 @@
     return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-psa_status_t psa_driver_wrapper_aead_verify(
+static inline psa_status_t psa_driver_wrapper_aead_verify(
    psa_aead_operation_t *operation,
    uint8_t *plaintext,
    size_t plaintext_size,
@@ -2289,7 +2137,7 @@
     return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-psa_status_t psa_driver_wrapper_aead_abort(
+static inline psa_status_t psa_driver_wrapper_aead_abort(
    psa_aead_operation_t *operation )
 {
     switch( operation->id )
@@ -2318,7 +2166,7 @@
 /*
  * MAC functions
  */
-psa_status_t psa_driver_wrapper_mac_compute(
+static inline psa_status_t psa_driver_wrapper_mac_compute(
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer,
     size_t key_buffer_size,
@@ -2386,7 +2234,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_mac_sign_setup(
+static inline psa_status_t psa_driver_wrapper_mac_sign_setup(
     psa_mac_operation_t *operation,
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer,
@@ -2458,7 +2306,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_mac_verify_setup(
+static inline psa_status_t psa_driver_wrapper_mac_verify_setup(
     psa_mac_operation_t *operation,
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer,
@@ -2530,7 +2378,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_mac_update(
+static inline psa_status_t psa_driver_wrapper_mac_update(
     psa_mac_operation_t *operation,
     const uint8_t *input,
     size_t input_length )
@@ -2563,7 +2411,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_mac_sign_finish(
+static inline psa_status_t psa_driver_wrapper_mac_sign_finish(
     psa_mac_operation_t *operation,
     uint8_t *mac,
     size_t mac_size,
@@ -2598,7 +2446,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_mac_verify_finish(
+static inline psa_status_t psa_driver_wrapper_mac_verify_finish(
     psa_mac_operation_t *operation,
     const uint8_t *mac,
     size_t mac_length )
@@ -2631,7 +2479,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_mac_abort(
+static inline psa_status_t psa_driver_wrapper_mac_abort(
     psa_mac_operation_t *operation )
 {
     switch( operation->id )
@@ -2659,7 +2507,7 @@
 /*
  * Asymmetric cryptography
  */
-psa_status_t psa_driver_wrapper_asymmetric_encrypt(
+static inline psa_status_t psa_driver_wrapper_asymmetric_encrypt(
     const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
     size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input,
     size_t input_length, const uint8_t *salt, size_t salt_length,
@@ -2717,7 +2565,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_asymmetric_decrypt(
+static inline psa_status_t psa_driver_wrapper_asymmetric_decrypt(
     const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
     size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input,
     size_t input_length, const uint8_t *salt, size_t salt_length,
@@ -2775,7 +2623,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_key_agreement(
+static inline psa_status_t psa_driver_wrapper_key_agreement(
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer,
     size_t key_buffer_size,
@@ -2786,7 +2634,7 @@
     size_t shared_secret_size,
     size_t *shared_secret_length
  )
- {
+{
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_location_t location =
         PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
@@ -2860,9 +2708,9 @@
             return( PSA_ERROR_NOT_SUPPORTED );
 
     }
- }
+}
 
-psa_status_t psa_driver_wrapper_pake_setup(
+static inline psa_status_t psa_driver_wrapper_pake_setup(
     psa_pake_operation_t *operation,
     const psa_crypto_driver_pake_inputs_t *inputs )
 {
@@ -2905,7 +2753,8 @@
             return( PSA_ERROR_INVALID_ARGUMENT );
     }
 }
-psa_status_t psa_driver_wrapper_pake_output(
+
+static inline psa_status_t psa_driver_wrapper_pake_output(
     psa_pake_operation_t *operation,
     psa_crypto_driver_pake_step_t step,
     uint8_t *output,
@@ -2937,7 +2786,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_pake_input(
+static inline psa_status_t psa_driver_wrapper_pake_input(
     psa_pake_operation_t *operation,
     psa_crypto_driver_pake_step_t step,
     const uint8_t *input,
@@ -2969,7 +2818,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_pake_get_implicit_key(
+static inline psa_status_t psa_driver_wrapper_pake_get_implicit_key(
     psa_pake_operation_t *operation,
     uint8_t *output, size_t output_size,
     size_t *output_length )
@@ -2998,7 +2847,7 @@
     }
 }
 
-psa_status_t psa_driver_wrapper_pake_abort(
+static inline psa_status_t psa_driver_wrapper_pake_abort(
     psa_pake_operation_t * operation )
 {
     switch( operation->id )
diff --git a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers_no_static.c.jinja b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers_no_static.c.jinja
new file mode 100644
index 0000000..dbe424c
--- /dev/null
+++ b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers_no_static.c.jinja
@@ -0,0 +1,236 @@
+/*
+ *  Functions to delegate cryptographic operations to an available
+ *  and appropriate accelerator.
+ *  Warning: This file is now auto-generated.
+ */
+/*  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.
+ */
+
+
+/* BEGIN-common headers */
+#include "common.h"
+#include "psa_crypto_aead.h"
+#include "psa_crypto_cipher.h"
+#include "psa_crypto_core.h"
+#include "psa_crypto_driver_wrappers_no_static.h"
+#include "psa_crypto_hash.h"
+#include "psa_crypto_mac.h"
+#include "psa_crypto_pake.h"
+#include "psa_crypto_rsa.h"
+
+#include "mbedtls/platform.h"
+/* END-common headers */
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+/* BEGIN-driver headers */
+{% for driver in drivers -%}
+/* Headers for {{driver.prefix}} {{driver.type}} driver */
+{% if driver['mbedtls/h_condition'] is defined -%}
+#if {{ driver['mbedtls/h_condition'] }}
+{% endif -%}
+{% for header in driver.headers -%}
+#include "{{ header }}"
+{% endfor %}
+{% if driver['mbedtls/h_condition'] is defined -%}
+#endif
+{% endif -%}
+{% endfor %}
+/* END-driver headers */
+
+/* Auto-generated values depending on which drivers are registered.
+ * ID 0 is reserved for unallocated operations.
+ * ID 1 is reserved for the Mbed TLS software driver. */
+/* BEGIN-driver id definition */
+#define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1)
+{% for driver in drivers -%}
+#define {{(driver.prefix + "_" + driver.type + "_driver_id").upper()}} ({{ loop.index + 1 }})
+{% endfor %}
+/* END-driver id */
+
+/* BEGIN-Common Macro definitions */
+{% macro entry_point_name(capability, entry_point, driver) -%}
+    {% if capability.name is defined and entry_point in capability.names.keys() -%}
+    {{ capability.names[entry_point]}}
+    {% else -%}
+    {{driver.prefix}}_{{driver.type}}_{{entry_point}}
+    {% endif -%}
+{% endmacro %}
+/* END-Common Macro definitions */
+
+/* Support the 'old' SE interface when asked to */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style
+ * SE driver is present, to avoid unused argument errors at compile time. */
+#ifndef PSA_CRYPTO_DRIVER_PRESENT
+#define PSA_CRYPTO_DRIVER_PRESENT
+#endif
+#include "psa_crypto_se.h"
+#endif
+
+/** Get the key buffer size required to store the key material of a key
+ *  associated with an opaque driver.
+ *
+ * \param[in] attributes  The key attributes.
+ * \param[out] key_buffer_size  Minimum buffer size to contain the key material
+ *
+ * \retval #PSA_SUCCESS
+ *         The minimum size for a buffer to contain the key material has been
+ *         returned successfully.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The type and/or the size in bits of the key or the combination of
+ *         the two is not supported.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The key is declared with a lifetime not known to us.
+ */
+psa_status_t psa_driver_wrapper_get_key_buffer_size(
+    const psa_key_attributes_t *attributes,
+    size_t *key_buffer_size )
+{
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
+    psa_key_type_t key_type = attributes->core.type;
+    size_t key_bits = attributes->core.bits;
+
+    *key_buffer_size = 0;
+    switch( location )
+    {
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
+            /* Emulate property 'builtin_key_size' */
+            if( psa_key_id_is_builtin(
+                    MBEDTLS_SVC_KEY_ID_GET_KEY_ID(
+                        psa_get_key_id( attributes ) ) ) )
+            {
+                *key_buffer_size = sizeof( psa_drv_slot_number_t );
+                return( PSA_SUCCESS );
+            }
+#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+            *key_buffer_size = mbedtls_test_opaque_size_function( key_type,
+                                                                  key_bits );
+            return( ( *key_buffer_size != 0 ) ?
+                    PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+
+        default:
+            (void)key_type;
+            (void)key_bits;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+psa_status_t psa_driver_wrapper_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    uint8_t *data, size_t data_size, size_t *data_length )
+
+{
+{% with entry_point = "export_public_key" -%}
+{% macro entry_point_param(driver) -%}
+attributes,
+key_buffer,
+key_buffer_size,
+data,
+data_size,
+data_length
+{% endmacro %}
+    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(
+                                      psa_get_key_lifetime( attributes ) );
+
+    /* Try dynamically-registered SE interface first */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    const psa_drv_se_t *drv;
+    psa_drv_se_context_t *drv_context;
+
+    if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) )
+    {
+        if( ( drv->key_management == NULL ) ||
+            ( drv->key_management->p_export_public == NULL ) )
+        {
+            return( PSA_ERROR_NOT_SUPPORTED );
+        }
+
+        return( drv->key_management->p_export_public(
+                    drv_context,
+                    *( (psa_key_slot_number_t *)key_buffer ),
+                    data, data_size, data_length ) );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    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_ACCELERATOR_DRIVER_PRESENT)
+{% with nest_indent=12 %}
+{% include "OS-template-transparent.jinja" -%}
+{% endwith -%}
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+            /* Fell through, meaning no accelerator supports this operation */
+            return( psa_export_public_key_internal( attributes,
+                                                    key_buffer,
+                                                    key_buffer_size,
+                                                    data,
+                                                    data_size,
+                                                    data_length ) );
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+{% with nest_indent=8 %}
+{% include "OS-template-opaque.jinja" -%}
+{% endwith -%}
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            return( status );
+    }
+{% endwith %}
+}
+
+psa_status_t psa_driver_wrapper_get_builtin_key(
+    psa_drv_slot_number_t slot_number,
+    psa_key_attributes_t *attributes,
+    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
+{
+{% with entry_point = "get_builtin_key" -%}
+{% macro entry_point_param(driver) -%}
+slot_number,
+attributes,
+key_buffer,
+key_buffer_size,
+key_buffer_length
+{% endmacro %}
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
+    switch( location )
+    {
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+{% with nest_indent=8 %}
+{% include "OS-template-opaque.jinja" -%}
+{% endwith -%}
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+        default:
+            (void) slot_number;
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) key_buffer_length;
+            return( PSA_ERROR_DOES_NOT_EXIST );
+    }
+{% endwith %}
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/scripts/data_files/vs2013-app-template.vcxproj b/scripts/data_files/vs2013-app-template.vcxproj
index 039fd09..2fe9cf3 100644
--- a/scripts/data_files/vs2013-app-template.vcxproj
+++ b/scripts/data_files/vs2013-app-template.vcxproj
@@ -99,7 +99,7 @@
     <Link>

       <SubSystem>Console</SubSystem>

       <GenerateDebugInformation>true</GenerateDebugInformation>

-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalDependencies>bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>

       <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

     </Link>

     <ProjectReference>

@@ -118,7 +118,7 @@
     <Link>

       <SubSystem>Console</SubSystem>

       <GenerateDebugInformation>true</GenerateDebugInformation>

-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalDependencies>bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>

       <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

     </Link>

     <ProjectReference>

@@ -142,7 +142,7 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>

       <OptimizeReferences>true</OptimizeReferences>

       <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalDependencies>bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>

     </Link>

   </ItemDefinitionGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

@@ -162,7 +162,7 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>

       <OptimizeReferences>true</OptimizeReferences>

       <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+      <AdditionalDependencies>bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>

     </Link>

   </ItemDefinitionGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

diff --git a/scripts/data_files/vs2013-main-template.vcxproj b/scripts/data_files/vs2013-main-template.vcxproj
index c0f3a3c..51861e1 100644
--- a/scripts/data_files/vs2013-main-template.vcxproj
+++ b/scripts/data_files/vs2013-main-template.vcxproj
@@ -91,6 +91,7 @@
     <Link>

       <SubSystem>Windows</SubSystem>

       <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>

     </Link>

   </ItemDefinitionGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

@@ -106,6 +107,7 @@
     <Link>

       <SubSystem>Windows</SubSystem>

       <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>

     </Link>

   </ItemDefinitionGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

@@ -124,6 +126,7 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>

       <EnableCOMDATFolding>true</EnableCOMDATFolding>

       <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalDependencies>bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>

     </Link>

   </ItemDefinitionGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

diff --git a/scripts/data_files/vs6-app-template.dsp b/scripts/data_files/vs6-app-template.dsp
deleted file mode 100644
index 87dbea2..0000000
--- a/scripts/data_files/vs6-app-template.dsp
+++ /dev/null
@@ -1,101 +0,0 @@
-# Microsoft Developer Studio Project File - Name="<APPNAME>" - Package Owner=<4>

-# Microsoft Developer Studio Generated Build File, Format Version 6.00

-# ** DO NOT EDIT **

-

-# TARGTYPE "Win32 (x86) Console Application" 0x0103

-

-CFG=<APPNAME> - Win32 Debug

-!MESSAGE This is not a valid makefile. To build this project using NMAKE,

-!MESSAGE use the Export Makefile command and run

-!MESSAGE 

-!MESSAGE NMAKE /f "<APPNAME>.mak".

-!MESSAGE 

-!MESSAGE You can specify a configuration when running NMAKE

-!MESSAGE by defining the macro CFG on the command line. For example:

-!MESSAGE 

-!MESSAGE NMAKE /f "<APPNAME>.mak" CFG="<APPNAME> - Win32 Debug"

-!MESSAGE 

-!MESSAGE Possible choices for configuration are:

-!MESSAGE 

-!MESSAGE "<APPNAME> - Win32 Release" (based on "Win32 (x86) Console Application")

-!MESSAGE "<APPNAME> - Win32 Debug" (based on "Win32 (x86) Console Application")

-!MESSAGE 

-

-# Begin Project

-# PROP AllowPerConfigDependencies 0

-# PROP Scc_ProjName ""

-# PROP Scc_LocalPath ""

-CPP=cl.exe

-RSC=rc.exe

-

-!IF  "$(CFG)" == "<APPNAME> - Win32 Release"

-

-# PROP BASE Use_MFC 0

-# PROP BASE Use_Debug_Libraries 0

-# PROP BASE Output_Dir ""

-# PROP BASE Intermediate_Dir "temp"

-# PROP BASE Target_Dir ""

-# PROP Use_MFC 0

-# PROP Use_Debug_Libraries 0

-# PROP Output_Dir ""

-# PROP Intermediate_Dir "temp"

-# PROP Target_Dir ""

-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c

-# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c

-# ADD BASE RSC /l 0x40c /d "NDEBUG"

-# ADD RSC /l 0x40c /d "NDEBUG"

-BSC32=bscmake.exe

-# ADD BASE BSC32 /nologo

-# ADD BSC32 /nologo

-LINK32=link.exe

-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386

-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386

-

-!ELSEIF  "$(CFG)" == "<APPNAME> - Win32 Debug"

-

-# PROP BASE Use_MFC 0

-# PROP BASE Use_Debug_Libraries 1

-# PROP BASE Output_Dir ""

-# PROP BASE Intermediate_Dir "temp"

-# PROP BASE Target_Dir ""

-# PROP Use_MFC 0

-# PROP Use_Debug_Libraries 1

-# PROP Output_Dir ""

-# PROP Intermediate_Dir "temp"

-# PROP Target_Dir ""

-# ADD BASE CPP /nologo /W3 /Gm /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ  /c

-# ADD CPP /nologo /W3 /Gm /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ  /c

-# ADD BASE RSC /l 0x40c /d "_DEBUG"

-# ADD RSC /l 0x40c /d "_DEBUG"

-BSC32=bscmake.exe

-# ADD BASE BSC32 /nologo

-# ADD BSC32 /nologo

-LINK32=link.exe

-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept

-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept

-

-!ENDIF 

-

-# Begin Target

-

-# Name "<APPNAME> - Win32 Release"

-# Name "<APPNAME> - Win32 Debug"

-# Begin Group "Source Files"

-

-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"

-# Begin Source File

-

-SOURCE=..\..\programs\<PATHNAME>.c

-# ADD CPP /I "../../include"

-# End Source File

-# End Group

-# Begin Group "Header Files"

-

-# PROP Default_Filter "h;hpp;hxx;hm;inl"

-# End Group

-# Begin Group "Resource Files"

-

-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"

-# End Group

-# End Target

-# End Project

diff --git a/scripts/data_files/vs6-main-template.dsp b/scripts/data_files/vs6-main-template.dsp
deleted file mode 100644
index 89d3fc7..0000000
--- a/scripts/data_files/vs6-main-template.dsp
+++ /dev/null
@@ -1,94 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mbedtls" - Package Owner=<4>

-# Microsoft Developer Studio Generated Build File, Format Version 6.00

-# ** DO NOT EDIT **

-

-# TARGTYPE "Win32 (x86) Static Library" 0x0104

-

-CFG=mbedtls - Win32 Debug

-!MESSAGE This is not a valid makefile. To build this project using NMAKE,

-!MESSAGE use the Export Makefile command and run

-!MESSAGE 

-!MESSAGE NMAKE /f "mbedtls.mak".

-!MESSAGE 

-!MESSAGE You can specify a configuration when running NMAKE

-!MESSAGE by defining the macro CFG on the command line. For example:

-!MESSAGE 

-!MESSAGE NMAKE /f "mbedtls.mak" CFG="mbedtls - Win32 Debug"

-!MESSAGE 

-!MESSAGE Possible choices for configuration are:

-!MESSAGE 

-!MESSAGE "mbedtls - Win32 Release" (based on "Win32 (x86) Static Library")

-!MESSAGE "mbedtls - Win32 Debug" (based on "Win32 (x86) Static Library")

-!MESSAGE 

-

-# Begin Project

-# PROP AllowPerConfigDependencies 0

-# PROP Scc_ProjName ""

-# PROP Scc_LocalPath ""

-CPP=cl.exe

-RSC=rc.exe

-

-!IF  "$(CFG)" == "mbedtls - Win32 Release"

-

-# PROP BASE Use_MFC 0

-# PROP BASE Use_Debug_Libraries 0

-# PROP BASE Output_Dir ""

-# PROP BASE Intermediate_Dir "temp"

-# PROP BASE Target_Dir ""

-# PROP Use_MFC 0

-# PROP Use_Debug_Libraries 0

-# PROP Output_Dir ""

-# PROP Intermediate_Dir "temp"

-# PROP Target_Dir ""

-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c

-# ADD CPP /nologo /W3 /GX /O2 /I "../../include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c

-# ADD BASE RSC /l 0x40c /d "NDEBUG"

-# ADD RSC /l 0x40c /d "NDEBUG"

-BSC32=bscmake.exe

-# ADD BASE BSC32 /nologo

-# ADD BSC32 /nologo

-LIB32=link.exe -lib

-# ADD BASE LIB32 /nologo

-# ADD LIB32 /nologo

-

-!ELSEIF  "$(CFG)" == "mbedtls - Win32 Debug"

-

-# PROP BASE Use_MFC 0

-# PROP BASE Use_Debug_Libraries 1

-# PROP BASE Output_Dir ""

-# PROP BASE Intermediate_Dir "temp"

-# PROP BASE Target_Dir ""

-# PROP Use_MFC 0

-# PROP Use_Debug_Libraries 1

-# PROP Output_Dir ""

-# PROP Intermediate_Dir "temp"

-# PROP Target_Dir ""

-# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c

-# ADD CPP /nologo /W3 /GX /Z7 /Od /I "../../include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c

-# ADD BASE RSC /l 0x40c /d "_DEBUG"

-# ADD RSC /l 0x40c /d "_DEBUG"

-BSC32=bscmake.exe

-# ADD BASE BSC32 /nologo

-# ADD BSC32 /nologo

-LIB32=link.exe -lib

-# ADD BASE LIB32 /nologo

-# ADD LIB32 /nologo

-

-!ENDIF

-

-# Begin Target

-

-# Name "mbedtls - Win32 Release"

-# Name "mbedtls - Win32 Debug"

-# Begin Group "Source Files"

-

-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"

-SOURCE_ENTRIES

-# End Group

-# Begin Group "Header Files"

-

-# PROP Default_Filter "h;hpp;hxx;hm;inl"

-HEADER_ENTRIES

-# End Group

-# End Target

-# End Project

diff --git a/scripts/data_files/vs6-workspace-template.dsw b/scripts/data_files/vs6-workspace-template.dsw
deleted file mode 100644
index ef90098..0000000
--- a/scripts/data_files/vs6-workspace-template.dsw
+++ /dev/null
@@ -1,18 +0,0 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00

-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

-

-APP_ENTRIES

-###############################################################################

-

-Global:

-

-Package=<5>

-{{{

-}}}

-

-Package=<3>

-{{{

-}}}

-

-###############################################################################

-

diff --git a/scripts/generate_driver_wrappers.py b/scripts/generate_driver_wrappers.py
index e0c4793..e0f2827 100755
--- a/scripts/generate_driver_wrappers.py
+++ b/scripts/generate_driver_wrappers.py
@@ -1,9 +1,10 @@
 #!/usr/bin/env python3
-"""Generate library/psa_crypto_driver_wrappers.c
+"""Generate library/psa_crypto_driver_wrappers.h
+            library/psa_crypto_driver_wrappers_no_static.c
 
    This module is invoked by the build scripts to auto generate the
-   psa_crypto_driver_wrappers.c based on template files in
-   script/data_files/driver_templates/.
+   psa_crypto_driver_wrappers.h and psa_crypto_driver_wrappers_no_static
+   based on template files in script/data_files/driver_templates/.
 """
 # Copyright The Mbed TLS Contributors
 # SPDX-License-Identifier: Apache-2.0
@@ -59,19 +60,19 @@
 
     return template.render(drivers=driver_jsoncontext)
 
-
 def generate_driver_wrapper_file(template_dir: str,
                                  output_dir: str,
+                                 template_file_name: str,
                                  driver_jsoncontext: list) -> None:
     """
     Generate the file psa_crypto_driver_wrapper.c.
     """
     driver_wrapper_template_filename = \
-        os.path.join(template_dir, "psa_crypto_driver_wrappers.c.jinja")
+        os.path.join(template_dir, template_file_name)
 
     result = render(driver_wrapper_template_filename, driver_jsoncontext)
 
-    with open(file=os.path.join(output_dir, "psa_crypto_driver_wrappers.c"),
+    with open(file=os.path.join(output_dir, os.path.splitext(template_file_name)[0]),
               mode='w',
               encoding='UTF-8') as out_file:
         out_file.write(result)
@@ -167,6 +168,9 @@
     ), file)
 
 
+TEMPLATE_FILENAMES = ["psa_crypto_driver_wrappers.h.jinja",
+                      "psa_crypto_driver_wrappers_no_static.c.jinja"]
+
 def main() -> int:
     """
     Main with command line arguments.
@@ -207,7 +211,9 @@
     except DriverReaderException as e:
         trace_exception(e)
         return 1
-    generate_driver_wrapper_file(template_directory, output_directory, merged_driver_json)
+    for template_filename in TEMPLATE_FILENAMES:
+        generate_driver_wrapper_file(template_directory, output_directory,
+                                     template_filename, merged_driver_json)
     return 0
 
 
diff --git a/scripts/make_generated_files.bat b/scripts/make_generated_files.bat
index 9cf34f6..abcfc39 100644
--- a/scripts/make_generated_files.bat
+++ b/scripts/make_generated_files.bat
@@ -1,7 +1,7 @@
 @rem Generate automatically-generated configuration-independent source files

 @rem and build scripts.

 @rem Perl and Python 3 must be on the PATH.

-@rem psa_crypto_driver_wrappers.c needs to be generated prior to

+@rem psa_crypto_driver_wrappers.h needs to be generated prior to

 @rem generate_visualc_files.pl being invoked.

 python scripts\generate_driver_wrappers.py || exit /b 1

 perl scripts\generate_errors.pl || exit /b 1

diff --git a/tests/Makefile b/tests/Makefile
index 60ab27e..2249a55 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -49,7 +49,7 @@
 ifdef WINDOWS_BUILD
 DLEXT=dll
 EXEXT=.exe
-LOCAL_LDFLAGS += -lws2_32
+LOCAL_LDFLAGS += -lws2_32 -lbcrypt
 ifdef SHARED
 SHARED_SUFFIX=.$(DLEXT)
 endif
diff --git a/tests/scripts/check-generated-files.sh b/tests/scripts/check-generated-files.sh
index a1c37e9..9140b4c 100755
--- a/tests/scripts/check-generated-files.sh
+++ b/tests/scripts/check-generated-files.sh
@@ -128,7 +128,7 @@
 
 check scripts/generate_errors.pl library/error.c
 check scripts/generate_query_config.pl programs/test/query_config.c
-check scripts/generate_driver_wrappers.py library/psa_crypto_driver_wrappers.c
+check scripts/generate_driver_wrappers.py library/psa_crypto_driver_wrappers.h
 check scripts/generate_features.pl library/version_features.c
 check scripts/generate_ssl_debug_helpers.py library/ssl_debug_helpers_generated.c
 # generate_visualc_files enumerates source files (library/*.c). It doesn't
diff --git a/tests/scripts/check_names.py b/tests/scripts/check_names.py
index e6a38ba..f812929 100755
--- a/tests/scripts/check_names.py
+++ b/tests/scripts/check_names.py
@@ -284,7 +284,7 @@
             "library/*.c",
             "3rdparty/everest/library/everest.c",
             "3rdparty/everest/library/x25519.c"
-        ], ["library/psa_crypto_driver_wrappers.c"])
+        ], ["library/psa_crypto_driver_wrappers.h"])
         symbols = self.parse_symbols()
 
         # Remove identifier macros like mbedtls_printf or mbedtls_calloc