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 6 package main 7 8 import ( 9 "fmt" 10 "os" 11 "sort" 12 "strings" 13 "xml" 14 ) 15 16 // Structures for parsing the XML 17 18 type TLSRegistry struct { 19 Registry []Registry 20 } 21 22 type Registry struct { 23 Id string "attr" 24 Title string 25 Record []Record 26 } 27 28 type Record struct { 29 Value string 30 Description string 31 } 32 33 type CipherSuite struct { 34 value uint16 35 kx string 36 cipher string 37 mac string 38 } 39 40 func 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 53 type TLSValue struct { 54 v int 55 name string 56 } 57 58 type TLSMapping []TLSValue 59 60 func (m TLSMapping) Len() int { 61 return len(m) 62 } 63 64 func (m TLSMapping) Less(i, j int) bool { 65 return m[i].v < m[j].v 66 } 67 68 func (m TLSMapping) Swap(i, j int) { 69 m[i], m[j] = m[j], m[i] 70 } 71 72 func 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 96 func 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 107 func 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