| // This program reads in the contents of [1] from /tmp/tls-parameters.xml and |
| // writes out a compact form the ciphersuite information found there in. |
| // It's used to generate the tables in net/base/ssl_cipher_suite_names.cc |
| // |
| // [1] http://www.iana.org/assignments/tls-parameters/tls-parameters.xml |
| package main |
| |
| import ( |
| "fmt" |
| "os" |
| "sort" |
| "strings" |
| "xml" |
| ) |
| |
| // Structures for parsing the XML |
| |
| type TLSRegistry struct { |
| Registry []Registry |
| } |
| |
| type Registry struct { |
| Id string "attr" |
| Title string |
| Record []Record |
| } |
| |
| type Record struct { |
| Value string |
| Description string |
| } |
| |
| type CipherSuite struct { |
| value uint16 |
| kx string |
| cipher string |
| mac string |
| } |
| |
| func fromHex(c byte) int { |
| if c >= '0' && c <= '9' { |
| return int(c - '0') |
| } |
| if c >= 'a' && c <= 'f' { |
| return int(c - 'a' + 10) |
| } |
| if c >= 'A' && c <= 'F' { |
| return int(c - 'A' + 10) |
| } |
| panic("Bad char passed to fromHex") |
| } |
| |
| type TLSValue struct { |
| v int |
| name string |
| } |
| |
| type TLSMapping []TLSValue |
| |
| func (m TLSMapping) Len() int { |
| return len(m) |
| } |
| |
| func (m TLSMapping) Less(i, j int) bool { |
| return m[i].v < m[j].v |
| } |
| |
| func (m TLSMapping) Swap(i, j int) { |
| m[i], m[j] = m[j], m[i] |
| } |
| |
| func printDict(d map[string]int, name string) { |
| a := make([]TLSValue, len(d)) |
| |
| maxLen := 0 |
| i := 0 |
| for k, v := range d { |
| if len(k) > maxLen { |
| maxLen = len(k) |
| } |
| a[i].v = v |
| a[i].name = k |
| i++ |
| } |
| |
| sort.Sort(TLSMapping(a)) |
| |
| fmt.Printf("static const struct {\n char name[%d];\n} %s[%d] = {\n", maxLen+1, name, len(d)) |
| for _, m := range a { |
| fmt.Printf(" {\"%s\"}, // %d\n", m.name, m.v) |
| } |
| |
| fmt.Printf("};\n\n") |
| } |
| |
| func parseCipherSuiteString(s string) (kx, cipher, mac string) { |
| s = s[4:] |
| i := strings.Index(s, "_WITH_") |
| kx = s[0:i] |
| s = s[i+6:] |
| i = strings.LastIndex(s, "_") |
| cipher = s[0:i] |
| mac = s[i+1:] |
| return |
| } |
| |
| func main() { |
| infile, err := os.Open("/tmp/tls-parameters.xml", os.O_RDONLY, 0) |
| if err != nil { |
| fmt.Printf("Cannot open input: %s\n", err) |
| return |
| } |
| |
| var input TLSRegistry |
| err = xml.Unmarshal(infile, &input) |
| if err != nil { |
| fmt.Printf("Error parsing XML: %s\n", err) |
| return |
| } |
| |
| var cipherSuitesRegistry *Registry |
| for _, r := range input.Registry { |
| if r.Id == "tls-parameters-4" { |
| cipherSuitesRegistry = &r |
| break |
| } |
| } |
| |
| if cipherSuitesRegistry == nil { |
| fmt.Printf("Didn't find tls-parameters-4 registry\n") |
| } |
| |
| kxs := make(map[string]int) |
| next_kx := 0 |
| ciphers := make(map[string]int) |
| next_cipher := 0 |
| macs := make(map[string]int) |
| next_mac := 0 |
| lastValue := uint16(0) |
| |
| fmt.Printf("struct CipherSuite {\n uint16 cipher_suite, encoded;\n};\n\n") |
| fmt.Printf("static const struct CipherSuite kCipherSuites[] = {\n") |
| |
| for _, r := range cipherSuitesRegistry.Record { |
| if strings.Index(r.Description, "_WITH_") == -1 { |
| continue |
| } |
| |
| value := uint16(fromHex(r.Value[2])<<12 | fromHex(r.Value[3])<<8 | fromHex(r.Value[7])<<4 | fromHex(r.Value[8])) |
| kx, cipher, mac := parseCipherSuiteString(r.Description) |
| |
| if value < lastValue { |
| panic("Input isn't sorted") |
| } |
| lastValue = value |
| |
| var kx_n, cipher_n, mac_n int |
| var ok bool |
| |
| if kx_n, ok = kxs[kx]; !ok { |
| kxs[kx] = next_kx |
| kx_n = next_kx |
| next_kx++ |
| } |
| if cipher_n, ok = ciphers[cipher]; !ok { |
| ciphers[cipher] = next_cipher |
| cipher_n = next_cipher |
| next_cipher++ |
| } |
| if mac_n, ok = macs[mac]; !ok { |
| macs[mac] = next_mac |
| mac_n = next_mac |
| next_mac++ |
| } |
| |
| if kx_n > 32 || cipher_n > 15 || mac_n > 7 { |
| panic("Need to shift bit boundaries") |
| } |
| |
| encoded := (kx_n << 7) | (cipher_n << 3) | mac_n |
| fmt.Printf(" {0x%x, 0x%x}, // %s\n", value, encoded, r.Description) |
| } |
| |
| fmt.Printf("};\n\n") |
| |
| printDict(kxs, "kKeyExchangeNames") |
| printDict(ciphers, "kCipherNames") |
| printDict(macs, "kMacNames") |
| } |