From 0d9ae6a986f0ed87962b3994968c5188a0fc479f Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 7 Nov 2025 22:35:28 +0100 Subject: [PATCH 01/25] Update test drivers for TF-PSA-Crypto test driver Update test drivers for TF-PSA-Crypto test driver based on a copy of `drivers/builtin`. We mainly keep using what is already in place for libtestdriver1 in Mbed TLS by still defining MBEDTLS_TEST_LIBTESTDRIVER1. As in TF-PSA-Crypto, the test driver is a derivative of a clone of the built-in driver, not of the whole library, the paths to the driver internal headers are different. The paths are relative to `drivers/libtestdriver1/include`. Otherwise, `psa_key_attributes_t` is prefixed with `libtestdriver1_` in Mbed TLS test driver but not in TF-PSA-Crypto one. Thus in TF-PSA-Crypto case define `libtestdriver1_psa_key_attributes_t` as `psa_key_attributes_t`. Signed-off-by: Ronald Cron --- tests/src/drivers/hash.c | 6 ++++-- tests/src/drivers/test_driver_aead.c | 7 +++++-- .../drivers/test_driver_asymmetric_encryption.c | 7 +++++-- tests/src/drivers/test_driver_cipher.c | 7 +++++-- tests/src/drivers/test_driver_key_agreement.c | 8 ++++++-- tests/src/drivers/test_driver_key_management.c | 17 +++++++++++------ tests/src/drivers/test_driver_mac.c | 7 +++++-- tests/src/drivers/test_driver_pake.c | 8 ++++++-- tests/src/drivers/test_driver_signature.c | 14 +++++++++----- 9 files changed, 56 insertions(+), 25 deletions(-) diff --git a/tests/src/drivers/hash.c b/tests/src/drivers/hash.c index 54aec93225..df19f10008 100644 --- a/tests/src/drivers/hash.c +++ b/tests/src/drivers/hash.c @@ -12,13 +12,15 @@ #include "test/drivers/hash.h" -#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) +#include "../../libtestdriver1/src/psa_crypto_hash.h" +#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 #include "libtestdriver1/library/psa_crypto_hash.h" #else #include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_hash.h" #endif -#endif +#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ mbedtls_test_driver_hash_hooks_t mbedtls_test_driver_hash_hooks = MBEDTLS_TEST_DRIVER_HASH_INIT; diff --git a/tests/src/drivers/test_driver_aead.c b/tests/src/drivers/test_driver_aead.c index f653d89b9b..8ee7e52190 100644 --- a/tests/src/drivers/test_driver_aead.c +++ b/tests/src/drivers/test_driver_aead.c @@ -15,13 +15,16 @@ #include "mbedtls/constant_time.h" -#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) +typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; +#include "../../libtestdriver1/src/psa_crypto_aead.h" +#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 #include "libtestdriver1/library/psa_crypto_aead.h" #else #include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_aead.h" #endif -#endif +#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ mbedtls_test_driver_aead_hooks_t mbedtls_test_driver_aead_hooks = MBEDTLS_TEST_DRIVER_AEAD_INIT; diff --git a/tests/src/drivers/test_driver_asymmetric_encryption.c b/tests/src/drivers/test_driver_asymmetric_encryption.c index 57adb5ce90..1faeecabf5 100644 --- a/tests/src/drivers/test_driver_asymmetric_encryption.c +++ b/tests/src/drivers/test_driver_asymmetric_encryption.c @@ -21,13 +21,16 @@ #include "test/drivers/asymmetric_encryption.h" #include "test/drivers/key_management.h" -#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) +typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; +#include "../../libtestdriver1/src/psa_crypto_rsa.h" +#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 #include "libtestdriver1/library/psa_crypto_rsa.h" #else #include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_rsa.h" #endif -#endif +#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ #define PSA_RSA_KEY_PAIR_MAX_SIZE \ PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) diff --git a/tests/src/drivers/test_driver_cipher.c b/tests/src/drivers/test_driver_cipher.c index 9b753cd89d..3c9b37e006 100644 --- a/tests/src/drivers/test_driver_cipher.c +++ b/tests/src/drivers/test_driver_cipher.c @@ -23,13 +23,16 @@ #include "test/random.h" -#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) +typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; +#include "../../libtestdriver1/src/psa_crypto_cipher.h" +#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 #include "libtestdriver1/library/psa_crypto_cipher.h" #else #include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_cipher.h" #endif -#endif +#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ #include diff --git a/tests/src/drivers/test_driver_key_agreement.c b/tests/src/drivers/test_driver_key_agreement.c index 8a7a9ea525..8f0571d1f3 100644 --- a/tests/src/drivers/test_driver_key_agreement.c +++ b/tests/src/drivers/test_driver_key_agreement.c @@ -19,7 +19,11 @@ #include -#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) +typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; +#include "../../libtestdriver1/src/psa_crypto_ecp.h" +#include "../../libtestdriver1/src/psa_crypto_ffdh.h" +#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 #include "libtestdriver1/include/psa/crypto.h" #include "libtestdriver1/library/psa_crypto_ecp.h" @@ -29,7 +33,7 @@ #include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_ecp.h" #include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_ffdh.h" #endif -#endif +#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ mbedtls_test_driver_key_agreement_hooks_t mbedtls_test_driver_key_agreement_hooks = MBEDTLS_TEST_DRIVER_KEY_AGREEMENT_INIT; diff --git a/tests/src/drivers/test_driver_key_management.c b/tests/src/drivers/test_driver_key_management.c index 90cdb2153b..6e724b8b0c 100644 --- a/tests/src/drivers/test_driver_key_management.c +++ b/tests/src/drivers/test_driver_key_management.c @@ -21,14 +21,17 @@ #include "mbedtls/ecp.h" #endif -#include "mbedtls/error.h" - #include "test/drivers/key_management.h" #include "test/drivers/test_driver.h" #include "test/random.h" -#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) +typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; +#include "../../libtestdriver1/src/psa_crypto_ecp.h" +#include "../../libtestdriver1/src/psa_crypto_rsa.h" +#include "../../libtestdriver1/src/psa_crypto_ffdh.h" +#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 #include "libtestdriver1/library/psa_crypto_ecp.h" #include "libtestdriver1/library/psa_crypto_rsa.h" @@ -38,7 +41,7 @@ #include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_rsa.h" #include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_ffdh.h" #endif -#endif +#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ #include @@ -68,7 +71,8 @@ psa_status_t mbedtls_test_transparent_init(void) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; -#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#if !defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) && \ + defined(MBEDTLS_TEST_LIBTESTDRIVER1) status = libtestdriver1_psa_crypto_init(); if (status != PSA_SUCCESS) { return status; @@ -81,7 +85,8 @@ psa_status_t mbedtls_test_transparent_init(void) void mbedtls_test_transparent_free(void) { -#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#if !defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) && \ + defined(MBEDTLS_TEST_LIBTESTDRIVER1) libtestdriver1_mbedtls_psa_crypto_free(); #endif diff --git a/tests/src/drivers/test_driver_mac.c b/tests/src/drivers/test_driver_mac.c index a123c22194..e45acdf587 100644 --- a/tests/src/drivers/test_driver_mac.c +++ b/tests/src/drivers/test_driver_mac.c @@ -12,13 +12,16 @@ #include "test/drivers/mac.h" -#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) +typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; +#include "../../libtestdriver1/src/psa_crypto_mac.h" +#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 #include "libtestdriver1/library/psa_crypto_mac.h" #else #include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_mac.h" #endif -#endif +#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ mbedtls_test_driver_mac_hooks_t mbedtls_test_driver_mac_hooks = MBEDTLS_TEST_DRIVER_MAC_INIT; diff --git a/tests/src/drivers/test_driver_pake.c b/tests/src/drivers/test_driver_pake.c index 07d6977014..6e6794ece5 100644 --- a/tests/src/drivers/test_driver_pake.c +++ b/tests/src/drivers/test_driver_pake.c @@ -13,13 +13,17 @@ #include "test/drivers/pake.h" #include "string.h" -#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) +typedef psa_crypto_driver_pake_inputs_t libtestdriver1_psa_crypto_driver_pake_inputs_t; +typedef psa_crypto_driver_pake_step_t libtestdriver1_psa_crypto_driver_pake_step_t; +#include "../../libtestdriver1/src/psa_crypto_pake.h" +#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 #include "libtestdriver1/library/psa_crypto_pake.h" #else #include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_pake.h" #endif -#endif +#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ mbedtls_test_driver_pake_hooks_t mbedtls_test_driver_pake_hooks = MBEDTLS_TEST_DRIVER_PAKE_INIT; diff --git a/tests/src/drivers/test_driver_signature.c b/tests/src/drivers/test_driver_signature.c index 2915b5426b..a89ee1507b 100644 --- a/tests/src/drivers/test_driver_signature.c +++ b/tests/src/drivers/test_driver_signature.c @@ -24,7 +24,6 @@ #include "test/drivers/hash.h" #include "test/drivers/signature.h" -#include "test/drivers/hash.h" #if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4 #include "mbedtls/private/ecdsa.h" @@ -34,7 +33,12 @@ #include "test/random.h" -#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) +typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; +#include "../../libtestdriver1/src/psa_crypto_ecp.h" +#include "../../libtestdriver1/src/psa_crypto_hash.h" +#include "../../libtestdriver1/src/psa_crypto_rsa.h" +#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 #include "libtestdriver1/library/psa_crypto_ecp.h" #include "libtestdriver1/library/psa_crypto_hash.h" @@ -44,7 +48,7 @@ #include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_hash.h" #include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_rsa.h" #endif -#endif +#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ #include @@ -53,7 +57,7 @@ mbedtls_test_driver_signature_hooks_t mbedtls_test_driver_signature_hooks_t mbedtls_test_driver_signature_verify_hooks = MBEDTLS_TEST_DRIVER_SIGNATURE_INIT; -psa_status_t sign_hash( +static psa_status_t sign_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, @@ -121,7 +125,7 @@ psa_status_t sign_hash( return PSA_ERROR_NOT_SUPPORTED; } -psa_status_t verify_hash( +static psa_status_t verify_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, From 936943b2632b1bf1acc9c50ba544f3065d1f6dd6 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 1 Dec 2025 09:45:18 +0100 Subject: [PATCH 02/25] Introduce test_driver.py Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 32 ++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 scripts/mbedtls_framework/test_driver.py diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py new file mode 100644 index 0000000000..dbd98a356c --- /dev/null +++ b/scripts/mbedtls_framework/test_driver.py @@ -0,0 +1,32 @@ +"""Library for building a TF-PSA-Crypto test driver from the built-in driver +""" + +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# + +import argparse + +from pathlib import Path + +def get_parsearg_base() -> argparse.ArgumentParser: + """ Get base arguments for scripts building a TF-PSA-Crypto test driver """ + parser = argparse.ArgumentParser(description= \ + "Clone partially builtin tree, rewrite header inclusions and prefix" + "exposed C identifiers.") + + parser.add_argument("dst_dir", metavar="DST_DIR", + help="Destination directory.\n" + " - If absolute, used as-is.\n" + " - If relative, interpreted relative to the repository root.\n") + parser.add_argument("--driver", default="libtestdriver1", metavar="DRIVER", + help="Test driver name (default: %(default)s).") + return parser + +class TestDriverGenerator: + """A TF-PSA-Crypto test driver generator""" + def __init__(self, dst_dir: Path, driver: str): + self.dst_dir = dst_dir + self.driver = driver + # Path of 'dst_dir'/include/'driver' + self.test_driver_include_dir = None #type: Path | None From 415201cc3634fcee8c53d16bbb74f3ebf11700ab Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 1 Dec 2025 09:54:16 +0100 Subject: [PATCH 03/25] test_driver.py: Add method to build the test driver tree Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 105 +++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index dbd98a356c..c40e46ce87 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -6,8 +6,12 @@ # import argparse +import re +import shutil +from fnmatch import fnmatch from pathlib import Path +from typing import Iterable, Match, Optional, Set def get_parsearg_base() -> argparse.ArgumentParser: """ Get base arguments for scripts building a TF-PSA-Crypto test driver """ @@ -23,6 +27,16 @@ def get_parsearg_base() -> argparse.ArgumentParser: help="Test driver name (default: %(default)s).") return parser +def iter_code_files(root: Path) -> Iterable[Path]: + """ + Iterate over all "*.c" and "*.h" files found recursively under the `include` + and `src` subdirectories of `root`. + """ + for directory in ("include", "src"): + directory_path = root / directory + for ext in (".c", ".h"): + yield from directory_path.rglob(f"*{ext}") + class TestDriverGenerator: """A TF-PSA-Crypto test driver generator""" def __init__(self, dst_dir: Path, driver: str): @@ -30,3 +44,94 @@ def __init__(self, dst_dir: Path, driver: str): self.driver = driver # Path of 'dst_dir'/include/'driver' self.test_driver_include_dir = None #type: Path | None + + def build_tree(self, src_dir: Path, exclude_files: Optional[Set[str]] = None) -> None: + """ + Build a test driver tree from `src_dir`. + + The source directory `src_dir` is expected to have the following structure: + - an `include` directory + - an `src` directory + - the `include` directory contains exactly one subdirectory + + Only the `include` and `src` directories from `src_dir` are used to build + the test driver tree, and their directory structure is preserved. + + Only "*.h" and "*.c" files are copied. Files whose names match any of the + patterns in `exclude_files` are excluded. + + The subdirectory inside `include` is renamed to `driver` in the test driver + tree, and header inclusions are adjusted accordingly. + """ + include = src_dir / "include" + if not include.is_dir(): + raise RuntimeError(f'Do not find "include" directory in {src_dir}') + + src = src_dir / "src" + if not src.is_dir(): + raise RuntimeError(f'Do not find "src" directory in {src_dir}') + + entries = list(include.iterdir()) + if len(entries) != 1 or not entries[0].is_dir(): + raise RuntimeError(f"Found more than one directory in {include}") + + src_include_dir_name = entries[0].name + + if (self.dst_dir / "include").exists(): + shutil.rmtree(self.dst_dir / "include") + + if (self.dst_dir / "src").exists(): + shutil.rmtree(self.dst_dir / "src") + + if exclude_files is None: + exclude_files = set() + + for file in iter_code_files(src_dir): + if any(fnmatch(file.name, pattern) for pattern in exclude_files): + continue + dst = self.dst_dir / file.relative_to(src_dir) + dst.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(file, dst) + + self.test_driver_include_dir = self.dst_dir / "include" / self.driver + (self.dst_dir / "include" / src_include_dir_name).rename( \ + self.test_driver_include_dir) + + headers = { + f.relative_to(self.test_driver_include_dir).as_posix() \ + for f in self.test_driver_include_dir.rglob("*.h") + } + for f in iter_code_files(self.dst_dir): + self.__rewrite_inclusions_in_file(f, headers, \ + src_include_dir_name, self.driver) + + @staticmethod + def __rewrite_inclusions_in_file(file: Path, headers: Set[str], + src_include_dir: str, driver: str,) -> None: + """ + Rewrite `#include` directives in `file` that refer to `src_include_dir/...` + so that they instead refer to `driver/...`. + + For example: + #include "mbedtls/private/aes.h" + becomes: + #include "libtestdriver1/private/aes.h" + """ + include_line_re = re.compile( + fr'^\s*#\s*include\s*([<"])\s*{src_include_dir}/([^>"]+)\s*([>"])', + re.MULTILINE + ) + text = file.read_text(encoding="utf-8") + changed = False + + def repl(m: Match) -> str: + nonlocal changed + header = m.group(2) + if header in headers: + changed = True + return f'#include {m.group(1)}{driver}/{header}{m.group(3)}' + return m.group(0) + + new_text = include_line_re.sub(repl, text) + if changed: + file.write_text(new_text, encoding="utf-8") From d95c135498abd866b98faf289ab6207583f02afe Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 1 Dec 2025 10:28:24 +0100 Subject: [PATCH 04/25] test_driver.py: Add get_identifiers_with_prefixes method Add get_identifiers_with_prefixes method that returns the list of identifiers that potentially need to be prefixed in the test driver code. Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 51 ++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index c40e46ce87..bce53f584b 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -8,6 +8,7 @@ import argparse import re import shutil +import subprocess from fnmatch import fnmatch from pathlib import Path @@ -37,6 +38,37 @@ def iter_code_files(root: Path) -> Iterable[Path]: for ext in (".c", ".h"): yield from directory_path.rglob(f"*{ext}") +def run_ctags(file: Path) -> Set[str]: + """ + Extract the C identifiers in `file` using ctags. + + Identifiers of the following types are returned (with their corresponding + ctags c-kinds flag in parentheses): + + - macro definitions (d) + - enum values (e) + - functions (f) + - enum tags (g) + - function prototypes (p) + - struct tags (s) + - typedefs (t) + - union tags (u) + - global variables (v) + """ + + result = subprocess.run( + ["ctags", "-x", "--language-force=C", "--c-kinds=defgpstuv", str(file)], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + check=True + ) + identifiers = set() + for line in result.stdout.splitlines(): + identifiers.add(line.split()[0]) + + return identifiers + class TestDriverGenerator: """A TF-PSA-Crypto test driver generator""" def __init__(self, dst_dir: Path, driver: str): @@ -105,6 +137,25 @@ def build_tree(self, src_dir: Path, exclude_files: Optional[Set[str]] = None) -> self.__rewrite_inclusions_in_file(f, headers, \ src_include_dir_name, self.driver) + def get_identifiers_with_prefixes(self, prefixes: Set[str]): + """ + Return the identifiers in the test driver that start with any of the given + prefixes. + + All exposed identifiers are expected to start with one of these prefixes. + The returned set is therefore a superset of the exposed identifiers that + need to be prefixed. + """ + identifiers = set() + for file in iter_code_files(self.dst_dir): + identifiers.update(run_ctags(file)) + + identifiers_with_prefixes = set() + for identifier in identifiers: + if any(identifier.startswith(prefix) for prefix in prefixes): + identifiers_with_prefixes.add(identifier) + return identifiers_with_prefixes + @staticmethod def __rewrite_inclusions_in_file(file: Path, headers: Set[str], src_include_dir: str, driver: str,) -> None: From 50bd6aae50075aaf47fd35ccb530c218e5b20275 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 1 Dec 2025 10:34:13 +0100 Subject: [PATCH 05/25] test_driver.py: Add method to prefix test driver exposed identifiers Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index bce53f584b..6f25d5a40e 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -156,6 +156,15 @@ def get_identifiers_with_prefixes(self, prefixes: Set[str]): identifiers_with_prefixes.add(identifier) return identifiers_with_prefixes + def prefix_identifiers(self, identifiers_to_prefix: Set[str]): + """ + In all test driver files, prefix each identifier in `identifiers_to_prefix` + with the test driver prefix: _ for uppercase identifiers, + and _ for lowercase ones. + """ + for f in iter_code_files(self.dst_dir): + self.__prefix_identifiers_in_file(f, identifiers_to_prefix, self.driver) + @staticmethod def __rewrite_inclusions_in_file(file: Path, headers: Set[str], src_include_dir: str, driver: str,) -> None: @@ -186,3 +195,28 @@ def repl(m: Match) -> str: new_text = include_line_re.sub(repl, text) if changed: file.write_text(new_text, encoding="utf-8") + + @staticmethod + def __prefix_identifiers_in_file(file: Path, identifiers: Set[str], \ + prefix: str) -> None: + """ + In `file`, prefix each identifier in `identifiers` with the uppercase + form of `prefix` if the identifier is uppercase, or with the lowercase + form of `prefix` otherwise. + """ + c_identifier_re = re.compile(r"\b[A-Za-z_][A-Za-z0-9_]*\b") + text = file.read_text(encoding="utf-8") + prefix_uppercased = prefix.upper() + prefix_lowercased = prefix.lower() + + def repl(m: Match) -> str: + identifier = m.group(0) + if identifier in identifiers: + if identifier[0].isupper(): + return f"{prefix_uppercased}_{identifier}" + else: + return f"{prefix_lowercased}_{identifier}" + return identifier + + new_text = c_identifier_re.sub(repl, text) + file.write_text(new_text, encoding="utf-8") From ca68ad83771ff3542fb2bf5a32270209c02a4690 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 5 Dec 2025 10:23:43 +0100 Subject: [PATCH 06/25] Move "libtestdriver1_" aliases to test_driver_common.h Signed-off-by: Ronald Cron --- .../include/test/drivers/test_driver_common.h | 23 +++++++++++++++++++ tests/src/drivers/test_driver_aead.c | 1 - .../test_driver_asymmetric_encryption.c | 1 - tests/src/drivers/test_driver_cipher.c | 1 - tests/src/drivers/test_driver_key_agreement.c | 1 - .../src/drivers/test_driver_key_management.c | 1 - tests/src/drivers/test_driver_mac.c | 1 - tests/src/drivers/test_driver_pake.c | 2 -- tests/src/drivers/test_driver_signature.c | 1 - 9 files changed, 23 insertions(+), 9 deletions(-) diff --git a/tests/include/test/drivers/test_driver_common.h b/tests/include/test/drivers/test_driver_common.h index a704adb2b4..785e5af66f 100644 --- a/tests/include/test/drivers/test_driver_common.h +++ b/tests/include/test/drivers/test_driver_common.h @@ -25,4 +25,27 @@ /* *INDENT-ON* */ +/* + * In the libtestdriver1 library used in Mbed TLS 3.6 and 4.0 for driver + * dispatch testing, the PSA core code is cloned and all identifiers starting + * with MBEDTLS_, PSA_, mbedtls_, or psa_ are prefixed with `libtestdriver1_`. + * As a result, libtestdriver1 drivers use, for example, + * `libtestdriver1_psa_key_attributes_t` instead of `psa_key_attributes_t`. + * + * With the generated test drivers introduced in TF-PSA-Crypto between 1.0 + * and 1.1, only the modules under `drivers/builtin` are cloned, not the PSA + * core. The generated test drivers therefore do not use prefixed PSA core + * identifiers. For example, they use the `psa_key_attributes_t` type, just + * like the built-in drivers. + * + * To make driver dispatch work in both cases, we define certain + * `libtestdriver1_xyz` identifiers as aliases of the corresponding `xyz` + * identifiers in the latter case. + */ +#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) +typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; +typedef psa_crypto_driver_pake_inputs_t libtestdriver1_psa_crypto_driver_pake_inputs_t; +typedef psa_crypto_driver_pake_step_t libtestdriver1_psa_crypto_driver_pake_step_t; +#endif + #endif /* test_driver_common.h */ diff --git a/tests/src/drivers/test_driver_aead.c b/tests/src/drivers/test_driver_aead.c index 8ee7e52190..05fe57a8d0 100644 --- a/tests/src/drivers/test_driver_aead.c +++ b/tests/src/drivers/test_driver_aead.c @@ -16,7 +16,6 @@ #include "mbedtls/constant_time.h" #if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; #include "../../libtestdriver1/src/psa_crypto_aead.h" #elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 diff --git a/tests/src/drivers/test_driver_asymmetric_encryption.c b/tests/src/drivers/test_driver_asymmetric_encryption.c index 1faeecabf5..63b9af46aa 100644 --- a/tests/src/drivers/test_driver_asymmetric_encryption.c +++ b/tests/src/drivers/test_driver_asymmetric_encryption.c @@ -22,7 +22,6 @@ #include "test/drivers/key_management.h" #if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; #include "../../libtestdriver1/src/psa_crypto_rsa.h" #elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 diff --git a/tests/src/drivers/test_driver_cipher.c b/tests/src/drivers/test_driver_cipher.c index 3c9b37e006..0ba7e9c4a4 100644 --- a/tests/src/drivers/test_driver_cipher.c +++ b/tests/src/drivers/test_driver_cipher.c @@ -24,7 +24,6 @@ #include "test/random.h" #if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; #include "../../libtestdriver1/src/psa_crypto_cipher.h" #elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 diff --git a/tests/src/drivers/test_driver_key_agreement.c b/tests/src/drivers/test_driver_key_agreement.c index 8f0571d1f3..60879bfa60 100644 --- a/tests/src/drivers/test_driver_key_agreement.c +++ b/tests/src/drivers/test_driver_key_agreement.c @@ -20,7 +20,6 @@ #include #if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; #include "../../libtestdriver1/src/psa_crypto_ecp.h" #include "../../libtestdriver1/src/psa_crypto_ffdh.h" #elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) diff --git a/tests/src/drivers/test_driver_key_management.c b/tests/src/drivers/test_driver_key_management.c index 6e724b8b0c..ed5d828184 100644 --- a/tests/src/drivers/test_driver_key_management.c +++ b/tests/src/drivers/test_driver_key_management.c @@ -27,7 +27,6 @@ #include "test/random.h" #if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; #include "../../libtestdriver1/src/psa_crypto_ecp.h" #include "../../libtestdriver1/src/psa_crypto_rsa.h" #include "../../libtestdriver1/src/psa_crypto_ffdh.h" diff --git a/tests/src/drivers/test_driver_mac.c b/tests/src/drivers/test_driver_mac.c index e45acdf587..3a149299d6 100644 --- a/tests/src/drivers/test_driver_mac.c +++ b/tests/src/drivers/test_driver_mac.c @@ -13,7 +13,6 @@ #include "test/drivers/mac.h" #if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; #include "../../libtestdriver1/src/psa_crypto_mac.h" #elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 diff --git a/tests/src/drivers/test_driver_pake.c b/tests/src/drivers/test_driver_pake.c index 6e6794ece5..466f246132 100644 --- a/tests/src/drivers/test_driver_pake.c +++ b/tests/src/drivers/test_driver_pake.c @@ -14,8 +14,6 @@ #include "string.h" #if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -typedef psa_crypto_driver_pake_inputs_t libtestdriver1_psa_crypto_driver_pake_inputs_t; -typedef psa_crypto_driver_pake_step_t libtestdriver1_psa_crypto_driver_pake_step_t; #include "../../libtestdriver1/src/psa_crypto_pake.h" #elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 diff --git a/tests/src/drivers/test_driver_signature.c b/tests/src/drivers/test_driver_signature.c index a89ee1507b..8620b14fc0 100644 --- a/tests/src/drivers/test_driver_signature.c +++ b/tests/src/drivers/test_driver_signature.c @@ -34,7 +34,6 @@ #include "test/random.h" #if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t; #include "../../libtestdriver1/src/psa_crypto_ecp.h" #include "../../libtestdriver1/src/psa_crypto_hash.h" #include "../../libtestdriver1/src/psa_crypto_rsa.h" From 9d7330c41175ed2a02c7852799fd5bf6c4526c09 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 5 Dec 2025 12:43:54 +0100 Subject: [PATCH 07/25] tests: drivers: Factorize internal header inclusion pre-processor logic Signed-off-by: Ronald Cron --- .../include/test/drivers/test_driver_common.h | 43 +++++++++++++++++++ tests/src/drivers/hash.c | 10 +---- tests/src/drivers/test_driver_aead.c | 10 +---- .../test_driver_asymmetric_encryption.c | 10 +---- tests/src/drivers/test_driver_cipher.c | 10 +---- tests/src/drivers/test_driver_key_agreement.c | 15 +++---- .../src/drivers/test_driver_key_management.c | 20 +++------ tests/src/drivers/test_driver_mac.c | 10 +---- tests/src/drivers/test_driver_pake.c | 10 +---- tests/src/drivers/test_driver_signature.c | 18 ++------ 10 files changed, 70 insertions(+), 86 deletions(-) diff --git a/tests/include/test/drivers/test_driver_common.h b/tests/include/test/drivers/test_driver_common.h index 785e5af66f..0a576595b5 100644 --- a/tests/include/test/drivers/test_driver_common.h +++ b/tests/include/test/drivers/test_driver_common.h @@ -48,4 +48,47 @@ typedef psa_crypto_driver_pake_inputs_t libtestdriver1_psa_crypto_driver_pake_in typedef psa_crypto_driver_pake_step_t libtestdriver1_psa_crypto_driver_pake_step_t; #endif +/* + * The LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(basename) macro expands to + * the path of the internal header `basename` of a libtestdriver1 test driver. + * + * The internal headers the macro is dedicated to are the `psa_crypto_xyz.h` + * headers located in `library` in 3.6, in `tf-psa-crypto/drivers/builtin/src` + * in 4.x and in`drivers/builtin/src` in TF-PSA-Crypto. + * + * - In Mbed TLS 3.6 and 4.x, when the libtestdriver1 library is built, its code + * is located in the `libtestdriver1` directory at the root of the project. + * The header path is relative to the repository root and therefore of the + * form: + * - Mbed TLS 3.6: `libtestdriver1/library/xyz` + * - Mbed TLS 4.x: `libtestdriver1/tf-psa-crypto/drivers/builtin/src/xyz` + * + * - In TF-PSA-Crypto, the libtestdriver1 library code is located in + * `drivers/libtestdriver1`. The header path is relative to + * `drivers/libtestdriver1/include` and has the form: + * `../../libtestdriver1/src/xyz` + * + * Note: the path cannot simply be `../src/xyz`, because that could refer to + * a header under `drivers/builtin/src`. The directory `drivers/builtin/include` + * is also in the header search path when compiling test drivers. + * + * Uncrustify is not happy with the macros, temporarily disable it. + * + * *INDENT-OFF* + */ +#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) +#define LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(basename) \ + <../../libtestdriver1/src/basename> +#else +#if MBEDTLS_VERSION_MAJOR < 4 +#define LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(basename) \ + +#else +#define LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(basename) \ + +#endif +#endif + +/* *INDENT-ON* */ + #endif /* test_driver_common.h */ diff --git a/tests/src/drivers/hash.c b/tests/src/drivers/hash.c index df19f10008..2998e0efde 100644 --- a/tests/src/drivers/hash.c +++ b/tests/src/drivers/hash.c @@ -12,15 +12,9 @@ #include "test/drivers/hash.h" -#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -#include "../../libtestdriver1/src/psa_crypto_hash.h" -#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) -#if MBEDTLS_VERSION_MAJOR < 4 -#include "libtestdriver1/library/psa_crypto_hash.h" -#else -#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_hash.h" +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_hash.h) #endif -#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ mbedtls_test_driver_hash_hooks_t mbedtls_test_driver_hash_hooks = MBEDTLS_TEST_DRIVER_HASH_INIT; diff --git a/tests/src/drivers/test_driver_aead.c b/tests/src/drivers/test_driver_aead.c index 05fe57a8d0..5ecd4d1fc7 100644 --- a/tests/src/drivers/test_driver_aead.c +++ b/tests/src/drivers/test_driver_aead.c @@ -15,15 +15,9 @@ #include "mbedtls/constant_time.h" -#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -#include "../../libtestdriver1/src/psa_crypto_aead.h" -#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) -#if MBEDTLS_VERSION_MAJOR < 4 -#include "libtestdriver1/library/psa_crypto_aead.h" -#else -#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_aead.h" +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_aead.h) #endif -#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ mbedtls_test_driver_aead_hooks_t mbedtls_test_driver_aead_hooks = MBEDTLS_TEST_DRIVER_AEAD_INIT; diff --git a/tests/src/drivers/test_driver_asymmetric_encryption.c b/tests/src/drivers/test_driver_asymmetric_encryption.c index 63b9af46aa..506a85de1a 100644 --- a/tests/src/drivers/test_driver_asymmetric_encryption.c +++ b/tests/src/drivers/test_driver_asymmetric_encryption.c @@ -21,15 +21,9 @@ #include "test/drivers/asymmetric_encryption.h" #include "test/drivers/key_management.h" -#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -#include "../../libtestdriver1/src/psa_crypto_rsa.h" -#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) -#if MBEDTLS_VERSION_MAJOR < 4 -#include "libtestdriver1/library/psa_crypto_rsa.h" -#else -#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_rsa.h" +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_rsa.h) #endif -#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ #define PSA_RSA_KEY_PAIR_MAX_SIZE \ PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) diff --git a/tests/src/drivers/test_driver_cipher.c b/tests/src/drivers/test_driver_cipher.c index 0ba7e9c4a4..0943b3423a 100644 --- a/tests/src/drivers/test_driver_cipher.c +++ b/tests/src/drivers/test_driver_cipher.c @@ -23,15 +23,9 @@ #include "test/random.h" -#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -#include "../../libtestdriver1/src/psa_crypto_cipher.h" -#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) -#if MBEDTLS_VERSION_MAJOR < 4 -#include "libtestdriver1/library/psa_crypto_cipher.h" -#else -#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_cipher.h" +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_cipher.h) #endif -#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ #include diff --git a/tests/src/drivers/test_driver_key_agreement.c b/tests/src/drivers/test_driver_key_agreement.c index 60879bfa60..0b88a4b4df 100644 --- a/tests/src/drivers/test_driver_key_agreement.c +++ b/tests/src/drivers/test_driver_key_agreement.c @@ -19,20 +19,17 @@ #include -#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -#include "../../libtestdriver1/src/psa_crypto_ecp.h" -#include "../../libtestdriver1/src/psa_crypto_ffdh.h" -#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_ecp.h) +#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_ffdh.h) +#if !defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) #if MBEDTLS_VERSION_MAJOR < 4 #include "libtestdriver1/include/psa/crypto.h" -#include "libtestdriver1/library/psa_crypto_ecp.h" -#include "libtestdriver1/library/psa_crypto_ffdh.h" #else #include "libtestdriver1/tf-psa-crypto/include/psa/crypto.h" -#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_ecp.h" -#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_ffdh.h" #endif -#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ +#endif +#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 */ mbedtls_test_driver_key_agreement_hooks_t mbedtls_test_driver_key_agreement_hooks = MBEDTLS_TEST_DRIVER_KEY_AGREEMENT_INIT; diff --git a/tests/src/drivers/test_driver_key_management.c b/tests/src/drivers/test_driver_key_management.c index ed5d828184..bbd5d0938d 100644 --- a/tests/src/drivers/test_driver_key_management.c +++ b/tests/src/drivers/test_driver_key_management.c @@ -26,21 +26,11 @@ #include "test/random.h" -#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -#include "../../libtestdriver1/src/psa_crypto_ecp.h" -#include "../../libtestdriver1/src/psa_crypto_rsa.h" -#include "../../libtestdriver1/src/psa_crypto_ffdh.h" -#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) -#if MBEDTLS_VERSION_MAJOR < 4 -#include "libtestdriver1/library/psa_crypto_ecp.h" -#include "libtestdriver1/library/psa_crypto_rsa.h" -#include "libtestdriver1/library/psa_crypto_ffdh.h" -#else -#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_ecp.h" -#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_rsa.h" -#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_ffdh.h" -#endif -#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_ecp.h) +#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_rsa.h) +#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_ffdh.h) +#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 */ #include diff --git a/tests/src/drivers/test_driver_mac.c b/tests/src/drivers/test_driver_mac.c index 3a149299d6..e4ce9ad9ea 100644 --- a/tests/src/drivers/test_driver_mac.c +++ b/tests/src/drivers/test_driver_mac.c @@ -12,15 +12,9 @@ #include "test/drivers/mac.h" -#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -#include "../../libtestdriver1/src/psa_crypto_mac.h" -#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) -#if MBEDTLS_VERSION_MAJOR < 4 -#include "libtestdriver1/library/psa_crypto_mac.h" -#else -#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_mac.h" +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_mac.h) #endif -#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ mbedtls_test_driver_mac_hooks_t mbedtls_test_driver_mac_hooks = MBEDTLS_TEST_DRIVER_MAC_INIT; diff --git a/tests/src/drivers/test_driver_pake.c b/tests/src/drivers/test_driver_pake.c index 466f246132..5191c7936a 100644 --- a/tests/src/drivers/test_driver_pake.c +++ b/tests/src/drivers/test_driver_pake.c @@ -13,15 +13,9 @@ #include "test/drivers/pake.h" #include "string.h" -#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -#include "../../libtestdriver1/src/psa_crypto_pake.h" -#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) -#if MBEDTLS_VERSION_MAJOR < 4 -#include "libtestdriver1/library/psa_crypto_pake.h" -#else -#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_pake.h" +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_pake.h) #endif -#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ mbedtls_test_driver_pake_hooks_t mbedtls_test_driver_pake_hooks = MBEDTLS_TEST_DRIVER_PAKE_INIT; diff --git a/tests/src/drivers/test_driver_signature.c b/tests/src/drivers/test_driver_signature.c index 8620b14fc0..e8dc07655f 100644 --- a/tests/src/drivers/test_driver_signature.c +++ b/tests/src/drivers/test_driver_signature.c @@ -33,21 +33,11 @@ #include "test/random.h" -#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) -#include "../../libtestdriver1/src/psa_crypto_ecp.h" -#include "../../libtestdriver1/src/psa_crypto_hash.h" -#include "../../libtestdriver1/src/psa_crypto_rsa.h" -#elif defined(MBEDTLS_TEST_LIBTESTDRIVER1) -#if MBEDTLS_VERSION_MAJOR < 4 -#include "libtestdriver1/library/psa_crypto_ecp.h" -#include "libtestdriver1/library/psa_crypto_hash.h" -#include "libtestdriver1/library/psa_crypto_rsa.h" -#else -#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_ecp.h" -#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_hash.h" -#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_rsa.h" +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_ecp.h) +#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_hash.h) +#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_rsa.h) #endif -#endif /* TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1 */ #include From 5fecb0e0fa80af14e399ed4ea19805ae0075ed43 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sat, 6 Dec 2025 11:16:31 +0100 Subject: [PATCH 08/25] test_driver.py: Add support for the list-vars-for-cmake option Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 118 +++++++++++++++++++---- 1 file changed, 97 insertions(+), 21 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 6f25d5a40e..2c8c4e12b7 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -12,7 +12,7 @@ from fnmatch import fnmatch from pathlib import Path -from typing import Iterable, Match, Optional, Set +from typing import Iterable, List, Match, Optional, Set def get_parsearg_base() -> argparse.ArgumentParser: """ Get base arguments for scripts building a TF-PSA-Crypto test driver """ @@ -26,6 +26,11 @@ def get_parsearg_base() -> argparse.ArgumentParser: " - If relative, interpreted relative to the repository root.\n") parser.add_argument("--driver", default="libtestdriver1", metavar="DRIVER", help="Test driver name (default: %(default)s).") + parser.add_argument('--list-vars-for-cmake', nargs="?", const="__AUTO__", metavar="FILE", + help="Generate a file to be included from a CMakeLists.txt.\n" + "The file defines CMake list variables with the script's\n" + "inputs/outputs files. If FILE is omitted, the output \n" + "name defaults to '-list-vars.cmake'.") return parser def iter_code_files(root: Path) -> Iterable[Path]: @@ -38,6 +43,40 @@ def iter_code_files(root: Path) -> Iterable[Path]: for ext in (".c", ".h"): yield from directory_path.rglob(f"*{ext}") +def get_src_relpaths(builtin: Path, exclude_files: Set[str]) -> List[Path]: + """ + Return the relative paths of all *.c and *.h files under `builtin`, + excluding those whose names match any of the patterns in `exclude_files`. + + The returned paths are relative to `builtin`. + """ + + out = [] + for file in iter_code_files(builtin): + if not any(fnmatch(file.name, pattern) for pattern in exclude_files): + out.append(file.relative_to(builtin)) + out.sort() + return out + +def get_dst_relpaths(src_relpaths: List[Path], driver: str) -> List[Path]: + """ + Return the relative paths of the *.c and *.h files generated by the script. + + These paths are the same as in `src_relpaths`, except that occurrences of + `mbedtls` in `include/mbedtls/...` paths are replaced with `driver`. + + The returned paths are relative to `dst_dir`. + """ + + out = [] + for path in src_relpaths: + parts = list(path.parts) + if parts[0] == "include" and parts[1] == "mbedtls": + parts[1] = driver + out.append(Path(*parts)) + + return out + def run_ctags(file: Path) -> Set[str]: """ Extract the C identifiers in `file` using ctags. @@ -71,20 +110,65 @@ def run_ctags(file: Path) -> Set[str]: class TestDriverGenerator: """A TF-PSA-Crypto test driver generator""" - def __init__(self, dst_dir: Path, driver: str): + def __init__(self, src_dir: Path, dst_dir: Path, driver: str, \ + exclude_files: Optional[Set[str]] = None) -> None: + """ + Initialize a test driver generator. + + Args: + src_dir (Path): + Path to the source directory that contains the built-in driver. + If this path is relative, it should be relative to the repository + root so that the source paths returned by `write_list_vars_for_cmake` + are correct. + + The source directory is expected to contain: + - an `include` directory + - an `src` directory + - the `include/` directory contains exactly one subdirectory + + dst_dir (Path): + Path to the destination directory where the rewritten tree will + be created. + + driver (str): + Name of the driver. This is used as a prefix when rewritting + the tree. + + exclude_files (Optional[Set[str]]): + Glob patterns for the basename of the files to be excluded from + the source directory. + """ + self.src_dir = src_dir self.dst_dir = dst_dir self.driver = driver + self.exclude_files = set() + if exclude_files is not None: + self.exclude_files = exclude_files # Path of 'dst_dir'/include/'driver' self.test_driver_include_dir = None #type: Path | None - def build_tree(self, src_dir: Path, exclude_files: Optional[Set[str]] = None) -> None: + if not (src_dir / "include").is_dir(): + raise RuntimeError(f'"include" directory in {src_dir} not found') + + if not (src_dir / "src").is_dir(): + raise RuntimeError(f'"src" directory in {src_dir} not found') + + def write_list_vars_for_cmake(self, fname: str) -> None: + src_relpaths = get_src_relpaths(self.src_dir, self.exclude_files) + with open(self.dst_dir / fname, "w") as f: + f.write(f"set({self.driver}_input_files " + \ + " ".join(str(path) for path in src_relpaths) + ")\n\n") + f.write(f"set({self.driver}_files " + \ + " ".join(str(path) \ + for path in get_dst_relpaths(src_relpaths, self.driver)) + ")\n\n") + f.write(f"set({self.driver}_src_files " + \ + " ".join(str(path) \ + for path in src_relpaths if path.suffix == ".c") + ")") + + def build_tree(self) -> None: """ - Build a test driver tree from `src_dir`. - - The source directory `src_dir` is expected to have the following structure: - - an `include` directory - - an `src` directory - - the `include` directory contains exactly one subdirectory + Build a test driver tree from `self.src_dir`. Only the `include` and `src` directories from `src_dir` are used to build the test driver tree, and their directory structure is preserved. @@ -95,14 +179,9 @@ def build_tree(self, src_dir: Path, exclude_files: Optional[Set[str]] = None) -> The subdirectory inside `include` is renamed to `driver` in the test driver tree, and header inclusions are adjusted accordingly. """ - include = src_dir / "include" - if not include.is_dir(): - raise RuntimeError(f'Do not find "include" directory in {src_dir}') - src = src_dir / "src" - if not src.is_dir(): - raise RuntimeError(f'Do not find "src" directory in {src_dir}') + include = self.src_dir / "include" entries = list(include.iterdir()) if len(entries) != 1 or not entries[0].is_dir(): raise RuntimeError(f"Found more than one directory in {include}") @@ -115,13 +194,10 @@ def build_tree(self, src_dir: Path, exclude_files: Optional[Set[str]] = None) -> if (self.dst_dir / "src").exists(): shutil.rmtree(self.dst_dir / "src") - if exclude_files is None: - exclude_files = set() - - for file in iter_code_files(src_dir): - if any(fnmatch(file.name, pattern) for pattern in exclude_files): + for file in iter_code_files(self.src_dir): + if any(fnmatch(file.name, pattern) for pattern in self.exclude_files): continue - dst = self.dst_dir / file.relative_to(src_dir) + dst = self.dst_dir / file.relative_to(self.src_dir) dst.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(file, dst) From 3b39e68363ed5664d89e00588e877b4f37a7d177 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sat, 6 Dec 2025 12:10:51 +0100 Subject: [PATCH 09/25] test_driver.py: Some refactoring of the test driver tree creation Introduce __iter_src_code_files and __get_dst_relpath. Use __get_dst_relpath to create the file under `include` directly with the right path. __iter_src_code_files and __get_dst_relpath will be used in `write_list_vars_for_cmake` to get rid of `get_src_relpaths` and `get_dst_relpaths` that share some logic with `__iter_src_code_files` and `__get_dst_relpath`. Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 48 ++++++++++++++++++------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 2c8c4e12b7..d3878918e9 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -145,8 +145,6 @@ def __init__(self, src_dir: Path, dst_dir: Path, driver: str, \ self.exclude_files = set() if exclude_files is not None: self.exclude_files = exclude_files - # Path of 'dst_dir'/include/'driver' - self.test_driver_include_dir = None #type: Path | None if not (src_dir / "include").is_dir(): raise RuntimeError(f'"include" directory in {src_dir} not found') @@ -194,20 +192,16 @@ def build_tree(self) -> None: if (self.dst_dir / "src").exists(): shutil.rmtree(self.dst_dir / "src") - for file in iter_code_files(self.src_dir): - if any(fnmatch(file.name, pattern) for pattern in self.exclude_files): - continue - dst = self.dst_dir / file.relative_to(self.src_dir) + for file in self.__iter_src_code_files(): + dst = self.dst_dir / \ + self.__get_dst_relpath(file.relative_to(self.src_dir)) dst.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(file, dst) - self.test_driver_include_dir = self.dst_dir / "include" / self.driver - (self.dst_dir / "include" / src_include_dir_name).rename( \ - self.test_driver_include_dir) - + test_driver_include_dir = self.dst_dir / "include" / self.driver headers = { - f.relative_to(self.test_driver_include_dir).as_posix() \ - for f in self.test_driver_include_dir.rglob("*.h") + f.relative_to(test_driver_include_dir).as_posix() \ + for f in test_driver_include_dir.rglob("*.h") } for f in iter_code_files(self.dst_dir): self.__rewrite_inclusions_in_file(f, headers, \ @@ -241,6 +235,36 @@ def prefix_identifiers(self, identifiers_to_prefix: Set[str]): for f in iter_code_files(self.dst_dir): self.__prefix_identifiers_in_file(f, identifiers_to_prefix, self.driver) + def __iter_src_code_files(self) -> List[Path]: + """ + Iterate over all "*.c" and "*.h" files found recursively under the + `include` and `src` subdirectories of the source directory `self.src_dir` + excluding the files whose basename match any of the patterns in + `self.exclude_files`. + """ + out = [] + for file in iter_code_files(self.src_dir): + if not any(fnmatch(file.name, pattern) for pattern in self.exclude_files): + out.append(file) + return out + + def __get_dst_relpath(self, src_relpath: Path) -> Path: + """ + Return the path relative to `dst_dir` of the file that corresponds to the + file with relative path `src_relpath` in the source tree. + + The path is the same as `src_relpath`, except that occurrences of + `include/mbedtls/...` are replaced with `include/driver/...`. + + """ + assert not src_relpath.is_absolute(), "src_relpath must be relative" + + parts = src_relpath.parts + if len(parts) > 2 and parts[0] == "include" and parts[1] == "mbedtls": + return Path("include", self.driver, *parts[2:]) + + return src_relpath + @staticmethod def __rewrite_inclusions_in_file(file: Path, headers: Set[str], src_include_dir: str, driver: str,) -> None: From 08b152ffcf7bf6af655a75d6b58a9d3c8bb1f722 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sat, 6 Dec 2025 12:37:08 +0100 Subject: [PATCH 10/25] test_driver.py: Refactor support for list-vars-for-cmake Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 71 +++++++----------------- 1 file changed, 19 insertions(+), 52 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index d3878918e9..7ea2ccc6df 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -33,50 +33,6 @@ def get_parsearg_base() -> argparse.ArgumentParser: "name defaults to '-list-vars.cmake'.") return parser -def iter_code_files(root: Path) -> Iterable[Path]: - """ - Iterate over all "*.c" and "*.h" files found recursively under the `include` - and `src` subdirectories of `root`. - """ - for directory in ("include", "src"): - directory_path = root / directory - for ext in (".c", ".h"): - yield from directory_path.rglob(f"*{ext}") - -def get_src_relpaths(builtin: Path, exclude_files: Set[str]) -> List[Path]: - """ - Return the relative paths of all *.c and *.h files under `builtin`, - excluding those whose names match any of the patterns in `exclude_files`. - - The returned paths are relative to `builtin`. - """ - - out = [] - for file in iter_code_files(builtin): - if not any(fnmatch(file.name, pattern) for pattern in exclude_files): - out.append(file.relative_to(builtin)) - out.sort() - return out - -def get_dst_relpaths(src_relpaths: List[Path], driver: str) -> List[Path]: - """ - Return the relative paths of the *.c and *.h files generated by the script. - - These paths are the same as in `src_relpaths`, except that occurrences of - `mbedtls` in `include/mbedtls/...` paths are replaced with `driver`. - - The returned paths are relative to `dst_dir`. - """ - - out = [] - for path in src_relpaths: - parts = list(path.parts) - if parts[0] == "include" and parts[1] == "mbedtls": - parts[1] = driver - out.append(Path(*parts)) - - return out - def run_ctags(file: Path) -> Set[str]: """ Extract the C identifiers in `file` using ctags. @@ -153,15 +109,15 @@ def __init__(self, src_dir: Path, dst_dir: Path, driver: str, \ raise RuntimeError(f'"src" directory in {src_dir} not found') def write_list_vars_for_cmake(self, fname: str) -> None: - src_relpaths = get_src_relpaths(self.src_dir, self.exclude_files) + src_relpaths = self.__iter_src_code_files() with open(self.dst_dir / fname, "w") as f: f.write(f"set({self.driver}_input_files " + \ " ".join(str(path) for path in src_relpaths) + ")\n\n") f.write(f"set({self.driver}_files " + \ - " ".join(str(path) \ - for path in get_dst_relpaths(src_relpaths, self.driver)) + ")\n\n") + " ".join(str(self.__get_dst_relpath(path.relative_to(self.src_dir))) \ + for path in src_relpaths) + ")\n\n") f.write(f"set({self.driver}_src_files " + \ - " ".join(str(path) \ + " ".join(str(path.relative_to(self.src_dir)) \ for path in src_relpaths if path.suffix == ".c") + ")") def build_tree(self) -> None: @@ -203,7 +159,7 @@ def build_tree(self) -> None: f.relative_to(test_driver_include_dir).as_posix() \ for f in test_driver_include_dir.rglob("*.h") } - for f in iter_code_files(self.dst_dir): + for f in self.__iter_code_files(self.dst_dir): self.__rewrite_inclusions_in_file(f, headers, \ src_include_dir_name, self.driver) @@ -217,7 +173,7 @@ def get_identifiers_with_prefixes(self, prefixes: Set[str]): need to be prefixed. """ identifiers = set() - for file in iter_code_files(self.dst_dir): + for file in self.__iter_code_files(self.dst_dir): identifiers.update(run_ctags(file)) identifiers_with_prefixes = set() @@ -232,9 +188,20 @@ def prefix_identifiers(self, identifiers_to_prefix: Set[str]): with the test driver prefix: _ for uppercase identifiers, and _ for lowercase ones. """ - for f in iter_code_files(self.dst_dir): + for f in self.__iter_code_files(self.dst_dir): self.__prefix_identifiers_in_file(f, identifiers_to_prefix, self.driver) + @staticmethod + def __iter_code_files(root: Path) -> Iterable[Path]: + """ + Iterate over all "*.c" and "*.h" files found recursively under the + `include` and `src` subdirectories of `root`. + """ + for directory in ("include", "src"): + directory_path = root / directory + for ext in (".c", ".h"): + yield from directory_path.rglob(f"*{ext}") + def __iter_src_code_files(self) -> List[Path]: """ Iterate over all "*.c" and "*.h" files found recursively under the @@ -243,7 +210,7 @@ def __iter_src_code_files(self) -> List[Path]: `self.exclude_files`. """ out = [] - for file in iter_code_files(self.src_dir): + for file in self.__iter_code_files(self.src_dir): if not any(fnmatch(file.name, pattern) for pattern in self.exclude_files): out.append(file) return out From 7bada0205a77397a48009202c973189398e8016a Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sat, 6 Dec 2025 18:23:29 +0100 Subject: [PATCH 11/25] test_driver.py: Create completely the test driver tree in `build_tree` A `get_identifiers_to_prefix` method is introduced. It should be amended in subclasses of TestDriverGenerator in consuming branches. The new method allows the `build_tree` method to get the list of identifiers to rename in the test driver code. `build_tree` can then now complete all the steps of the test driver tree creation. Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 85 ++++++++++++++++-------- 1 file changed, 58 insertions(+), 27 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 7ea2ccc6df..03fd57329b 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -120,21 +120,68 @@ def write_list_vars_for_cmake(self, fname: str) -> None: " ".join(str(path.relative_to(self.src_dir)) \ for path in src_relpaths if path.suffix == ".c") + ")") - def build_tree(self) -> None: + + def get_identifiers_to_prefix(self, prefixes: Set[str]) -> Set[str]: """ - Build a test driver tree from `self.src_dir`. + Get the set of identifiers that will be prefixed in the test driver code. + + This method is intended to be amended by subclasses in consuming branches. + + The default implementation returns the complete set of identifiers from + the built-in driver whose names begin with any of the `prefixes`. These + are the identifiers that could be renamed in the test driver before + adaptation. + + Subclasses need to filter, transform, or otherwise adjust the set of + identifiers that should be renamed when generating the test driver. - Only the `include` and `src` directories from `src_dir` are used to build - the test driver tree, and their directory structure is preserved. + Args: + prefixes (Set[str]): + The set of identifier prefixes used by the built-in driver + for the symbols it exposes to the other parts of the crypto + library. All identifiers beginning with any of these + prefixes are candidates for renaming in the test driver to + avoid symbol clashes. + + Returns: + Set[str]: The default set of identifiers to rename. + """ + identifiers = set() + for file in self.__iter_code_files(self.dst_dir): + identifiers.update(run_ctags(file)) - Only "*.h" and "*.c" files are copied. Files whose names match any of the - patterns in `exclude_files` are excluded. + identifiers_with_prefixes = set() + for identifier in identifiers: + if any(identifier.startswith(prefix) for prefix in prefixes): + identifiers_with_prefixes.add(identifier) + return identifiers_with_prefixes - The subdirectory inside `include` is renamed to `driver` in the test driver - tree, and header inclusions are adjusted accordingly. + def build_tree(self, prefixes: Set[str]) -> None: """ + Build a test driver tree from `self.src_dir` into `self.dst_dir`. + + Only the `include/` and `src/` subdirectories of the source tree are + used, and their internal directory structure is preserved. + + Only "*.h" and "*.c" files are copied. Files whose basenames match any + of the glob patterns in `self.exclude_files` are excluded. + Inside the destination tree, the single subdirectory of `include/` + is renamed to `self.driver`, and any header inclusions referencing it are + rewritten accordingly. + Symbol identifiers exposed by the built-in driver are renamed by + prefixing them with `{self.driver}_` to avoid collisions when linking the + built-in driver and the test driver together in the crypto library. + + Args: + prefixes (Set[str]): + The set of identifier prefixes used by the built-in driver + for the symbols it exposes to the other parts of the crypto + library. All identifiers beginning with any of these + prefixes are candidates for renaming in the test driver to + avoid symbol clashes. + """ include = self.src_dir / "include" entries = list(include.iterdir()) if len(entries) != 1 or not entries[0].is_dir(): @@ -163,26 +210,10 @@ def build_tree(self) -> None: self.__rewrite_inclusions_in_file(f, headers, \ src_include_dir_name, self.driver) - def get_identifiers_with_prefixes(self, prefixes: Set[str]): - """ - Return the identifiers in the test driver that start with any of the given - prefixes. - - All exposed identifiers are expected to start with one of these prefixes. - The returned set is therefore a superset of the exposed identifiers that - need to be prefixed. - """ - identifiers = set() - for file in self.__iter_code_files(self.dst_dir): - identifiers.update(run_ctags(file)) - - identifiers_with_prefixes = set() - for identifier in identifiers: - if any(identifier.startswith(prefix) for prefix in prefixes): - identifiers_with_prefixes.add(identifier) - return identifiers_with_prefixes + identifiers_to_prefix = self.get_identifiers_to_prefix(prefixes) + self.__prefix_identifiers(identifiers_to_prefix) - def prefix_identifiers(self, identifiers_to_prefix: Set[str]): + def __prefix_identifiers(self, identifiers_to_prefix: Set[str]): """ In all test driver files, prefix each identifier in `identifiers_to_prefix` with the test driver prefix: _ for uppercase identifiers, From c5384feb275aafb5ab820ecfb06d8b47046a9cf3 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sun, 7 Dec 2025 10:40:23 +0100 Subject: [PATCH 12/25] test_driver.py: Rename run_ctags and move it as a method Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 64 ++++++++++++------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 03fd57329b..5fd26eb80b 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -33,37 +33,6 @@ def get_parsearg_base() -> argparse.ArgumentParser: "name defaults to '-list-vars.cmake'.") return parser -def run_ctags(file: Path) -> Set[str]: - """ - Extract the C identifiers in `file` using ctags. - - Identifiers of the following types are returned (with their corresponding - ctags c-kinds flag in parentheses): - - - macro definitions (d) - - enum values (e) - - functions (f) - - enum tags (g) - - function prototypes (p) - - struct tags (s) - - typedefs (t) - - union tags (u) - - global variables (v) - """ - - result = subprocess.run( - ["ctags", "-x", "--language-force=C", "--c-kinds=defgpstuv", str(file)], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True, - check=True - ) - identifiers = set() - for line in result.stdout.splitlines(): - identifiers.add(line.split()[0]) - - return identifiers - class TestDriverGenerator: """A TF-PSA-Crypto test driver generator""" def __init__(self, src_dir: Path, dst_dir: Path, driver: str, \ @@ -148,7 +117,7 @@ def get_identifiers_to_prefix(self, prefixes: Set[str]) -> Set[str]: """ identifiers = set() for file in self.__iter_code_files(self.dst_dir): - identifiers.update(run_ctags(file)) + identifiers.update(self.get_c_identifiers(file)) identifiers_with_prefixes = set() for identifier in identifiers: @@ -263,6 +232,37 @@ def __get_dst_relpath(self, src_relpath: Path) -> Path: return src_relpath + @staticmethod + def get_c_identifiers(file: Path) -> Set[str]: + """ + Extract the C identifiers in `file` using ctags. + + Identifiers of the following types are returned (with their corresponding + ctags c-kinds flag in parentheses): + + - macro definitions (d) + - enum values (e) + - functions (f) + - enum tags (g) + - function prototypes (p) + - struct tags (s) + - typedefs (t) + - union tags (u) + - global variables (v) + """ + result = subprocess.run( + ["ctags", "-x", "--language-force=C", "--c-kinds=defgpstuv", str(file)], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + check=True + ) + identifiers = set() + for line in result.stdout.splitlines(): + identifiers.add(line.split()[0]) + + return identifiers + @staticmethod def __rewrite_inclusions_in_file(file: Path, headers: Set[str], src_include_dir: str, driver: str,) -> None: From a09ed59b155d8d9649d159da27aa0fbe49f00290 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sun, 7 Dec 2025 10:03:41 +0100 Subject: [PATCH 13/25] test_driver.py: Modify test driver files in a single pass Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 72 +++++++++--------------- 1 file changed, 28 insertions(+), 44 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 5fd26eb80b..68cb608665 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -164,32 +164,25 @@ def build_tree(self, prefixes: Set[str]) -> None: if (self.dst_dir / "src").exists(): shutil.rmtree(self.dst_dir / "src") + # Clone the source tree into `dst_dir` for file in self.__iter_src_code_files(): dst = self.dst_dir / \ self.__get_dst_relpath(file.relative_to(self.src_dir)) dst.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(file, dst) + # Modify the test driver files test_driver_include_dir = self.dst_dir / "include" / self.driver headers = { f.relative_to(test_driver_include_dir).as_posix() \ for f in test_driver_include_dir.rglob("*.h") } - for f in self.__iter_code_files(self.dst_dir): - self.__rewrite_inclusions_in_file(f, headers, \ - src_include_dir_name, self.driver) - identifiers_to_prefix = self.get_identifiers_to_prefix(prefixes) - self.__prefix_identifiers(identifiers_to_prefix) - def __prefix_identifiers(self, identifiers_to_prefix: Set[str]): - """ - In all test driver files, prefix each identifier in `identifiers_to_prefix` - with the test driver prefix: _ for uppercase identifiers, - and _ for lowercase ones. - """ for f in self.__iter_code_files(self.dst_dir): - self.__prefix_identifiers_in_file(f, identifiers_to_prefix, self.driver) + self.__rewrite_test_driver_file(f, headers,\ + src_include_dir_name, + identifiers_to_prefix, self.driver) @staticmethod def __iter_code_files(root: Path) -> Iterable[Path]: @@ -264,57 +257,48 @@ def get_c_identifiers(file: Path) -> Set[str]: return identifiers @staticmethod - def __rewrite_inclusions_in_file(file: Path, headers: Set[str], - src_include_dir: str, driver: str,) -> None: + def __rewrite_test_driver_file(file: Path, headers: Set[str], + src_include_dir: str, + identifiers_to_prefix: Set[str], + driver: str) -> None: """ - Rewrite `#include` directives in `file` that refer to `src_include_dir/...` - so that they instead refer to `driver/...`. - - For example: - #include "mbedtls/private/aes.h" - becomes: - #include "libtestdriver1/private/aes.h" + Rewrite a test driver file: + 1) Rewrite `#include` directives in `file` that refer to `src_include_dir/...` + so that they instead refer to `driver/...`. + + For example: + #include "mbedtls/private/aes.h" + becomes: + #include "libtestdriver1/private/aes.h" + 2) Prefix each identifier in `identifiers` with the uppercase + form of `driver` if the identifier is uppercase, or with the lowercase + form of `driver` otherwise. """ + text = file.read_text(encoding="utf-8") + include_line_re = re.compile( fr'^\s*#\s*include\s*([<"])\s*{src_include_dir}/([^>"]+)\s*([>"])', re.MULTILINE ) - text = file.read_text(encoding="utf-8") - changed = False - - def repl(m: Match) -> str: - nonlocal changed + def repl_header_inclusion(m: Match) -> str: header = m.group(2) if header in headers: - changed = True return f'#include {m.group(1)}{driver}/{header}{m.group(3)}' return m.group(0) + intermediate_text = include_line_re.sub(repl_header_inclusion, text) - new_text = include_line_re.sub(repl, text) - if changed: - file.write_text(new_text, encoding="utf-8") - - @staticmethod - def __prefix_identifiers_in_file(file: Path, identifiers: Set[str], \ - prefix: str) -> None: - """ - In `file`, prefix each identifier in `identifiers` with the uppercase - form of `prefix` if the identifier is uppercase, or with the lowercase - form of `prefix` otherwise. - """ c_identifier_re = re.compile(r"\b[A-Za-z_][A-Za-z0-9_]*\b") - text = file.read_text(encoding="utf-8") - prefix_uppercased = prefix.upper() - prefix_lowercased = prefix.lower() + prefix_uppercased = driver.upper() + prefix_lowercased = driver.lower() def repl(m: Match) -> str: identifier = m.group(0) - if identifier in identifiers: + if identifier in identifiers_to_prefix: if identifier[0].isupper(): return f"{prefix_uppercased}_{identifier}" else: return f"{prefix_lowercased}_{identifier}" return identifier - new_text = c_identifier_re.sub(repl, text) + new_text = c_identifier_re.sub(repl, intermediate_text) file.write_text(new_text, encoding="utf-8") From e8dcf71c2bead6d87248956a0ba014cdfaa7d61d Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 5 Dec 2025 16:27:11 +0100 Subject: [PATCH 14/25] test_driver.py: Fix/improve help/comments Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 29 +++++++++++++++--------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 68cb608665..51ab19613a 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -16,21 +16,22 @@ def get_parsearg_base() -> argparse.ArgumentParser: """ Get base arguments for scripts building a TF-PSA-Crypto test driver """ - parser = argparse.ArgumentParser(description= \ - "Clone partially builtin tree, rewrite header inclusions and prefix" - "exposed C identifiers.") + parser = argparse.ArgumentParser(description="""\ + Clone the built-in driver tree, rewrite header inclusions and prefix + exposed C identifiers. + """) parser.add_argument("dst_dir", metavar="DST_DIR", - help="Destination directory.\n" - " - If absolute, used as-is.\n" - " - If relative, interpreted relative to the repository root.\n") + help="Destination directory (relative to repository root)") parser.add_argument("--driver", default="libtestdriver1", metavar="DRIVER", help="Test driver name (default: %(default)s).") - parser.add_argument('--list-vars-for-cmake', nargs="?", const="__AUTO__", metavar="FILE", - help="Generate a file to be included from a CMakeLists.txt.\n" - "The file defines CMake list variables with the script's\n" - "inputs/outputs files. If FILE is omitted, the output \n" - "name defaults to '-list-vars.cmake'.") + parser.add_argument('--list-vars-for-cmake', nargs="?", \ + const="__AUTO__", metavar="FILE", + help=""" + Generate a file to be included from a CMakeLists.txt and exit. The file + defines CMake list variables with the script's inputs/outputs files. If + FILE is omitted, the output name defaults to '-list-vars.cmake'. + """) return parser class TestDriverGenerator: @@ -242,6 +243,12 @@ def get_c_identifiers(file: Path) -> Set[str]: - typedefs (t) - union tags (u) - global variables (v) + + This method requires `Universal Ctags`. The command used here has been + validated with Universal Ctags 5.9.0 (the default `ctags` on Ubuntu + 22.04 and 24.04). `Exuberant Ctags` is not compatible: it does not + support all `--c-kinds` flags used here, and will either fail with an + error or produce incomplete results. """ result = subprocess.run( ["ctags", "-x", "--language-force=C", "--c-kinds=defgpstuv", str(file)], From ed9c4a31e4a3c3ddf4aa77456fdad898920b277a Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 5 Dec 2025 18:10:46 +0100 Subject: [PATCH 15/25] test_driver.py: Various small code improvements Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 41 ++++++++++++------------ 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 51ab19613a..4c088b1bc0 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -37,7 +37,7 @@ def get_parsearg_base() -> argparse.ArgumentParser: class TestDriverGenerator: """A TF-PSA-Crypto test driver generator""" def __init__(self, src_dir: Path, dst_dir: Path, driver: str, \ - exclude_files: Optional[Set[str]] = None) -> None: + exclude_files: Optional[Iterable[str]] = None) -> None: """ Initialize a test driver generator. @@ -68,7 +68,7 @@ def __init__(self, src_dir: Path, dst_dir: Path, driver: str, \ self.src_dir = src_dir self.dst_dir = dst_dir self.driver = driver - self.exclude_files = set() + self.exclude_files: Iterable[str] = () if exclude_files is not None: self.exclude_files = exclude_files @@ -79,16 +79,16 @@ def __init__(self, src_dir: Path, dst_dir: Path, driver: str, \ raise RuntimeError(f'"src" directory in {src_dir} not found') def write_list_vars_for_cmake(self, fname: str) -> None: - src_relpaths = self.__iter_src_code_files() + src_relpaths = self.__get_src_code_files() with open(self.dst_dir / fname, "w") as f: f.write(f"set({self.driver}_input_files " + \ - " ".join(str(path) for path in src_relpaths) + ")\n\n") + "\n".join(str(path) for path in src_relpaths) + ")\n\n") f.write(f"set({self.driver}_files " + \ - " ".join(str(self.__get_dst_relpath(path.relative_to(self.src_dir))) \ + "\n".join(str(self.__get_dst_relpath(path.relative_to(self.src_dir))) \ for path in src_relpaths) + ")\n\n") f.write(f"set({self.driver}_src_files " + \ - " ".join(str(path.relative_to(self.src_dir)) \ - for path in src_relpaths if path.suffix == ".c") + ")") + "\n".join(str(path.relative_to(self.src_dir)) \ + for path in src_relpaths if path.suffix == ".c") + ")\n") def get_identifiers_to_prefix(self, prefixes: Set[str]) -> Set[str]: @@ -117,7 +117,7 @@ def get_identifiers_to_prefix(self, prefixes: Set[str]) -> Set[str]: Set[str]: The default set of identifiers to rename. """ identifiers = set() - for file in self.__iter_code_files(self.dst_dir): + for file in self.__get_code_files(self.dst_dir): identifiers.update(self.get_c_identifiers(file)) identifiers_with_prefixes = set() @@ -126,7 +126,7 @@ def get_identifiers_to_prefix(self, prefixes: Set[str]) -> Set[str]: identifiers_with_prefixes.add(identifier) return identifiers_with_prefixes - def build_tree(self, prefixes: Set[str]) -> None: + def create_test_driver_tree(self, prefixes: Set[str]) -> None: """ Build a test driver tree from `self.src_dir` into `self.dst_dir`. @@ -166,7 +166,7 @@ def build_tree(self, prefixes: Set[str]) -> None: shutil.rmtree(self.dst_dir / "src") # Clone the source tree into `dst_dir` - for file in self.__iter_src_code_files(): + for file in self.__get_src_code_files(): dst = self.dst_dir / \ self.__get_dst_relpath(file.relative_to(self.src_dir)) dst.parent.mkdir(parents=True, exist_ok=True) @@ -180,31 +180,30 @@ def build_tree(self, prefixes: Set[str]) -> None: } identifiers_to_prefix = self.get_identifiers_to_prefix(prefixes) - for f in self.__iter_code_files(self.dst_dir): + for f in self.__get_code_files(self.dst_dir): self.__rewrite_test_driver_file(f, headers,\ src_include_dir_name, identifiers_to_prefix, self.driver) @staticmethod - def __iter_code_files(root: Path) -> Iterable[Path]: + def __get_code_files(root: Path) -> List[Path]: """ - Iterate over all "*.c" and "*.h" files found recursively under the + Return all "*.c" and "*.h" files found recursively under the `include` and `src` subdirectories of `root`. """ - for directory in ("include", "src"): - directory_path = root / directory - for ext in (".c", ".h"): - yield from directory_path.rglob(f"*{ext}") + return sorted(path + for directory in ('include', 'src') + for path in (root / directory).rglob('*.[hc]')) - def __iter_src_code_files(self) -> List[Path]: + def __get_src_code_files(self) -> List[Path]: """ - Iterate over all "*.c" and "*.h" files found recursively under the + Return all "*.c" and "*.h" files found recursively under the `include` and `src` subdirectories of the source directory `self.src_dir` excluding the files whose basename match any of the patterns in `self.exclude_files`. """ out = [] - for file in self.__iter_code_files(self.src_dir): + for file in self.__get_code_files(self.src_dir): if not any(fnmatch(file.name, pattern) for pattern in self.exclude_files): out.append(file) return out @@ -284,7 +283,7 @@ def __rewrite_test_driver_file(file: Path, headers: Set[str], text = file.read_text(encoding="utf-8") include_line_re = re.compile( - fr'^\s*#\s*include\s*([<"])\s*{src_include_dir}/([^>"]+)\s*([>"])', + fr'^\s*#\s*include\s*([<"]){src_include_dir}/([^>"]+)([>"])', re.MULTILINE ) def repl_header_inclusion(m: Match) -> str: From 9ce24b367d00b2df4cb7fc8866b9a5e0528035a4 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 5 Dec 2025 18:32:15 +0100 Subject: [PATCH 16/25] test_driver.py: Use subprocess.check_output rather than subprocess.run Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 4c088b1bc0..092d462c99 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -249,15 +249,13 @@ def get_c_identifiers(file: Path) -> Set[str]: support all `--c-kinds` flags used here, and will either fail with an error or produce incomplete results. """ - result = subprocess.run( + output = subprocess.check_output( ["ctags", "-x", "--language-force=C", "--c-kinds=defgpstuv", str(file)], - stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, - check=True ) identifiers = set() - for line in result.stdout.splitlines(): + for line in output.splitlines(): identifiers.add(line.split()[0]) return identifiers From c806e683f81d7fb29c1ca3c699f31d48e8f3aa02 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 5 Dec 2025 23:27:28 +0100 Subject: [PATCH 17/25] test_driver.py: Get rid of one subdirectory in include/ limitation Get rid of one subdirectory in include/ limitation. Prefix all file basename instead of changing the name of `include/mbedtls` to `include/libtestdriver1`. Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 50 +++++++------------ .../include/test/drivers/test_driver_common.h | 2 +- 2 files changed, 20 insertions(+), 32 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 092d462c99..37dcc37f2e 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -87,10 +87,9 @@ def write_list_vars_for_cmake(self, fname: str) -> None: "\n".join(str(self.__get_dst_relpath(path.relative_to(self.src_dir))) \ for path in src_relpaths) + ")\n\n") f.write(f"set({self.driver}_src_files " + \ - "\n".join(str(path.relative_to(self.src_dir)) \ + "\n".join(str(self.__get_dst_relpath(path.relative_to(self.src_dir))) \ for path in src_relpaths if path.suffix == ".c") + ")\n") - def get_identifiers_to_prefix(self, prefixes: Set[str]) -> Set[str]: """ Get the set of identifiers that will be prefixed in the test driver code. @@ -136,9 +135,9 @@ def create_test_driver_tree(self, prefixes: Set[str]) -> None: Only "*.h" and "*.c" files are copied. Files whose basenames match any of the glob patterns in `self.exclude_files` are excluded. - Inside the destination tree, the single subdirectory of `include/` - is renamed to `self.driver`, and any header inclusions referencing it are - rewritten accordingly. + The basename of all files is prefixed with `{self.driver}-`. The + header inclusions referencing the renamed headers are rewritten + accordingly. Symbol identifiers exposed by the built-in driver are renamed by prefixing them with `{self.driver}_` to avoid collisions when linking the @@ -152,13 +151,6 @@ def create_test_driver_tree(self, prefixes: Set[str]) -> None: prefixes are candidates for renaming in the test driver to avoid symbol clashes. """ - include = self.src_dir / "include" - entries = list(include.iterdir()) - if len(entries) != 1 or not entries[0].is_dir(): - raise RuntimeError(f"Found more than one directory in {include}") - - src_include_dir_name = entries[0].name - if (self.dst_dir / "include").exists(): shutil.rmtree(self.dst_dir / "include") @@ -173,16 +165,14 @@ def create_test_driver_tree(self, prefixes: Set[str]) -> None: shutil.copy2(file, dst) # Modify the test driver files - test_driver_include_dir = self.dst_dir / "include" / self.driver headers = { - f.relative_to(test_driver_include_dir).as_posix() \ - for f in test_driver_include_dir.rglob("*.h") + f.name \ + for f in self.__get_src_code_files() if f.suffix == ".h" } identifiers_to_prefix = self.get_identifiers_to_prefix(prefixes) for f in self.__get_code_files(self.dst_dir): self.__rewrite_test_driver_file(f, headers,\ - src_include_dir_name, identifiers_to_prefix, self.driver) @staticmethod @@ -213,17 +203,15 @@ def __get_dst_relpath(self, src_relpath: Path) -> Path: Return the path relative to `dst_dir` of the file that corresponds to the file with relative path `src_relpath` in the source tree. - The path is the same as `src_relpath`, except that occurrences of - `include/mbedtls/...` are replaced with `include/driver/...`. - + Same as `src_relpath` but the basename prefixed with `self.driver` """ assert not src_relpath.is_absolute(), "src_relpath must be relative" parts = src_relpath.parts - if len(parts) > 2 and parts[0] == "include" and parts[1] == "mbedtls": - return Path("include", self.driver, *parts[2:]) - - return src_relpath + if len(parts) > 1: + return Path(*parts[:-1], f"{self.driver}-{parts[-1]}") + else: + return Path(f"{self.driver}-{parts[-1]}") @staticmethod def get_c_identifiers(file: Path) -> Set[str]: @@ -262,18 +250,17 @@ def get_c_identifiers(file: Path) -> Set[str]: @staticmethod def __rewrite_test_driver_file(file: Path, headers: Set[str], - src_include_dir: str, identifiers_to_prefix: Set[str], driver: str) -> None: """ Rewrite a test driver file: - 1) Rewrite `#include` directives in `file` that refer to `src_include_dir/...` - so that they instead refer to `driver/...`. + 1) Rewrite `#include` directives that include one of the header in + headers. The basename of the header is prefixed by `{driver}-`. For example: #include "mbedtls/private/aes.h" becomes: - #include "libtestdriver1/private/aes.h" + #include "mbedtls/private/libtestdriver1-aes.h" 2) Prefix each identifier in `identifiers` with the uppercase form of `driver` if the identifier is uppercase, or with the lowercase form of `driver` otherwise. @@ -281,13 +268,14 @@ def __rewrite_test_driver_file(file: Path, headers: Set[str], text = file.read_text(encoding="utf-8") include_line_re = re.compile( - fr'^\s*#\s*include\s*([<"]){src_include_dir}/([^>"]+)([>"])', + fr'^\s*#\s*include\s*([<"])([^>"]+)([>"])', re.MULTILINE ) def repl_header_inclusion(m: Match) -> str: - header = m.group(2) - if header in headers: - return f'#include {m.group(1)}{driver}/{header}{m.group(3)}' + parts = m.group(2).split("/") + if parts[-1] in headers: + path = "/".join(parts[:-1] + [driver + "-" + parts[-1]]) + return f'#include {m.group(1)}{path}{m.group(3)}' return m.group(0) intermediate_text = include_line_re.sub(repl_header_inclusion, text) diff --git a/tests/include/test/drivers/test_driver_common.h b/tests/include/test/drivers/test_driver_common.h index 0a576595b5..51ab6d436c 100644 --- a/tests/include/test/drivers/test_driver_common.h +++ b/tests/include/test/drivers/test_driver_common.h @@ -78,7 +78,7 @@ typedef psa_crypto_driver_pake_step_t libtestdriver1_psa_crypto_driver_pake_step */ #if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) #define LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(basename) \ - <../../libtestdriver1/src/basename> + <../src/libtestdriver1-basename> #else #if MBEDTLS_VERSION_MAJOR < 4 #define LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(basename) \ From 450a7c9e260a323c75f5b4026a9f25730eec4a4e Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 9 Dec 2025 10:21:38 +0100 Subject: [PATCH 18/25] test_driver.py: Create the test driver tree in one pass Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 31 +++++++++++------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 37dcc37f2e..6c3d99bb21 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -116,7 +116,7 @@ def get_identifiers_to_prefix(self, prefixes: Set[str]) -> Set[str]: Set[str]: The default set of identifiers to rename. """ identifiers = set() - for file in self.__get_code_files(self.dst_dir): + for file in self.__get_src_code_files(): identifiers.update(self.get_c_identifiers(file)) identifiers_with_prefixes = set() @@ -157,23 +157,19 @@ def create_test_driver_tree(self, prefixes: Set[str]) -> None: if (self.dst_dir / "src").exists(): shutil.rmtree(self.dst_dir / "src") - # Clone the source tree into `dst_dir` - for file in self.__get_src_code_files(): - dst = self.dst_dir / \ - self.__get_dst_relpath(file.relative_to(self.src_dir)) - dst.parent.mkdir(parents=True, exist_ok=True) - shutil.copy2(file, dst) - - # Modify the test driver files headers = { f.name \ for f in self.__get_src_code_files() if f.suffix == ".h" } identifiers_to_prefix = self.get_identifiers_to_prefix(prefixes) - for f in self.__get_code_files(self.dst_dir): - self.__rewrite_test_driver_file(f, headers,\ - identifiers_to_prefix, self.driver) + # Create the test driver tree + for file in self.__get_src_code_files(): + dst = self.dst_dir / \ + self.__get_dst_relpath(file.relative_to(self.src_dir)) + dst.parent.mkdir(parents=True, exist_ok=True) + self.__write_test_driver_file(file, dst, headers,\ + identifiers_to_prefix, self.driver) @staticmethod def __get_code_files(root: Path) -> List[Path]: @@ -249,9 +245,10 @@ def get_c_identifiers(file: Path) -> Set[str]: return identifiers @staticmethod - def __rewrite_test_driver_file(file: Path, headers: Set[str], - identifiers_to_prefix: Set[str], - driver: str) -> None: + def __write_test_driver_file(src: Path, dst: Path, + headers: Set[str], + identifiers_to_prefix: Set[str], + driver: str) -> None: """ Rewrite a test driver file: 1) Rewrite `#include` directives that include one of the header in @@ -265,7 +262,7 @@ def __rewrite_test_driver_file(file: Path, headers: Set[str], form of `driver` if the identifier is uppercase, or with the lowercase form of `driver` otherwise. """ - text = file.read_text(encoding="utf-8") + text = src.read_text(encoding="utf-8") include_line_re = re.compile( fr'^\s*#\s*include\s*([<"])([^>"]+)([>"])', @@ -293,4 +290,4 @@ def repl(m: Match) -> str: return identifier new_text = c_identifier_re.sub(repl, intermediate_text) - file.write_text(new_text, encoding="utf-8") + dst.write_text(new_text, encoding="utf-8") From c9740a6492f66c607e20abcbbe684338266d8c02 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 10 Dec 2025 14:19:08 +0100 Subject: [PATCH 19/25] test_driver.py: Fix self.exclude_files initialization Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 6c3d99bb21..56e3d582fc 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -61,16 +61,14 @@ def __init__(self, src_dir: Path, dst_dir: Path, driver: str, \ Name of the driver. This is used as a prefix when rewritting the tree. - exclude_files (Optional[Set[str]]): + exclude_files (Optional[Iterable[str]]): Glob patterns for the basename of the files to be excluded from the source directory. """ self.src_dir = src_dir self.dst_dir = dst_dir self.driver = driver - self.exclude_files: Iterable[str] = () - if exclude_files is not None: - self.exclude_files = exclude_files + self.exclude_files = [] if exclude_files is None else list(exclude_files) if not (src_dir / "include").is_dir(): raise RuntimeError(f'"include" directory in {src_dir} not found') From 17750d1f3a0bf97786f8fcd5b93d7625c0570f54 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 10 Dec 2025 14:25:40 +0100 Subject: [PATCH 20/25] test_driver.py: Fix/Improve some comments Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 57 ++++++++++++++----- .../include/test/drivers/test_driver_common.h | 6 +- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 56e3d582fc..be3d7fd4d6 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -15,7 +15,7 @@ from typing import Iterable, List, Match, Optional, Set def get_parsearg_base() -> argparse.ArgumentParser: - """ Get base arguments for scripts building a TF-PSA-Crypto test driver """ + """ Get base arguments for scripts generating a TF-PSA-Crypto test driver """ parser = argparse.ArgumentParser(description="""\ Clone the built-in driver tree, rewrite header inclusions and prefix exposed C identifiers. @@ -51,11 +51,11 @@ def __init__(self, src_dir: Path, dst_dir: Path, driver: str, \ The source directory is expected to contain: - an `include` directory - an `src` directory - - the `include/` directory contains exactly one subdirectory dst_dir (Path): Path to the destination directory where the rewritten tree will - be created. + be created. If the directory already exists, only the `include` + and `src` subdirectories are modified. driver (str): Name of the driver. This is used as a prefix when rewritting @@ -125,7 +125,7 @@ def get_identifiers_to_prefix(self, prefixes: Set[str]) -> Set[str]: def create_test_driver_tree(self, prefixes: Set[str]) -> None: """ - Build a test driver tree from `self.src_dir` into `self.dst_dir`. + Create a test driver tree from `self.src_dir` into `self.dst_dir`. Only the `include/` and `src/` subdirectories of the source tree are used, and their internal directory structure is preserved. @@ -248,17 +248,46 @@ def __write_test_driver_file(src: Path, dst: Path, identifiers_to_prefix: Set[str], driver: str) -> None: """ - Rewrite a test driver file: - 1) Rewrite `#include` directives that include one of the header in - headers. The basename of the header is prefixed by `{driver}-`. - - For example: - #include "mbedtls/private/aes.h" - becomes: + Write a test driver file to `dst` based on the contents of `src` with + two transformations: rewriting of `#include` directives and identifier + renaming. + + 1. Rewrite header inclusions + Any `#include` directive whose header basename matches an entry of + `headers` is rewritten so that the basename is prefixed with + `{driver}-`. Directory components (if any) are preserved. + + Example: + #include "mbedtls/private/aes.h" + becomes #include "mbedtls/private/libtestdriver1-aes.h" - 2) Prefix each identifier in `identifiers` with the uppercase - form of `driver` if the identifier is uppercase, or with the lowercase - form of `driver` otherwise. + + 2. Rename selected identifiers + Each identifier in `identifiers_to_prefix` is prefixed with `driver`. + Case is preserved: if the identifier is all-uppercase, then the + uppercase form of `driver` is used, the lowercase form otherwise. + + Examples: + `MBEDTLS_AES_C` becomes `LIBTESTDRIVER1_MBEDTLS_AES_C` + `mbedtls_sha256_init` becomes `libtestdriver1_mbedtls_sha256_init` + + Args: + src (Path): + The source file to read. + + dst (Path): + The destination file where the rewritten version is written. + + headers (Set[str]): + Basenames of headers whose includes should be rewritten. + + identifiers_to_prefix (Set[str]): + Identifiers that must be renamed by prefixing with `driver` + (using uppercase or lowercase depending on the identifier's casing). + + driver (str): + The name of the driver. Used as a prefix for rewritten include + paths and identifier names. """ text = src.read_text(encoding="utf-8") diff --git a/tests/include/test/drivers/test_driver_common.h b/tests/include/test/drivers/test_driver_common.h index 51ab6d436c..92b1ddabeb 100644 --- a/tests/include/test/drivers/test_driver_common.h +++ b/tests/include/test/drivers/test_driver_common.h @@ -66,11 +66,7 @@ typedef psa_crypto_driver_pake_step_t libtestdriver1_psa_crypto_driver_pake_step * - In TF-PSA-Crypto, the libtestdriver1 library code is located in * `drivers/libtestdriver1`. The header path is relative to * `drivers/libtestdriver1/include` and has the form: - * `../../libtestdriver1/src/xyz` - * - * Note: the path cannot simply be `../src/xyz`, because that could refer to - * a header under `drivers/builtin/src`. The directory `drivers/builtin/include` - * is also in the header search path when compiling test drivers. + * `../src/libtestdriver1-xyz` * * Uncrustify is not happy with the macros, temporarily disable it. * From 3ddf5113945c580bc87a024169d170b278c62a35 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 10 Dec 2025 14:51:48 +0100 Subject: [PATCH 21/25] Add ctags in scripts/output_env.sh Signed-off-by: Ronald Cron --- scripts/output_env.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/output_env.sh b/scripts/output_env.sh index 32f1f86efc..e138dca7f7 100755 --- a/scripts/output_env.sh +++ b/scripts/output_env.sh @@ -126,6 +126,9 @@ echo print_version "valgrind" "--version" "" echo +print_version "ctags" "--version" "" "head -n 1" +echo + print_version "gdb" "--version" "" "head -n 1" echo From 47f3c9fe845f890a7062416515efa63f159bd3f8 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 10 Dec 2025 15:12:08 +0100 Subject: [PATCH 22/25] test_driver.py: Various small code improvements Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 26 ++++++++++-------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index be3d7fd4d6..025e04a283 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -79,14 +79,14 @@ def __init__(self, src_dir: Path, dst_dir: Path, driver: str, \ def write_list_vars_for_cmake(self, fname: str) -> None: src_relpaths = self.__get_src_code_files() with open(self.dst_dir / fname, "w") as f: - f.write(f"set({self.driver}_input_files " + \ - "\n".join(str(path) for path in src_relpaths) + ")\n\n") - f.write(f"set({self.driver}_files " + \ - "\n".join(str(self.__get_dst_relpath(path.relative_to(self.src_dir))) \ - for path in src_relpaths) + ")\n\n") - f.write(f"set({self.driver}_src_files " + \ - "\n".join(str(self.__get_dst_relpath(path.relative_to(self.src_dir))) \ - for path in src_relpaths if path.suffix == ".c") + ")\n") + f.write(f"set({self.driver}_input_files\n " + \ + "\n ".join(f'"{path}"' for path in src_relpaths) + "\n)\n\n") + f.write(f"set({self.driver}_files\n " + \ + "\n ".join(f'"{self.__get_dst_relpath(path.relative_to(self.src_dir))}"' \ + for path in src_relpaths) + "\n)\n\n") + f.write(f"set({self.driver}_src_files\n " + \ + "\n ".join(f'"{self.__get_dst_relpath(path.relative_to(self.src_dir))}"' \ + for path in src_relpaths if path.suffix == ".c") + "\n)\n") def get_identifiers_to_prefix(self, prefixes: Set[str]) -> Set[str]: """ @@ -201,11 +201,7 @@ def __get_dst_relpath(self, src_relpath: Path) -> Path: """ assert not src_relpath.is_absolute(), "src_relpath must be relative" - parts = src_relpath.parts - if len(parts) > 1: - return Path(*parts[:-1], f"{self.driver}-{parts[-1]}") - else: - return Path(f"{self.driver}-{parts[-1]}") + return src_relpath.parent / (self.driver + '-' + src_relpath.name) @staticmethod def get_c_identifiers(file: Path) -> Set[str]: @@ -292,14 +288,14 @@ def __write_test_driver_file(src: Path, dst: Path, text = src.read_text(encoding="utf-8") include_line_re = re.compile( - fr'^\s*#\s*include\s*([<"])([^>"]+)([>"])', + fr'^(\s*#\s*include\s*[<"])([^>"]+)([>"])', re.MULTILINE ) def repl_header_inclusion(m: Match) -> str: parts = m.group(2).split("/") if parts[-1] in headers: path = "/".join(parts[:-1] + [driver + "-" + parts[-1]]) - return f'#include {m.group(1)}{path}{m.group(3)}' + return f'{m.group(1)}{path}{m.group(3)}' return m.group(0) intermediate_text = include_line_re.sub(repl_header_inclusion, text) From 9ee360adb8fe805a98389c1036b8c9f6548e997c Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 10 Dec 2025 16:49:34 +0100 Subject: [PATCH 23/25] test_driver.py: Documentation same header basename limitation Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 025e04a283..01964fc3c0 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -258,6 +258,27 @@ def __write_test_driver_file(src: Path, dst: Path, becomes #include "mbedtls/private/libtestdriver1-aes.h" + LIMITATION: + The current implementation does not correctly handle the case + where a built-in header and a non–built-in header share the same + basename. In principle, only inclusions of built-in headers + should be rewritten, while inclusions of non–built-in headers + should be left unchanged. However, the current logic only matches + on the basename, so both are rewritten. + + For example, if both `include/psa/foo.h` (non–built-in) and + `drivers/builtin/include/mbedtls/foo.h` (built-in) exist, then + in the test driver: + + - `#include ` should not be rewritten + - `#include ` should be rewritten to + `#include ` + + With the current basename-only matching, both inclusions are + rewritten, which is incorrect. No practical implications + currently, such same header basename case does not occur in the + code base. + 2. Rename selected identifiers Each identifier in `identifiers_to_prefix` is prefixed with `driver`. Case is preserved: if the identifier is all-uppercase, then the From 2dec1b3b63ca2a738ce979a24b20c5c62f22c886 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 11 Dec 2025 14:23:49 +0100 Subject: [PATCH 24/25] test_driver.py: Fix get_c_identifiers documentation Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 49 ++++++++++++++---------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 01964fc3c0..8ec74f5be7 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -206,26 +206,35 @@ def __get_dst_relpath(self, src_relpath: Path) -> Path: @staticmethod def get_c_identifiers(file: Path) -> Set[str]: """ - Extract the C identifiers in `file` using ctags. - - Identifiers of the following types are returned (with their corresponding - ctags c-kinds flag in parentheses): - - - macro definitions (d) - - enum values (e) - - functions (f) - - enum tags (g) - - function prototypes (p) - - struct tags (s) - - typedefs (t) - - union tags (u) - - global variables (v) - - This method requires `Universal Ctags`. The command used here has been - validated with Universal Ctags 5.9.0 (the default `ctags` on Ubuntu - 22.04 and 24.04). `Exuberant Ctags` is not compatible: it does not - support all `--c-kinds` flags used here, and will either fail with an - error or produce incomplete results. + Extract the C identifiers present in `file` using `ctags -x` + + The following C symbol kinds are included (with their `--c-kinds` + flags in parentheses): + + - macro definitions (d) + - enum values (e) + - functions (f) + - enum tags (g) + - function prototypes (p) + - struct tags (s) + - typedefs (t) + - union tags (u) + - global variables (v) + + Compatibility + ------------- + The command used here has been validated with the following `ctags` + implementations: + - Exuberant Ctags 5.8 + - Exuberant Ctags 5.9~svn20110310 (default on Ubuntu 16.04–24.04) + - Universal Ctags 5.9.0 (Ubuntu 24.04) + - Universal Ctags 6.2.0 (Ubuntu 26.04) + + All of these versions support the options `-x`, `--language-force=C`, + and ``--c-kinds=defgpstuv`` sufficiently for the use case here. + + Returns: + Set[str]: The set of identifiers found in `file`. """ output = subprocess.check_output( ["ctags", "-x", "--language-force=C", "--c-kinds=defgpstuv", str(file)], From 2bde77939f26904d6df2ab11388ff852112eabaa Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 11 Dec 2025 14:32:15 +0100 Subject: [PATCH 25/25] test_driver.py: Make __write_test_driver_files an instance method Make __write_test_driver_files an instance method instead of a static method as it is supposed to be used only in an instance context. Signed-off-by: Ronald Cron --- scripts/mbedtls_framework/test_driver.py | 29 ++++++++++-------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/scripts/mbedtls_framework/test_driver.py b/scripts/mbedtls_framework/test_driver.py index 8ec74f5be7..da7edcd2b2 100644 --- a/scripts/mbedtls_framework/test_driver.py +++ b/scripts/mbedtls_framework/test_driver.py @@ -167,7 +167,7 @@ def create_test_driver_tree(self, prefixes: Set[str]) -> None: self.__get_dst_relpath(file.relative_to(self.src_dir)) dst.parent.mkdir(parents=True, exist_ok=True) self.__write_test_driver_file(file, dst, headers,\ - identifiers_to_prefix, self.driver) + identifiers_to_prefix) @staticmethod def __get_code_files(root: Path) -> List[Path]: @@ -247,11 +247,9 @@ def get_c_identifiers(file: Path) -> Set[str]: return identifiers - @staticmethod - def __write_test_driver_file(src: Path, dst: Path, + def __write_test_driver_file(self, src: Path, dst: Path, headers: Set[str], - identifiers_to_prefix: Set[str], - driver: str) -> None: + identifiers_to_prefix: Set[str]) -> None: """ Write a test driver file to `dst` based on the contents of `src` with two transformations: rewriting of `#include` directives and identifier @@ -260,7 +258,7 @@ def __write_test_driver_file(src: Path, dst: Path, 1. Rewrite header inclusions Any `#include` directive whose header basename matches an entry of `headers` is rewritten so that the basename is prefixed with - `{driver}-`. Directory components (if any) are preserved. + `{self.driver}-`. Directory components (if any) are preserved. Example: #include "mbedtls/private/aes.h" @@ -289,9 +287,10 @@ def __write_test_driver_file(src: Path, dst: Path, code base. 2. Rename selected identifiers - Each identifier in `identifiers_to_prefix` is prefixed with `driver`. - Case is preserved: if the identifier is all-uppercase, then the - uppercase form of `driver` is used, the lowercase form otherwise. + Each identifier in `identifiers_to_prefix` is prefixed with + `self.driver`. Case is preserved: if the identifier is all-uppercase, + then the uppercase form of `driver` is used, the lowercase form + otherwise. Examples: `MBEDTLS_AES_C` becomes `LIBTESTDRIVER1_MBEDTLS_AES_C` @@ -308,12 +307,8 @@ def __write_test_driver_file(src: Path, dst: Path, Basenames of headers whose includes should be rewritten. identifiers_to_prefix (Set[str]): - Identifiers that must be renamed by prefixing with `driver` + Identifiers that must be renamed by prefixing with `self.driver` (using uppercase or lowercase depending on the identifier's casing). - - driver (str): - The name of the driver. Used as a prefix for rewritten include - paths and identifier names. """ text = src.read_text(encoding="utf-8") @@ -324,14 +319,14 @@ def __write_test_driver_file(src: Path, dst: Path, def repl_header_inclusion(m: Match) -> str: parts = m.group(2).split("/") if parts[-1] in headers: - path = "/".join(parts[:-1] + [driver + "-" + parts[-1]]) + path = "/".join(parts[:-1] + [self.driver + "-" + parts[-1]]) return f'{m.group(1)}{path}{m.group(3)}' return m.group(0) intermediate_text = include_line_re.sub(repl_header_inclusion, text) c_identifier_re = re.compile(r"\b[A-Za-z_][A-Za-z0-9_]*\b") - prefix_uppercased = driver.upper() - prefix_lowercased = driver.lower() + prefix_uppercased = self.driver.upper() + prefix_lowercased = self.driver.lower() def repl(m: Match) -> str: identifier = m.group(0)