generate_tls13_compat_tests.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. #!/usr/bin/env python3
  2. # generate_tls13_compat_tests.py
  3. #
  4. # Copyright The Mbed TLS Contributors
  5. # SPDX-License-Identifier: Apache-2.0
  6. #
  7. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  8. # not use this file except in compliance with the License.
  9. # You may obtain a copy of the License at
  10. #
  11. # http://www.apache.org/licenses/LICENSE-2.0
  12. #
  13. # Unless required by applicable law or agreed to in writing, software
  14. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. # See the License for the specific language governing permissions and
  17. # limitations under the License.
  18. """
  19. Generate TLSv1.3 Compat test cases
  20. """
  21. import sys
  22. import os
  23. import argparse
  24. import itertools
  25. from collections import namedtuple
  26. # define certificates configuration entry
  27. Certificate = namedtuple("Certificate", ['cafile', 'certfile', 'keyfile'])
  28. # define the certificate parameters for signature algorithms
  29. CERTIFICATES = {
  30. 'ecdsa_secp256r1_sha256': Certificate('data_files/test-ca2.crt',
  31. 'data_files/ecdsa_secp256r1.crt',
  32. 'data_files/ecdsa_secp256r1.key'),
  33. 'ecdsa_secp384r1_sha384': Certificate('data_files/test-ca2.crt',
  34. 'data_files/ecdsa_secp384r1.crt',
  35. 'data_files/ecdsa_secp384r1.key'),
  36. 'ecdsa_secp521r1_sha512': Certificate('data_files/test-ca2.crt',
  37. 'data_files/ecdsa_secp521r1.crt',
  38. 'data_files/ecdsa_secp521r1.key'),
  39. 'rsa_pss_rsae_sha256': Certificate('data_files/test-ca_cat12.crt',
  40. 'data_files/server2-sha256.crt', 'data_files/server2.key'
  41. )
  42. }
  43. CIPHER_SUITE_IANA_VALUE = {
  44. "TLS_AES_128_GCM_SHA256": 0x1301,
  45. "TLS_AES_256_GCM_SHA384": 0x1302,
  46. "TLS_CHACHA20_POLY1305_SHA256": 0x1303,
  47. "TLS_AES_128_CCM_SHA256": 0x1304,
  48. "TLS_AES_128_CCM_8_SHA256": 0x1305
  49. }
  50. SIG_ALG_IANA_VALUE = {
  51. "ecdsa_secp256r1_sha256": 0x0403,
  52. "ecdsa_secp384r1_sha384": 0x0503,
  53. "ecdsa_secp521r1_sha512": 0x0603,
  54. 'rsa_pss_rsae_sha256': 0x0804,
  55. }
  56. NAMED_GROUP_IANA_VALUE = {
  57. 'secp256r1': 0x17,
  58. 'secp384r1': 0x18,
  59. 'secp521r1': 0x19,
  60. 'x25519': 0x1d,
  61. 'x448': 0x1e,
  62. }
  63. class TLSProgram:
  64. """
  65. Base class for generate server/client command.
  66. """
  67. # pylint: disable=too-many-arguments
  68. def __init__(self, ciphersuite=None, signature_algorithm=None, named_group=None,
  69. cert_sig_alg=None, compat_mode=True):
  70. self._ciphers = []
  71. self._sig_algs = []
  72. self._named_groups = []
  73. self._cert_sig_algs = []
  74. if ciphersuite:
  75. self.add_ciphersuites(ciphersuite)
  76. if named_group:
  77. self.add_named_groups(named_group)
  78. if signature_algorithm:
  79. self.add_signature_algorithms(signature_algorithm)
  80. if cert_sig_alg:
  81. self.add_cert_signature_algorithms(cert_sig_alg)
  82. self._compat_mode = compat_mode
  83. # add_ciphersuites should not override by sub class
  84. def add_ciphersuites(self, *ciphersuites):
  85. self._ciphers.extend(
  86. [cipher for cipher in ciphersuites if cipher not in self._ciphers])
  87. # add_signature_algorithms should not override by sub class
  88. def add_signature_algorithms(self, *signature_algorithms):
  89. self._sig_algs.extend(
  90. [sig_alg for sig_alg in signature_algorithms if sig_alg not in self._sig_algs])
  91. # add_named_groups should not override by sub class
  92. def add_named_groups(self, *named_groups):
  93. self._named_groups.extend(
  94. [named_group for named_group in named_groups if named_group not in self._named_groups])
  95. # add_cert_signature_algorithms should not override by sub class
  96. def add_cert_signature_algorithms(self, *signature_algorithms):
  97. self._cert_sig_algs.extend(
  98. [sig_alg for sig_alg in signature_algorithms if sig_alg not in self._cert_sig_algs])
  99. # pylint: disable=no-self-use
  100. def pre_checks(self):
  101. return []
  102. # pylint: disable=no-self-use
  103. def cmd(self):
  104. if not self._cert_sig_algs:
  105. self._cert_sig_algs = list(CERTIFICATES.keys())
  106. return self.pre_cmd()
  107. # pylint: disable=no-self-use
  108. def post_checks(self):
  109. return []
  110. # pylint: disable=no-self-use
  111. def pre_cmd(self):
  112. return ['false']
  113. # pylint: disable=unused-argument,no-self-use
  114. def hrr_post_checks(self, named_group):
  115. return []
  116. class OpenSSLBase(TLSProgram):
  117. """
  118. Generate base test commands for OpenSSL.
  119. """
  120. NAMED_GROUP = {
  121. 'secp256r1': 'P-256',
  122. 'secp384r1': 'P-384',
  123. 'secp521r1': 'P-521',
  124. 'x25519': 'X25519',
  125. 'x448': 'X448',
  126. }
  127. def cmd(self):
  128. ret = super().cmd()
  129. if self._ciphers:
  130. ciphersuites = ':'.join(self._ciphers)
  131. ret += ["-ciphersuites {ciphersuites}".format(ciphersuites=ciphersuites)]
  132. if self._sig_algs:
  133. signature_algorithms = set(self._sig_algs + self._cert_sig_algs)
  134. signature_algorithms = ':'.join(signature_algorithms)
  135. ret += ["-sigalgs {signature_algorithms}".format(
  136. signature_algorithms=signature_algorithms)]
  137. if self._named_groups:
  138. named_groups = ':'.join(
  139. map(lambda named_group: self.NAMED_GROUP[named_group], self._named_groups))
  140. ret += ["-groups {named_groups}".format(named_groups=named_groups)]
  141. ret += ['-msg -tls1_3']
  142. if not self._compat_mode:
  143. ret += ['-no_middlebox']
  144. return ret
  145. def pre_checks(self):
  146. return ["requires_openssl_tls1_3"]
  147. class OpenSSLServ(OpenSSLBase):
  148. """
  149. Generate test commands for OpenSSL server.
  150. """
  151. def cmd(self):
  152. ret = super().cmd()
  153. ret += ['-num_tickets 0 -no_resume_ephemeral -no_cache']
  154. return ret
  155. def post_checks(self):
  156. return ['-c "HTTP/1.0 200 ok"']
  157. def pre_cmd(self):
  158. ret = ['$O_NEXT_SRV_NO_CERT']
  159. for _, cert, key in map(lambda sig_alg: CERTIFICATES[sig_alg], self._cert_sig_algs):
  160. ret += ['-cert {cert} -key {key}'.format(cert=cert, key=key)]
  161. return ret
  162. class OpenSSLCli(OpenSSLBase):
  163. """
  164. Generate test commands for OpenSSL client.
  165. """
  166. def pre_cmd(self):
  167. return ['$O_NEXT_CLI_NO_CERT',
  168. '-CAfile {cafile}'.format(cafile=CERTIFICATES[self._cert_sig_algs[0]].cafile)]
  169. class GnuTLSBase(TLSProgram):
  170. """
  171. Generate base test commands for GnuTLS.
  172. """
  173. CIPHER_SUITE = {
  174. 'TLS_AES_256_GCM_SHA384': [
  175. 'AES-256-GCM',
  176. 'SHA384',
  177. 'AEAD'],
  178. 'TLS_AES_128_GCM_SHA256': [
  179. 'AES-128-GCM',
  180. 'SHA256',
  181. 'AEAD'],
  182. 'TLS_CHACHA20_POLY1305_SHA256': [
  183. 'CHACHA20-POLY1305',
  184. 'SHA256',
  185. 'AEAD'],
  186. 'TLS_AES_128_CCM_SHA256': [
  187. 'AES-128-CCM',
  188. 'SHA256',
  189. 'AEAD'],
  190. 'TLS_AES_128_CCM_8_SHA256': [
  191. 'AES-128-CCM-8',
  192. 'SHA256',
  193. 'AEAD']}
  194. SIGNATURE_ALGORITHM = {
  195. 'ecdsa_secp256r1_sha256': ['SIGN-ECDSA-SECP256R1-SHA256'],
  196. 'ecdsa_secp521r1_sha512': ['SIGN-ECDSA-SECP521R1-SHA512'],
  197. 'ecdsa_secp384r1_sha384': ['SIGN-ECDSA-SECP384R1-SHA384'],
  198. 'rsa_pss_rsae_sha256': ['SIGN-RSA-PSS-RSAE-SHA256']}
  199. NAMED_GROUP = {
  200. 'secp256r1': ['GROUP-SECP256R1'],
  201. 'secp384r1': ['GROUP-SECP384R1'],
  202. 'secp521r1': ['GROUP-SECP521R1'],
  203. 'x25519': ['GROUP-X25519'],
  204. 'x448': ['GROUP-X448'],
  205. }
  206. def pre_checks(self):
  207. return ["requires_gnutls_tls1_3",
  208. "requires_gnutls_next_no_ticket",
  209. "requires_gnutls_next_disable_tls13_compat", ]
  210. def cmd(self):
  211. ret = super().cmd()
  212. priority_string_list = []
  213. def update_priority_string_list(items, map_table):
  214. for item in items:
  215. for i in map_table[item]:
  216. if i not in priority_string_list:
  217. yield i
  218. if self._ciphers:
  219. priority_string_list.extend(update_priority_string_list(
  220. self._ciphers, self.CIPHER_SUITE))
  221. else:
  222. priority_string_list.extend(['CIPHER-ALL', 'MAC-ALL'])
  223. if self._sig_algs:
  224. signature_algorithms = set(self._sig_algs + self._cert_sig_algs)
  225. priority_string_list.extend(update_priority_string_list(
  226. signature_algorithms, self.SIGNATURE_ALGORITHM))
  227. else:
  228. priority_string_list.append('SIGN-ALL')
  229. if self._named_groups:
  230. priority_string_list.extend(update_priority_string_list(
  231. self._named_groups, self.NAMED_GROUP))
  232. else:
  233. priority_string_list.append('GROUP-ALL')
  234. priority_string_list = ['NONE'] + \
  235. priority_string_list + ['VERS-TLS1.3']
  236. priority_string = ':+'.join(priority_string_list)
  237. priority_string += ':%NO_TICKETS'
  238. if not self._compat_mode:
  239. priority_string += [':%DISABLE_TLS13_COMPAT_MODE']
  240. ret += ['--priority={priority_string}'.format(
  241. priority_string=priority_string)]
  242. return ret
  243. class GnuTLSServ(GnuTLSBase):
  244. """
  245. Generate test commands for GnuTLS server.
  246. """
  247. def pre_cmd(self):
  248. ret = ['$G_NEXT_SRV_NO_CERT', '--http', '--disable-client-cert', '--debug=4']
  249. for _, cert, key in map(lambda sig_alg: CERTIFICATES[sig_alg], self._cert_sig_algs):
  250. ret += ['--x509certfile {cert} --x509keyfile {key}'.format(
  251. cert=cert, key=key)]
  252. return ret
  253. def post_checks(self):
  254. return ['-c "HTTP/1.0 200 OK"']
  255. class GnuTLSCli(GnuTLSBase):
  256. """
  257. Generate test commands for GnuTLS client.
  258. """
  259. def pre_cmd(self):
  260. return ['$G_NEXT_CLI_NO_CERT', '--debug=4', '--single-key-share',
  261. '--x509cafile {cafile}'.format(cafile=CERTIFICATES[self._cert_sig_algs[0]].cafile)]
  262. class MbedTLSBase(TLSProgram):
  263. """
  264. Generate base test commands for mbedTLS.
  265. """
  266. CIPHER_SUITE = {
  267. 'TLS_AES_256_GCM_SHA384': 'TLS1-3-AES-256-GCM-SHA384',
  268. 'TLS_AES_128_GCM_SHA256': 'TLS1-3-AES-128-GCM-SHA256',
  269. 'TLS_CHACHA20_POLY1305_SHA256': 'TLS1-3-CHACHA20-POLY1305-SHA256',
  270. 'TLS_AES_128_CCM_SHA256': 'TLS1-3-AES-128-CCM-SHA256',
  271. 'TLS_AES_128_CCM_8_SHA256': 'TLS1-3-AES-128-CCM-8-SHA256'}
  272. def cmd(self):
  273. ret = super().cmd()
  274. ret += ['debug_level=4']
  275. if self._ciphers:
  276. ciphers = ','.join(
  277. map(lambda cipher: self.CIPHER_SUITE[cipher], self._ciphers))
  278. ret += ["force_ciphersuite={ciphers}".format(ciphers=ciphers)]
  279. if self._sig_algs + self._cert_sig_algs:
  280. ret += ['sig_algs={sig_algs}'.format(
  281. sig_algs=','.join(set(self._sig_algs + self._cert_sig_algs)))]
  282. if self._named_groups:
  283. named_groups = ','.join(self._named_groups)
  284. ret += ["curves={named_groups}".format(named_groups=named_groups)]
  285. ret += ['force_version=tls13']
  286. return ret
  287. def pre_checks(self):
  288. ret = ['requires_config_enabled MBEDTLS_DEBUG_C',
  289. 'requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED']
  290. if self._compat_mode:
  291. ret += ['requires_config_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE']
  292. if 'rsa_pss_rsae_sha256' in self._sig_algs + self._cert_sig_algs:
  293. ret.append(
  294. 'requires_config_enabled MBEDTLS_X509_RSASSA_PSS_SUPPORT')
  295. return ret
  296. class MbedTLSServ(MbedTLSBase):
  297. """
  298. Generate test commands for mbedTLS server.
  299. """
  300. def cmd(self):
  301. ret = super().cmd()
  302. ret += ['tls13_kex_modes=ephemeral cookies=0 tickets=0']
  303. return ret
  304. def pre_checks(self):
  305. return ['requires_config_enabled MBEDTLS_SSL_SRV_C'] + super().pre_checks()
  306. def post_checks(self):
  307. check_strings = ["Protocol is TLSv1.3"]
  308. if self._ciphers:
  309. check_strings.append(
  310. "server hello, chosen ciphersuite: {} ( id={:04d} )".format(
  311. self.CIPHER_SUITE[self._ciphers[0]],
  312. CIPHER_SUITE_IANA_VALUE[self._ciphers[0]]))
  313. if self._sig_algs:
  314. check_strings.append(
  315. "received signature algorithm: 0x{:x}".format(
  316. SIG_ALG_IANA_VALUE[self._sig_algs[0]]))
  317. for named_group in self._named_groups:
  318. check_strings += ['got named group: {named_group}({iana_value:04x})'.format(
  319. named_group=named_group,
  320. iana_value=NAMED_GROUP_IANA_VALUE[named_group])]
  321. check_strings.append("Certificate verification was skipped")
  322. return ['-s "{}"'.format(i) for i in check_strings]
  323. def pre_cmd(self):
  324. ret = ['$P_SRV']
  325. for _, cert, key in map(lambda sig_alg: CERTIFICATES[sig_alg], self._cert_sig_algs):
  326. ret += ['crt_file={cert} key_file={key}'.format(cert=cert, key=key)]
  327. return ret
  328. def hrr_post_checks(self, named_group):
  329. return ['-s "HRR selected_group: {:s}"'.format(named_group)]
  330. class MbedTLSCli(MbedTLSBase):
  331. """
  332. Generate test commands for mbedTLS client.
  333. """
  334. def pre_cmd(self):
  335. return ['$P_CLI',
  336. 'ca_file={cafile}'.format(cafile=CERTIFICATES[self._cert_sig_algs[0]].cafile)]
  337. def pre_checks(self):
  338. return ['requires_config_enabled MBEDTLS_SSL_CLI_C'] + super().pre_checks()
  339. def hrr_post_checks(self, named_group):
  340. ret = ['-c "received HelloRetryRequest message"']
  341. ret += ['-c "selected_group ( {:d} )"'.format(NAMED_GROUP_IANA_VALUE[named_group])]
  342. return ret
  343. def post_checks(self):
  344. check_strings = ["Protocol is TLSv1.3"]
  345. if self._ciphers:
  346. check_strings.append(
  347. "server hello, chosen ciphersuite: ( {:04x} ) - {}".format(
  348. CIPHER_SUITE_IANA_VALUE[self._ciphers[0]],
  349. self.CIPHER_SUITE[self._ciphers[0]]))
  350. if self._sig_algs:
  351. check_strings.append(
  352. "Certificate Verify: Signature algorithm ( {:04x} )".format(
  353. SIG_ALG_IANA_VALUE[self._sig_algs[0]]))
  354. for named_group in self._named_groups:
  355. check_strings += ['NamedGroup: {named_group} ( {iana_value:x} )'.format(
  356. named_group=named_group,
  357. iana_value=NAMED_GROUP_IANA_VALUE[named_group])]
  358. check_strings.append("Verifying peer X.509 certificate... ok")
  359. return ['-c "{}"'.format(i) for i in check_strings]
  360. SERVER_CLASSES = {'OpenSSL': OpenSSLServ, 'GnuTLS': GnuTLSServ, 'mbedTLS': MbedTLSServ}
  361. CLIENT_CLASSES = {'OpenSSL': OpenSSLCli, 'GnuTLS': GnuTLSCli, 'mbedTLS': MbedTLSCli}
  362. def generate_compat_test(client=None, server=None, cipher=None, named_group=None, sig_alg=None):
  363. """
  364. Generate test case with `ssl-opt.sh` format.
  365. """
  366. name = 'TLS 1.3 {client[0]}->{server[0]}: {cipher},{named_group},{sig_alg}'.format(
  367. client=client, server=server, cipher=cipher[4:], sig_alg=sig_alg, named_group=named_group)
  368. server_object = SERVER_CLASSES[server](ciphersuite=cipher,
  369. named_group=named_group,
  370. signature_algorithm=sig_alg,
  371. cert_sig_alg=sig_alg)
  372. client_object = CLIENT_CLASSES[client](ciphersuite=cipher,
  373. named_group=named_group,
  374. signature_algorithm=sig_alg,
  375. cert_sig_alg=sig_alg)
  376. cmd = ['run_test "{}"'.format(name),
  377. '"{}"'.format(' '.join(server_object.cmd())),
  378. '"{}"'.format(' '.join(client_object.cmd())),
  379. '0']
  380. cmd += server_object.post_checks()
  381. cmd += client_object.post_checks()
  382. cmd += ['-C "received HelloRetryRequest message"']
  383. prefix = ' \\\n' + (' '*9)
  384. cmd = prefix.join(cmd)
  385. return '\n'.join(server_object.pre_checks() + client_object.pre_checks() + [cmd])
  386. def generate_hrr_compat_test(client=None, server=None,
  387. client_named_group=None, server_named_group=None,
  388. cert_sig_alg=None):
  389. """
  390. Generate Hello Retry Request test case with `ssl-opt.sh` format.
  391. """
  392. name = 'TLS 1.3 {client[0]}->{server[0]}: HRR {c_named_group} -> {s_named_group}'.format(
  393. client=client, server=server, c_named_group=client_named_group,
  394. s_named_group=server_named_group)
  395. server_object = SERVER_CLASSES[server](named_group=server_named_group,
  396. cert_sig_alg=cert_sig_alg)
  397. client_object = CLIENT_CLASSES[client](named_group=client_named_group,
  398. cert_sig_alg=cert_sig_alg)
  399. client_object.add_named_groups(server_named_group)
  400. cmd = ['run_test "{}"'.format(name),
  401. '"{}"'.format(' '.join(server_object.cmd())),
  402. '"{}"'.format(' '.join(client_object.cmd())),
  403. '0']
  404. cmd += server_object.post_checks()
  405. cmd += client_object.post_checks()
  406. cmd += server_object.hrr_post_checks(server_named_group)
  407. cmd += client_object.hrr_post_checks(server_named_group)
  408. prefix = ' \\\n' + (' '*9)
  409. cmd = prefix.join(cmd)
  410. return '\n'.join(server_object.pre_checks() +
  411. client_object.pre_checks() +
  412. [cmd])
  413. SSL_OUTPUT_HEADER = '''#!/bin/sh
  414. # {filename}
  415. #
  416. # Copyright The Mbed TLS Contributors
  417. # SPDX-License-Identifier: Apache-2.0
  418. #
  419. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  420. # not use this file except in compliance with the License.
  421. # You may obtain a copy of the License at
  422. #
  423. # http://www.apache.org/licenses/LICENSE-2.0
  424. #
  425. # Unless required by applicable law or agreed to in writing, software
  426. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  427. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  428. # See the License for the specific language governing permissions and
  429. # limitations under the License.
  430. #
  431. # Purpose
  432. #
  433. # List TLS1.3 compat test cases. They are generated by
  434. # `{cmd}`.
  435. #
  436. # PLEASE DO NOT EDIT THIS FILE. IF NEEDED, PLEASE MODIFY `generate_tls13_compat_tests.py`
  437. # AND REGENERATE THIS FILE.
  438. #
  439. '''
  440. def main():
  441. """
  442. Main function of this program
  443. """
  444. parser = argparse.ArgumentParser()
  445. parser.add_argument('-o', '--output', nargs='?',
  446. default=None, help='Output file path if `-a` was set')
  447. parser.add_argument('-a', '--generate-all-tls13-compat-tests', action='store_true',
  448. default=False, help='Generate all available tls13 compat tests')
  449. parser.add_argument('--list-ciphers', action='store_true',
  450. default=False, help='List supported ciphersuites')
  451. parser.add_argument('--list-sig-algs', action='store_true',
  452. default=False, help='List supported signature algorithms')
  453. parser.add_argument('--list-named-groups', action='store_true',
  454. default=False, help='List supported named groups')
  455. parser.add_argument('--list-servers', action='store_true',
  456. default=False, help='List supported TLS servers')
  457. parser.add_argument('--list-clients', action='store_true',
  458. default=False, help='List supported TLS Clients')
  459. parser.add_argument('server', choices=SERVER_CLASSES.keys(), nargs='?',
  460. default=list(SERVER_CLASSES.keys())[0],
  461. help='Choose TLS server program for test')
  462. parser.add_argument('client', choices=CLIENT_CLASSES.keys(), nargs='?',
  463. default=list(CLIENT_CLASSES.keys())[0],
  464. help='Choose TLS client program for test')
  465. parser.add_argument('cipher', choices=CIPHER_SUITE_IANA_VALUE.keys(), nargs='?',
  466. default=list(CIPHER_SUITE_IANA_VALUE.keys())[0],
  467. help='Choose cipher suite for test')
  468. parser.add_argument('sig_alg', choices=SIG_ALG_IANA_VALUE.keys(), nargs='?',
  469. default=list(SIG_ALG_IANA_VALUE.keys())[0],
  470. help='Choose cipher suite for test')
  471. parser.add_argument('named_group', choices=NAMED_GROUP_IANA_VALUE.keys(), nargs='?',
  472. default=list(NAMED_GROUP_IANA_VALUE.keys())[0],
  473. help='Choose cipher suite for test')
  474. args = parser.parse_args()
  475. def get_all_test_cases():
  476. # Generate normal compat test cases
  477. for client, server, cipher, named_group, sig_alg in \
  478. itertools.product(CLIENT_CLASSES.keys(),
  479. SERVER_CLASSES.keys(),
  480. CIPHER_SUITE_IANA_VALUE.keys(),
  481. NAMED_GROUP_IANA_VALUE.keys(),
  482. SIG_ALG_IANA_VALUE.keys()):
  483. if server == 'mbedTLS' or client == 'mbedTLS':
  484. yield generate_compat_test(client=client, server=server,
  485. cipher=cipher, named_group=named_group,
  486. sig_alg=sig_alg)
  487. # Generate Hello Retry Request compat test cases
  488. for client, server, client_named_group, server_named_group in \
  489. itertools.product(CLIENT_CLASSES.keys(),
  490. SERVER_CLASSES.keys(),
  491. NAMED_GROUP_IANA_VALUE.keys(),
  492. NAMED_GROUP_IANA_VALUE.keys()):
  493. if (client == 'mbedTLS' or server == 'mbedTLS') and \
  494. client_named_group != server_named_group:
  495. yield generate_hrr_compat_test(client=client, server=server,
  496. client_named_group=client_named_group,
  497. server_named_group=server_named_group,
  498. cert_sig_alg="ecdsa_secp256r1_sha256")
  499. if args.generate_all_tls13_compat_tests:
  500. if args.output:
  501. with open(args.output, 'w', encoding="utf-8") as f:
  502. f.write(SSL_OUTPUT_HEADER.format(
  503. filename=os.path.basename(args.output), cmd=' '.join(sys.argv)))
  504. f.write('\n\n'.join(get_all_test_cases()))
  505. f.write('\n')
  506. else:
  507. print('\n\n'.join(get_all_test_cases()))
  508. return 0
  509. if args.list_ciphers or args.list_sig_algs or args.list_named_groups \
  510. or args.list_servers or args.list_clients:
  511. if args.list_ciphers:
  512. print(*CIPHER_SUITE_IANA_VALUE.keys())
  513. if args.list_sig_algs:
  514. print(*SIG_ALG_IANA_VALUE.keys())
  515. if args.list_named_groups:
  516. print(*NAMED_GROUP_IANA_VALUE.keys())
  517. if args.list_servers:
  518. print(*SERVER_CLASSES.keys())
  519. if args.list_clients:
  520. print(*CLIENT_CLASSES.keys())
  521. return 0
  522. print(generate_compat_test(server=args.server, client=args.client, sig_alg=args.sig_alg,
  523. cipher=args.cipher, named_group=args.named_group))
  524. return 0
  525. if __name__ == "__main__":
  526. sys.exit(main())