blob: 8412637235970ae60465943742a2f03a3ecd73b0 [file] [log] [blame]
Gabor Mezei31911442024-11-20 17:05:16 +01001#!/usr/bin/env python3
2
3"""TF PSA Crypto configuration file manipulation library and tool
4
5Basic usage, to read the TF PSA Crypto configuration:
Gabor Mezeiafc5fa52024-11-29 12:57:53 +01006 config = TFPSACryptoConfig()
Gabor Mezei31911442024-11-20 17:05:16 +01007 if 'PSA_WANT_ALG_MD5' in config: print('MD5 is enabled')
8"""
9
10## Copyright The Mbed TLS Contributors
11## SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
12##
13
Gabor Mezeifc719d62024-12-05 18:40:22 +010014import re
Gabor Mezei31911442024-11-20 17:05:16 +010015import os
16import sys
17
18import framework_scripts_path # pylint: disable=unused-import
19from mbedtls_framework import config_common
20
21
Gabor Mezeifc719d62024-12-05 18:40:22 +010022PSA_SYMBOL_REGEXP = re.compile(r'^PSA_.*')
23
Gabor Mezei31911442024-11-20 17:05:16 +010024PSA_UNSUPPORTED_FEATURE = frozenset([
25 'PSA_WANT_ALG_CBC_MAC',
26 'PSA_WANT_ALG_XTS',
27 'PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE',
28 'PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE'
29])
30
Gabor Mezei871cde62024-11-20 17:08:19 +010031PSA_DEPRECATED_FEATURE = frozenset([
32 'PSA_WANT_KEY_TYPE_ECC_KEY_PAIR',
33 'PSA_WANT_KEY_TYPE_RSA_KEY_PAIR'
34])
35
Gabor Mezei31911442024-11-20 17:05:16 +010036PSA_UNSTABLE_FEATURE = frozenset([
37 'PSA_WANT_ECC_SECP_K1_224'
38])
39
Gabor Mezei871cde62024-11-20 17:08:19 +010040# The goal of the full configuration is to have everything that can be tested
41# together. This includes deprecated or insecure options. It excludes:
42# * Options that require additional build dependencies or unusual hardware.
43# * Options that make testing less effective.
44# * Options that are incompatible with other options, or more generally that
45# interact with other parts of the code in such a way that a bulk enabling
46# is not a good way to test them.
47# * Options that remove features.
48EXCLUDE_FROM_FULL = frozenset([
49 #pylint: disable=line-too-long
50 'MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH', # interacts with CTR_DRBG_128_BIT_KEY
51 'MBEDTLS_AES_USE_HARDWARE_ONLY', # hardware dependency
52 'MBEDTLS_BLOCK_CIPHER_NO_DECRYPT', # incompatible with ECB in PSA, CBC/XTS/NIST_KW/DES
53 'MBEDTLS_CTR_DRBG_USE_128_BIT_KEY', # interacts with ENTROPY_FORCE_SHA256
54 'MBEDTLS_DEPRECATED_REMOVED', # conflicts with deprecated options
55 'MBEDTLS_DEPRECATED_WARNING', # conflicts with deprecated options
56 'MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED', # influences the use of ECDH in TLS
57 'MBEDTLS_ECP_WITH_MPI_UINT', # disables the default ECP and is experimental
58 'MBEDTLS_ENTROPY_FORCE_SHA256', # interacts with CTR_DRBG_128_BIT_KEY
59 'MBEDTLS_HAVE_SSE2', # hardware dependency
60 'MBEDTLS_MEMORY_BACKTRACE', # depends on MEMORY_BUFFER_ALLOC_C
61 'MBEDTLS_MEMORY_DEBUG', # depends on MEMORY_BUFFER_ALLOC_C
62 'MBEDTLS_NO_64BIT_MULTIPLICATION', # influences anything that uses bignum
63 'MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES', # removes a feature
64 'MBEDTLS_NO_PLATFORM_ENTROPY', # removes a feature
65 'MBEDTLS_NO_UDBL_DIVISION', # influences anything that uses bignum
66 'MBEDTLS_PSA_P256M_DRIVER_ENABLED', # influences SECP256R1 KeyGen/ECDH/ECDSA
67 'MBEDTLS_PLATFORM_NO_STD_FUNCTIONS', # removes a feature
68 'MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS', # removes a feature
69 'MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG', # behavior change + build dependency
70 'MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER', # interface and behavior change
71 'MBEDTLS_PSA_CRYPTO_SPM', # platform dependency (PSA SPM)
72 'MBEDTLS_PSA_INJECT_ENTROPY', # conflicts with platform entropy sources
73 'MBEDTLS_RSA_NO_CRT', # influences the use of RSA in X.509 and TLS
74 'MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY', # interacts with *_USE_A64_CRYPTO_IF_PRESENT
75 'MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY', # interacts with *_USE_ARMV8_A_CRYPTO_IF_PRESENT
76 'MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY', # interacts with *_USE_A64_CRYPTO_IF_PRESENT
77 'MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT', # setting *_USE_ARMV8_A_CRYPTO is sufficient
78 'MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN', # build dependency (clang+memsan)
79 'MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND', # build dependency (valgrind headers)
80 'MBEDTLS_X509_REMOVE_INFO', # removes a feature
81 *PSA_UNSUPPORTED_FEATURE,
82 *PSA_DEPRECATED_FEATURE,
83 *PSA_UNSTABLE_FEATURE
84])
85
86def is_boolean_setting(name, value):
87 """Is this a boolean setting?
88
89 Mbed TLS boolean settings are enabled if the preprocessor macro is
90 defined, and disabled if the preprocessor macro is not defined. The
91 macro definition line in the configuration file has an empty expansion.
92
93 PSA_WANT_xxx settings are also boolean, but when they are enabled,
94 they expand to a nonzero value. We leave them undefined when they
95 are disabled. (Setting them to 0 currently means to enable them, but
96 this might change to mean disabling them. Currently we just never set
97 them to 0.)
98 """
Gabor Mezeifc719d62024-12-05 18:40:22 +010099 if re.match(PSA_SYMBOL_REGEXP, name):
Gabor Mezei871cde62024-11-20 17:08:19 +0100100 return True
101 if not value:
102 return True
103 return False
104
Gabor Mezei1a7bbe12024-12-05 10:17:13 +0100105def is_seamless_alt(name):
106 """Whether the xxx_ALT symbol should be included in the full configuration.
107
108 Include alternative implementations of platform functions, which are
109 configurable function pointers that default to the built-in function.
110 This way we test that the function pointers exist and build correctly
111 without changing the behavior, and tests can verify that the function
112 pointers are used by modifying those pointers.
113
114 Exclude alternative implementations of library functions since they require
115 an implementation of the relevant functions and an xxx_alt.h header.
116 """
117 if name in (
118 'MBEDTLS_PLATFORM_GMTIME_R_ALT',
119 'MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT',
120 'MBEDTLS_PLATFORM_MS_TIME_ALT',
121 'MBEDTLS_PLATFORM_ZEROIZE_ALT',
122 ):
123 # Similar to non-platform xxx_ALT, requires platform_alt.h
124 return False
125 return name.startswith('MBEDTLS_PLATFORM_')
126
Gabor Mezei871cde62024-11-20 17:08:19 +0100127def include_in_full(name):
128 """Rules for symbols in the "full" configuration."""
129 if name in EXCLUDE_FROM_FULL:
130 return False
Gabor Mezei1a7bbe12024-12-05 10:17:13 +0100131 if name.endswith('_ALT'):
132 return is_seamless_alt(name)
Gabor Mezei871cde62024-11-20 17:08:19 +0100133 return True
134
135def full_adapter(name, value, active):
136 """Config adapter for "full"."""
137 if not is_boolean_setting(name, value):
138 return active
139 return include_in_full(name)
140
Gabor Mezei31911442024-11-20 17:05:16 +0100141
Gabor Mezeiafc5fa52024-11-29 12:57:53 +0100142class TFPSACryptoConfigFile(config_common.ConfigFile):
Gabor Mezei31911442024-11-20 17:05:16 +0100143 """Representation of a TF PSA Crypto configuration file."""
144
Gabor Mezei37bf61e2024-11-29 12:59:26 +0100145 _path_in_tree = 'include/psa/crypto_config.h'
Gabor Mezei31911442024-11-20 17:05:16 +0100146 default_path = [_path_in_tree,
147 os.path.join(os.path.dirname(__file__),
148 os.pardir,
149 _path_in_tree),
150 os.path.join(os.path.dirname(os.path.abspath(os.path.dirname(__file__))),
151 _path_in_tree)]
152
153 def __init__(self, filename=None):
Gabor Mezei1044a802024-11-29 12:58:44 +0100154 super().__init__(self.default_path, 'TF-PSA-Crypto', filename)
Gabor Mezei31911442024-11-20 17:05:16 +0100155
156
Gabor Mezeiafc5fa52024-11-29 12:57:53 +0100157class TFPSACryptoConfig(config_common.Config):
Gabor Mezei31911442024-11-20 17:05:16 +0100158 """Representation of the TF PSA Crypto configuration.
159
160 See the documentation of the `Config` class for methods to query
161 and modify the configuration.
162 """
163
Gabor Mezeifb368142024-12-05 10:11:46 +0100164 def __init__(self, filename=None):
Gabor Mezei31911442024-11-20 17:05:16 +0100165 """Read the PSA crypto configuration files."""
166
167 super().__init__()
Gabor Mezei680a7c32024-11-29 13:09:10 +0100168 configfile = TFPSACryptoConfigFile(filename)
169 self.configfiles.append(configfile)
Gabor Mezei31911442024-11-20 17:05:16 +0100170 self.settings.update({name: config_common.Setting(configfile, active, name, value, section)
Gabor Mezei31911442024-11-20 17:05:16 +0100171 for (active, name, value, section) in configfile.parse_file()})
172
173 def set(self, name, value=None):
174 """Set name to the given value and make it active."""
175
176 if name in PSA_UNSUPPORTED_FEATURE:
177 raise ValueError(f'Feature is unsupported: \'{name}\'')
178 if name in PSA_UNSTABLE_FEATURE:
179 raise ValueError(f'Feature is unstable: \'{name}\'')
180
181 if name not in self.settings:
182 self._get_configfile().templates.append((name, '', f'#define {name} '))
183
184 # Default value for PSA macros is '1'
Gabor Mezeifc719d62024-12-05 18:40:22 +0100185 if not value and re.match(PSA_SYMBOL_REGEXP, name):
Gabor Mezei31911442024-11-20 17:05:16 +0100186 value = '1'
187
188 super().set(name, value)
189
190
Gabor Mezeiafc5fa52024-11-29 12:57:53 +0100191class TFPSACryptoConfigTool(config_common.ConfigTool):
Gabor Mezei31911442024-11-20 17:05:16 +0100192 """Command line TF PSA Crypto config file manipulation tool."""
193
194 def __init__(self):
Gabor Mezei680a7c32024-11-29 13:09:10 +0100195 super().__init__(TFPSACryptoConfigFile.default_path[0])
196 self.config = TFPSACryptoConfig(self.args.file)
Gabor Mezei31911442024-11-20 17:05:16 +0100197
198 def custom_parser_options(self):
199 """Adds TF PSA Crypto specific options for the parser."""
200
Gabor Mezei871cde62024-11-20 17:08:19 +0100201 self.add_adapter(
202 'full', full_adapter,
203 """Uncomment most features.
204 Exclude alternative implementations and platform support options, as well as
205 some options that are awkward to test.
206 """)
207
Gabor Mezei31911442024-11-20 17:05:16 +0100208
209if __name__ == '__main__':
Gabor Mezeiafc5fa52024-11-29 12:57:53 +0100210 sys.exit(TFPSACryptoConfigTool().main())