1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
import logging
import os
from configparser import ConfigParser, ExtendedInterpolation
from typing import Dict, Optional
from .certs import CertificateSpec, Ngtcp2TestCA, Credentials
log = logging.getLogger(__name__)
class CryptoLib:
IGNORES_CIPHER_CONFIG = [
'picotls', 'boringssl'
]
UNSUPPORTED_CIPHERS = {
'wolfssl': [
'TLS_AES_128_CCM_SHA256', # no plans to
],
'picotls': [
'TLS_AES_128_CCM_SHA256', # no plans to
],
'boringssl': [
'TLS_AES_128_CCM_SHA256', # no plans to
]
}
GNUTLS_CIPHERS = {
'TLS_AES_128_GCM_SHA256': 'AES-128-GCM',
'TLS_AES_256_GCM_SHA384': 'AES-256-GCM',
'TLS_CHACHA20_POLY1305_SHA256': 'CHACHA20-POLY1305',
'TLS_AES_128_CCM_SHA256': 'AES-128-CCM',
}
@classmethod
def uses_cipher_config(cls, crypto_lib):
return crypto_lib not in cls.IGNORES_CIPHER_CONFIG
@classmethod
def supports_cipher(cls, crypto_lib, cipher):
return crypto_lib not in cls.UNSUPPORTED_CIPHERS or \
cipher not in cls.UNSUPPORTED_CIPHERS[crypto_lib]
@classmethod
def adjust_ciphers(cls, crypto_lib, ciphers: str) -> str:
if crypto_lib == 'gnutls':
gciphers = "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL"
for cipher in ciphers.split(':'):
gciphers += f':+{cls.GNUTLS_CIPHERS[cipher]}'
return gciphers
return ciphers
def init_config_from(conf_path):
if os.path.isfile(conf_path):
config = ConfigParser(interpolation=ExtendedInterpolation())
config.read(conf_path)
return config
return None
TESTS_PATH = os.path.dirname(os.path.dirname(__file__))
EXAMPLES_PATH = os.path.dirname(TESTS_PATH)
DEF_CONFIG = init_config_from(os.path.join(TESTS_PATH, 'config.ini'))
class Env:
@classmethod
def get_crypto_libs(cls, configurable_ciphers=None):
names = [name for name in DEF_CONFIG['examples']
if DEF_CONFIG['examples'][name] == 'yes']
if configurable_ciphers is not None:
names = [n for n in names if CryptoLib.uses_cipher_config(n)]
return names
def __init__(self, examples_dir=None, tests_dir=None, config=None,
pytestconfig=None):
self._verbose = pytestconfig.option.verbose if pytestconfig is not None else 0
self._examples_dir = examples_dir if examples_dir is not None else EXAMPLES_PATH
self._tests_dir = examples_dir if tests_dir is not None else TESTS_PATH
self._gen_dir = os.path.join(self._tests_dir, 'gen')
self.config = config if config is not None else DEF_CONFIG
self._version = self.config['ngtcp2']['version']
self._crypto_libs = [name for name in self.config['examples']
if self.config['examples'][name] == 'yes']
self._clients = [self.config['clients'][lib] for lib in self._crypto_libs
if lib in self.config['clients']]
self._servers = [self.config['servers'][lib] for lib in self._crypto_libs
if lib in self.config['servers']]
self._examples_pem = {
'key': 'xxx',
'cert': 'xxx',
}
self._htdocs_dir = os.path.join(self._gen_dir, 'htdocs')
self._tld = 'tests.ngtcp2.nghttp2.org'
self._example_domain = f"one.{self._tld}"
self._ca = None
self._cert_specs = [
CertificateSpec(domains=[self._example_domain], key_type='rsa2048'),
CertificateSpec(name="clientsX", sub_specs=[
CertificateSpec(name="user1", client=True),
]),
]
def issue_certs(self):
if self._ca is None:
self._ca = Ngtcp2TestCA.create_root(name=self._tld,
store_dir=os.path.join(self.gen_dir, 'ca'),
key_type="rsa2048")
self._ca.issue_certs(self._cert_specs)
def setup(self):
os.makedirs(self._gen_dir, exist_ok=True)
os.makedirs(self._htdocs_dir, exist_ok=True)
self.issue_certs()
def get_server_credentials(self) -> Optional[Credentials]:
creds = self.ca.get_credentials_for_name(self._example_domain)
if len(creds) > 0:
return creds[0]
return None
@property
def verbose(self) -> int:
return self._verbose
@property
def version(self) -> str:
return self._version
@property
def gen_dir(self) -> str:
return self._gen_dir
@property
def ca(self):
return self._ca
@property
def htdocs_dir(self) -> str:
return self._htdocs_dir
@property
def example_domain(self) -> str:
return self._example_domain
@property
def examples_dir(self) -> str:
return self._examples_dir
@property
def examples_port(self) -> int:
return int(self.config['examples']['port'])
@property
def examples_pem(self) -> Dict[str, str]:
return self._examples_pem
@property
def crypto_libs(self):
return self._crypto_libs
@property
def clients(self):
return self._clients
@property
def servers(self):
return self._servers
def client_name(self, crypto_lib):
if crypto_lib in self.config['clients']:
return self.config['clients'][crypto_lib]
return None
def client_path(self, crypto_lib):
cname = self.client_name(crypto_lib)
if cname is not None:
return os.path.join(self.examples_dir, cname)
return None
def server_name(self, crypto_lib):
if crypto_lib in self.config['servers']:
return self.config['servers'][crypto_lib]
return None
def server_path(self, crypto_lib):
sname = self.server_name(crypto_lib)
if sname is not None:
return os.path.join(self.examples_dir, sname)
return None
|