blob: 30b6067578d9d66a8d41b820f50110b9d4d59220 [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)
Gabor Mezei871cde62024-11-20 17:08:19 +010080 *PSA_UNSUPPORTED_FEATURE,
81 *PSA_DEPRECATED_FEATURE,
82 *PSA_UNSTABLE_FEATURE
83])
84
85def is_boolean_setting(name, value):
86 """Is this a boolean setting?
87
88 Mbed TLS boolean settings are enabled if the preprocessor macro is
89 defined, and disabled if the preprocessor macro is not defined. The
90 macro definition line in the configuration file has an empty expansion.
91
92 PSA_WANT_xxx settings are also boolean, but when they are enabled,
93 they expand to a nonzero value. We leave them undefined when they
94 are disabled. (Setting them to 0 currently means to enable them, but
95 this might change to mean disabling them. Currently we just never set
96 them to 0.)
97 """
Gabor Mezeifc719d62024-12-05 18:40:22 +010098 if re.match(PSA_SYMBOL_REGEXP, name):
Gabor Mezei871cde62024-11-20 17:08:19 +010099 return True
100 if not value:
101 return True
102 return False
103
Gabor Mezei1a7bbe12024-12-05 10:17:13 +0100104def is_seamless_alt(name):
105 """Whether the xxx_ALT symbol should be included in the full configuration.
106
107 Include alternative implementations of platform functions, which are
108 configurable function pointers that default to the built-in function.
109 This way we test that the function pointers exist and build correctly
110 without changing the behavior, and tests can verify that the function
111 pointers are used by modifying those pointers.
112
113 Exclude alternative implementations of library functions since they require
114 an implementation of the relevant functions and an xxx_alt.h header.
115 """
116 if name in (
117 'MBEDTLS_PLATFORM_GMTIME_R_ALT',
118 'MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT',
119 'MBEDTLS_PLATFORM_MS_TIME_ALT',
120 'MBEDTLS_PLATFORM_ZEROIZE_ALT',
121 ):
122 # Similar to non-platform xxx_ALT, requires platform_alt.h
123 return False
124 return name.startswith('MBEDTLS_PLATFORM_')
125
Gabor Mezei871cde62024-11-20 17:08:19 +0100126def include_in_full(name):
127 """Rules for symbols in the "full" configuration."""
128 if name in EXCLUDE_FROM_FULL:
129 return False
Gabor Mezei1a7bbe12024-12-05 10:17:13 +0100130 if name.endswith('_ALT'):
131 return is_seamless_alt(name)
Gabor Mezei871cde62024-11-20 17:08:19 +0100132 return True
133
134def full_adapter(name, value, active):
135 """Config adapter for "full"."""
136 if not is_boolean_setting(name, value):
137 return active
138 return include_in_full(name)
139
Gabor Mezei31911442024-11-20 17:05:16 +0100140
Gabor Mezeiafc5fa52024-11-29 12:57:53 +0100141class TFPSACryptoConfigFile(config_common.ConfigFile):
Gabor Mezei31911442024-11-20 17:05:16 +0100142 """Representation of a TF PSA Crypto configuration file."""
143
Gabor Mezei37bf61e2024-11-29 12:59:26 +0100144 _path_in_tree = 'include/psa/crypto_config.h'
Gabor Mezei31911442024-11-20 17:05:16 +0100145 default_path = [_path_in_tree,
146 os.path.join(os.path.dirname(__file__),
147 os.pardir,
148 _path_in_tree),
Gabor Mezeic716aad2024-12-05 18:41:27 +0100149 os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
Gabor Mezei31911442024-11-20 17:05:16 +0100150 _path_in_tree)]
151
152 def __init__(self, filename=None):
Gabor Mezei1044a802024-11-29 12:58:44 +0100153 super().__init__(self.default_path, 'TF-PSA-Crypto', filename)
Gabor Mezei31911442024-11-20 17:05:16 +0100154
155
Gabor Mezeiafc5fa52024-11-29 12:57:53 +0100156class TFPSACryptoConfig(config_common.Config):
Gabor Mezei31911442024-11-20 17:05:16 +0100157 """Representation of the TF PSA Crypto configuration.
158
159 See the documentation of the `Config` class for methods to query
160 and modify the configuration.
161 """
162
Gabor Mezeifb368142024-12-05 10:11:46 +0100163 def __init__(self, filename=None):
Gabor Mezei31911442024-11-20 17:05:16 +0100164 """Read the PSA crypto configuration files."""
165
166 super().__init__()
Gabor Mezei680a7c32024-11-29 13:09:10 +0100167 configfile = TFPSACryptoConfigFile(filename)
168 self.configfiles.append(configfile)
Gabor Mezei31911442024-11-20 17:05:16 +0100169 self.settings.update({name: config_common.Setting(configfile, active, name, value, section)
Gabor Mezei31911442024-11-20 17:05:16 +0100170 for (active, name, value, section) in configfile.parse_file()})
171
172 def set(self, name, value=None):
173 """Set name to the given value and make it active."""
174
175 if name in PSA_UNSUPPORTED_FEATURE:
176 raise ValueError(f'Feature is unsupported: \'{name}\'')
177 if name in PSA_UNSTABLE_FEATURE:
178 raise ValueError(f'Feature is unstable: \'{name}\'')
179
180 if name not in self.settings:
181 self._get_configfile().templates.append((name, '', f'#define {name} '))
182
183 # Default value for PSA macros is '1'
Gabor Mezeifc719d62024-12-05 18:40:22 +0100184 if not value and re.match(PSA_SYMBOL_REGEXP, name):
Gabor Mezei31911442024-11-20 17:05:16 +0100185 value = '1'
186
187 super().set(name, value)
188
189
Gabor Mezeiafc5fa52024-11-29 12:57:53 +0100190class TFPSACryptoConfigTool(config_common.ConfigTool):
Gabor Mezei31911442024-11-20 17:05:16 +0100191 """Command line TF PSA Crypto config file manipulation tool."""
192
193 def __init__(self):
Gabor Mezei680a7c32024-11-29 13:09:10 +0100194 super().__init__(TFPSACryptoConfigFile.default_path[0])
195 self.config = TFPSACryptoConfig(self.args.file)
Gabor Mezei31911442024-11-20 17:05:16 +0100196
197 def custom_parser_options(self):
198 """Adds TF PSA Crypto specific options for the parser."""
199
Gabor Mezei871cde62024-11-20 17:08:19 +0100200 self.add_adapter(
201 'full', full_adapter,
202 """Uncomment most features.
203 Exclude alternative implementations and platform support options, as well as
204 some options that are awkward to test.
205 """)
206
Gabor Mezei31911442024-11-20 17:05:16 +0100207
208if __name__ == '__main__':
Gabor Mezeiafc5fa52024-11-29 12:57:53 +0100209 sys.exit(TFPSACryptoConfigTool().main())