test_psa_compliance.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #!/usr/bin/env python3
  2. """Run the PSA Cryto API compliance test suite.
  3. Clone the repo and check out the commit specified by PSA_ARCH_TEST_REPO and PSA_ARCH_TEST_REF,
  4. then complie and run the test suite. The clone is stored at <Mbed TLS root>/psa-arch-tests.
  5. Known defects in either the test suite or mbedtls - identified by their test number - are ignored,
  6. while unexpected failures AND successes are reported as errors,
  7. to help keep the list of known defects as up to date as possible.
  8. """
  9. # Copyright The Mbed TLS Contributors
  10. # SPDX-License-Identifier: Apache-2.0
  11. #
  12. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  13. # not use this file except in compliance with the License.
  14. # You may obtain a copy of the License at
  15. #
  16. # http://www.apache.org/licenses/LICENSE-2.0
  17. #
  18. # Unless required by applicable law or agreed to in writing, software
  19. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  20. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  21. # See the License for the specific language governing permissions and
  22. # limitations under the License.
  23. import os
  24. import re
  25. import shutil
  26. import subprocess
  27. import sys
  28. # PSA Compliance tests we expect to fail due to known defects in Mbed TLS (or the test suite)
  29. # The test numbers correspond to the numbers used by the console output of the test suite.
  30. # Test number 2xx corresponds to the files in the folder
  31. # psa-arch-tests/api-tests/dev_apis/crypto/test_c0xx
  32. EXPECTED_FAILURES = {
  33. # Multipart AEAD is not supported in Mbed TLS 2.x.
  34. 252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
  35. # psa_hash_suspend() and psa_hash_resume() are not supported.
  36. # - Tracked in issue #3274
  37. 262, 263
  38. }
  39. # We currently use a fork of ARM-software/psa-arch-tests, with a couple of downstream patches
  40. # that allow it to build with Mbed TLS 2, and fixes a couple of issues in the compliance test suite.
  41. # These fixes allow the tests numbered 216, 248 and 249 to complete successfully.
  42. #
  43. # Once all the fixes are upstreamed, this fork should be replaced with an upstream commit/tag.
  44. # - Tracked in issue #5145
  45. #
  46. # Web URL: https://github.com/bensze01/psa-arch-tests/tree/fixes-for-mbedtls-2
  47. PSA_ARCH_TESTS_REPO = 'https://github.com/bensze01/psa-arch-tests.git'
  48. PSA_ARCH_TESTS_REF = 'fixes-for-mbedtls-2'
  49. #pylint: disable=too-many-branches,too-many-statements
  50. def main():
  51. mbedtls_dir = os.getcwd()
  52. if not os.path.exists('library/libmbedcrypto.a'):
  53. subprocess.check_call(['make', '-C', 'library', 'libmbedcrypto.a'])
  54. psa_arch_tests_dir = 'psa-arch-tests'
  55. os.makedirs(psa_arch_tests_dir, exist_ok=True)
  56. try:
  57. os.chdir(psa_arch_tests_dir)
  58. # Reuse existing local clone
  59. subprocess.check_call(['git', 'init'])
  60. subprocess.check_call(['git', 'fetch', PSA_ARCH_TESTS_REPO, PSA_ARCH_TESTS_REF])
  61. subprocess.check_call(['git', 'checkout', 'FETCH_HEAD'])
  62. build_dir = 'api-tests/build'
  63. try:
  64. shutil.rmtree(build_dir)
  65. except FileNotFoundError:
  66. pass
  67. os.mkdir(build_dir)
  68. os.chdir(build_dir)
  69. #pylint: disable=bad-continuation
  70. subprocess.check_call([
  71. 'cmake', '..',
  72. '-GUnix Makefiles',
  73. '-DTARGET=tgt_dev_apis_stdc',
  74. '-DTOOLCHAIN=HOST_GCC',
  75. '-DSUITE=CRYPTO',
  76. '-DMISSING_CRYPTO_1_0=1',
  77. '-DPSA_CRYPTO_LIB_FILENAME={}/library/libmbedcrypto.a'.format(mbedtls_dir),
  78. '-DPSA_INCLUDE_PATHS={}/include'.format(mbedtls_dir)
  79. ])
  80. subprocess.check_call(['cmake', '--build', '.'])
  81. proc = subprocess.Popen(['./psa-arch-tests-crypto'],
  82. bufsize=1, stdout=subprocess.PIPE, universal_newlines=True)
  83. test_re = re.compile(
  84. '^TEST: (?P<test_num>[0-9]*)|'
  85. '^TEST RESULT: (?P<test_result>FAILED|PASSED)'
  86. )
  87. test = -1
  88. unexpected_successes = set(EXPECTED_FAILURES)
  89. expected_failures = []
  90. unexpected_failures = []
  91. for line in proc.stdout:
  92. print(line, end='')
  93. match = test_re.match(line)
  94. if match is not None:
  95. groupdict = match.groupdict()
  96. test_num = groupdict['test_num']
  97. if test_num is not None:
  98. test = int(test_num)
  99. elif groupdict['test_result'] == 'FAILED':
  100. try:
  101. unexpected_successes.remove(test)
  102. expected_failures.append(test)
  103. print('Expected failure, ignoring')
  104. except KeyError:
  105. unexpected_failures.append(test)
  106. print('ERROR: Unexpected failure')
  107. elif test in unexpected_successes:
  108. print('ERROR: Unexpected success')
  109. proc.wait()
  110. print()
  111. print('***** test_psa_compliance.py report ******')
  112. print()
  113. print('Expected failures:', ', '.join(str(i) for i in expected_failures))
  114. print('Unexpected failures:', ', '.join(str(i) for i in unexpected_failures))
  115. print('Unexpected successes:', ', '.join(str(i) for i in sorted(unexpected_successes)))
  116. print()
  117. if unexpected_successes or unexpected_failures:
  118. if unexpected_successes:
  119. print('Unexpected successes encountered.')
  120. print('Please remove the corresponding tests from '
  121. 'EXPECTED_FAILURES in tests/scripts/compliance_test.py')
  122. print()
  123. print('FAILED')
  124. return 1
  125. else:
  126. print('SUCCESS')
  127. return 0
  128. finally:
  129. os.chdir(mbedtls_dir)
  130. if __name__ == '__main__':
  131. sys.exit(main())