Merge remote-tracking branch 'main' into psa-storage-test-cases-never-supported-negative-framework
diff --git a/data_files/.gitignore b/data_files/.gitignore
index 1564eee..0d66179 100644
--- a/data_files/.gitignore
+++ b/data_files/.gitignore
@@ -2,7 +2,7 @@
 server2-rsa.csr
 test-ca.csr
 
-/data_files/mpi_write
-/data_files/hmac_drbg_seed
-/data_files/ctr_drbg_seed
-/data_files/entropy_seed
+mpi_write
+hmac_drbg_seed
+ctr_drbg_seed
+entropy_seed
diff --git a/scripts/all-core.sh b/scripts/all-core.sh
index 4652fe4..1882c1c 100644
--- a/scripts/all-core.sh
+++ b/scripts/all-core.sh
@@ -938,7 +938,7 @@
     esac
     "${dd_cmd[@]}"
 
-    if [ -d tf-psa-crypto ]; then
+    if in_mbedtls_repo && in_4_x_branch; then
         dd_cmd=(dd if=/dev/urandom of=./tf-psa-crypto/tests/seedfile bs=64 count=1)
         case $OSTYPE in
             linux*|freebsd*|openbsd*) dd_cmd+=(status=none)
diff --git a/scripts/check_files.py b/scripts/check_files.py
index 399d371..d3a61c1 100755
--- a/scripts/check_files.py
+++ b/scripts/check_files.py
@@ -371,10 +371,10 @@
     LICENSE_EXEMPTION_RE_LIST = []
 
     # Exempt third-party drivers which may be under a different license
-    if build_tree.is_mbedtls_3_6():
+    if build_tree.looks_like_tf_psa_crypto_root(os.getcwd()):
+        LICENSE_EXEMPTION_RE_LIST.append(r'drivers/(?=(everest)/.*)')
+    elif build_tree.is_mbedtls_3_6():
         LICENSE_EXEMPTION_RE_LIST.append(r'3rdparty/(?!(p256-m)/.*)')
