4
Used to generate lib/tls/tls_suite_info.cpp from IANA params
6
(C) 2011, 2012, 2013, 2014, 2015, 2016, 2017 Jack Lloyd
8
Botan is released under the Simplified BSD License (see license.txt)
17
def to_ciphersuite_info(code, name):
19
(sig_and_kex,cipher_and_mac) = name.split('_WITH_')
21
if sig_and_kex == 'RSA':
24
elif 'PSK' in sig_and_kex:
26
kex_algo = sig_and_kex
27
elif 'SRP' in sig_and_kex:
28
srp_info = sig_and_kex.split('_')
29
if len(srp_info) == 2: # 'SRP_' + hash
30
kex_algo = sig_and_kex
33
kex_algo = '_'.join(srp_info[0:-1])
34
sig_algo = srp_info[-1]
36
(kex_algo, sig_algo) = sig_and_kex.split('_')
38
cipher_and_mac = cipher_and_mac.split('_')
40
mac_algo = cipher_and_mac[-1]
42
cipher = cipher_and_mac[:-1]
44
if mac_algo == '8' and cipher[-1] == 'CCM':
47
elif cipher[-2] == 'CCM' and cipher[-1] == '8':
54
elif mac_algo == 'CCM_8':
59
'CHACHA20': ('ChaCha',32),
63
'CAMELLIA': ('Camellia',None),
66
'ARIA': ('ARIA',None),
69
tls_to_botan_names = {
92
'ECDHE_PSK': 'ECDHE_PSK',
94
'CECPQ1_PSK': 'CECPQ1_PSK',
105
mac_algo = tls_to_botan_names[mac_algo]
106
sig_algo = tls_to_botan_names[sig_algo]
107
kex_algo = tls_to_botan_names[kex_algo]
109
(cipher_algo, cipher_keylen) = cipher_info[cipher[0]]
111
if cipher_keylen is None:
112
cipher_keylen = int(cipher[1]) / 8
114
if cipher_algo in ['AES', 'Camellia', 'ARIA']:
115
cipher_algo += '-%d' % (cipher_keylen*8)
121
if cipher[0] == 'CHACHA20' and cipher[1] == 'POLY1305':
123
if code in ['CC13', 'CC14', 'CC15']:
124
iv_len = 0 # Google variant
127
return (name, code, sig_algo, kex_algo, "ChaCha20Poly1305", cipher_keylen, iv_len, record_iv_len, "AEAD", 0, mac_algo)
130
if mode not in ['CBC', 'GCM', 'CCM(8)', 'CCM', 'OCB']:
131
print "#warning Unknown mode '%s' for ciphersuite %s (0x%d)" % (' '.join(cipher), name, code)
133
ivlen = 8 if cipher_algo == '3DES' else 16
137
cipher_algo += '/OCB(12)'
139
cipher_algo += '/' + mode
142
return (name, code, sig_algo, kex_algo, cipher_algo, cipher_keylen, ivlen, 0, mac_algo, mac_keylen[mac_algo], "")
145
return (name, code, sig_algo, kex_algo, cipher_algo, cipher_keylen, 12, 0, "AEAD", 0, mac_algo)
149
iv_bytes_from_rec = 8
151
return (name, code, sig_algo, kex_algo, cipher_algo, cipher_keylen, iv_bytes_from_hs, iv_bytes_from_rec, "AEAD", 0, mac_algo)
153
def open_input(args):
154
iana_url = 'https://www.iana.org/assignments/tls-parameters/tls-parameters.txt'
158
return open('tls-parameters.txt')
163
return urllib2.urlopen(iana_url)
168
Handle command line options
170
def process_command_line(args):
172
parser = optparse.OptionParser()
174
parser.add_option('--with-ocb', action='store_true', default=True,
175
help='enable OCB AEAD suites')
176
parser.add_option('--without-ocb', action='store_false', dest='with_ocb',
177
help='disable OCB AEAD suites')
179
parser.add_option('--with-aria-cbc', action='store_true', default=False,
180
help='enable ARIA CBC suites')
181
parser.add_option('--without-aria-cbc', action='store_false', dest='with_aria_cbc',
182
help='disable ARIA CBC suites')
184
parser.add_option('--with-cecpq1', action='store_true', default=True,
185
help='enable CECPQ1 suites')
186
parser.add_option('--without-cecpq1', action='store_false', dest='with_cecpq1',
187
help='disable CECPQ1 suites')
189
parser.add_option('--with-srp-aead', action='store_true', default=False,
190
help='add SRP AEAD suites')
191
parser.add_option('--without-srp-aead', action='store_false', dest='with_srp_aead',
192
help='disable SRP AEAD suites')
194
parser.add_option('--save-download', action='store_true', default=False,
195
help='save downloaded tls-parameters.txt to cwd')
197
parser.add_option('--output', '-o',
198
help='file to write output to (default %default)',
199
default='src/lib/tls/tls_suite_info.cpp')
201
return parser.parse_args(args)
203
def main(args = None):
207
weak_crypto = ['EXPORT', 'RC2', 'IDEA', 'RC4', '_DES_', 'WITH_NULL']
208
static_dh = ['ECDH_ECDSA', 'ECDH_RSA', 'DH_DSS', 'DH_RSA'] # not supported
209
protocol_goop = ['SCSV', 'KRB5']
210
maybe_someday = ['RSA_PSK']
211
not_supported = weak_crypto + static_dh + protocol_goop + maybe_someday
213
(options, args) = process_command_line(args)
215
if not options.with_aria_cbc:
216
not_supported += ['ARIA_128_CBC', 'ARIA_256_CBC']
218
ciphersuite_re = re.compile(' +0x([0-9a-fA-F][0-9a-fA-F]),0x([0-9a-fA-F][0-9a-fA-F]) + TLS_([A-Za-z_0-9]+) ')
225
for line in open_input(args):
227
match = ciphersuite_re.match(line)
229
code = match.group(1) + match.group(2)
230
name = match.group(3)
233
for ns in not_supported:
238
suites[code] = to_ciphersuite_info(code, name)
240
sha1 = hashlib.sha1()
241
sha1.update(contents)
242
contents_hash = sha1.hexdigest()
244
if options.save_download:
245
out = open('tls-parameters.txt', 'w')
249
def define_custom_ciphersuite(name, code):
250
suites[code] = to_ciphersuite_info(code, name)
252
# Google servers - draft-agl-tls-chacha20poly1305-04
253
define_custom_ciphersuite('ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256', 'CC13')
254
define_custom_ciphersuite('ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256', 'CC14')
255
define_custom_ciphersuite('DHE_RSA_WITH_CHACHA20_POLY1305_SHA256', 'CC15')
257
if options.with_cecpq1:
258
# CECPQ1 key exchange
259
define_custom_ciphersuite('CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256', '16B7')
260
define_custom_ciphersuite('CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256', '16B8')
261
define_custom_ciphersuite('CECPQ1_RSA_WITH_AES_256_GCM_SHA384', '16B9')
262
define_custom_ciphersuite('CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384', '16BA')
265
# OCB ciphersuites draft-zauner-tls-aes-ocb-04
266
define_custom_ciphersuite('DHE_RSA_WITH_AES_128_OCB_SHA256', 'FFC0')
267
define_custom_ciphersuite('DHE_RSA_WITH_AES_256_OCB_SHA256', 'FFC1')
268
define_custom_ciphersuite('ECDHE_RSA_WITH_AES_128_OCB_SHA256', 'FFC2')
269
define_custom_ciphersuite('ECDHE_RSA_WITH_AES_256_OCB_SHA256', 'FFC3')
270
define_custom_ciphersuite('ECDHE_ECDSA_WITH_AES_128_OCB_SHA256', 'FFC4')
271
define_custom_ciphersuite('ECDHE_ECDSA_WITH_AES_256_OCB_SHA256', 'FFC5')
273
define_custom_ciphersuite('PSK_WITH_AES_128_OCB_SHA256', 'FFC6')
274
define_custom_ciphersuite('PSK_WITH_AES_256_OCB_SHA256', 'FFC7')
275
define_custom_ciphersuite('DHE_PSK_WITH_AES_128_OCB_SHA256', 'FFC8')
276
define_custom_ciphersuite('DHE_PSK_WITH_AES_256_OCB_SHA256', 'FFC9')
277
define_custom_ciphersuite('ECDHE_PSK_WITH_AES_128_OCB_SHA256', 'FFCA')
278
define_custom_ciphersuite('ECDHE_PSK_WITH_AES_256_OCB_SHA256', 'FFCB')
280
if options.with_cecpq1 and options.with_ocb:
281
# CECPQ1 OCB ciphersuites - Botan extension
282
define_custom_ciphersuite('CECPQ1_RSA_WITH_AES_256_OCB_SHA256', 'FFCC')
283
define_custom_ciphersuite('CECPQ1_ECDSA_WITH_AES_256_OCB_SHA256', 'FFCD')
284
#define_custom_ciphersuite('CECPQ1_PSK_WITH_AES_256_OCB_SHA256', 'FFCE')
286
if options.with_srp_aead:
287
# SRP using GCM or OCB - Botan extension
288
define_custom_ciphersuite('SRP_SHA_WITH_AES_256_GCM_SHA384', 'FFA0')
289
define_custom_ciphersuite('SRP_SHA_RSA_WITH_AES_256_GCM_SHA384', 'FFA1')
290
define_custom_ciphersuite('SRP_SHA_DSS_WITH_AES_256_GCM_SHA384', 'FFA2')
291
define_custom_ciphersuite('SRP_SHA_ECDSA_WITH_AES_256_GCM_SHA384', 'FFA3')
294
define_custom_ciphersuite('SRP_SHA_WITH_AES_256_OCB_SHA256', 'FFA4')
295
define_custom_ciphersuite('SRP_SHA_RSA_WITH_AES_256_OCB_SHA256', 'FFA5')
296
define_custom_ciphersuite('SRP_SHA_DSS_WITH_AES_256_OCB_SHA256', 'FFA6')
297
define_custom_ciphersuite('SRP_SHA_ECDSA_WITH_AES_256_OCB_SHA256', 'FFA7')
303
* TLS cipher suite information
305
* This file was automatically generated from the IANA assignments
306
* (tls-parameters.txt hash %s)
309
* Botan is released under the Simplified BSD License (see license.txt)
312
""" % (contents_hash, sys.argv[0], datetime.date.today().strftime("%Y-%m-%d"))
314
suite_info += header()
316
suite_info += """#include <botan/tls_ciphersuite.h>
323
const std::vector<Ciphersuite>& Ciphersuite::all_known_ciphersuites()
325
// Note that this list of ciphersuites is ordered by id!
326
static const std::vector<Ciphersuite> g_ciphersuite_list = {
329
for code in sorted(suites.keys()):
331
assert len(info) == 11
332
suite_expr = 'Ciphersuite(0x%s, "%s", "%s", "%s", "%s", %d, %d, %d, "%s", %d, "%s")' % (
333
code, info[0], info[2], info[3], info[4], info[5], info[6], info[7], info[8], info[9], info[10])
335
suite_info += " " + suite_expr + ",\n"
340
return g_ciphersuite_list;
348
if options.output == '-':
351
out = open(options.output, 'w')
352
out.write(suite_info)
355
if __name__ == '__main__':