1*62c56f98SSadaf Ebrahimi#!/usr/bin/env python3 2*62c56f98SSadaf Ebrahimi"""Run the PSA Crypto API compliance test suite. 3*62c56f98SSadaf EbrahimiClone the repo and check out the commit specified by PSA_ARCH_TEST_REPO and PSA_ARCH_TEST_REF, 4*62c56f98SSadaf Ebrahimithen compile and run the test suite. The clone is stored at <repository root>/psa-arch-tests. 5*62c56f98SSadaf EbrahimiKnown defects in either the test suite or mbedtls / psa-crypto - identified by their test 6*62c56f98SSadaf Ebrahiminumber - are ignored, while unexpected failures AND successes are reported as errors, to help 7*62c56f98SSadaf Ebrahimikeep the list of known defects as up to date as possible. 8*62c56f98SSadaf Ebrahimi""" 9*62c56f98SSadaf Ebrahimi 10*62c56f98SSadaf Ebrahimi# Copyright The Mbed TLS Contributors 11*62c56f98SSadaf Ebrahimi# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 12*62c56f98SSadaf Ebrahimi 13*62c56f98SSadaf Ebrahimiimport argparse 14*62c56f98SSadaf Ebrahimiimport os 15*62c56f98SSadaf Ebrahimiimport re 16*62c56f98SSadaf Ebrahimiimport shutil 17*62c56f98SSadaf Ebrahimiimport subprocess 18*62c56f98SSadaf Ebrahimiimport sys 19*62c56f98SSadaf Ebrahimifrom typing import List 20*62c56f98SSadaf Ebrahimi 21*62c56f98SSadaf Ebrahimi#pylint: disable=unused-import 22*62c56f98SSadaf Ebrahimiimport scripts_path 23*62c56f98SSadaf Ebrahimifrom mbedtls_dev import build_tree 24*62c56f98SSadaf Ebrahimi 25*62c56f98SSadaf Ebrahimi# PSA Compliance tests we expect to fail due to known defects in Mbed TLS / PSA Crypto 26*62c56f98SSadaf Ebrahimi# (or the test suite). 27*62c56f98SSadaf Ebrahimi# The test numbers correspond to the numbers used by the console output of the test suite. 28*62c56f98SSadaf Ebrahimi# Test number 2xx corresponds to the files in the folder 29*62c56f98SSadaf Ebrahimi# psa-arch-tests/api-tests/dev_apis/crypto/test_c0xx 30*62c56f98SSadaf EbrahimiEXPECTED_FAILURES = { 31*62c56f98SSadaf Ebrahimi # psa_hash_suspend() and psa_hash_resume() are not supported. 32*62c56f98SSadaf Ebrahimi # - Tracked in issue #3274 33*62c56f98SSadaf Ebrahimi 262, 263 34*62c56f98SSadaf Ebrahimi} 35*62c56f98SSadaf Ebrahimi 36*62c56f98SSadaf Ebrahimi# We currently use a fork of ARM-software/psa-arch-tests, with a couple of downstream patches 37*62c56f98SSadaf Ebrahimi# that allow it to build with MbedTLS 3, and fixes a couple of issues in the compliance test suite. 38*62c56f98SSadaf Ebrahimi# These fixes allow the tests numbered 216, 248 and 249 to complete successfully. 39*62c56f98SSadaf Ebrahimi# 40*62c56f98SSadaf Ebrahimi# Once all the fixes are upstreamed, this fork should be replaced with an upstream commit/tag. 41*62c56f98SSadaf Ebrahimi# - Tracked in issue #5145 42*62c56f98SSadaf Ebrahimi# 43*62c56f98SSadaf Ebrahimi# Web URL: https://github.com/bensze01/psa-arch-tests/tree/fixes-for-mbedtls-3 44*62c56f98SSadaf EbrahimiPSA_ARCH_TESTS_REPO = 'https://github.com/bensze01/psa-arch-tests.git' 45*62c56f98SSadaf EbrahimiPSA_ARCH_TESTS_REF = 'fix-pr-5736' 46*62c56f98SSadaf Ebrahimi 47*62c56f98SSadaf Ebrahimi#pylint: disable=too-many-branches,too-many-statements,too-many-locals 48*62c56f98SSadaf Ebrahimidef main(library_build_dir: str): 49*62c56f98SSadaf Ebrahimi root_dir = os.getcwd() 50*62c56f98SSadaf Ebrahimi 51*62c56f98SSadaf Ebrahimi in_psa_crypto_repo = build_tree.looks_like_psa_crypto_root(root_dir) 52*62c56f98SSadaf Ebrahimi 53*62c56f98SSadaf Ebrahimi if in_psa_crypto_repo: 54*62c56f98SSadaf Ebrahimi crypto_name = 'psacrypto' 55*62c56f98SSadaf Ebrahimi library_subdir = 'core' 56*62c56f98SSadaf Ebrahimi else: 57*62c56f98SSadaf Ebrahimi crypto_name = 'mbedcrypto' 58*62c56f98SSadaf Ebrahimi library_subdir = 'library' 59*62c56f98SSadaf Ebrahimi 60*62c56f98SSadaf Ebrahimi crypto_lib_filename = (library_build_dir + '/' + 61*62c56f98SSadaf Ebrahimi library_subdir + '/' + 62*62c56f98SSadaf Ebrahimi 'lib' + crypto_name + '.a') 63*62c56f98SSadaf Ebrahimi 64*62c56f98SSadaf Ebrahimi if not os.path.exists(crypto_lib_filename): 65*62c56f98SSadaf Ebrahimi #pylint: disable=bad-continuation 66*62c56f98SSadaf Ebrahimi subprocess.check_call([ 67*62c56f98SSadaf Ebrahimi 'cmake', '.', 68*62c56f98SSadaf Ebrahimi '-GUnix Makefiles', 69*62c56f98SSadaf Ebrahimi '-B' + library_build_dir 70*62c56f98SSadaf Ebrahimi ]) 71*62c56f98SSadaf Ebrahimi subprocess.check_call(['cmake', '--build', library_build_dir, 72*62c56f98SSadaf Ebrahimi '--target', crypto_name]) 73*62c56f98SSadaf Ebrahimi 74*62c56f98SSadaf Ebrahimi psa_arch_tests_dir = 'psa-arch-tests' 75*62c56f98SSadaf Ebrahimi os.makedirs(psa_arch_tests_dir, exist_ok=True) 76*62c56f98SSadaf Ebrahimi try: 77*62c56f98SSadaf Ebrahimi os.chdir(psa_arch_tests_dir) 78*62c56f98SSadaf Ebrahimi 79*62c56f98SSadaf Ebrahimi # Reuse existing local clone 80*62c56f98SSadaf Ebrahimi subprocess.check_call(['git', 'init']) 81*62c56f98SSadaf Ebrahimi subprocess.check_call(['git', 'fetch', PSA_ARCH_TESTS_REPO, PSA_ARCH_TESTS_REF]) 82*62c56f98SSadaf Ebrahimi subprocess.check_call(['git', 'checkout', 'FETCH_HEAD']) 83*62c56f98SSadaf Ebrahimi 84*62c56f98SSadaf Ebrahimi build_dir = 'api-tests/build' 85*62c56f98SSadaf Ebrahimi try: 86*62c56f98SSadaf Ebrahimi shutil.rmtree(build_dir) 87*62c56f98SSadaf Ebrahimi except FileNotFoundError: 88*62c56f98SSadaf Ebrahimi pass 89*62c56f98SSadaf Ebrahimi os.mkdir(build_dir) 90*62c56f98SSadaf Ebrahimi os.chdir(build_dir) 91*62c56f98SSadaf Ebrahimi 92*62c56f98SSadaf Ebrahimi extra_includes = (';{}/drivers/builtin/include'.format(root_dir) 93*62c56f98SSadaf Ebrahimi if in_psa_crypto_repo else '') 94*62c56f98SSadaf Ebrahimi 95*62c56f98SSadaf Ebrahimi #pylint: disable=bad-continuation 96*62c56f98SSadaf Ebrahimi subprocess.check_call([ 97*62c56f98SSadaf Ebrahimi 'cmake', '..', 98*62c56f98SSadaf Ebrahimi '-GUnix Makefiles', 99*62c56f98SSadaf Ebrahimi '-DTARGET=tgt_dev_apis_stdc', 100*62c56f98SSadaf Ebrahimi '-DTOOLCHAIN=HOST_GCC', 101*62c56f98SSadaf Ebrahimi '-DSUITE=CRYPTO', 102*62c56f98SSadaf Ebrahimi '-DPSA_CRYPTO_LIB_FILENAME={}/{}'.format(root_dir, 103*62c56f98SSadaf Ebrahimi crypto_lib_filename), 104*62c56f98SSadaf Ebrahimi ('-DPSA_INCLUDE_PATHS={}/include' + extra_includes).format(root_dir) 105*62c56f98SSadaf Ebrahimi ]) 106*62c56f98SSadaf Ebrahimi subprocess.check_call(['cmake', '--build', '.']) 107*62c56f98SSadaf Ebrahimi 108*62c56f98SSadaf Ebrahimi proc = subprocess.Popen(['./psa-arch-tests-crypto'], 109*62c56f98SSadaf Ebrahimi bufsize=1, stdout=subprocess.PIPE, universal_newlines=True) 110*62c56f98SSadaf Ebrahimi 111*62c56f98SSadaf Ebrahimi test_re = re.compile( 112*62c56f98SSadaf Ebrahimi '^TEST: (?P<test_num>[0-9]*)|' 113*62c56f98SSadaf Ebrahimi '^TEST RESULT: (?P<test_result>FAILED|PASSED)' 114*62c56f98SSadaf Ebrahimi ) 115*62c56f98SSadaf Ebrahimi test = -1 116*62c56f98SSadaf Ebrahimi unexpected_successes = set(EXPECTED_FAILURES) 117*62c56f98SSadaf Ebrahimi expected_failures = [] # type: List[int] 118*62c56f98SSadaf Ebrahimi unexpected_failures = [] # type: List[int] 119*62c56f98SSadaf Ebrahimi if proc.stdout is None: 120*62c56f98SSadaf Ebrahimi return 1 121*62c56f98SSadaf Ebrahimi 122*62c56f98SSadaf Ebrahimi for line in proc.stdout: 123*62c56f98SSadaf Ebrahimi print(line, end='') 124*62c56f98SSadaf Ebrahimi match = test_re.match(line) 125*62c56f98SSadaf Ebrahimi if match is not None: 126*62c56f98SSadaf Ebrahimi groupdict = match.groupdict() 127*62c56f98SSadaf Ebrahimi test_num = groupdict['test_num'] 128*62c56f98SSadaf Ebrahimi if test_num is not None: 129*62c56f98SSadaf Ebrahimi test = int(test_num) 130*62c56f98SSadaf Ebrahimi elif groupdict['test_result'] == 'FAILED': 131*62c56f98SSadaf Ebrahimi try: 132*62c56f98SSadaf Ebrahimi unexpected_successes.remove(test) 133*62c56f98SSadaf Ebrahimi expected_failures.append(test) 134*62c56f98SSadaf Ebrahimi print('Expected failure, ignoring') 135*62c56f98SSadaf Ebrahimi except KeyError: 136*62c56f98SSadaf Ebrahimi unexpected_failures.append(test) 137*62c56f98SSadaf Ebrahimi print('ERROR: Unexpected failure') 138*62c56f98SSadaf Ebrahimi elif test in unexpected_successes: 139*62c56f98SSadaf Ebrahimi print('ERROR: Unexpected success') 140*62c56f98SSadaf Ebrahimi proc.wait() 141*62c56f98SSadaf Ebrahimi 142*62c56f98SSadaf Ebrahimi print() 143*62c56f98SSadaf Ebrahimi print('***** test_psa_compliance.py report ******') 144*62c56f98SSadaf Ebrahimi print() 145*62c56f98SSadaf Ebrahimi print('Expected failures:', ', '.join(str(i) for i in expected_failures)) 146*62c56f98SSadaf Ebrahimi print('Unexpected failures:', ', '.join(str(i) for i in unexpected_failures)) 147*62c56f98SSadaf Ebrahimi print('Unexpected successes:', ', '.join(str(i) for i in sorted(unexpected_successes))) 148*62c56f98SSadaf Ebrahimi print() 149*62c56f98SSadaf Ebrahimi if unexpected_successes or unexpected_failures: 150*62c56f98SSadaf Ebrahimi if unexpected_successes: 151*62c56f98SSadaf Ebrahimi print('Unexpected successes encountered.') 152*62c56f98SSadaf Ebrahimi print('Please remove the corresponding tests from ' 153*62c56f98SSadaf Ebrahimi 'EXPECTED_FAILURES in tests/scripts/compliance_test.py') 154*62c56f98SSadaf Ebrahimi print() 155*62c56f98SSadaf Ebrahimi print('FAILED') 156*62c56f98SSadaf Ebrahimi return 1 157*62c56f98SSadaf Ebrahimi else: 158*62c56f98SSadaf Ebrahimi print('SUCCESS') 159*62c56f98SSadaf Ebrahimi return 0 160*62c56f98SSadaf Ebrahimi finally: 161*62c56f98SSadaf Ebrahimi os.chdir(root_dir) 162*62c56f98SSadaf Ebrahimi 163*62c56f98SSadaf Ebrahimiif __name__ == '__main__': 164*62c56f98SSadaf Ebrahimi BUILD_DIR = 'out_of_source_build' 165*62c56f98SSadaf Ebrahimi 166*62c56f98SSadaf Ebrahimi # pylint: disable=invalid-name 167*62c56f98SSadaf Ebrahimi parser = argparse.ArgumentParser() 168*62c56f98SSadaf Ebrahimi parser.add_argument('--build-dir', nargs=1, 169*62c56f98SSadaf Ebrahimi help='path to Mbed TLS / PSA Crypto build directory') 170*62c56f98SSadaf Ebrahimi args = parser.parse_args() 171*62c56f98SSadaf Ebrahimi 172*62c56f98SSadaf Ebrahimi if args.build_dir is not None: 173*62c56f98SSadaf Ebrahimi BUILD_DIR = args.build_dir[0] 174*62c56f98SSadaf Ebrahimi 175*62c56f98SSadaf Ebrahimi sys.exit(main(BUILD_DIR)) 176