|
1 | 1 | package tlsprofiles |
2 | 2 |
|
3 | | -// DO NOT EDIT, GENERATED BY hack/tools/update-tls-profiles.sh |
4 | | -// DATA SOURCE: https://ssl-config.mozilla.org/guidelines/latest.json |
5 | | -// DATA VERSION: 6 |
| 3 | +// This file embeds the Mozilla SSL/TLS Configuration Guidelines JSON and parses |
| 4 | +// it at init() time to populate the modern and intermediate TLS profiles. |
| 5 | +// Run `make update-tls-profiles` to refresh mozilla_data.json from the upstream spec. |
6 | 6 |
|
7 | 7 | import ( |
8 | 8 | "crypto/tls" |
| 9 | + _ "embed" |
| 10 | + "encoding/json" |
| 11 | + "fmt" |
9 | 12 | ) |
10 | 13 |
|
11 | | -var modernTLSProfile = tlsProfile{ |
12 | | - ciphers: cipherSlice{ |
13 | | - cipherNums: []uint16{ |
14 | | - tls.TLS_AES_128_GCM_SHA256, |
15 | | - tls.TLS_AES_256_GCM_SHA384, |
16 | | - tls.TLS_CHACHA20_POLY1305_SHA256, |
17 | | - }, |
18 | | - }, |
19 | | - curves: curveSlice{ |
20 | | - curveNums: []tls.CurveID{ |
21 | | - X25519MLKEM768, |
22 | | - X25519, |
23 | | - prime256v1, |
24 | | - secp384r1, |
25 | | - }, |
26 | | - }, |
27 | | - minTLSVersion: tls.VersionTLS13, |
| 14 | +//go:embed mozilla_data.json |
| 15 | +var mozillaDataJSON []byte |
| 16 | + |
| 17 | +// skippedCiphers records cipher names from mozilla_data.json that are not |
| 18 | +// supported by Go's crypto/tls and were omitted from the profiles. |
| 19 | +var skippedCiphers []string |
| 20 | + |
| 21 | +var ( |
| 22 | + modernTLSProfile tlsProfile |
| 23 | + intermediateTLSProfile tlsProfile |
| 24 | +) |
| 25 | + |
| 26 | +type mozillaConfiguration struct { |
| 27 | + Ciphersuites []string `json:"ciphersuites"` |
| 28 | + Ciphers struct { |
| 29 | + IANA []string `json:"iana"` |
| 30 | + } `json:"ciphers"` |
| 31 | + TLSCurves []string `json:"tls_curves"` |
| 32 | + TLSVersions []string `json:"tls_versions"` |
28 | 33 | } |
29 | 34 |
|
30 | | -var intermediateTLSProfile = tlsProfile{ |
31 | | - ciphers: cipherSlice{ |
32 | | - cipherNums: []uint16{ |
33 | | - tls.TLS_AES_128_GCM_SHA256, |
34 | | - tls.TLS_AES_256_GCM_SHA384, |
35 | | - tls.TLS_CHACHA20_POLY1305_SHA256, |
36 | | - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, |
37 | | - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, |
38 | | - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, |
39 | | - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, |
40 | | - tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, |
41 | | - tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, |
42 | | - }, |
43 | | - }, |
44 | | - curves: curveSlice{ |
45 | | - curveNums: []tls.CurveID{ |
46 | | - X25519MLKEM768, |
47 | | - X25519, |
48 | | - prime256v1, |
49 | | - secp384r1, |
50 | | - }, |
51 | | - }, |
52 | | - minTLSVersion: tls.VersionTLS12, |
| 35 | +type mozillaSpec struct { |
| 36 | + Configurations map[string]mozillaConfiguration `json:"configurations"` |
| 37 | +} |
| 38 | + |
| 39 | +func init() { |
| 40 | + var spec mozillaSpec |
| 41 | + if err := json.Unmarshal(mozillaDataJSON, &spec); err != nil { |
| 42 | + panic(fmt.Sprintf("tlsprofiles: failed to parse embedded mozilla_data.json: %v", err)) |
| 43 | + } |
| 44 | + |
| 45 | + for _, name := range []string{"modern", "intermediate"} { |
| 46 | + cfg, ok := spec.Configurations[name] |
| 47 | + if !ok { |
| 48 | + panic(fmt.Sprintf("tlsprofiles: profile %q not found in embedded mozilla_data.json", name)) |
| 49 | + } |
| 50 | + |
| 51 | + p, skipped := parseProfile(name, cfg) |
| 52 | + skippedCiphers = append(skippedCiphers, skipped...) |
| 53 | + |
| 54 | + switch name { |
| 55 | + case "modern": |
| 56 | + modernTLSProfile = p |
| 57 | + case "intermediate": |
| 58 | + intermediateTLSProfile = p |
| 59 | + } |
| 60 | + } |
| 61 | +} |
| 62 | + |
| 63 | +func parseProfile(name string, cfg mozillaConfiguration) (tlsProfile, []string) { |
| 64 | + var skipped []string |
| 65 | + var cipherNums []uint16 |
| 66 | + for _, c := range append(cfg.Ciphersuites, cfg.Ciphers.IANA...) { |
| 67 | + id := cipherSuiteId(c) |
| 68 | + if id == 0 { |
| 69 | + skipped = append(skipped, c) |
| 70 | + continue |
| 71 | + } |
| 72 | + cipherNums = append(cipherNums, id) |
| 73 | + } |
| 74 | + |
| 75 | + var curveNums []tls.CurveID |
| 76 | + for _, c := range cfg.TLSCurves { |
| 77 | + id := curveId(c) |
| 78 | + if id == 0 { |
| 79 | + continue |
| 80 | + } |
| 81 | + curveNums = append(curveNums, id) |
| 82 | + } |
| 83 | + |
| 84 | + if len(cfg.TLSVersions) == 0 { |
| 85 | + panic(fmt.Sprintf("tlsprofiles: profile %q has no tls_versions in embedded mozilla_data.json", name)) |
| 86 | + } |
| 87 | + |
| 88 | + var version tlsVersion |
| 89 | + if err := version.Set(cfg.TLSVersions[0]); err != nil { |
| 90 | + panic(fmt.Sprintf("tlsprofiles: profile %q has unrecognized tls_versions[0] %q: %v", name, cfg.TLSVersions[0], err)) |
| 91 | + } |
| 92 | + |
| 93 | + return tlsProfile{ |
| 94 | + ciphers: cipherSlice{cipherNums: cipherNums}, |
| 95 | + curves: curveSlice{curveNums: curveNums}, |
| 96 | + minTLSVersion: version, |
| 97 | + }, skipped |
53 | 98 | } |
0 commit comments