• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// This program reads in the contents of [1] from /tmp/tls-parameters.xml and
2// writes out a compact form the ciphersuite information found there in.
3// It's used to generate the tables in net/base/ssl_cipher_suite_names.cc
4//
5// [1] http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
6package main
7
8import (
9	"fmt"
10	"os"
11	"sort"
12	"strings"
13	"xml"
14)
15
16// Structures for parsing the XML
17
18type TLSRegistry struct {
19	Registry []Registry
20}
21
22type Registry struct {
23	Id     string "attr"
24	Title  string
25	Record []Record
26}
27
28type Record struct {
29	Value       string
30	Description string
31}
32
33type CipherSuite struct {
34	value  uint16
35	kx     string
36	cipher string
37	mac    string
38}
39
40func fromHex(c byte) int {
41	if c >= '0' && c <= '9' {
42		return int(c - '0')
43	}
44	if c >= 'a' && c <= 'f' {
45		return int(c - 'a' + 10)
46	}
47	if c >= 'A' && c <= 'F' {
48		return int(c - 'A' + 10)
49	}
50	panic("Bad char passed to fromHex")
51}
52
53type TLSValue struct {
54	v    int
55	name string
56}
57
58type TLSMapping []TLSValue
59
60func (m TLSMapping) Len() int {
61	return len(m)
62}
63
64func (m TLSMapping) Less(i, j int) bool {
65	return m[i].v < m[j].v
66}
67
68func (m TLSMapping) Swap(i, j int) {
69	m[i], m[j] = m[j], m[i]
70}
71
72func printDict(d map[string]int, name string) {
73	a := make([]TLSValue, len(d))
74
75	maxLen := 0
76	i := 0
77	for k, v := range d {
78		if len(k) > maxLen {
79			maxLen = len(k)
80		}
81		a[i].v = v
82		a[i].name = k
83		i++
84	}
85
86	sort.Sort(TLSMapping(a))
87
88	fmt.Printf("static const struct {\n  char name[%d];\n} %s[%d] = {\n", maxLen+1, name, len(d))
89	for _, m := range a {
90		fmt.Printf("  {\"%s\"},  // %d\n", m.name, m.v)
91	}
92
93	fmt.Printf("};\n\n")
94}
95
96func parseCipherSuiteString(s string) (kx, cipher, mac string) {
97	s = s[4:]
98	i := strings.Index(s, "_WITH_")
99	kx = s[0:i]
100	s = s[i+6:]
101	i = strings.LastIndex(s, "_")
102	cipher = s[0:i]
103	mac = s[i+1:]
104	return
105}
106
107func main() {
108	infile, err := os.Open("/tmp/tls-parameters.xml", os.O_RDONLY, 0)
109	if err != nil {
110		fmt.Printf("Cannot open input: %s\n", err)
111		return
112	}
113
114	var input TLSRegistry
115	err = xml.Unmarshal(infile, &input)
116	if err != nil {
117		fmt.Printf("Error parsing XML: %s\n", err)
118		return
119	}
120
121	var cipherSuitesRegistry *Registry
122	for _, r := range input.Registry {
123		if r.Id == "tls-parameters-4" {
124			cipherSuitesRegistry = &r
125			break
126		}
127	}
128
129	if cipherSuitesRegistry == nil {
130		fmt.Printf("Didn't find tls-parameters-4 registry\n")
131	}
132
133	kxs := make(map[string]int)
134	next_kx := 0
135	ciphers := make(map[string]int)
136	next_cipher := 0
137	macs := make(map[string]int)
138	next_mac := 0
139	lastValue := uint16(0)
140
141	fmt.Printf("struct CipherSuite {\n  uint16 cipher_suite, encoded;\n};\n\n")
142	fmt.Printf("static const struct CipherSuite kCipherSuites[] = {\n")
143
144	for _, r := range cipherSuitesRegistry.Record {
145		if strings.Index(r.Description, "_WITH_") == -1 {
146			continue
147		}
148
149		value := uint16(fromHex(r.Value[2])<<12 | fromHex(r.Value[3])<<8 | fromHex(r.Value[7])<<4 | fromHex(r.Value[8]))
150		kx, cipher, mac := parseCipherSuiteString(r.Description)
151
152		if value < lastValue {
153			panic("Input isn't sorted")
154		}
155		lastValue = value
156
157		var kx_n, cipher_n, mac_n int
158		var ok bool
159
160		if kx_n, ok = kxs[kx]; !ok {
161			kxs[kx] = next_kx
162			kx_n = next_kx
163			next_kx++
164		}
165		if cipher_n, ok = ciphers[cipher]; !ok {
166			ciphers[cipher] = next_cipher
167			cipher_n = next_cipher
168			next_cipher++
169		}
170		if mac_n, ok = macs[mac]; !ok {
171			macs[mac] = next_mac
172			mac_n = next_mac
173			next_mac++
174		}
175
176		if kx_n > 32 || cipher_n > 15 || mac_n > 7 {
177			panic("Need to shift bit boundaries")
178		}
179
180		encoded := (kx_n << 7) | (cipher_n << 3) | mac_n
181		fmt.Printf("  {0x%x, 0x%x},  // %s\n", value, encoded, r.Description)
182	}
183
184	fmt.Printf("};\n\n")
185
186	printDict(kxs, "kKeyExchangeNames")
187	printDict(ciphers, "kCipherNames")
188	printDict(macs, "kMacNames")
189}
190