blob: 105a4aaeddd9868004e41d42f28149fe45804f65 [file] [log] [blame]
Gilles Peskine15c2cbf2020-06-25 18:36:28 +02001#!/usr/bin/env python3
2
3"""Analyze the test outcomes from a full CI run.
4
5This script can also run on outcomes from a partial run, but the results are
6less likely to be useful.
7"""
8
9import argparse
10import sys
11import traceback
Przemek Stekiel85c54ea2022-11-17 11:50:23 +010012import re
Valerio Settia2663322023-03-24 08:20:18 +010013import subprocess
14import os
Gilles Peskine15c2cbf2020-06-25 18:36:28 +020015
Gilles Peskine8d3c70a2020-06-25 18:37:43 +020016import check_test_cases
17
Valerio Settiaaef0bc2023-10-10 09:42:13 +020018class TestLog:
Gilles Peskine15c2cbf2020-06-25 18:36:28 +020019 """Process analysis results."""
20
21 def __init__(self):
22 self.error_count = 0
23 self.warning_count = 0
Valerio Settiaaef0bc2023-10-10 09:42:13 +020024 self.output = ""
Gilles Peskine15c2cbf2020-06-25 18:36:28 +020025
Valerio Settiaaef0bc2023-10-10 09:42:13 +020026 def add_line(self, fmt, *args, **kwargs):
27 self.output = self.output + (fmt + '\n').format(*args, **kwargs)
28
29 def info(self, fmt, *args, **kwargs):
Valerio Settib0c618e2023-10-16 14:19:49 +020030 self.add_line('Info: ' + fmt, *args, **kwargs)
Gilles Peskine15c2cbf2020-06-25 18:36:28 +020031
32 def error(self, fmt, *args, **kwargs):
Valerio Settiaaef0bc2023-10-10 09:42:13 +020033 self.info('Error: ' + fmt, *args, **kwargs)
Gilles Peskine15c2cbf2020-06-25 18:36:28 +020034 self.error_count += 1
35
36 def warning(self, fmt, *args, **kwargs):
Valerio Settiaaef0bc2023-10-10 09:42:13 +020037 self.info('Warning: ' + fmt, *args, **kwargs)
Gilles Peskine15c2cbf2020-06-25 18:36:28 +020038 self.warning_count += 1
39
Valerio Settiaaef0bc2023-10-10 09:42:13 +020040 def print_output(self):
41 sys.stderr.write(self.output)
42
Gilles Peskine15c2cbf2020-06-25 18:36:28 +020043class TestCaseOutcomes:
44 """The outcomes of one test case across many configurations."""
45 # pylint: disable=too-few-public-methods
46
47 def __init__(self):
Gilles Peskine3d863f22020-06-26 13:02:30 +020048 # Collect a list of witnesses of the test case succeeding or failing.
49 # Currently we don't do anything with witnesses except count them.
50 # The format of a witness is determined by the read_outcome_file
51 # function; it's the platform and configuration joined by ';'.
Gilles Peskine15c2cbf2020-06-25 18:36:28 +020052 self.successes = []
53 self.failures = []
54
55 def hits(self):
56 """Return the number of times a test case has been run.
57
58 This includes passes and failures, but not skips.
59 """
60 return len(self.successes) + len(self.failures)
61
Valerio Settiaaef0bc2023-10-10 09:42:13 +020062def execute_reference_driver_tests(log: TestLog, ref_component, driver_component, \
63 outcome_file) -> TestLog:
Valerio Setti22992a02023-03-29 11:15:28 +020064 """Run the tests specified in ref_component and driver_component. Results
65 are stored in the output_file and they will be used for the following
Valerio Settia2663322023-03-24 08:20:18 +010066 coverage analysis"""
67 # If the outcome file already exists, we assume that the user wants to
68 # perform the comparison analysis again without repeating the tests.
69 if os.path.exists(outcome_file):
Valerio Settiaaef0bc2023-10-10 09:42:13 +020070 log.info("Outcome file (" + outcome_file + ") already exists. " + \
71 "Tests will be skipped.")
72 return log
Valerio Settia2663322023-03-24 08:20:18 +010073
74 shell_command = "tests/scripts/all.sh --outcome-file " + outcome_file + \
75 " " + ref_component + " " + driver_component
Valerio Settiaaef0bc2023-10-10 09:42:13 +020076 log.info("Running: " + shell_command)
Valerio Settia2663322023-03-24 08:20:18 +010077 ret_val = subprocess.run(shell_command.split(), check=False).returncode
78
79 if ret_val != 0:
Valerio Settiaaef0bc2023-10-10 09:42:13 +020080 log.error("failed to run reference/driver components")
81
82 return log
Valerio Settia2663322023-03-24 08:20:18 +010083
Tomás Gonzálezb401e112023-08-11 15:22:04 +010084def analyze_coverage(results, outcomes, allow_list, full_coverage):
Gilles Peskine8d3c70a2020-06-25 18:37:43 +020085 """Check that all available test cases are executed at least once."""
Gilles Peskine686c2922022-01-07 15:58:38 +010086 available = check_test_cases.collect_available_test_cases()
Gilles Peskine8d3c70a2020-06-25 18:37:43 +020087 for key in available:
88 hits = outcomes[key].hits() if key in outcomes else 0
Tomás González07bdcc22023-08-11 14:59:03 +010089 if hits == 0 and key not in allow_list:
Tomás Gonzálezb401e112023-08-11 15:22:04 +010090 if full_coverage:
91 results.error('Test case not executed: {}', key)
92 else:
93 results.warning('Test case not executed: {}', key)
Tomás González07bdcc22023-08-11 14:59:03 +010094 elif hits != 0 and key in allow_list:
95 # Test Case should be removed from the allow list.
Tomás González7ebb18f2023-08-22 09:40:23 +010096 if full_coverage:
Tomás Gonzáleza0631442023-08-22 12:17:57 +010097 results.error('Allow listed test case was executed: {}', key)
Tomás González7ebb18f2023-08-22 09:40:23 +010098 else:
99 results.warning('Allow listed test case was executed: {}', key)
Gilles Peskine8d3c70a2020-06-25 18:37:43 +0200100
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200101def analyze_driver_vs_reference(log: TestLog, outcomes,
102 component_ref, component_driver,
Valerio Setti3002c992023-01-18 17:28:36 +0100103 ignored_suites, ignored_test=None):
Przemek Stekiel4e955902022-10-21 13:42:08 +0200104 """Check that all tests executed in the reference component are also
105 executed in the corresponding driver component.
Valerio Setti3002c992023-01-18 17:28:36 +0100106 Skip:
107 - full test suites provided in ignored_suites list
108 - only some specific test inside a test suite, for which the corresponding
109 output string is provided
Przemek Stekiel4e955902022-10-21 13:42:08 +0200110 """
Przemek Stekiel4e955902022-10-21 13:42:08 +0200111 available = check_test_cases.collect_available_test_cases()
Przemek Stekiel4e955902022-10-21 13:42:08 +0200112
113 for key in available:
Przemek Stekiel4e955902022-10-21 13:42:08 +0200114 # Continue if test was not executed by any component
115 hits = outcomes[key].hits() if key in outcomes else 0
Przemek Stekielc86dedf2022-10-24 09:16:04 +0200116 if hits == 0:
Przemek Stekiel4e955902022-10-21 13:42:08 +0200117 continue
Valerio Setti00c1ccb2023-02-02 11:33:31 +0100118 # Skip ignored test suites
119 full_test_suite = key.split(';')[0] # retrieve full test suite name
120 test_string = key.split(';')[1] # retrieve the text string of this test
121 test_suite = full_test_suite.split('.')[0] # retrieve main part of test suite name
Manuel Pégourié-Gonnard7d381f52023-03-17 15:13:08 +0100122 if test_suite in ignored_suites or full_test_suite in ignored_suites:
Valerio Setti00c1ccb2023-02-02 11:33:31 +0100123 continue
Valerio Setti3002c992023-01-18 17:28:36 +0100124 if ((full_test_suite in ignored_test) and
125 (test_string in ignored_test[full_test_suite])):
126 continue
Przemek Stekiel4e955902022-10-21 13:42:08 +0200127 # Search for tests that run in reference component and not in driver component
128 driver_test_passed = False
129 reference_test_passed = False
130 for entry in outcomes[key].successes:
Przemek Stekiel51f30ff2022-11-09 12:07:29 +0100131 if component_driver in entry:
Przemek Stekiel4e955902022-10-21 13:42:08 +0200132 driver_test_passed = True
Przemek Stekiel51f30ff2022-11-09 12:07:29 +0100133 if component_ref in entry:
Przemek Stekiel4e955902022-10-21 13:42:08 +0200134 reference_test_passed = True
Manuel Pégourié-Gonnardc6967d22022-12-30 13:40:34 +0100135 if(reference_test_passed and not driver_test_passed):
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200136 log.error(key)
Przemek Stekiel4e955902022-10-21 13:42:08 +0200137
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200138 return log
139
140def analyze_outcomes(log: TestLog, outcomes, args) -> TestLog:
Gilles Peskine15c2cbf2020-06-25 18:36:28 +0200141 """Run all analyses on the given outcome collection."""
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200142 analyze_coverage(log, outcomes, args['allow_list'],
Tomás Gonzálezb401e112023-08-11 15:22:04 +0100143 args['full_coverage'])
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200144 return log
Gilles Peskine15c2cbf2020-06-25 18:36:28 +0200145
146def read_outcome_file(outcome_file):
147 """Parse an outcome file and return an outcome collection.
148
149An outcome collection is a dictionary mapping keys to TestCaseOutcomes objects.
150The keys are the test suite name and the test case description, separated
151by a semicolon.
152"""
153 outcomes = {}
154 with open(outcome_file, 'r', encoding='utf-8') as input_file:
155 for line in input_file:
156 (platform, config, suite, case, result, _cause) = line.split(';')
157 key = ';'.join([suite, case])
158 setup = ';'.join([platform, config])
159 if key not in outcomes:
160 outcomes[key] = TestCaseOutcomes()
161 if result == 'PASS':
162 outcomes[key].successes.append(setup)
163 elif result == 'FAIL':
164 outcomes[key].failures.append(setup)
165 return outcomes
166
Przemek Stekiel4d13c832022-10-26 16:11:26 +0200167def do_analyze_coverage(outcome_file, args):
Przemek Stekiel6856f4c2022-11-09 10:50:29 +0100168 """Perform coverage analysis."""
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200169 log = TestLog()
170 log.info("\n*** Analyze coverage ***\n")
Gilles Peskine15c2cbf2020-06-25 18:36:28 +0200171 outcomes = read_outcome_file(outcome_file)
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200172 log = analyze_outcomes(log, outcomes, args)
173 return log
Przemek Stekiel4e955902022-10-21 13:42:08 +0200174
Przemek Stekiel4d13c832022-10-26 16:11:26 +0200175def do_analyze_driver_vs_reference(outcome_file, args):
Przemek Stekiel4e955902022-10-21 13:42:08 +0200176 """Perform driver vs reference analyze."""
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200177 log = TestLog()
178
Valerio Settib0c618e2023-10-16 14:19:49 +0200179 log.info("\n*** Analyze driver {} vs reference {} ***\n".format(
180 args['component_driver'], args['component_ref']))
181
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200182 log = execute_reference_driver_tests(log, args['component_ref'], \
183 args['component_driver'], outcome_file)
184 if log.error_count != 0:
185 return log
Valerio Settia2663322023-03-24 08:20:18 +0100186
Valerio Setti3002c992023-01-18 17:28:36 +0100187 ignored_suites = ['test_suite_' + x for x in args['ignored_suites']]
Przemek Stekiel51f30ff2022-11-09 12:07:29 +0100188
Przemek Stekiel4e955902022-10-21 13:42:08 +0200189 outcomes = read_outcome_file(outcome_file)
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200190
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200191 log = analyze_driver_vs_reference(log, outcomes,
192 args['component_ref'], args['component_driver'],
193 ignored_suites, args['ignored_tests'])
194
195 return log
Gilles Peskine15c2cbf2020-06-25 18:36:28 +0200196
Przemek Stekiel6856f4c2022-11-09 10:50:29 +0100197# List of tasks with a function that can handle this task and additional arguments if required
Valerio Settidfd7ca62023-10-09 16:30:11 +0200198KNOWN_TASKS = {
Przemek Stekiel4d13c832022-10-26 16:11:26 +0200199 'analyze_coverage': {
200 'test_function': do_analyze_coverage,
Tomás González07bdcc22023-08-11 14:59:03 +0100201 'args': {
Tomás González358c6c62023-08-14 15:43:46 +0100202 'allow_list': [
Tomás González50223112023-08-22 09:52:06 +0100203 # Algorithm not supported yet
204 'test_suite_psa_crypto_metadata;Asymmetric signature: pure EdDSA',
205 # Algorithm not supported yet
206 'test_suite_psa_crypto_metadata;Cipher: XTS',
Tomás Gonzálezd43cab32023-08-24 09:12:40 +0100207 ],
Tomás Gonzálezb401e112023-08-11 15:22:04 +0100208 'full_coverage': False,
Tomás González07bdcc22023-08-11 14:59:03 +0100209 }
Tomás Gonzálezd43cab32023-08-24 09:12:40 +0100210 },
Valerio Settia2663322023-03-24 08:20:18 +0100211 # There are 2 options to use analyze_driver_vs_reference_xxx locally:
212 # 1. Run tests and then analysis:
213 # - tests/scripts/all.sh --outcome-file "$PWD/out.csv" <component_ref> <component_driver>
214 # - tests/scripts/analyze_outcomes.py out.csv analyze_driver_vs_reference_xxx
215 # 2. Let this script run both automatically:
216 # - tests/scripts/analyze_outcomes.py out.csv analyze_driver_vs_reference_xxx
Przemek Stekiel4d13c832022-10-26 16:11:26 +0200217 'analyze_driver_vs_reference_hash': {
218 'test_function': do_analyze_driver_vs_reference,
219 'args': {
Przemek Stekiel51f30ff2022-11-09 12:07:29 +0100220 'component_ref': 'test_psa_crypto_config_reference_hash_use_psa',
221 'component_driver': 'test_psa_crypto_config_accel_hash_use_psa',
Manuel Pégourié-Gonnard10e39632022-12-29 12:29:09 +0100222 'ignored_suites': [
223 'shax', 'mdx', # the software implementations that are being excluded
Manuel Pégourié-Gonnard7d381f52023-03-17 15:13:08 +0100224 'md.psa', # purposefully depends on whether drivers are present
Gilles Peskine35b49c42023-10-04 12:28:41 +0200225 'psa_crypto_low_hash.generated', # testing the builtins
Valerio Setti3002c992023-01-18 17:28:36 +0100226 ],
227 'ignored_tests': {
228 }
229 }
230 },
Valerio Setti4d25a8d2023-06-14 10:33:10 +0200231 'analyze_driver_vs_reference_ecp_light_only': {
Valerio Setti42d5f192023-03-20 13:54:41 +0100232 'test_function': do_analyze_driver_vs_reference,
233 'args': {
Valerio Setti4d25a8d2023-06-14 10:33:10 +0200234 'component_ref': 'test_psa_crypto_config_reference_ecc_ecp_light_only',
235 'component_driver': 'test_psa_crypto_config_accel_ecc_ecp_light_only',
Valerio Setti42d5f192023-03-20 13:54:41 +0100236 'ignored_suites': [
237 'ecdsa',
238 'ecdh',
239 'ecjpake',
240 ],
241 'ignored_tests': {
242 'test_suite_random': [
243 'PSA classic wrapper: ECDSA signature (SECP256R1)',
244 ],
Valerio Setti0c477d32023-04-07 15:54:20 +0200245 # In the accelerated test ECP_C is not set (only ECP_LIGHT is)
246 # so we must ignore disparities in the tests for which ECP_C
247 # is required.
248 'test_suite_ecp': [
249 'ECP check public-private #1 (OK)',
250 'ECP check public-private #2 (group none)',
251 'ECP check public-private #3 (group mismatch)',
252 'ECP check public-private #4 (Qx mismatch)',
253 'ECP check public-private #5 (Qy mismatch)',
254 'ECP check public-private #6 (wrong Qx)',
255 'ECP check public-private #7 (wrong Qy)',
256 'ECP gen keypair [#1]',
257 'ECP gen keypair [#2]',
258 'ECP gen keypair [#3]',
259 'ECP gen keypair wrapper',
260 'ECP point muladd secp256r1 #1',
261 'ECP point muladd secp256r1 #2',
262 'ECP point multiplication Curve25519 (element of order 2: origin) #3',
263 'ECP point multiplication Curve25519 (element of order 4: 1) #4',
264 'ECP point multiplication Curve25519 (element of order 8) #5',
265 'ECP point multiplication Curve25519 (normalized) #1',
266 'ECP point multiplication Curve25519 (not normalized) #2',
267 'ECP point multiplication rng fail Curve25519',
268 'ECP point multiplication rng fail secp256r1',
269 'ECP test vectors Curve25519',
270 'ECP test vectors Curve448 (RFC 7748 6.2, after decodeUCoordinate)',
271 'ECP test vectors brainpoolP256r1 rfc 7027',
272 'ECP test vectors brainpoolP384r1 rfc 7027',
273 'ECP test vectors brainpoolP512r1 rfc 7027',
274 'ECP test vectors secp192k1',
275 'ECP test vectors secp192r1 rfc 5114',
276 'ECP test vectors secp224k1',
277 'ECP test vectors secp224r1 rfc 5114',
278 'ECP test vectors secp256k1',
279 'ECP test vectors secp256r1 rfc 5114',
280 'ECP test vectors secp384r1 rfc 5114',
281 'ECP test vectors secp521r1 rfc 5114',
Valerio Settie50a75f2023-05-19 17:43:06 +0200282 ],
Valerio Setti482a0b92023-08-18 15:55:10 +0200283 'test_suite_psa_crypto': [
284 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1',
285 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1 (1 redraw)',
286 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1, exercise ECDSA',
287 'PSA key derivation: HKDF-SHA-256 -> ECC secp384r1',
288 'PSA key derivation: HKDF-SHA-256 -> ECC secp521r1 #0',
289 'PSA key derivation: HKDF-SHA-256 -> ECC secp521r1 #1',
290 ],
Manuel Pégourié-Gonnardf07ce3b2023-09-22 11:53:41 +0200291 'test_suite_ssl': [
292 'Test configuration of groups for DHE through mbedtls_ssl_conf_curves()',
293 ],
Valerio Setti5f540202023-06-30 17:20:49 +0200294 }
Valerio Setti42d5f192023-03-20 13:54:41 +0100295 }
296 },
Valerio Setti4d25a8d2023-06-14 10:33:10 +0200297 'analyze_driver_vs_reference_no_ecp_at_all': {
Valerio Settie618cb02023-04-12 14:59:16 +0200298 'test_function': do_analyze_driver_vs_reference,
299 'args': {
Valerio Setti4d25a8d2023-06-14 10:33:10 +0200300 'component_ref': 'test_psa_crypto_config_reference_ecc_no_ecp_at_all',
301 'component_driver': 'test_psa_crypto_config_accel_ecc_no_ecp_at_all',
Valerio Settie618cb02023-04-12 14:59:16 +0200302 'ignored_suites': [
303 # Ignore test suites for the modules that are disabled in the
304 # accelerated test case.
305 'ecp',
306 'ecdsa',
307 'ecdh',
308 'ecjpake',
309 ],
310 'ignored_tests': {
311 'test_suite_random': [
312 'PSA classic wrapper: ECDSA signature (SECP256R1)',
313 ],
314 'test_suite_psa_crypto': [
315 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1',
316 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1 (1 redraw)',
317 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1, exercise ECDSA',
318 'PSA key derivation: HKDF-SHA-256 -> ECC secp384r1',
319 'PSA key derivation: HKDF-SHA-256 -> ECC secp521r1 #0',
320 'PSA key derivation: HKDF-SHA-256 -> ECC secp521r1 #1',
321 'PSA key derivation: bits=7 invalid for ECC BRAINPOOL_P_R1 (ECC enabled)',
322 'PSA key derivation: bits=7 invalid for ECC SECP_K1 (ECC enabled)',
323 'PSA key derivation: bits=7 invalid for ECC SECP_R1 (ECC enabled)',
324 'PSA key derivation: bits=7 invalid for ECC SECP_R2 (ECC enabled)',
325 'PSA key derivation: bits=7 invalid for ECC SECT_K1 (ECC enabled)',
326 'PSA key derivation: bits=7 invalid for ECC SECT_R1 (ECC enabled)',
327 'PSA key derivation: bits=7 invalid for ECC SECT_R2 (ECC enabled)',
Valerio Settiaddeee42023-06-14 10:46:55 +0200328 ],
329 'test_suite_pkparse': [
Valerio Setti5bd25232023-06-19 19:32:14 +0200330 # When PK_PARSE_C and ECP_C are defined then PK_PARSE_EC_COMPRESSED
331 # is automatically enabled in build_info.h (backward compatibility)
332 # even if it is disabled in config_psa_crypto_no_ecp_at_all(). As a
333 # consequence compressed points are supported in the reference
334 # component but not in the accelerated one, so they should be skipped
335 # while checking driver's coverage.
336 'Parse EC Key #10a (SEC1 PEM, secp384r1, compressed)',
337 'Parse EC Key #11a (SEC1 PEM, secp521r1, compressed)',
338 'Parse EC Key #12a (SEC1 PEM, bp256r1, compressed)',
339 'Parse EC Key #13a (SEC1 PEM, bp384r1, compressed)',
340 'Parse EC Key #14a (SEC1 PEM, bp512r1, compressed)',
341 'Parse EC Key #2a (SEC1 PEM, secp192r1, compressed)',
342 'Parse EC Key #8a (SEC1 PEM, secp224r1, compressed)',
343 'Parse EC Key #9a (SEC1 PEM, secp256r1, compressed)',
344 'Parse Public EC Key #2a (RFC 5480, PEM, secp192r1, compressed)',
345 'Parse Public EC Key #3a (RFC 5480, secp224r1, compressed)',
346 'Parse Public EC Key #4a (RFC 5480, secp256r1, compressed)',
347 'Parse Public EC Key #5a (RFC 5480, secp384r1, compressed)',
348 'Parse Public EC Key #6a (RFC 5480, secp521r1, compressed)',
349 'Parse Public EC Key #7a (RFC 5480, brainpoolP256r1, compressed)',
350 'Parse Public EC Key #8a (RFC 5480, brainpoolP384r1, compressed)',
351 'Parse Public EC Key #9a (RFC 5480, brainpoolP512r1, compressed)',
Valerio Settiaddeee42023-06-14 10:46:55 +0200352 ],
Manuel Pégourié-Gonnardf07ce3b2023-09-22 11:53:41 +0200353 'test_suite_ssl': [
354 'Test configuration of groups for DHE through mbedtls_ssl_conf_curves()',
355 ],
Valerio Settie618cb02023-04-12 14:59:16 +0200356 }
357 }
358 },
Valerio Setti307810b2023-08-15 10:12:25 +0200359 'analyze_driver_vs_reference_ecc_no_bignum': {
Manuel Pégourié-Gonnardabd00d02023-06-12 17:51:33 +0200360 'test_function': do_analyze_driver_vs_reference,
361 'args': {
362 'component_ref': 'test_psa_crypto_config_reference_ecc_no_bignum',
363 'component_driver': 'test_psa_crypto_config_accel_ecc_no_bignum',
364 'ignored_suites': [
365 # Ignore test suites for the modules that are disabled in the
366 # accelerated test case.
367 'ecp',
368 'ecdsa',
369 'ecdh',
370 'ecjpake',
Valerio Setti9b3dbcc2023-07-26 18:00:31 +0200371 'bignum_core',
372 'bignum_random',
373 'bignum_mod',
374 'bignum_mod_raw',
375 'bignum.generated',
376 'bignum.misc',
Manuel Pégourié-Gonnardabd00d02023-06-12 17:51:33 +0200377 ],
378 'ignored_tests': {
379 'test_suite_random': [
380 'PSA classic wrapper: ECDSA signature (SECP256R1)',
381 ],
382 'test_suite_psa_crypto': [
383 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1',
384 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1 (1 redraw)',
385 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1, exercise ECDSA',
386 'PSA key derivation: HKDF-SHA-256 -> ECC secp384r1',
387 'PSA key derivation: HKDF-SHA-256 -> ECC secp521r1 #0',
388 'PSA key derivation: HKDF-SHA-256 -> ECC secp521r1 #1',
389 'PSA key derivation: bits=7 invalid for ECC BRAINPOOL_P_R1 (ECC enabled)',
390 'PSA key derivation: bits=7 invalid for ECC SECP_K1 (ECC enabled)',
391 'PSA key derivation: bits=7 invalid for ECC SECP_R1 (ECC enabled)',
392 'PSA key derivation: bits=7 invalid for ECC SECP_R2 (ECC enabled)',
393 'PSA key derivation: bits=7 invalid for ECC SECT_K1 (ECC enabled)',
394 'PSA key derivation: bits=7 invalid for ECC SECT_R1 (ECC enabled)',
395 'PSA key derivation: bits=7 invalid for ECC SECT_R2 (ECC enabled)',
396 ],
397 'test_suite_pkparse': [
398 # See the description provided above in the
399 # analyze_driver_vs_reference_no_ecp_at_all component.
400 'Parse EC Key #10a (SEC1 PEM, secp384r1, compressed)',
401 'Parse EC Key #11a (SEC1 PEM, secp521r1, compressed)',
402 'Parse EC Key #12a (SEC1 PEM, bp256r1, compressed)',
403 'Parse EC Key #13a (SEC1 PEM, bp384r1, compressed)',
404 'Parse EC Key #14a (SEC1 PEM, bp512r1, compressed)',
405 'Parse EC Key #2a (SEC1 PEM, secp192r1, compressed)',
406 'Parse EC Key #8a (SEC1 PEM, secp224r1, compressed)',
407 'Parse EC Key #9a (SEC1 PEM, secp256r1, compressed)',
408 'Parse Public EC Key #2a (RFC 5480, PEM, secp192r1, compressed)',
409 'Parse Public EC Key #3a (RFC 5480, secp224r1, compressed)',
410 'Parse Public EC Key #4a (RFC 5480, secp256r1, compressed)',
411 'Parse Public EC Key #5a (RFC 5480, secp384r1, compressed)',
412 'Parse Public EC Key #6a (RFC 5480, secp521r1, compressed)',
413 'Parse Public EC Key #7a (RFC 5480, brainpoolP256r1, compressed)',
414 'Parse Public EC Key #8a (RFC 5480, brainpoolP384r1, compressed)',
415 'Parse Public EC Key #9a (RFC 5480, brainpoolP512r1, compressed)',
416 ],
Valerio Setti9b3dbcc2023-07-26 18:00:31 +0200417 'test_suite_asn1parse': [
418 # This test depends on BIGNUM_C
419 'INTEGER too large for mpi',
420 ],
421 'test_suite_asn1write': [
422 # Following tests depends on BIGNUM_C
423 'ASN.1 Write mpi 0 (1 limb)',
424 'ASN.1 Write mpi 0 (null)',
425 'ASN.1 Write mpi 0x100',
426 'ASN.1 Write mpi 0x7f',
427 'ASN.1 Write mpi 0x7f with leading 0 limb',
428 'ASN.1 Write mpi 0x80',
429 'ASN.1 Write mpi 0x80 with leading 0 limb',
430 'ASN.1 Write mpi 0xff',
431 'ASN.1 Write mpi 1',
432 'ASN.1 Write mpi, 127*8 bits',
433 'ASN.1 Write mpi, 127*8+1 bits',
434 'ASN.1 Write mpi, 127*8-1 bits',
435 'ASN.1 Write mpi, 255*8 bits',
436 'ASN.1 Write mpi, 255*8-1 bits',
437 'ASN.1 Write mpi, 256*8-1 bits',
438 ],
Valerio Settie0be95e2023-08-01 09:07:43 +0200439 'test_suite_debug': [
440 # Following tests depends on BIGNUM_C
441 'Debug print mbedtls_mpi #2: 3 bits',
442 'Debug print mbedtls_mpi: 0 (empty representation)',
443 'Debug print mbedtls_mpi: 0 (non-empty representation)',
444 'Debug print mbedtls_mpi: 49 bits',
445 'Debug print mbedtls_mpi: 759 bits',
446 'Debug print mbedtls_mpi: 764 bits #1',
447 'Debug print mbedtls_mpi: 764 bits #2',
448 ],
Manuel Pégourié-Gonnardf07ce3b2023-09-22 11:53:41 +0200449 'test_suite_ssl': [
450 'Test configuration of groups for DHE through mbedtls_ssl_conf_curves()',
451 ],
Manuel Pégourié-Gonnardabd00d02023-06-12 17:51:33 +0200452 }
453 }
454 },
Valerio Setti307810b2023-08-15 10:12:25 +0200455 'analyze_driver_vs_reference_ecc_ffdh_no_bignum': {
456 'test_function': do_analyze_driver_vs_reference,
457 'args': {
458 'component_ref': 'test_psa_crypto_config_reference_ecc_ffdh_no_bignum',
459 'component_driver': 'test_psa_crypto_config_accel_ecc_ffdh_no_bignum',
460 'ignored_suites': [
461 # Ignore test suites for the modules that are disabled in the
462 # accelerated test case.
463 'ecp',
464 'ecdsa',
465 'ecdh',
466 'ecjpake',
467 'bignum_core',
468 'bignum_random',
469 'bignum_mod',
470 'bignum_mod_raw',
471 'bignum.generated',
472 'bignum.misc',
473 'dhm',
474 ],
475 'ignored_tests': {
476 'test_suite_random': [
477 'PSA classic wrapper: ECDSA signature (SECP256R1)',
478 ],
479 'test_suite_psa_crypto': [
480 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1',
481 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1 (1 redraw)',
482 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1, exercise ECDSA',
483 'PSA key derivation: HKDF-SHA-256 -> ECC secp384r1',
484 'PSA key derivation: HKDF-SHA-256 -> ECC secp521r1 #0',
485 'PSA key derivation: HKDF-SHA-256 -> ECC secp521r1 #1',
486 'PSA key derivation: bits=7 invalid for ECC BRAINPOOL_P_R1 (ECC enabled)',
487 'PSA key derivation: bits=7 invalid for ECC SECP_K1 (ECC enabled)',
488 'PSA key derivation: bits=7 invalid for ECC SECP_R1 (ECC enabled)',
489 'PSA key derivation: bits=7 invalid for ECC SECP_R2 (ECC enabled)',
490 'PSA key derivation: bits=7 invalid for ECC SECT_K1 (ECC enabled)',
491 'PSA key derivation: bits=7 invalid for ECC SECT_R1 (ECC enabled)',
492 'PSA key derivation: bits=7 invalid for ECC SECT_R2 (ECC enabled)',
493 ],
494 'test_suite_pkparse': [
495 # See the description provided above in the
496 # analyze_driver_vs_reference_no_ecp_at_all component.
497 'Parse EC Key #10a (SEC1 PEM, secp384r1, compressed)',
498 'Parse EC Key #11a (SEC1 PEM, secp521r1, compressed)',
499 'Parse EC Key #12a (SEC1 PEM, bp256r1, compressed)',
500 'Parse EC Key #13a (SEC1 PEM, bp384r1, compressed)',
501 'Parse EC Key #14a (SEC1 PEM, bp512r1, compressed)',
502 'Parse EC Key #2a (SEC1 PEM, secp192r1, compressed)',
503 'Parse EC Key #8a (SEC1 PEM, secp224r1, compressed)',
504 'Parse EC Key #9a (SEC1 PEM, secp256r1, compressed)',
505 'Parse Public EC Key #2a (RFC 5480, PEM, secp192r1, compressed)',
506 'Parse Public EC Key #3a (RFC 5480, secp224r1, compressed)',
507 'Parse Public EC Key #4a (RFC 5480, secp256r1, compressed)',
508 'Parse Public EC Key #5a (RFC 5480, secp384r1, compressed)',
509 'Parse Public EC Key #6a (RFC 5480, secp521r1, compressed)',
510 'Parse Public EC Key #7a (RFC 5480, brainpoolP256r1, compressed)',
511 'Parse Public EC Key #8a (RFC 5480, brainpoolP384r1, compressed)',
512 'Parse Public EC Key #9a (RFC 5480, brainpoolP512r1, compressed)',
513 ],
514 'test_suite_asn1parse': [
515 # This test depends on BIGNUM_C
516 'INTEGER too large for mpi',
517 ],
518 'test_suite_asn1write': [
519 # Following tests depends on BIGNUM_C
520 'ASN.1 Write mpi 0 (1 limb)',
521 'ASN.1 Write mpi 0 (null)',
522 'ASN.1 Write mpi 0x100',
523 'ASN.1 Write mpi 0x7f',
524 'ASN.1 Write mpi 0x7f with leading 0 limb',
525 'ASN.1 Write mpi 0x80',
526 'ASN.1 Write mpi 0x80 with leading 0 limb',
527 'ASN.1 Write mpi 0xff',
528 'ASN.1 Write mpi 1',
529 'ASN.1 Write mpi, 127*8 bits',
530 'ASN.1 Write mpi, 127*8+1 bits',
531 'ASN.1 Write mpi, 127*8-1 bits',
532 'ASN.1 Write mpi, 255*8 bits',
533 'ASN.1 Write mpi, 255*8-1 bits',
534 'ASN.1 Write mpi, 256*8-1 bits',
535 ],
536 'test_suite_debug': [
537 # Following tests depends on BIGNUM_C
538 'Debug print mbedtls_mpi #2: 3 bits',
539 'Debug print mbedtls_mpi: 0 (empty representation)',
540 'Debug print mbedtls_mpi: 0 (non-empty representation)',
541 'Debug print mbedtls_mpi: 49 bits',
542 'Debug print mbedtls_mpi: 759 bits',
543 'Debug print mbedtls_mpi: 764 bits #1',
544 'Debug print mbedtls_mpi: 764 bits #2',
545 ],
Manuel Pégourié-Gonnardf07ce3b2023-09-22 11:53:41 +0200546 'test_suite_ssl': [
547 'Test configuration of groups for DHE through mbedtls_ssl_conf_curves()',
548 ],
Valerio Setti307810b2023-08-15 10:12:25 +0200549 }
550 }
551 },
Przemek Stekiel85b64422023-05-26 09:55:23 +0200552 'analyze_driver_vs_reference_ffdh_alg': {
553 'test_function': do_analyze_driver_vs_reference,
554 'args': {
555 'component_ref': 'test_psa_crypto_config_reference_ffdh',
556 'component_driver': 'test_psa_crypto_config_accel_ffdh',
Przemek Stekiel84f4ff12023-07-04 12:35:31 +0200557 'ignored_suites': ['dhm'],
Przemek Stekiel565353e2023-07-05 11:07:07 +0200558 'ignored_tests': {}
Przemek Stekiel85b64422023-05-26 09:55:23 +0200559 }
560 },
Valerio Settif01d6482023-08-04 13:51:18 +0200561 'analyze_driver_vs_reference_tfm_config': {
562 'test_function': do_analyze_driver_vs_reference,
563 'args': {
564 'component_ref': 'test_tfm_config',
565 'component_driver': 'test_tfm_config_p256m_driver_accel_ec',
Manuel Pégourié-Gonnarde9d97972023-08-08 18:34:47 +0200566 'ignored_suites': [
567 # Ignore test suites for the modules that are disabled in the
568 # accelerated test case.
569 'ecp',
570 'ecdsa',
571 'ecdh',
572 'ecjpake',
573 'bignum_core',
574 'bignum_random',
575 'bignum_mod',
576 'bignum_mod_raw',
577 'bignum.generated',
578 'bignum.misc',
579 ],
Valerio Settif01d6482023-08-04 13:51:18 +0200580 'ignored_tests': {
581 # Ignore all tests that require DERIVE support which is disabled
582 # in the driver version
583 'test_suite_psa_crypto': [
584 'PSA key agreement setup: ECDH + HKDF-SHA-256: good',
585 ('PSA key agreement setup: ECDH + HKDF-SHA-256: good, key algorithm broader '
586 'than required'),
587 'PSA key agreement setup: ECDH + HKDF-SHA-256: public key not on curve',
588 'PSA key agreement setup: KDF instead of a key agreement algorithm',
589 'PSA key agreement setup: bad key agreement algorithm',
590 'PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: capacity=8160',
591 'PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 0+32',
592 'PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 1+31',
593 'PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 31+1',
594 'PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 32+0',
595 'PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 32+32',
596 'PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 64+0',
597 'PSA key derivation: ECDH on P256 with HKDF-SHA256, info first',
598 'PSA key derivation: ECDH on P256 with HKDF-SHA256, key output',
599 'PSA key derivation: ECDH on P256 with HKDF-SHA256, missing info',
600 'PSA key derivation: ECDH on P256 with HKDF-SHA256, omitted salt',
601 'PSA key derivation: ECDH on P256 with HKDF-SHA256, raw output',
602 'PSA key derivation: ECDH on P256 with HKDF-SHA256, salt after secret',
603 'PSA key derivation: ECDH with TLS 1.2 PRF SHA-256, good case',
604 'PSA key derivation: ECDH with TLS 1.2 PRF SHA-256, missing label',
605 'PSA key derivation: ECDH with TLS 1.2 PRF SHA-256, missing label and secret',
606 'PSA key derivation: ECDH with TLS 1.2 PRF SHA-256, no inputs',
607 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1',
608 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1 (1 redraw)',
609 'PSA key derivation: HKDF-SHA-256 -> ECC secp256r1, exercise ECDSA',
610 'PSA key derivation: TLS 1.2 Mix-PSK-to-MS, SHA-256, 0+48, ka',
611 'PSA key derivation: TLS 1.2 Mix-PSK-to-MS, SHA-256, 24+24, ka',
612 'PSA key derivation: TLS 1.2 Mix-PSK-to-MS, SHA-256, 48+0, ka',
613 'PSA key derivation: TLS 1.2 Mix-PSK-to-MS, bad state #1, ka',
614 'PSA key derivation: TLS 1.2 Mix-PSK-to-MS, bad state #3, ka',
615 'PSA key derivation: TLS 1.2 Mix-PSK-to-MS, bad state #4, ka',
616 'PSA key derivation: bits=7 invalid for ECC BRAINPOOL_P_R1 (ECC enabled)',
617 'PSA key derivation: bits=7 invalid for ECC MONTGOMERY (ECC enabled)',
618 'PSA key derivation: bits=7 invalid for ECC SECP_K1 (ECC enabled)',
619 'PSA key derivation: bits=7 invalid for ECC SECP_R1 (ECC enabled)',
620 'PSA key derivation: bits=7 invalid for ECC SECP_R2 (ECC enabled)',
621 'PSA key derivation: bits=7 invalid for ECC SECT_K1 (ECC enabled)',
622 'PSA key derivation: bits=7 invalid for ECC SECT_R1 (ECC enabled)',
623 'PSA key derivation: bits=7 invalid for ECC SECT_R2 (ECC enabled)',
624 'PSA raw key agreement: ECDH SECP256R1 (RFC 5903)',
625 ],
Manuel Pégourié-Gonnarde9d97972023-08-08 18:34:47 +0200626 'test_suite_random': [
627 'PSA classic wrapper: ECDSA signature (SECP256R1)',
628 ],
Valerio Settif01d6482023-08-04 13:51:18 +0200629 'test_suite_psa_crypto_pake': [
630 'PSA PAKE: ecjpake size macros',
Manuel Pégourié-Gonnarde9d97972023-08-08 18:34:47 +0200631 ],
632 'test_suite_asn1parse': [
633 # This test depends on BIGNUM_C
634 'INTEGER too large for mpi',
635 ],
636 'test_suite_asn1write': [
637 # Following tests depends on BIGNUM_C
638 'ASN.1 Write mpi 0 (1 limb)',
639 'ASN.1 Write mpi 0 (null)',
640 'ASN.1 Write mpi 0x100',
641 'ASN.1 Write mpi 0x7f',
642 'ASN.1 Write mpi 0x7f with leading 0 limb',
643 'ASN.1 Write mpi 0x80',
644 'ASN.1 Write mpi 0x80 with leading 0 limb',
645 'ASN.1 Write mpi 0xff',
646 'ASN.1 Write mpi 1',
647 'ASN.1 Write mpi, 127*8 bits',
648 'ASN.1 Write mpi, 127*8+1 bits',
649 'ASN.1 Write mpi, 127*8-1 bits',
650 'ASN.1 Write mpi, 255*8 bits',
651 'ASN.1 Write mpi, 255*8-1 bits',
652 'ASN.1 Write mpi, 256*8-1 bits',
653 ],
Valerio Settif01d6482023-08-04 13:51:18 +0200654 }
655 }
656 }
Przemek Stekiel4d13c832022-10-26 16:11:26 +0200657}
Przemek Stekiel4d13c832022-10-26 16:11:26 +0200658
Gilles Peskine15c2cbf2020-06-25 18:36:28 +0200659def main():
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200660 main_log = TestLog()
661
Gilles Peskine15c2cbf2020-06-25 18:36:28 +0200662 try:
663 parser = argparse.ArgumentParser(description=__doc__)
Przemek Stekiel58bbc232022-10-24 08:10:10 +0200664 parser.add_argument('outcomes', metavar='OUTCOMES.CSV',
Gilles Peskine15c2cbf2020-06-25 18:36:28 +0200665 help='Outcome file to analyze')
Valerio Settidfd7ca62023-10-09 16:30:11 +0200666 parser.add_argument('specified_tasks', default='all', nargs='?',
Przemek Stekiel992de3c2022-11-09 13:54:49 +0100667 help='Analysis to be done. By default, run all tasks. '
668 'With one or more TASK, run only those. '
669 'TASK can be the name of a single task or '
Przemek Stekiel85c54ea2022-11-17 11:50:23 +0100670 'comma/space-separated list of tasks. ')
Przemek Stekiel992de3c2022-11-09 13:54:49 +0100671 parser.add_argument('--list', action='store_true',
672 help='List all available tasks and exit.')
Tomás Gonzálezb401e112023-08-11 15:22:04 +0100673 parser.add_argument('--require-full-coverage', action='store_true',
674 dest='full_coverage', help="Require all available "
675 "test cases to be executed and issue an error "
676 "otherwise. This flag is ignored if 'task' is "
677 "neither 'all' nor 'analyze_coverage'")
Gilles Peskine15c2cbf2020-06-25 18:36:28 +0200678 options = parser.parse_args()
Przemek Stekiel4e955902022-10-21 13:42:08 +0200679
Przemek Stekiel992de3c2022-11-09 13:54:49 +0100680 if options.list:
Valerio Settidfd7ca62023-10-09 16:30:11 +0200681 for task in KNOWN_TASKS:
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200682 main_log.info(task)
683 main_log.print_output()
Przemek Stekiel992de3c2022-11-09 13:54:49 +0100684 sys.exit(0)
685
Valerio Settidfd7ca62023-10-09 16:30:11 +0200686 if options.specified_tasks == 'all':
687 tasks_list = KNOWN_TASKS.keys()
Przemek Stekiel992de3c2022-11-09 13:54:49 +0100688 else:
Valerio Settidfd7ca62023-10-09 16:30:11 +0200689 tasks_list = re.split(r'[, ]+', options.specified_tasks)
Valerio Settidfd7ca62023-10-09 16:30:11 +0200690 for task in tasks_list:
691 if task not in KNOWN_TASKS:
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200692 main_log.error('invalid task: {}'.format(task))
Przemek Stekiel992de3c2022-11-09 13:54:49 +0100693
Valerio Settidfd7ca62023-10-09 16:30:11 +0200694 KNOWN_TASKS['analyze_coverage']['args']['full_coverage'] = options.full_coverage
Tomás Gonzálezb401e112023-08-11 15:22:04 +0100695
Valerio Settidfd7ca62023-10-09 16:30:11 +0200696 all_succeeded = True
Przemek Stekiel4e955902022-10-21 13:42:08 +0200697
Valerio Settidfd7ca62023-10-09 16:30:11 +0200698 for task in KNOWN_TASKS:
699 if task in tasks_list:
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200700 test_function = KNOWN_TASKS[task]['test_function']
701 test_args = KNOWN_TASKS[task]['args']
702 test_log = test_function(options.outcomes, test_args)
703 # Merge the output of this task with the main one
704 main_log.output = main_log.output + test_log.output
705 main_log.info("Task {} completed with:\n".format(task) + \
706 "{} warnings\n".format(test_log.warning_count) + \
707 "{} errors\n".format(test_log.error_count))
708 if test_log.error_count != 0:
Valerio Settidfd7ca62023-10-09 16:30:11 +0200709 all_succeeded = False
710
Valerio Settiaaef0bc2023-10-10 09:42:13 +0200711 main_log.print_output()
712 sys.exit(0 if all_succeeded else 1)
713
Gilles Peskine15c2cbf2020-06-25 18:36:28 +0200714 except Exception: # pylint: disable=broad-except
715 # Print the backtrace and exit explicitly with our chosen status.
716 traceback.print_exc()
717 sys.exit(120)
718
719if __name__ == '__main__':
720 main()