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