tlsenum package probes a remote endpoint with one ClientHello per (version, cipher) pair via utls, so the checker can report the exact set the server accepts rather than only the suite Go's stdlib happens to negotiate. Probe accepts an Upgrader callback so STARTTLS dialects plug in without tlsenum learning about them; the checker bridges its existing dialect registry through upgraderFor.
103 lines
4.5 KiB
Go
103 lines
4.5 KiB
Go
package tlsenum
|
|
|
|
// CipherSuite pairs an IANA TLS cipher suite ID with its standard name.
|
|
//
|
|
// The catalog below intentionally covers the "real-world" set: modern AEAD
|
|
// suites used by TLS 1.2/1.3, plus a long tail of legacy CBC/RC4/3DES/EXPORT
|
|
// suites we want to *detect* on remote servers (so we can flag them), even
|
|
// though Go's stdlib refuses to negotiate them. utls lets us put any 16-bit
|
|
// value in the offered list, so the server's accept/reject decision is the
|
|
// source of truth.
|
|
type CipherSuite struct {
|
|
ID uint16
|
|
Name string
|
|
// TLS13 is true for the five TLS 1.3 AEAD suites; those must only be
|
|
// offered with TLS 1.3 ClientHellos.
|
|
TLS13 bool
|
|
}
|
|
|
|
// TLS13Ciphers are the AEAD suites defined for TLS 1.3 (RFC 8446 §B.4).
|
|
var TLS13Ciphers = []CipherSuite{
|
|
{0x1301, "TLS_AES_128_GCM_SHA256", true},
|
|
{0x1302, "TLS_AES_256_GCM_SHA384", true},
|
|
{0x1303, "TLS_CHACHA20_POLY1305_SHA256", true},
|
|
{0x1304, "TLS_AES_128_CCM_SHA256", true},
|
|
{0x1305, "TLS_AES_128_CCM_8_SHA256", true},
|
|
}
|
|
|
|
// LegacyCiphers covers TLS 1.0/1.1/1.2 (and SSLv3) suites. Not exhaustive of
|
|
// the IANA registry, but it includes everything any modern audit cares about:
|
|
// ECDHE/DHE/RSA/PSK kex, AES-GCM/CCM/CBC, ChaCha20, 3DES, RC4, NULL, EXPORT,
|
|
// anonymous, and a handful of GOST/CAMELLIA/ARIA entries seen in the wild.
|
|
var LegacyCiphers = []CipherSuite{
|
|
// ECDHE-ECDSA
|
|
{0xC02B, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", false},
|
|
{0xC02C, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", false},
|
|
{0xCCA9, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", false},
|
|
{0xC023, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", false},
|
|
{0xC024, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", false},
|
|
{0xC009, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", false},
|
|
{0xC00A, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", false},
|
|
{0xC008, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", false},
|
|
{0xC007, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", false},
|
|
{0xC006, "TLS_ECDHE_ECDSA_WITH_NULL_SHA", false},
|
|
|
|
// ECDHE-RSA
|
|
{0xC02F, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", false},
|
|
{0xC030, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", false},
|
|
{0xCCA8, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", false},
|
|
{0xC027, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", false},
|
|
{0xC028, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", false},
|
|
{0xC013, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", false},
|
|
{0xC014, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", false},
|
|
{0xC012, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", false},
|
|
{0xC011, "TLS_ECDHE_RSA_WITH_RC4_128_SHA", false},
|
|
{0xC010, "TLS_ECDHE_RSA_WITH_NULL_SHA", false},
|
|
|
|
// DHE-RSA
|
|
{0x009E, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", false},
|
|
{0x009F, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", false},
|
|
{0xCCAA, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", false},
|
|
{0x0067, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", false},
|
|
{0x006B, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", false},
|
|
{0x0033, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", false},
|
|
{0x0039, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", false},
|
|
{0x0016, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", false},
|
|
|
|
// Plain RSA
|
|
{0x009C, "TLS_RSA_WITH_AES_128_GCM_SHA256", false},
|
|
{0x009D, "TLS_RSA_WITH_AES_256_GCM_SHA384", false},
|
|
{0x003C, "TLS_RSA_WITH_AES_128_CBC_SHA256", false},
|
|
{0x003D, "TLS_RSA_WITH_AES_256_CBC_SHA256", false},
|
|
{0x002F, "TLS_RSA_WITH_AES_128_CBC_SHA", false},
|
|
{0x0035, "TLS_RSA_WITH_AES_256_CBC_SHA", false},
|
|
{0x000A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", false},
|
|
{0x0005, "TLS_RSA_WITH_RC4_128_SHA", false},
|
|
{0x0004, "TLS_RSA_WITH_RC4_128_MD5", false},
|
|
{0x003B, "TLS_RSA_WITH_NULL_SHA256", false},
|
|
{0x0002, "TLS_RSA_WITH_NULL_SHA", false},
|
|
{0x0001, "TLS_RSA_WITH_NULL_MD5", false},
|
|
|
|
// Anonymous (broken by design — flag if seen)
|
|
{0x006D, "TLS_DH_anon_WITH_AES_256_CBC_SHA256", false},
|
|
{0x0034, "TLS_DH_anon_WITH_AES_128_CBC_SHA", false},
|
|
{0x003A, "TLS_DH_anon_WITH_AES_256_CBC_SHA", false},
|
|
{0xC018, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA", false},
|
|
{0xC019, "TLS_ECDH_anon_WITH_AES_256_CBC_SHA", false},
|
|
|
|
// EXPORT (40-bit, illegal since ~2000 — flag if seen)
|
|
{0x0008, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", false},
|
|
{0x0014, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", false},
|
|
{0x0017, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5", false},
|
|
{0x0019, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA", false},
|
|
{0x0003, "TLS_RSA_EXPORT_WITH_RC4_40_MD5", false},
|
|
{0x0006, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", false},
|
|
}
|
|
|
|
// AllCiphers concatenates legacy and TLS 1.3 cipher suites.
|
|
func AllCiphers() []CipherSuite {
|
|
out := make([]CipherSuite, 0, len(LegacyCiphers)+len(TLS13Ciphers))
|
|
out = append(out, LegacyCiphers...)
|
|
out = append(out, TLS13Ciphers...)
|
|
return out
|
|
}
|