From 3db28eaea2802c20909a2622c312eaab7fd5b0fb Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 24 Jan 2017 15:02:36 -0500 Subject: [PATCH 1/5] Update ciphers.inc script to understand openssl-1.1 --- scripts/codegen/get_mozilla_ciphers.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) mode change 100644 => 100755 scripts/codegen/get_mozilla_ciphers.py diff --git a/scripts/codegen/get_mozilla_ciphers.py b/scripts/codegen/get_mozilla_ciphers.py old mode 100644 new mode 100755 index e673ec7dc..b07746c2e --- a/scripts/codegen/get_mozilla_ciphers.py +++ b/scripts/codegen/get_mozilla_ciphers.py @@ -127,9 +127,9 @@ for k, v in enabled_ciphers.items(): #oSSLinclude = ('/usr/include/openssl/ssl3.h', '/usr/include/openssl/ssl.h', # '/usr/include/openssl/ssl2.h', '/usr/include/openssl/ssl23.h', # '/usr/include/openssl/tls1.h') -oSSLinclude = ('ssl/ssl3.h', 'ssl/ssl.h', - 'ssl/ssl2.h', 'ssl/ssl23.h', - 'ssl/tls1.h') +oSSLinclude = ['ssl3.h', 'ssl.h' + 'ssl2.h', 'ssl23.h', + 'tls1.h'] ##### # This reads the hex code for the ciphers that are used by firefox. @@ -155,9 +155,12 @@ for x in used_ciphers: openssl_macro_by_hex = {} all_openssl_macros = {} for fl in oSSLinclude: - fp = open(ossl(fl), 'r') + fname = ossl("include/openssl/"+fl) + if not os.path.exists(fname): + continue + fp = open(fname, 'r') for line in fp.readlines(): - m = re.match('#define\s+(\S+)\s+(\S+)', line) + m = re.match('# *define\s+(\S+)\s+(\S+)', line) if m: value,key = m.groups() if key.startswith('0x') and "_CK_" in value: From 4f1dc34e3664607f61bfee1514826cca786ef488 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 24 Jan 2017 15:05:35 -0500 Subject: [PATCH 2/5] Regenerate ciphers.inc --- changes/ciphers.inc | 5 +++ src/common/ciphers.inc | 80 +++++++++++------------------------------- 2 files changed, 25 insertions(+), 60 deletions(-) create mode 100644 changes/ciphers.inc diff --git a/changes/ciphers.inc b/changes/ciphers.inc new file mode 100644 index 000000000..71208b196 --- /dev/null +++ b/changes/ciphers.inc @@ -0,0 +1,5 @@ + o Minor features (ciphersuite selection): + - Clients now advertise a list of ciphersuites closer to the ones + preferred by Firefox. Closes ticket #15426. + + diff --git a/src/common/ciphers.inc b/src/common/ciphers.inc index ab4ac4072..a336e2dfa 100644 --- a/src/common/ciphers.inc +++ b/src/common/ciphers.inc @@ -14,6 +14,26 @@ #else XCIPHER(0xc02f, TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256) #endif +#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 + CIPHER(0xcca9, TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305) +#else + XCIPHER(0xcca9, TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305) +#endif +#ifdef TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 + CIPHER(0xcca8, TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305) +#else + XCIPHER(0xcca8, TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305) +#endif +#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + CIPHER(0xc02c, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) +#else + XCIPHER(0xc02c, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) +#endif +#ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + CIPHER(0xc030, TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384) +#else + XCIPHER(0xc030, TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384) +#endif #ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CIPHER(0xc00a, TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) #else @@ -34,88 +54,28 @@ #else XCIPHER(0xc014, TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA) #endif -#ifdef TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA - CIPHER(0xc012, TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA) -#else - XCIPHER(0xc012, TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA) -#endif -#ifdef TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA - CIPHER(0xc007, TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA) -#else - XCIPHER(0xc007, TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA) -#endif -#ifdef TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA - CIPHER(0xc011, TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA) -#else - XCIPHER(0xc011, TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA) -#endif #ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_SHA CIPHER(0x0033, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA) #else XCIPHER(0x0033, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA) #endif -#ifdef TLS1_TXT_DHE_DSS_WITH_AES_128_SHA - CIPHER(0x0032, TLS1_TXT_DHE_DSS_WITH_AES_128_SHA) -#else - XCIPHER(0x0032, TLS1_TXT_DHE_DSS_WITH_AES_128_SHA) -#endif -#ifdef TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - CIPHER(0x0045, TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA) -#else - XCIPHER(0x0045, TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA) -#endif #ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_SHA CIPHER(0x0039, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) #else XCIPHER(0x0039, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) #endif -#ifdef TLS1_TXT_DHE_DSS_WITH_AES_256_SHA - CIPHER(0x0038, TLS1_TXT_DHE_DSS_WITH_AES_256_SHA) -#else - XCIPHER(0x0038, TLS1_TXT_DHE_DSS_WITH_AES_256_SHA) -#endif -#ifdef TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - CIPHER(0x0088, TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA) -#else - XCIPHER(0x0088, TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA) -#endif -#ifdef SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA - CIPHER(0x0016, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) -#else - XCIPHER(0x0016, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) -#endif #ifdef TLS1_TXT_RSA_WITH_AES_128_SHA CIPHER(0x002f, TLS1_TXT_RSA_WITH_AES_128_SHA) #else XCIPHER(0x002f, TLS1_TXT_RSA_WITH_AES_128_SHA) #endif -#ifdef TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA - CIPHER(0x0041, TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA) -#else - XCIPHER(0x0041, TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA) -#endif #ifdef TLS1_TXT_RSA_WITH_AES_256_SHA CIPHER(0x0035, TLS1_TXT_RSA_WITH_AES_256_SHA) #else XCIPHER(0x0035, TLS1_TXT_RSA_WITH_AES_256_SHA) #endif -#ifdef TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA - CIPHER(0x0084, TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA) -#else - XCIPHER(0x0084, TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA) -#endif #ifdef SSL3_TXT_RSA_DES_192_CBC3_SHA CIPHER(0x000a, SSL3_TXT_RSA_DES_192_CBC3_SHA) #else XCIPHER(0x000a, SSL3_TXT_RSA_DES_192_CBC3_SHA) #endif -#ifdef SSL3_TXT_RSA_RC4_128_SHA - CIPHER(0x0005, SSL3_TXT_RSA_RC4_128_SHA) -#else - XCIPHER(0x0005, SSL3_TXT_RSA_RC4_128_SHA) -#endif -#ifdef SSL3_TXT_RSA_RC4_128_MD5 - CIPHER(0x0004, SSL3_TXT_RSA_RC4_128_MD5) -#else - XCIPHER(0x0004, SSL3_TXT_RSA_RC4_128_MD5) -#endif From 8a9eca12677f906dcd7e2161c3c5b4e338b9d204 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 24 Jan 2017 15:29:26 -0500 Subject: [PATCH 3/5] Teach gen_server_ciphers about CCM and Chacha. Also, teach it to not use 3DES any more. --- scripts/codegen/gen_server_ciphers.py | 50 +++++++++++++++++---------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/scripts/codegen/gen_server_ciphers.py b/scripts/codegen/gen_server_ciphers.py index 0dca8a673..7b61d865a 100755 --- a/scripts/codegen/gen_server_ciphers.py +++ b/scripts/codegen/gen_server_ciphers.py @@ -13,7 +13,8 @@ import sys EPHEMERAL_INDICATORS = [ "_EDH_", "_DHE_", "_ECDHE_" ] BAD_STUFF = [ "_DES_40_", "MD5", "_RC4_", "_DES_64_", - "_SEED_", "_CAMELLIA_", "_NULL" ] + "_SEED_", "_CAMELLIA_", "_NULL", + "_CCM_8", "_DES_", ] # these never get #ifdeffed. MANDATORY = [ @@ -48,15 +49,23 @@ def usable_cipher(ciph): # All fields we sort on, in order of priority. FIELDS = [ 'cipher', 'fwsec', 'mode', 'digest', 'bitlength' ] # Map from sorted fields to recognized value in descending order of goodness -FIELD_VALS = { 'cipher' : [ 'AES', 'DES'], +FIELD_VALS = { 'cipher' : [ 'AES', 'CHACHA20' ], 'fwsec' : [ 'ECDHE', 'DHE' ], - 'mode' : [ 'GCM', 'CBC' ], - 'digest' : [ 'SHA384', 'SHA256', 'SHA' ], + 'mode' : [ 'POLY1305', 'GCM', 'CCM', 'CBC', ], + 'digest' : [ 'n/a', 'SHA384', 'SHA256', 'SHA', ], 'bitlength' : [ '256', '128', '192' ], } class Ciphersuite(object): def __init__(self, name, fwsec, cipher, bitlength, mode, digest): + if fwsec == 'EDH': + fwsec = 'DHE' + + if mode in [ '_CBC3', '_CBC', '' ]: + mode = 'CBC' + elif mode == '_GCM': + mode = 'GCM' + self.name = name self.fwsec = fwsec self.cipher = cipher @@ -74,27 +83,32 @@ class Ciphersuite(object): def parse_cipher(ciph): m = re.match('(?:TLS1|SSL3)_TXT_(EDH|DHE|ECDHE)_RSA(?:_WITH)?_(AES|DES)_(256|128|192)(|_CBC|_CBC3|_GCM)_(SHA|SHA256|SHA384)$', ciph) - if not m: - print "/* Couldn't parse %s ! */"%ciph - return None + if m: + fwsec, cipher, bits, mode, digest = m.groups() + return Ciphersuite(ciph, fwsec, cipher, bits, mode, digest) - fwsec, cipher, bits, mode, digest = m.groups() - if fwsec == 'EDH': - fwsec = 'DHE' + m = re.match('(?:TLS1|SSL3)_TXT_(EDH|DHE|ECDHE)_RSA(?:_WITH)?_(AES|DES)_(256|128|192)_CCM', ciph) + if m: + fwsec, cipher, bits = m.groups() + return Ciphersuite(ciph, fwsec, cipher, bits, "CCM", "n/a") - if mode in [ '_CBC3', '_CBC', '' ]: - mode = 'CBC' - elif mode == '_GCM': - mode = 'GCM' + m = re.match('(?:TLS1|SSL3)_TXT_(EDH|DHE|ECDHE)_RSA(?:_WITH)?_CHACHA20_POLY1305', ciph) + if m: + fwsec, = m.groups() + return Ciphersuite(ciph, fwsec, "CHACHA20", "256", "POLY1305", "n/a") + + print "/* Couldn't parse %s ! */"%ciph + return None - return Ciphersuite(ciph, fwsec, cipher, bits, mode, digest) ALL_CIPHERS = [] for fname in sys.argv[1:]: - ALL_CIPHERS += (parse_cipher(c) - for c in find_ciphers(fname) - if usable_cipher(c) ) + for c in find_ciphers(fname): + if usable_cipher(c): + parsed = parse_cipher(c) + if parsed != None: + ALL_CIPHERS.append(parsed) ALL_CIPHERS.sort(key=Ciphersuite.sort_key) From 363be43df36faa631fe0a49239e27489db466dc2 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 24 Jan 2017 15:30:35 -0500 Subject: [PATCH 4/5] Re-run gen_server_ciphers --- changes/server_cipher | 3 +++ src/common/tortls.c | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 changes/server_cipher diff --git a/changes/server_cipher b/changes/server_cipher new file mode 100644 index 000000000..b80c88a9c --- /dev/null +++ b/changes/server_cipher @@ -0,0 +1,3 @@ + o Minor features (ciphersuite choices): + - Allow servers to accept a wider range of ciphersuites, including + chacha20-poly1305 and AES-CCM. Closes the other part of 15426. diff --git a/src/common/tortls.c b/src/common/tortls.c index 2efb3baa7..1fe91edf0 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -585,6 +585,12 @@ static const char UNRESTRICTED_SERVER_CIPHER_LIST[] = #ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256 TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256 ":" #endif +#ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_CCM + TLS1_TXT_DHE_RSA_WITH_AES_256_CCM ":" +#endif +#ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_CCM + TLS1_TXT_DHE_RSA_WITH_AES_128_CCM ":" +#endif #ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256 TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256 ":" #endif @@ -594,8 +600,14 @@ static const char UNRESTRICTED_SERVER_CIPHER_LIST[] = /* Required */ TLS1_TXT_DHE_RSA_WITH_AES_256_SHA ":" /* Required */ - TLS1_TXT_DHE_RSA_WITH_AES_128_SHA - ; + TLS1_TXT_DHE_RSA_WITH_AES_128_SHA ":" +#ifdef TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 + TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 ":" +#endif +#ifdef TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305 + TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305 +#endif + ; /* Note: to set up your own private testing network with link crypto * disabled, set your Tors' cipher list to From 26a9787aa50b50f724f3f58294f3780b83149acf Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 27 Jan 2017 16:15:26 -0500 Subject: [PATCH 5/5] MOre gen_server_ciphers improvements: - Remove DES from mandatory list. - always put the closing ; on its own line. --- scripts/codegen/gen_server_ciphers.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/codegen/gen_server_ciphers.py b/scripts/codegen/gen_server_ciphers.py index 7b61d865a..7470f8a02 100755 --- a/scripts/codegen/gen_server_ciphers.py +++ b/scripts/codegen/gen_server_ciphers.py @@ -20,7 +20,6 @@ BAD_STUFF = [ "_DES_40_", "MD5", "_RC4_", "_DES_64_", MANDATORY = [ "TLS1_TXT_DHE_RSA_WITH_AES_256_SHA", "TLS1_TXT_DHE_RSA_WITH_AES_128_SHA", - "SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA", ] def find_ciphers(filename): @@ -112,18 +111,21 @@ for fname in sys.argv[1:]: ALL_CIPHERS.sort(key=Ciphersuite.sort_key) +indent = " "*7 + for c in ALL_CIPHERS: if c is ALL_CIPHERS[-1]: - colon = ';' + colon = '' else: colon = ' ":"' if c.name in MANDATORY: - print " /* Required */" - print ' %s%s'%(c.name,colon) + print "%s/* Required */"%indent + print '%s%s%s'%(indent,c.name,colon) else: print "#ifdef %s"%c.name - print ' %s%s'%(c.name,colon) + print '%s%s%s'%(indent,c.name,colon) print "#endif" +print '%s;'%indent