Home | History | Annotate | Download | only in base
      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