-    else:
-        LICENSE_EXEMPTION_RE_LIST.append(r'tf-psa-crypto/drivers/(?=(everest)/.*)')
 
     LICENSE_EXEMPTION_RE_LIST += [
         # Documentation explaining the license may have accidental
@@ -479,7 +479,8 @@
         """Instantiate the sanity checker.
         Check files under the current directory.
         Write a report of issues to log_file."""
-        build_tree.check_repo_path()
+        if not build_tree.looks_like_root(os.getcwd()):
+            raise Exception("This script must be run from Mbed TLS or TF-PSA-Crypto root")
         self.logger = None
         self.setup_logger(log_file)
         self.issues_to_check = [
diff --git a/scripts/mbedtls_framework/build_tree.py b/scripts/mbedtls_framework/build_tree.py
index 2d720a4..00868f5 100644
--- a/scripts/mbedtls_framework/build_tree.py
+++ b/scripts/mbedtls_framework/build_tree.py
@@ -44,10 +44,10 @@
             return "core"
         return os.path.join(root, "core")
     elif looks_like_mbedtls_root(root):
-        if os.path.isdir(os.path.join(root, 'tf-psa-crypto')):
-            path = "tf-psa-crypto/core"
-        else:
+        if is_mbedtls_3_6():
             path = "library"
+        else:
+            path = "tf-psa-crypto/core"
         if relative:
             return path
         return os.path.join(root, path)
diff --git a/scripts/mbedtls_framework/code_wrapper/psa_wrapper.py b/scripts/mbedtls_framework/code_wrapper/psa_wrapper.py
index 7e6b3e8..0148cde 100644
--- a/scripts/mbedtls_framework/code_wrapper/psa_wrapper.py
+++ b/scripts/mbedtls_framework/code_wrapper/psa_wrapper.py
@@ -106,7 +106,7 @@
         # Temporary, while Mbed TLS does not just rely on the TF-PSA-Crypto
         # build system to build its crypto library. When it does, the first
         # case can just be removed.
-        if os.path.isdir(os.path.join(self.mbedtls_root, 'tf-psa-crypto')):
+        if not build_tree.is_mbedtls_3_6():
             path_list = ['tf-psa-crypto' ] + path_list
             return os.path.join(self.mbedtls_root, *path_list, filename)
 
diff --git a/scripts/mbedtls_framework/min_requirements.py b/scripts/mbedtls_framework/min_requirements.py
new file mode 100644
index 0000000..fb20d5b
--- /dev/null
+++ b/scripts/mbedtls_framework/min_requirements.py
@@ -0,0 +1,122 @@
+"""Install all the required Python packages, with the minimum Python version.
+"""
+
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+import argparse
+import os
+import re
+import subprocess
+import sys
+import tempfile
+import typing
+
+from typing import List, Optional
+
+import framework_scripts_path # pylint: disable=unused-import
+from mbedtls_framework import typing_util
+
+def pylint_doesn_t_notice_that_certain_types_are_used_in_annotations(
+        _list: List[typing.Any],
+) -> None:
+    pass
+
+
+class Requirements:
+    """Collect and massage Python requirements."""
+
+    def __init__(self) -> None:
+        self.requirements = [] #type: List[str]
+
+    def adjust_requirement(self, req: str) -> str:
+        """Adjust a requirement to the minimum specified version."""
+        # allow inheritance #pylint: disable=no-self-use
+        # If a requirement specifies a minimum version, impose that version.
+        split_req = req.split(';', 1)
+        split_req[0] = re.sub(r'>=|~=', r'==', split_req[0])
+        return ';'.join(split_req)
+
+    def add_file(self, filename: str) -> None:
+        """Add requirements from the specified file.
+
+        This method supports a subset of pip's requirement file syntax:
+        * One requirement specifier per line, which is passed to
+          `adjust_requirement`.
+        * Comments (``#`` at the beginning of the line or after whitespace).
+        * ``-r FILENAME`` to include another file.
+        """
+        for line in open(filename):
+            line = line.strip()
+            line = re.sub(r'(\A|\s+)#.*', r'', line)
+            if not line:
+                continue
+            m = re.match(r'-r\s+', line)
+            if m:
+                nested_file = os.path.join(os.path.dirname(filename),
+                                           line[m.end(0):])
+                self.add_file(nested_file)
+                continue
+            self.requirements.append(self.adjust_requirement(line))
+
+    def write(self, out: typing_util.Writable) -> None:
+        """List the gathered requirements."""
+        for req in self.requirements:
+            out.write(req + '\n')
+
+    def install(
+            self,
+            pip_general_options: Optional[List[str]] = None,
+            pip_install_options: Optional[List[str]] = None,
+    ) -> None:
+        """Call pip to install the requirements."""
+        if pip_general_options is None:
+            pip_general_options = []
+        if pip_install_options is None:
+            pip_install_options = []
+        with tempfile.TemporaryDirectory() as temp_dir:
+            # This is more complicated than it needs to be for the sake
+            # of Windows. Use a temporary file rather than the command line
+            # to avoid quoting issues. Use a temporary directory rather
+            # than NamedTemporaryFile because with a NamedTemporaryFile on
+            # Windows, the subprocess can't open the file because this process
+            # has an exclusive lock on it.
+            req_file_name = os.path.join(temp_dir, 'requirements.txt')
+            with open(req_file_name, 'w') as req_file:
+                self.write(req_file)
+            subprocess.check_call([sys.executable, '-m', 'pip'] +
+                                  pip_general_options +
+                                  ['install'] + pip_install_options +
+                                  ['-r', req_file_name])
+
+def main(default_requirement_file: str) -> None:
+    """Command line entry point."""
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument('--no-act', '-n',
+                        action='store_true',
+                        help="Don't act, just print what will be done")
+    parser.add_argument('--pip-install-option',
+                        action='append', dest='pip_install_options',
+                        help="Pass this option to pip install")
+    parser.add_argument('--pip-option',
+                        action='append', dest='pip_general_options',
+                        help="Pass this general option to pip")
+    parser.add_argument('--user',
+                        action='append_const', dest='pip_install_options',
+                        const='--user',
+                        help="Install to the Python user install directory"
+                             " (short for --pip-install-option --user)")
+    parser.add_argument('files', nargs='*', metavar='FILE',
+                        help="Requirement files"
+                             " (default: {})" \
+                             .format(default_requirement_file))
+    options = parser.parse_args()
+    if not options.files:
+        options.files = [default_requirement_file]
+    reqs = Requirements()
+    for filename in options.files:
+        reqs.add_file(filename)
+    reqs.write(sys.stdout)
+    if not options.no_act:
+        reqs.install(pip_general_options=options.pip_general_options,
+                     pip_install_options=options.pip_install_options)
diff --git a/scripts/mbedtls_framework/psa_information.py b/scripts/mbedtls_framework/psa_information.py
index 015dfe3..f0d0e79 100644
--- a/scripts/mbedtls_framework/psa_information.py
+++ b/scripts/mbedtls_framework/psa_information.py
@@ -5,11 +5,11 @@
 # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
 #
 
-import os
 import re
 from collections import OrderedDict
 from typing import List, Optional
 
+from . import build_tree
 from . import macro_collector
 
 
@@ -36,17 +36,17 @@
     def read_psa_interface(self) -> macro_collector.PSAMacroEnumerator:
         """Return the list of known key types, algorithms, etc."""
         constructors = macro_collector.InputsForTest()
-        # Temporary, while Mbed TLS does not just rely on the TF-PSA-Crypto
-        # build system to build its crypto library. When it does, the first
-        # case can just be removed.
-        if os.path.isdir('tf-psa-crypto'):
-            header_file_names = ['tf-psa-crypto/include/psa/crypto_values.h',
-                                 'tf-psa-crypto/include/psa/crypto_extra.h']
-            test_suites = ['tf-psa-crypto/tests/suites/test_suite_psa_crypto_metadata.data']
-        else:
-            header_file_names = ['include/psa/crypto_values.h',
-                                 'include/psa/crypto_extra.h']
-            test_suites = ['tests/suites/test_suite_psa_crypto_metadata.data']
+
+        if build_tree.looks_like_root('.'):
+            if build_tree.looks_like_mbedtls_root('.') and \
+               (not build_tree.is_mbedtls_3_6()):
+                header_file_names = ['tf-psa-crypto/include/psa/crypto_values.h',
+                                     'tf-psa-crypto/include/psa/crypto_extra.h']
+                test_suites = ['tf-psa-crypto/tests/suites/test_suite_psa_crypto_metadata.data']
+            else:
+                header_file_names = ['include/psa/crypto_values.h',
+                                     'include/psa/crypto_extra.h']
+                test_suites = ['tests/suites/test_suite_psa_crypto_metadata.data']
 
         for header_file_name in header_file_names:
             constructors.parse_header(header_file_name)
diff --git a/scripts/mbedtls_framework/psa_storage.py b/scripts/mbedtls_framework/psa_storage.py
index 479510a..9630b95 100644
--- a/scripts/mbedtls_framework/psa_storage.py
+++ b/scripts/mbedtls_framework/psa_storage.py
@@ -10,7 +10,6 @@
 # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
 #
 
-import os
 import re
 import struct
 from typing import Dict, List, Optional, Set, Union
@@ -45,21 +44,17 @@
         # Temporary, while Mbed TLS does not just rely on the TF-PSA-Crypto
         # build system to build its crypto library. When it does, the first
         # case can just be removed.
-        if os.path.isdir('tf-psa-crypto'):
-            includes = ['include', 'tf-psa-crypto/include',
-                        'tf-psa-crypto/drivers/builtin/include',
-                        'tf-psa-crypto/drivers/everest/include']
-        else:
-            includes = ['include']
 
-        if build_tree.looks_like_tf_psa_crypto_root('.'):
-            includes.append('drivers/builtin/include')
-            includes.append('drivers/everest/include')
-            # Temporary, while TF-PSA-Crypto build system in Mbed TLS still
-            # reference some files in Mbed TLS include directory. When it does
-            # not anymore, this can be removed.
-            if build_tree.looks_like_mbedtls_root('..'):
-                includes.append('../include')
+        if build_tree.looks_like_root('.'):
+            includes = ['include']
+            if build_tree.looks_like_tf_psa_crypto_root('.'):
+                includes.append('drivers/builtin/include')
+                includes.append('drivers/everest/include')
+            elif not build_tree.is_mbedtls_3_6():
+                includes.append('tf-psa-crypto/include')
+                includes.append('tf-psa-crypto/drivers/builtin/include')
+                includes.append('tf-psa-crypto/drivers/everest/include')
+
         values = c_build_helper.get_c_expression_values(
             'unsigned long', '%lu',
             expressions,
diff --git a/scripts/mbedtls_framework/psa_test_case.py b/scripts/mbedtls_framework/psa_test_case.py
index 77ba31b..5964cad 100644
--- a/scripts/mbedtls_framework/psa_test_case.py
+++ b/scripts/mbedtls_framework/psa_test_case.py
@@ -9,6 +9,7 @@
 import re
 from typing import FrozenSet, List, Optional, Set
 
+from . import build_tree
 from . import psa_information
 from . import test_case
 
@@ -36,10 +37,14 @@
         # Temporary, while Mbed TLS does not just rely on the TF-PSA-Crypto
         # build system to build its crypto library. When it does, the first
         # case can just be removed.
-        if os.path.isdir('tf-psa-crypto'):
-            include_dir = 'tf-psa-crypto/include'
-        else:
-            include_dir = 'include'
+
+        if build_tree.looks_like_root('.'):
+            if build_tree.looks_like_mbedtls_root('.') and \
+               (not build_tree.is_mbedtls_3_6()):
+                include_dir = 'tf-psa-crypto/include'
+            else:
+                include_dir = 'include'
+
         acc = set() #type: Set[str]
         for filename in [
                 os.path.join(include_dir, 'psa/crypto_config.h'),
diff --git a/scripts/pkgconfig.sh b/scripts/pkgconfig.sh
new file mode 100755
index 0000000..07a73b3
--- /dev/null
+++ b/scripts/pkgconfig.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+#
+# Purpose
+#
+# Test pkgconfig files.
+#
+# For each of the build pkg-config files, .pc files, check that
+# they validate and do some basic sanity testing on the output,
+# i.e. that the strings are non-empty.
+#
+# NOTE: This requires the built pc files to be on the pkg-config
+# search path, this can be controlled with env variable
+# PKG_CONFIG_PATH. See man(1) pkg-config for details.
+#
+
+set -e -u
+
+if [ $# -le 0 ]
+then
+    echo " [!] No package names specified" >&2
+    echo "Usage: $0 <package name 1> <package name 2> ..." >&2
+    exit 1
+fi
+
+for pc in "$@"; do
+    printf "testing package config file: ${pc} ... "
+    pkg-config --validate "${pc}"
+    version="$(pkg-config --modversion "${pc}")"
+    test -n "$version"
+    cflags="$(pkg-config --cflags "${pc}")"
+    test -n "$cflags"
+    libs="$(pkg-config --libs "${pc}")"
+    test -n "$libs"
+    printf "passed\n"
+done
+
+exit 0