Merge pull request #6902 from yanrayw/6651-enable-cipher-suite-names-consistent

compat.sh: report and filter cipher suite names consistently
This commit is contained in:
Gilles Peskine 2023-02-03 11:38:31 +01:00 committed by GitHub
commit e2db23d741
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 316 additions and 280 deletions

View file

@ -18,8 +18,7 @@
# limitations under the License.
"""
Translate ciphersuite names in Mbed TLS format to OpenSSL and GNUTLS
standards.
Translate standard ciphersuite names to GnuTLS, OpenSSL and Mbed TLS standards.
To test the translation functions run:
python3 -m unittest translate_cipher.py
@ -36,124 +35,158 @@ class TestTranslateCiphers(unittest.TestCase):
"""
def test_translate_all_cipher_names(self):
"""
Translate MbedTLS ciphersuite names to their OpenSSL and
GnuTLS counterpart. Use only a small subset of ciphers
that exercise each step of the translate functions
Translate standard ciphersuite names to GnuTLS, OpenSSL and
Mbed TLS counterpart. Use only a small subset of ciphers
that exercise each step of the translation functions
"""
ciphers = [
("TLS-ECDHE-ECDSA-WITH-NULL-SHA",
("TLS_ECDHE_ECDSA_WITH_NULL_SHA",
"+ECDHE-ECDSA:+NULL:+SHA1",
"ECDHE-ECDSA-NULL-SHA"),
("TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256",
"ECDHE-ECDSA-NULL-SHA",
"TLS-ECDHE-ECDSA-WITH-NULL-SHA"),
("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"+ECDHE-ECDSA:+AES-128-GCM:+AEAD",
"ECDHE-ECDSA-AES128-GCM-SHA256"),
("TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA",
"ECDHE-ECDSA-AES128-GCM-SHA256",
"TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256"),
("TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
"+DHE-RSA:+3DES-CBC:+SHA1",
"EDH-RSA-DES-CBC3-SHA"),
("TLS-RSA-WITH-AES-256-CBC-SHA",
"EDH-RSA-DES-CBC3-SHA",
"TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA"),
("TLS_RSA_WITH_AES_256_CBC_SHA",
"+RSA:+AES-256-CBC:+SHA1",
"AES256-SHA"),
("TLS-PSK-WITH-3DES-EDE-CBC-SHA",
"AES256-SHA",
"TLS-RSA-WITH-AES-256-CBC-SHA"),
("TLS_PSK_WITH_3DES_EDE_CBC_SHA",
"+PSK:+3DES-CBC:+SHA1",
"PSK-3DES-EDE-CBC-SHA"),
("TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256",
"PSK-3DES-EDE-CBC-SHA",
"TLS-PSK-WITH-3DES-EDE-CBC-SHA"),
("TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
None,
"ECDHE-ECDSA-CHACHA20-POLY1305"),
("TLS-ECDHE-ECDSA-WITH-AES-128-CCM",
"ECDHE-ECDSA-CHACHA20-POLY1305",
"TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256"),
("TLS_ECDHE_ECDSA_WITH_AES_128_CCM",
"+ECDHE-ECDSA:+AES-128-CCM:+AEAD",
None),
("TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384",
None,
"ECDHE-ARIA256-GCM-SHA384"),
"TLS-ECDHE-ECDSA-WITH-AES-128-CCM"),
("TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384",
None,
"ECDHE-ARIA256-GCM-SHA384",
"TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384"),
]
for m, g_exp, o_exp in ciphers:
for s, g_exp, o_exp, m_exp in ciphers:
if g_exp is not None:
g = translate_gnutls(m)
g = translate_gnutls(s)
self.assertEqual(g, g_exp)
if o_exp is not None:
o = translate_ossl(m)
o = translate_ossl(s)
self.assertEqual(o, o_exp)
def translate_gnutls(m_cipher):
if m_exp is not None:
m = translate_mbedtls(s)
self.assertEqual(m, m_exp)
def translate_gnutls(s_cipher):
"""
Translate m_cipher from Mbed TLS ciphersuite naming convention
Translate s_cipher from standard ciphersuite naming convention
and return the GnuTLS naming convention
"""
m_cipher = re.sub(r'\ATLS-', '+', m_cipher)
m_cipher = m_cipher.replace("-WITH-", ":+")
m_cipher = m_cipher.replace("-EDE", "")
# Replace "_" with "-" to handle ciphersuite names based on Mbed TLS
# naming convention
s_cipher = s_cipher.replace("_", "-")
s_cipher = re.sub(r'\ATLS-', '+', s_cipher)
s_cipher = s_cipher.replace("-WITH-", ":+")
s_cipher = s_cipher.replace("-EDE", "")
# SHA in Mbed TLS == SHA1 GnuTLS,
# if the last 3 chars are SHA append 1
if m_cipher[-3:] == "SHA":
m_cipher = m_cipher+"1"
if s_cipher[-3:] == "SHA":
s_cipher = s_cipher+"1"
# CCM or CCM-8 should be followed by ":+AEAD"
# Replace "GCM:+SHAxyz" with "GCM:+AEAD"
if "CCM" in m_cipher or "GCM" in m_cipher:
m_cipher = re.sub(r"GCM-SHA\d\d\d", "GCM", m_cipher)
m_cipher = m_cipher+":+AEAD"
if "CCM" in s_cipher or "GCM" in s_cipher:
s_cipher = re.sub(r"GCM-SHA\d\d\d", "GCM", s_cipher)
s_cipher = s_cipher+":+AEAD"
# Replace the last "-" with ":+"
else:
index = m_cipher.rindex("-")
m_cipher = m_cipher[:index] + ":+" + m_cipher[index+1:]
index = s_cipher.rindex("-")
s_cipher = s_cipher[:index] + ":+" + s_cipher[index+1:]
return m_cipher
return s_cipher
def translate_ossl(m_cipher):
def translate_ossl(s_cipher):
"""
Translate m_cipher from Mbed TLS ciphersuite naming convention
Translate s_cipher from standard ciphersuite naming convention
and return the OpenSSL naming convention
"""
m_cipher = re.sub(r'^TLS-', '', m_cipher)
m_cipher = m_cipher.replace("-WITH", "")
# Replace "_" with "-" to handle ciphersuite names based on Mbed TLS
# naming convention
s_cipher = s_cipher.replace("_", "-")
s_cipher = re.sub(r'^TLS-', '', s_cipher)
s_cipher = s_cipher.replace("-WITH", "")
# Remove the "-" from "ABC-xyz"
m_cipher = m_cipher.replace("AES-", "AES")
m_cipher = m_cipher.replace("CAMELLIA-", "CAMELLIA")
m_cipher = m_cipher.replace("ARIA-", "ARIA")
s_cipher = s_cipher.replace("AES-", "AES")
s_cipher = s_cipher.replace("CAMELLIA-", "CAMELLIA")
s_cipher = s_cipher.replace("ARIA-", "ARIA")
# Remove "RSA" if it is at the beginning
m_cipher = re.sub(r'^RSA-', r'', m_cipher)
s_cipher = re.sub(r'^RSA-', r'', s_cipher)
# For all circumstances outside of PSK
if "PSK" not in m_cipher:
m_cipher = m_cipher.replace("-EDE", "")
m_cipher = m_cipher.replace("3DES-CBC", "DES-CBC3")
if "PSK" not in s_cipher:
s_cipher = s_cipher.replace("-EDE", "")
s_cipher = s_cipher.replace("3DES-CBC", "DES-CBC3")
# Remove "CBC" if it is not prefixed by DES
m_cipher = re.sub(r'(?<!DES-)CBC-', r'', m_cipher)
s_cipher = re.sub(r'(?<!DES-)CBC-', r'', s_cipher)
# ECDHE-RSA-ARIA does not exist in OpenSSL
m_cipher = m_cipher.replace("ECDHE-RSA-ARIA", "ECDHE-ARIA")
s_cipher = s_cipher.replace("ECDHE-RSA-ARIA", "ECDHE-ARIA")
# POLY1305 should not be followed by anything
if "POLY1305" in m_cipher:
index = m_cipher.rindex("POLY1305")
m_cipher = m_cipher[:index+8]
if "POLY1305" in s_cipher:
index = s_cipher.rindex("POLY1305")
s_cipher = s_cipher[:index+8]
# If DES is being used, Replace DHE with EDH
if "DES" in m_cipher and "DHE" in m_cipher and "ECDHE" not in m_cipher:
m_cipher = m_cipher.replace("DHE", "EDH")
if "DES" in s_cipher and "DHE" in s_cipher and "ECDHE" not in s_cipher:
s_cipher = s_cipher.replace("DHE", "EDH")
return m_cipher
return s_cipher
def translate_mbedtls(s_cipher):
"""
Translate s_cipher from standard ciphersuite naming convention
and return Mbed TLS ciphersuite naming convention
"""
# Replace "_" with "-"
s_cipher = s_cipher.replace("_", "-")
return s_cipher
def format_ciphersuite_names(mode, names):
t = {"g": translate_gnutls, "o": translate_ossl}[mode]
return " ".join(t(c) for c in names)
t = {"g": translate_gnutls,
"o": translate_ossl,
"m": translate_mbedtls
}[mode]
return " ".join(c + '=' + t(c) for c in names)
def main(target, names):
print(format_ciphersuite_names(target, names))
if __name__ == "__main__":
PARSER = argparse.ArgumentParser()
PARSER.add_argument('target', metavar='TARGET', choices=['o', 'g'])
PARSER.add_argument('target', metavar='TARGET', choices=['o', 'g', 'm'])
PARSER.add_argument('names', metavar='NAMES', nargs='+')
ARGS = PARSER.parse_args()
main(ARGS.target, ARGS.names)