blob: a5253b4c0aaa4d011bc676cbedb8d5bcb5756d43 [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
14import os
15import sys
16
17import framework_scripts_path # pylint: disable=unused-import
18from mbedtls_framework import config_common
19
20
21PSA_UNSUPPORTED_FEATURE = frozenset([
22 'PSA_WANT_ALG_CBC_MAC',
23 'PSA_WANT_ALG_XTS',
24 'PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE',
25 'PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE'
26])
27
Gabor Mezei871cde62024-11-20 17:08:19 +010028PSA_DEPRECATED_FEATURE = frozenset([
29 'PSA_WANT_KEY_TYPE_ECC_KEY_PAIR',
30 'PSA_WANT_KEY_TYPE_RSA_KEY_PAIR'
31])
32
Gabor Mezei31911442024-11-20 17:05:16 +010033PSA_UNSTABLE_FEATURE = frozenset([
34 'PSA_WANT_ECC_SECP_K1_224'
35])
36
Gabor Mezei871cde62024-11-20 17:08:19 +010037# The goal of the full configuration is to have everything that can be tested
38# together. This includes deprecated or insecure options. It excludes:
39# * Options that require additional build dependencies or unusual hardware.
40# * Options that make testing less effective.
41# * Options that are incompatible with other options, or more generally that
42# interact with other parts of the code in such a way that a bulk enabling
43# is not a good way to test them.
44# * Options that remove features.
45EXCLUDE_FROM_FULL = frozenset([
46 #pylint: disable=line-too-long
47 'MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH', # interacts with CTR_DRBG_128_BIT_KEY
48 'MBEDTLS_AES_USE_HARDWARE_ONLY', # hardware dependency
49 'MBEDTLS_BLOCK_CIPHER_NO_DECRYPT', # incompatible with ECB in PSA, CBC/XTS/NIST_KW/DES
50 'MBEDTLS_CTR_DRBG_USE_128_BIT_KEY', # interacts with ENTROPY_FORCE_SHA256
51 'MBEDTLS_DEPRECATED_REMOVED', # conflicts with deprecated options
52 'MBEDTLS_DEPRECATED_WARNING', # conflicts with deprecated options
53 'MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED', # influences the use of ECDH in TLS
54 'MBEDTLS_ECP_WITH_MPI_UINT', # disables the default ECP and is experimental
55 'MBEDTLS_ENTROPY_FORCE_SHA256', # interacts with CTR_DRBG_128_BIT_KEY
56 'MBEDTLS_HAVE_SSE2', # hardware dependency
57 'MBEDTLS_MEMORY_BACKTRACE', # depends on MEMORY_BUFFER_ALLOC_C
58 'MBEDTLS_MEMORY_DEBUG', # depends on MEMORY_BUFFER_ALLOC_C
59 'MBEDTLS_NO_64BIT_MULTIPLICATION', # influences anything that uses bignum
60 'MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES', # removes a feature
61 'MBEDTLS_NO_PLATFORM_ENTROPY', # removes a feature
62 'MBEDTLS_NO_UDBL_DIVISION', # influences anything that uses bignum
63 'MBEDTLS_PSA_P256M_DRIVER_ENABLED', # influences SECP256R1 KeyGen/ECDH/ECDSA
64 'MBEDTLS_PLATFORM_NO_STD_FUNCTIONS', # removes a feature
65 'MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS', # removes a feature
66 'MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG', # behavior change + build dependency
67 'MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER', # interface and behavior change
68 'MBEDTLS_PSA_CRYPTO_SPM', # platform dependency (PSA SPM)
69 'MBEDTLS_PSA_INJECT_ENTROPY', # conflicts with platform entropy sources
70 'MBEDTLS_RSA_NO_CRT', # influences the use of RSA in X.509 and TLS
71 'MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY', # interacts with *_USE_A64_CRYPTO_IF_PRESENT
72 'MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY', # interacts with *_USE_ARMV8_A_CRYPTO_IF_PRESENT
73 'MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY', # interacts with *_USE_A64_CRYPTO_IF_PRESENT
74 'MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT', # setting *_USE_ARMV8_A_CRYPTO is sufficient
75 'MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN', # build dependency (clang+memsan)
76 'MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND', # build dependency (valgrind headers)
77 'MBEDTLS_X509_REMOVE_INFO', # removes a feature
78 *PSA_UNSUPPORTED_FEATURE,
79 *PSA_DEPRECATED_FEATURE,
80 *PSA_UNSTABLE_FEATURE
81])
82
83def is_boolean_setting(name, value):
84 """Is this a boolean setting?
85
86 Mbed TLS boolean settings are enabled if the preprocessor macro is
87 defined, and disabled if the preprocessor macro is not defined. The
88 macro definition line in the configuration file has an empty expansion.
89
90 PSA_WANT_xxx settings are also boolean, but when they are enabled,
91 they expand to a nonzero value. We leave them undefined when they
92 are disabled. (Setting them to 0 currently means to enable them, but
93 this might change to mean disabling them. Currently we just never set
94 them to 0.)
95 """
96 if name.startswith('PSA_WANT_'):
97 return True
98 if not value:
99 return True
100 return False
101
Gabor Mezei1a7bbe12024-12-05 10:17:13 +0100102def is_seamless_alt(name):
103 """Whether the xxx_ALT symbol should be included in the full configuration.
104
105 Include alternative implementations of platform functions, which are
106 configurable function pointers that default to the built-in function.
107 This way we test that the function pointers exist and build correctly
108 without changing the behavior, and tests can verify that the function
109 pointers are used by modifying those pointers.
110
111 Exclude alternative implementations of library functions since they require
112 an implementation of the relevant functions and an xxx_alt.h header.
113 """
114 if name in (
115 'MBEDTLS_PLATFORM_GMTIME_R_ALT',
116 'MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT',
117 'MBEDTLS_PLATFORM_MS_TIME_ALT',
118 'MBEDTLS_PLATFORM_ZEROIZE_ALT',
119 ):
120 # Similar to non-platform xxx_ALT, requires platform_alt.h
121 return False
122 return name.startswith('MBEDTLS_PLATFORM_')
123
Gabor Mezei871cde62024-11-20 17:08:19 +0100124def include_in_full(name):
125 """Rules for symbols in the "full" configuration."""
126 if name in EXCLUDE_FROM_FULL:
127 return False
Gabor Mezei1a7bbe12024-12-05 10:17:13 +0100128 if name.endswith('_ALT'):
129 return is_seamless_alt(name)
Gabor Mezei871cde62024-11-20 17:08:19 +0100130 return True
131
132def full_adapter(name, value, active):
133 """Config adapter for "full"."""
134 if not is_boolean_setting(name, value):
135 return active
136 return include_in_full(name)
137
Gabor Mezei31911442024-11-20 17:05:16 +0100138
Gabor Mezeiafc5fa52024-11-29 12:57:53 +0100139class TFPSACryptoConfigFile(config_common.ConfigFile):
Gabor Mezei31911442024-11-20 17:05:16 +0100140 """Representation of a TF PSA Crypto configuration file."""
141
Gabor Mezei37bf61e2024-11-29 12:59:26 +0100142 _path_in_tree = 'include/psa/crypto_config.h'
Gabor Mezei31911442024-11-20 17:05:16 +0100143 default_path = [_path_in_tree,
144 os.path.join(os.path.dirname(__file__),
145 os.pardir,
146 _path_in_tree),
147 os.path.join(os.path.dirname(os.path.abspath(os.path.dirname(__file__))),
148 _path_in_tree)]
149
150 def __init__(self, filename=None):
Gabor Mezei1044a802024-11-29 12:58:44 +0100151 super().__init__(self.default_path, 'TF-PSA-Crypto', filename)
Gabor Mezei31911442024-11-20 17:05:16 +0100152
153
Gabor Mezeiafc5fa52024-11-29 12:57:53 +0100154class TFPSACryptoConfig(config_common.Config):
Gabor Mezei31911442024-11-20 17:05:16 +0100155 """Representation of the TF PSA Crypto configuration.
156
157 See the documentation of the `Config` class for methods to query
158 and modify the configuration.
159 """
160
Gabor Mezeifb368142024-12-05 10:11:46 +0100161 def __init__(self, filename=None):
Gabor Mezei31911442024-11-20 17:05:16 +0100162 """Read the PSA crypto configuration files."""
163
164 super().__init__()
Gabor Mezei680a7c32024-11-29 13:09:10 +0100165 configfile = TFPSACryptoConfigFile(filename)
166 self.configfiles.append(configfile)
Gabor Mezei31911442024-11-20 17:05:16 +0100167 self.settings.update({name: config_common.Setting(configfile, active, name, value, section)
Gabor Mezei31911442024-11-20 17:05:16 +0100168 for (active, name, value, section) in configfile.parse_file()})
169
170 def set(self, name, value=None):
171 """Set name to the given value and make it active."""
172
173 if name in PSA_UNSUPPORTED_FEATURE:
174 raise ValueError(f'Feature is unsupported: \'{name}\'')
175 if name in PSA_UNSTABLE_FEATURE:
176 raise ValueError(f'Feature is unstable: \'{name}\'')
177
178 if name not in self.settings:
179 self._get_configfile().templates.append((name, '', f'#define {name} '))
180
181 # Default value for PSA macros is '1'
182 if name.startswith('PSA_') and not value:
183 value = '1'
184
185 super().set(name, value)
186
187
Gabor Mezeiafc5fa52024-11-29 12:57:53 +0100188class TFPSACryptoConfigTool(config_common.ConfigTool):
Gabor Mezei31911442024-11-20 17:05:16 +0100189 """Command line TF PSA Crypto config file manipulation tool."""
190
191 def __init__(self):
Gabor Mezei680a7c32024-11-29 13:09:10 +0100192 super().__init__(TFPSACryptoConfigFile.default_path[0])
193 self.config = TFPSACryptoConfig(self.args.file)
Gabor Mezei31911442024-11-20 17:05:16 +0100194
195 def custom_parser_options(self):
196 """Adds TF PSA Crypto specific options for the parser."""
197
Gabor Mezei871cde62024-11-20 17:08:19 +0100198 self.add_adapter(
199 'full', full_adapter,
200 """Uncomment most features.
201 Exclude alternative implementations and platform support options, as well as
202 some options that are awkward to test.
203 """)
204
Gabor Mezei31911442024-11-20 17:05:16 +0100205
206if __name__ == '__main__':
Gabor Mezeiafc5fa52024-11-29 12:57:53 +0100207 sys.exit(TFPSACryptoConfigTool().main())