generate_tls13_compat_tests.py (24294B)
1 #!/usr/bin/env python3 2 3 # generate_tls13_compat_tests.py 4 # 5 # Copyright The Mbed TLS Contributors 6 # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 7 8 """ 9 Generate TLSv1.3 Compat test cases 10 11 """ 12 13 import sys 14 import os 15 import argparse 16 import itertools 17 from collections import namedtuple 18 19 # define certificates configuration entry 20 Certificate = namedtuple("Certificate", ['cafile', 'certfile', 'keyfile']) 21 # define the certificate parameters for signature algorithms 22 CERTIFICATES = { 23 'ecdsa_secp256r1_sha256': Certificate('$DATA_FILES_PATH/test-ca2.crt', 24 '$DATA_FILES_PATH/ecdsa_secp256r1.crt', 25 '$DATA_FILES_PATH/ecdsa_secp256r1.key'), 26 'ecdsa_secp384r1_sha384': Certificate('$DATA_FILES_PATH/test-ca2.crt', 27 '$DATA_FILES_PATH/ecdsa_secp384r1.crt', 28 '$DATA_FILES_PATH/ecdsa_secp384r1.key'), 29 'ecdsa_secp521r1_sha512': Certificate('$DATA_FILES_PATH/test-ca2.crt', 30 '$DATA_FILES_PATH/ecdsa_secp521r1.crt', 31 '$DATA_FILES_PATH/ecdsa_secp521r1.key'), 32 'rsa_pss_rsae_sha256': Certificate('$DATA_FILES_PATH/test-ca_cat12.crt', 33 '$DATA_FILES_PATH/server2-sha256.crt', 34 '$DATA_FILES_PATH/server2.key') 35 } 36 37 CIPHER_SUITE_IANA_VALUE = { 38 "TLS_AES_128_GCM_SHA256": 0x1301, 39 "TLS_AES_256_GCM_SHA384": 0x1302, 40 "TLS_CHACHA20_POLY1305_SHA256": 0x1303, 41 "TLS_AES_128_CCM_SHA256": 0x1304, 42 "TLS_AES_128_CCM_8_SHA256": 0x1305 43 } 44 45 SIG_ALG_IANA_VALUE = { 46 "ecdsa_secp256r1_sha256": 0x0403, 47 "ecdsa_secp384r1_sha384": 0x0503, 48 "ecdsa_secp521r1_sha512": 0x0603, 49 'rsa_pss_rsae_sha256': 0x0804, 50 } 51 52 NAMED_GROUP_IANA_VALUE = { 53 'secp256r1': 0x17, 54 'secp384r1': 0x18, 55 'secp521r1': 0x19, 56 'x25519': 0x1d, 57 'x448': 0x1e, 58 # Only one finite field group to keep testing time within reasonable bounds. 59 'ffdhe2048': 0x100, 60 } 61 62 class TLSProgram: 63 """ 64 Base class for generate server/client command. 65 """ 66 67 # pylint: disable=too-many-arguments 68 def __init__(self, ciphersuite=None, signature_algorithm=None, named_group=None, 69 cert_sig_alg=None): 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 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 88 # add_signature_algorithms should not override by sub class 89 def add_signature_algorithms(self, *signature_algorithms): 90 self._sig_algs.extend( 91 [sig_alg for sig_alg in signature_algorithms if sig_alg not in self._sig_algs]) 92 93 # add_named_groups should not override by sub class 94 def add_named_groups(self, *named_groups): 95 self._named_groups.extend( 96 [named_group for named_group in named_groups if named_group not in self._named_groups]) 97 98 # add_cert_signature_algorithms should not override by sub class 99 def add_cert_signature_algorithms(self, *signature_algorithms): 100 self._cert_sig_algs.extend( 101 [sig_alg for sig_alg in signature_algorithms if sig_alg not in self._cert_sig_algs]) 102 103 # pylint: disable=no-self-use 104 def pre_checks(self): 105 return [] 106 107 # pylint: disable=no-self-use 108 def cmd(self): 109 if not self._cert_sig_algs: 110 self._cert_sig_algs = list(CERTIFICATES.keys()) 111 return self.pre_cmd() 112 113 # pylint: disable=no-self-use 114 def post_checks(self): 115 return [] 116 117 # pylint: disable=no-self-use 118 def pre_cmd(self): 119 return ['false'] 120 121 # pylint: disable=unused-argument,no-self-use 122 def hrr_post_checks(self, named_group): 123 return [] 124 125 126 class OpenSSLBase(TLSProgram): 127 """ 128 Generate base test commands for OpenSSL. 129 """ 130 131 NAMED_GROUP = { 132 'secp256r1': 'P-256', 133 'secp384r1': 'P-384', 134 'secp521r1': 'P-521', 135 'x25519': 'X25519', 136 'x448': 'X448', 137 'ffdhe2048': 'ffdhe2048', 138 } 139 140 def cmd(self): 141 ret = super().cmd() 142 143 if self._ciphers: 144 ciphersuites = ':'.join(self._ciphers) 145 ret += ["-ciphersuites {ciphersuites}".format(ciphersuites=ciphersuites)] 146 147 if self._sig_algs: 148 signature_algorithms = set(self._sig_algs + self._cert_sig_algs) 149 signature_algorithms = ':'.join(signature_algorithms) 150 ret += ["-sigalgs {signature_algorithms}".format( 151 signature_algorithms=signature_algorithms)] 152 153 if self._named_groups: 154 named_groups = ':'.join( 155 map(lambda named_group: self.NAMED_GROUP[named_group], self._named_groups)) 156 ret += ["-groups {named_groups}".format(named_groups=named_groups)] 157 158 ret += ['-msg -tls1_3'] 159 160 return ret 161 162 def pre_checks(self): 163 ret = ["requires_openssl_tls1_3"] 164 165 # ffdh groups require at least openssl 3.0 166 ffdh_groups = ['ffdhe2048'] 167 168 if any(x in ffdh_groups for x in self._named_groups): 169 ret = ["requires_openssl_tls1_3_with_ffdh"] 170 171 return ret 172 173 174 class OpenSSLServ(OpenSSLBase): 175 """ 176 Generate test commands for OpenSSL server. 177 """ 178 179 def cmd(self): 180 ret = super().cmd() 181 ret += ['-num_tickets 0 -no_resume_ephemeral -no_cache'] 182 return ret 183 184 def post_checks(self): 185 return ['-c "HTTP/1.0 200 ok"'] 186 187 def pre_cmd(self): 188 ret = ['$O_NEXT_SRV_NO_CERT'] 189 for _, cert, key in map(lambda sig_alg: CERTIFICATES[sig_alg], self._cert_sig_algs): 190 ret += ['-cert {cert} -key {key}'.format(cert=cert, key=key)] 191 return ret 192 193 194 class OpenSSLCli(OpenSSLBase): 195 """ 196 Generate test commands for OpenSSL client. 197 """ 198 199 def pre_cmd(self): 200 return ['$O_NEXT_CLI_NO_CERT', 201 '-CAfile {cafile}'.format(cafile=CERTIFICATES[self._cert_sig_algs[0]].cafile)] 202 203 204 class GnuTLSBase(TLSProgram): 205 """ 206 Generate base test commands for GnuTLS. 207 """ 208 209 CIPHER_SUITE = { 210 'TLS_AES_256_GCM_SHA384': [ 211 'AES-256-GCM', 212 'SHA384', 213 'AEAD'], 214 'TLS_AES_128_GCM_SHA256': [ 215 'AES-128-GCM', 216 'SHA256', 217 'AEAD'], 218 'TLS_CHACHA20_POLY1305_SHA256': [ 219 'CHACHA20-POLY1305', 220 'SHA256', 221 'AEAD'], 222 'TLS_AES_128_CCM_SHA256': [ 223 'AES-128-CCM', 224 'SHA256', 225 'AEAD'], 226 'TLS_AES_128_CCM_8_SHA256': [ 227 'AES-128-CCM-8', 228 'SHA256', 229 'AEAD']} 230 231 SIGNATURE_ALGORITHM = { 232 'ecdsa_secp256r1_sha256': ['SIGN-ECDSA-SECP256R1-SHA256'], 233 'ecdsa_secp521r1_sha512': ['SIGN-ECDSA-SECP521R1-SHA512'], 234 'ecdsa_secp384r1_sha384': ['SIGN-ECDSA-SECP384R1-SHA384'], 235 'rsa_pss_rsae_sha256': ['SIGN-RSA-PSS-RSAE-SHA256']} 236 237 NAMED_GROUP = { 238 'secp256r1': ['GROUP-SECP256R1'], 239 'secp384r1': ['GROUP-SECP384R1'], 240 'secp521r1': ['GROUP-SECP521R1'], 241 'x25519': ['GROUP-X25519'], 242 'x448': ['GROUP-X448'], 243 'ffdhe2048': ['GROUP-FFDHE2048'], 244 } 245 246 def pre_checks(self): 247 return ["requires_gnutls_tls1_3", 248 "requires_gnutls_next_no_ticket"] 249 250 def cmd(self): 251 ret = super().cmd() 252 253 priority_string_list = [] 254 255 def update_priority_string_list(items, map_table): 256 for item in items: 257 for i in map_table[item]: 258 if i not in priority_string_list: 259 yield i 260 261 if self._ciphers: 262 priority_string_list.extend(update_priority_string_list( 263 self._ciphers, self.CIPHER_SUITE)) 264 else: 265 priority_string_list.extend(['CIPHER-ALL', 'MAC-ALL']) 266 267 if self._sig_algs: 268 signature_algorithms = set(self._sig_algs + self._cert_sig_algs) 269 priority_string_list.extend(update_priority_string_list( 270 signature_algorithms, self.SIGNATURE_ALGORITHM)) 271 else: 272 priority_string_list.append('SIGN-ALL') 273 274 275 if self._named_groups: 276 priority_string_list.extend(update_priority_string_list( 277 self._named_groups, self.NAMED_GROUP)) 278 else: 279 priority_string_list.append('GROUP-ALL') 280 281 priority_string_list = ['NONE'] + \ 282 priority_string_list + ['VERS-TLS1.3'] 283 284 priority_string = ':+'.join(priority_string_list) 285 priority_string += ':%NO_TICKETS' 286 287 ret += ['--priority={priority_string}'.format( 288 priority_string=priority_string)] 289 return ret 290 291 class GnuTLSServ(GnuTLSBase): 292 """ 293 Generate test commands for GnuTLS server. 294 """ 295 296 def pre_cmd(self): 297 ret = ['$G_NEXT_SRV_NO_CERT', '--http', '--disable-client-cert', '--debug=4'] 298 299 for _, cert, key in map(lambda sig_alg: CERTIFICATES[sig_alg], self._cert_sig_algs): 300 ret += ['--x509certfile {cert} --x509keyfile {key}'.format( 301 cert=cert, key=key)] 302 return ret 303 304 def post_checks(self): 305 return ['-c "HTTP/1.0 200 OK"'] 306 307 308 class GnuTLSCli(GnuTLSBase): 309 """ 310 Generate test commands for GnuTLS client. 311 """ 312 313 def pre_cmd(self): 314 return ['$G_NEXT_CLI_NO_CERT', '--debug=4', '--single-key-share', 315 '--x509cafile {cafile}'.format(cafile=CERTIFICATES[self._cert_sig_algs[0]].cafile)] 316 317 318 class MbedTLSBase(TLSProgram): 319 """ 320 Generate base test commands for mbedTLS. 321 """ 322 323 CIPHER_SUITE = { 324 'TLS_AES_256_GCM_SHA384': 'TLS1-3-AES-256-GCM-SHA384', 325 'TLS_AES_128_GCM_SHA256': 'TLS1-3-AES-128-GCM-SHA256', 326 'TLS_CHACHA20_POLY1305_SHA256': 'TLS1-3-CHACHA20-POLY1305-SHA256', 327 'TLS_AES_128_CCM_SHA256': 'TLS1-3-AES-128-CCM-SHA256', 328 'TLS_AES_128_CCM_8_SHA256': 'TLS1-3-AES-128-CCM-8-SHA256'} 329 330 def cmd(self): 331 ret = super().cmd() 332 ret += ['debug_level=4'] 333 334 335 if self._ciphers: 336 ciphers = ','.join( 337 map(lambda cipher: self.CIPHER_SUITE[cipher], self._ciphers)) 338 ret += ["force_ciphersuite={ciphers}".format(ciphers=ciphers)] 339 340 if self._sig_algs + self._cert_sig_algs: 341 ret += ['sig_algs={sig_algs}'.format( 342 sig_algs=','.join(set(self._sig_algs + self._cert_sig_algs)))] 343 344 if self._named_groups: 345 named_groups = ','.join(self._named_groups) 346 ret += ["groups={named_groups}".format(named_groups=named_groups)] 347 return ret 348 349 #pylint: disable=missing-function-docstring 350 def add_ffdh_group_requirements(self, requirement_list): 351 if 'ffdhe2048' in self._named_groups: 352 requirement_list.append('requires_config_enabled PSA_WANT_DH_RFC7919_2048') 353 if 'ffdhe3072' in self._named_groups: 354 requirement_list.append('requires_config_enabled PSA_WANT_DH_RFC7919_2048') 355 if 'ffdhe4096' in self._named_groups: 356 requirement_list.append('requires_config_enabled PSA_WANT_DH_RFC7919_2048') 357 if 'ffdhe6144' in self._named_groups: 358 requirement_list.append('requires_config_enabled PSA_WANT_DH_RFC7919_2048') 359 if 'ffdhe8192' in self._named_groups: 360 requirement_list.append('requires_config_enabled PSA_WANT_DH_RFC7919_2048') 361 362 def pre_checks(self): 363 ret = ['requires_config_enabled MBEDTLS_DEBUG_C', 364 'requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED'] 365 366 if 'rsa_pss_rsae_sha256' in self._sig_algs + self._cert_sig_algs: 367 ret.append( 368 'requires_config_enabled MBEDTLS_X509_RSASSA_PSS_SUPPORT') 369 370 ec_groups = ['secp256r1', 'secp384r1', 'secp521r1', 'x25519', 'x448'] 371 ffdh_groups = ['ffdhe2048', 'ffdhe3072', 'ffdhe4096', 'ffdhe6144', 'ffdhe8192'] 372 373 if any(x in ec_groups for x in self._named_groups): 374 ret.append('requires_config_enabled PSA_WANT_ALG_ECDH') 375 376 if any(x in ffdh_groups for x in self._named_groups): 377 ret.append('requires_config_enabled PSA_WANT_ALG_FFDH') 378 self.add_ffdh_group_requirements(ret) 379 380 return ret 381 382 383 class MbedTLSServ(MbedTLSBase): 384 """ 385 Generate test commands for mbedTLS server. 386 """ 387 388 def cmd(self): 389 ret = super().cmd() 390 ret += ['tls13_kex_modes=ephemeral cookies=0 tickets=0'] 391 return ret 392 393 def pre_checks(self): 394 return ['requires_config_enabled MBEDTLS_SSL_SRV_C'] + super().pre_checks() 395 396 def post_checks(self): 397 check_strings = ["Protocol is TLSv1.3"] 398 if self._ciphers: 399 check_strings.append( 400 "server hello, chosen ciphersuite: {} ( id={:04d} )".format( 401 self.CIPHER_SUITE[self._ciphers[0]], 402 CIPHER_SUITE_IANA_VALUE[self._ciphers[0]])) 403 if self._sig_algs: 404 check_strings.append( 405 "received signature algorithm: 0x{:x}".format( 406 SIG_ALG_IANA_VALUE[self._sig_algs[0]])) 407 408 for named_group in self._named_groups: 409 check_strings += ['got named group: {named_group}({iana_value:04x})'.format( 410 named_group=named_group, 411 iana_value=NAMED_GROUP_IANA_VALUE[named_group])] 412 413 check_strings.append("Certificate verification was skipped") 414 return ['-s "{}"'.format(i) for i in check_strings] 415 416 def pre_cmd(self): 417 ret = ['$P_SRV'] 418 for _, cert, key in map(lambda sig_alg: CERTIFICATES[sig_alg], self._cert_sig_algs): 419 ret += ['crt_file={cert} key_file={key}'.format(cert=cert, key=key)] 420 return ret 421 422 def hrr_post_checks(self, named_group): 423 return ['-s "HRR selected_group: {:s}"'.format(named_group)] 424 425 426 class MbedTLSCli(MbedTLSBase): 427 """ 428 Generate test commands for mbedTLS client. 429 """ 430 431 def pre_cmd(self): 432 return ['$P_CLI', 433 'ca_file={cafile}'.format(cafile=CERTIFICATES[self._cert_sig_algs[0]].cafile)] 434 435 def pre_checks(self): 436 return ['requires_config_enabled MBEDTLS_SSL_CLI_C'] + super().pre_checks() 437 438 def hrr_post_checks(self, named_group): 439 ret = ['-c "received HelloRetryRequest message"'] 440 ret += ['-c "selected_group ( {:d} )"'.format(NAMED_GROUP_IANA_VALUE[named_group])] 441 return ret 442 443 def post_checks(self): 444 check_strings = ["Protocol is TLSv1.3"] 445 if self._ciphers: 446 check_strings.append( 447 "server hello, chosen ciphersuite: ( {:04x} ) - {}".format( 448 CIPHER_SUITE_IANA_VALUE[self._ciphers[0]], 449 self.CIPHER_SUITE[self._ciphers[0]])) 450 if self._sig_algs: 451 check_strings.append( 452 "Certificate Verify: Signature algorithm ( {:04x} )".format( 453 SIG_ALG_IANA_VALUE[self._sig_algs[0]])) 454 455 for named_group in self._named_groups: 456 check_strings += ['NamedGroup: {named_group} ( {iana_value:x} )'.format( 457 named_group=named_group, 458 iana_value=NAMED_GROUP_IANA_VALUE[named_group])] 459 460 check_strings.append("Verifying peer X.509 certificate... ok") 461 return ['-c "{}"'.format(i) for i in check_strings] 462 463 464 SERVER_CLASSES = {'OpenSSL': OpenSSLServ, 'GnuTLS': GnuTLSServ, 'mbedTLS': MbedTLSServ} 465 CLIENT_CLASSES = {'OpenSSL': OpenSSLCli, 'GnuTLS': GnuTLSCli, 'mbedTLS': MbedTLSCli} 466 467 468 def generate_compat_test(client=None, server=None, cipher=None, named_group=None, sig_alg=None): 469 """ 470 Generate test case with `ssl-opt.sh` format. 471 """ 472 name = 'TLS 1.3 {client[0]}->{server[0]}: {cipher},{named_group},{sig_alg}'.format( 473 client=client, server=server, cipher=cipher[4:], sig_alg=sig_alg, named_group=named_group) 474 475 server_object = SERVER_CLASSES[server](ciphersuite=cipher, 476 named_group=named_group, 477 signature_algorithm=sig_alg, 478 cert_sig_alg=sig_alg) 479 client_object = CLIENT_CLASSES[client](ciphersuite=cipher, 480 named_group=named_group, 481 signature_algorithm=sig_alg, 482 cert_sig_alg=sig_alg) 483 484 cmd = ['run_test "{}"'.format(name), 485 '"{}"'.format(' '.join(server_object.cmd())), 486 '"{}"'.format(' '.join(client_object.cmd())), 487 '0'] 488 cmd += server_object.post_checks() 489 cmd += client_object.post_checks() 490 cmd += ['-C "received HelloRetryRequest message"'] 491 prefix = ' \\\n' + (' '*9) 492 cmd = prefix.join(cmd) 493 return '\n'.join(server_object.pre_checks() + client_object.pre_checks() + [cmd]) 494 495 496 def generate_hrr_compat_test(client=None, server=None, 497 client_named_group=None, server_named_group=None, 498 cert_sig_alg=None): 499 """ 500 Generate Hello Retry Request test case with `ssl-opt.sh` format. 501 """ 502 name = 'TLS 1.3 {client[0]}->{server[0]}: HRR {c_named_group} -> {s_named_group}'.format( 503 client=client, server=server, c_named_group=client_named_group, 504 s_named_group=server_named_group) 505 server_object = SERVER_CLASSES[server](named_group=server_named_group, 506 cert_sig_alg=cert_sig_alg) 507 508 client_object = CLIENT_CLASSES[client](named_group=client_named_group, 509 cert_sig_alg=cert_sig_alg) 510 client_object.add_named_groups(server_named_group) 511 512 cmd = ['run_test "{}"'.format(name), 513 '"{}"'.format(' '.join(server_object.cmd())), 514 '"{}"'.format(' '.join(client_object.cmd())), 515 '0'] 516 cmd += server_object.post_checks() 517 cmd += client_object.post_checks() 518 cmd += server_object.hrr_post_checks(server_named_group) 519 cmd += client_object.hrr_post_checks(server_named_group) 520 prefix = ' \\\n' + (' '*9) 521 cmd = prefix.join(cmd) 522 return '\n'.join(server_object.pre_checks() + 523 client_object.pre_checks() + 524 [cmd]) 525 526 SSL_OUTPUT_HEADER = '''\ 527 # TLS 1.3 interoperability test cases (equivalent of compat.sh for TLS 1.3). 528 # 529 # Automatically generated by {cmd}. Do not edit! 530 531 # Copyright The Mbed TLS Contributors 532 # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 533 ''' 534 DATA_FILES_PATH_VAR = ''' 535 DATA_FILES_PATH=../framework/data_files 536 ''' 537 538 def main(): 539 """ 540 Main function of this program 541 """ 542 parser = argparse.ArgumentParser() 543 544 parser.add_argument('-o', '--output', 545 default='tests/opt-testcases/tls13-compat.sh', 546 help='Output file path (not used with -1)') 547 548 parser.add_argument('-1', '--single', action='store_true', 549 help='Print a single test case') 550 # Single mode used to be the default. 551 parser.add_argument('-a', '--generate-all-tls13-compat-tests', 552 action='store_false', dest='single', 553 help='Generate all test cases (negates -1) (default)') 554 555 parser.add_argument('--list-ciphers', action='store_true', 556 default=False, help='List supported ciphersuites') 557 558 parser.add_argument('--list-sig-algs', action='store_true', 559 default=False, help='List supported signature algorithms') 560 561 parser.add_argument('--list-named-groups', action='store_true', 562 default=False, help='List supported named groups') 563 564 parser.add_argument('--list-servers', action='store_true', 565 default=False, help='List supported TLS servers') 566 567 parser.add_argument('--list-clients', action='store_true', 568 default=False, help='List supported TLS Clients') 569 570 parser.add_argument('server', choices=SERVER_CLASSES.keys(), nargs='?', 571 default=list(SERVER_CLASSES.keys())[0], 572 help='Choose TLS server program for test') 573 parser.add_argument('client', choices=CLIENT_CLASSES.keys(), nargs='?', 574 default=list(CLIENT_CLASSES.keys())[0], 575 help='Choose TLS client program for test') 576 parser.add_argument('cipher', choices=CIPHER_SUITE_IANA_VALUE.keys(), nargs='?', 577 default=list(CIPHER_SUITE_IANA_VALUE.keys())[0], 578 help='Choose cipher suite for test') 579 parser.add_argument('sig_alg', choices=SIG_ALG_IANA_VALUE.keys(), nargs='?', 580 default=list(SIG_ALG_IANA_VALUE.keys())[0], 581 help='Choose cipher suite for test') 582 parser.add_argument('named_group', choices=NAMED_GROUP_IANA_VALUE.keys(), nargs='?', 583 default=list(NAMED_GROUP_IANA_VALUE.keys())[0], 584 help='Choose cipher suite for test') 585 586 args = parser.parse_args() 587 588 def get_all_test_cases(): 589 # Generate normal compat test cases 590 for client, server, cipher, named_group, sig_alg in \ 591 itertools.product(CLIENT_CLASSES.keys(), 592 SERVER_CLASSES.keys(), 593 CIPHER_SUITE_IANA_VALUE.keys(), 594 NAMED_GROUP_IANA_VALUE.keys(), 595 SIG_ALG_IANA_VALUE.keys()): 596 if server == 'mbedTLS' or client == 'mbedTLS': 597 yield generate_compat_test(client=client, server=server, 598 cipher=cipher, named_group=named_group, 599 sig_alg=sig_alg) 600 601 602 # Generate Hello Retry Request compat test cases 603 for client, server, client_named_group, server_named_group in \ 604 itertools.product(CLIENT_CLASSES.keys(), 605 SERVER_CLASSES.keys(), 606 NAMED_GROUP_IANA_VALUE.keys(), 607 NAMED_GROUP_IANA_VALUE.keys()): 608 609 if (client == 'mbedTLS' or server == 'mbedTLS') and \ 610 client_named_group != server_named_group: 611 yield generate_hrr_compat_test(client=client, server=server, 612 client_named_group=client_named_group, 613 server_named_group=server_named_group, 614 cert_sig_alg="ecdsa_secp256r1_sha256") 615 616 if not args.single: 617 if args.output: 618 with open(args.output, 'w', encoding="utf-8") as f: 619 f.write(SSL_OUTPUT_HEADER.format( 620 filename=os.path.basename(args.output), 621 cmd=os.path.basename(sys.argv[0]))) 622 f.write(DATA_FILES_PATH_VAR) 623 f.write('\n\n'.join(get_all_test_cases())) 624 f.write('\n') 625 else: 626 print('\n\n'.join(get_all_test_cases())) 627 return 0 628 629 if args.list_ciphers or args.list_sig_algs or args.list_named_groups \ 630 or args.list_servers or args.list_clients: 631 if args.list_ciphers: 632 print(*CIPHER_SUITE_IANA_VALUE.keys()) 633 if args.list_sig_algs: 634 print(*SIG_ALG_IANA_VALUE.keys()) 635 if args.list_named_groups: 636 print(*NAMED_GROUP_IANA_VALUE.keys()) 637 if args.list_servers: 638 print(*SERVER_CLASSES.keys()) 639 if args.list_clients: 640 print(*CLIENT_CLASSES.keys()) 641 return 0 642 643 print(generate_compat_test(server=args.server, client=args.client, sig_alg=args.sig_alg, 644 cipher=args.cipher, named_group=args.named_group)) 645 return 0 646 647 648 if __name__ == "__main__": 649 sys.exit(main())