123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712 |
- // Copyright 2016 Google Inc. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- // Package tls implements functionality for dealing with TLS-encoded data,
- // as defined in RFC 5246. This includes parsing and generation of TLS-encoded
- // data, together with utility functions for dealing with the DigitallySigned
- // TLS type.
- package tls
- import (
- "bytes"
- "encoding/binary"
- "fmt"
- "reflect"
- "strconv"
- "strings"
- )
- // This file holds utility functions for TLS encoding/decoding data
- // as per RFC 5246 section 4.
- // A structuralError suggests that the TLS data is valid, but the Go type
- // which is receiving it doesn't match.
- type structuralError struct {
- field string
- msg string
- }
- func (e structuralError) Error() string {
- var prefix string
- if e.field != "" {
- prefix = e.field + ": "
- }
- return "tls: structure error: " + prefix + e.msg
- }
- // A syntaxError suggests that the TLS data is invalid.
- type syntaxError struct {
- field string
- msg string
- }
- func (e syntaxError) Error() string {
- var prefix string
- if e.field != "" {
- prefix = e.field + ": "
- }
- return "tls: syntax error: " + prefix + e.msg
- }
- // Uint24 is an unsigned 3-byte integer.
- type Uint24 uint32
- // Enum is an unsigned integer.
- type Enum uint64
- var (
- uint8Type = reflect.TypeOf(uint8(0))
- uint16Type = reflect.TypeOf(uint16(0))
- uint24Type = reflect.TypeOf(Uint24(0))
- uint32Type = reflect.TypeOf(uint32(0))
- uint64Type = reflect.TypeOf(uint64(0))
- enumType = reflect.TypeOf(Enum(0))
- )
- // Unmarshal parses the TLS-encoded data in b and uses the reflect package to
- // fill in an arbitrary value pointed at by val. Because Unmarshal uses the
- // reflect package, the structs being written to must use exported fields
- // (upper case names).
- //
- // The mappings between TLS types and Go types is as follows; some fields
- // must have tags (to indicate their encoded size).
- //
- // TLS Go Required Tags
- // opaque byte / uint8
- // uint8 byte / uint8
- // uint16 uint16
- // uint24 tls.Uint24
- // uint32 uint32
- // uint64 uint64
- // enum tls.Enum size:S or maxval:N
- // Type<N,M> []Type minlen:N,maxlen:M
- // opaque[N] [N]byte / [N]uint8
- // uint8[N] [N]byte / [N]uint8
- // struct { } struct { }
- // select(T) {
- // case e1: Type *T selector:Field,val:e1
- // }
- //
- // TLS variants (RFC 5246 s4.6.1) are only supported when the value of the
- // associated enumeration type is available earlier in the same enclosing
- // struct, and each possible variant is marked with a selector tag (to
- // indicate which field selects the variants) and a val tag (to indicate
- // what value of the selector picks this particular field).
- //
- // For example, a TLS structure:
- //
- // enum { e1(1), e2(2) } EnumType;
- // struct {
- // EnumType sel;
- // select(sel) {
- // case e1: uint16
- // case e2: uint32
- // } data;
- // } VariantItem;
- //
- // would have a corresponding Go type:
- //
- // type VariantItem struct {
- // Sel tls.Enum `tls:"maxval:2"`
- // Data16 *uint16 `tls:"selector:Sel,val:1"`
- // Data32 *uint32 `tls:"selector:Sel,val:2"`
- // }
- //
- // TLS fixed-length vectors of types other than opaque or uint8 are not supported.
- //
- // For TLS variable-length vectors that are themselves used in other vectors,
- // create a single-field structure to represent the inner type. For example, for:
- //
- // opaque InnerType<1..65535>;
- // struct {
- // InnerType inners<1,65535>;
- // } Something;
- //
- // convert to:
- //
- // type InnerType struct {
- // Val []byte `tls:"minlen:1,maxlen:65535"`
- // }
- // type Something struct {
- // Inners []InnerType `tls:"minlen:1,maxlen:65535"`
- // }
- //
- // If the encoded value does not fit in the Go type, Unmarshal returns a parse error.
- func Unmarshal(b []byte, val interface{}) ([]byte, error) {
- return UnmarshalWithParams(b, val, "")
- }
- // UnmarshalWithParams allows field parameters to be specified for the
- // top-level element. The form of the params is the same as the field tags.
- func UnmarshalWithParams(b []byte, val interface{}, params string) ([]byte, error) {
- info, err := fieldTagToFieldInfo(params, "")
- if err != nil {
- return nil, err
- }
- // The passed in interface{} is a pointer (to allow the value to be written
- // to); extract the pointed-to object as a reflect.Value, so parseField
- // can do various introspection things.
- v := reflect.ValueOf(val).Elem()
- offset, err := parseField(v, b, 0, info)
- if err != nil {
- return nil, err
- }
- return b[offset:], nil
- }
- // Return the number of bytes needed to encode values up to (and including) x.
- func byteCount(x uint64) uint {
- switch {
- case x < 0x100:
- return 1
- case x < 0x10000:
- return 2
- case x < 0x1000000:
- return 3
- case x < 0x100000000:
- return 4
- case x < 0x10000000000:
- return 5
- case x < 0x1000000000000:
- return 6
- case x < 0x100000000000000:
- return 7
- default:
- return 8
- }
- }
- type fieldInfo struct {
- count uint // Number of bytes
- countSet bool
- minlen uint64 // Only relevant for slices
- maxlen uint64 // Only relevant for slices
- selector string // Only relevant for select sub-values
- val uint64 // Only relevant for select sub-values
- name string // Used for better error messages
- }
- func (i *fieldInfo) fieldName() string {
- if i == nil {
- return ""
- }
- return i.name
- }
- // Given a tag string, return a fieldInfo describing the field.
- func fieldTagToFieldInfo(str string, name string) (*fieldInfo, error) {
- var info *fieldInfo
- // Iterate over clauses in the tag, ignoring any that don't parse properly.
- for _, part := range strings.Split(str, ",") {
- switch {
- case strings.HasPrefix(part, "maxval:"):
- if v, err := strconv.ParseUint(part[7:], 10, 64); err == nil {
- info = &fieldInfo{count: byteCount(v), countSet: true}
- }
- case strings.HasPrefix(part, "size:"):
- if sz, err := strconv.ParseUint(part[5:], 10, 32); err == nil {
- info = &fieldInfo{count: uint(sz), countSet: true}
- }
- case strings.HasPrefix(part, "maxlen:"):
- v, err := strconv.ParseUint(part[7:], 10, 64)
- if err != nil {
- continue
- }
- if info == nil {
- info = &fieldInfo{}
- }
- info.count = byteCount(v)
- info.countSet = true
- info.maxlen = v
- case strings.HasPrefix(part, "minlen:"):
- v, err := strconv.ParseUint(part[7:], 10, 64)
- if err != nil {
- continue
- }
- if info == nil {
- info = &fieldInfo{}
- }
- info.minlen = v
- case strings.HasPrefix(part, "selector:"):
- if info == nil {
- info = &fieldInfo{}
- }
- info.selector = part[9:]
- case strings.HasPrefix(part, "val:"):
- v, err := strconv.ParseUint(part[4:], 10, 64)
- if err != nil {
- continue
- }
- if info == nil {
- info = &fieldInfo{}
- }
- info.val = v
- }
- }
- if info != nil {
- info.name = name
- if info.selector == "" {
- if info.count < 1 {
- return nil, structuralError{name, "field of unknown size in " + str}
- } else if info.count > 8 {
- return nil, structuralError{name, "specified size too large in " + str}
- } else if info.minlen > info.maxlen {
- return nil, structuralError{name, "specified length range inverted in " + str}
- } else if info.val > 0 {
- return nil, structuralError{name, "specified selector value but not field in " + str}
- }
- }
- } else if name != "" {
- info = &fieldInfo{name: name}
- }
- return info, nil
- }
- // Check that a value fits into a field described by a fieldInfo structure.
- func (i fieldInfo) check(val uint64, fldName string) error {
- if val >= (1 << (8 * i.count)) {
- return structuralError{fldName, fmt.Sprintf("value %d too large for size", val)}
- }
- if i.maxlen != 0 {
- if val < i.minlen {
- return structuralError{fldName, fmt.Sprintf("value %d too small for minimum %d", val, i.minlen)}
- }
- if val > i.maxlen {
- return structuralError{fldName, fmt.Sprintf("value %d too large for maximum %d", val, i.maxlen)}
- }
- }
- return nil
- }
- // readVarUint reads an big-endian unsigned integer of the given size in
- // bytes.
- func readVarUint(data []byte, info *fieldInfo) (uint64, error) {
- if info == nil || !info.countSet {
- return 0, structuralError{info.fieldName(), "no field size information available"}
- }
- if len(data) < int(info.count) {
- return 0, syntaxError{info.fieldName(), "truncated variable-length integer"}
- }
- var result uint64
- for i := uint(0); i < info.count; i++ {
- result = (result << 8) | uint64(data[i])
- }
- if err := info.check(result, info.name); err != nil {
- return 0, err
- }
- return result, nil
- }
- // parseField is the main parsing function. Given a byte slice and an offset
- // (in bytes) into the data, it will try to parse a suitable ASN.1 value out
- // and store it in the given Value.
- func parseField(v reflect.Value, data []byte, initOffset int, info *fieldInfo) (int, error) {
- offset := initOffset
- rest := data[offset:]
- fieldType := v.Type()
- // First look for known fixed types.
- switch fieldType {
- case uint8Type:
- if len(rest) < 1 {
- return offset, syntaxError{info.fieldName(), "truncated uint8"}
- }
- v.SetUint(uint64(rest[0]))
- offset++
- return offset, nil
- case uint16Type:
- if len(rest) < 2 {
- return offset, syntaxError{info.fieldName(), "truncated uint16"}
- }
- v.SetUint(uint64(binary.BigEndian.Uint16(rest)))
- offset += 2
- return offset, nil
- case uint24Type:
- if len(rest) < 3 {
- return offset, syntaxError{info.fieldName(), "truncated uint24"}
- }
- v.SetUint(uint64(data[0])<<16 | uint64(data[1])<<8 | uint64(data[2]))
- offset += 3
- return offset, nil
- case uint32Type:
- if len(rest) < 4 {
- return offset, syntaxError{info.fieldName(), "truncated uint32"}
- }
- v.SetUint(uint64(binary.BigEndian.Uint32(rest)))
- offset += 4
- return offset, nil
- case uint64Type:
- if len(rest) < 8 {
- return offset, syntaxError{info.fieldName(), "truncated uint64"}
- }
- v.SetUint(uint64(binary.BigEndian.Uint64(rest)))
- offset += 8
- return offset, nil
- }
- // Now deal with user-defined types.
- switch v.Kind() {
- case enumType.Kind():
- // Assume that anything of the same kind as Enum is an Enum, so that
- // users can alias types of their own to Enum.
- val, err := readVarUint(rest, info)
- if err != nil {
- return offset, err
- }
- v.SetUint(val)
- offset += int(info.count)
- return offset, nil
- case reflect.Struct:
- structType := fieldType
- // TLS includes a select(Enum) {..} construct, where the value of an enum
- // indicates which variant field is present (like a C union). We require
- // that the enum value be an earlier field in the same structure (the selector),
- // and that each of the possible variant destination fields be pointers.
- // So the Go mapping looks like:
- // type variantType struct {
- // Which tls.Enum `tls:"size:1"` // this is the selector
- // Val1 *type1 `tls:"selector:Which,val:1"` // this is a destination
- // Val2 *type2 `tls:"selector:Which,val:1"` // this is a destination
- // }
- // To deal with this, we track any enum-like fields and their values...
- enums := make(map[string]uint64)
- // .. and we track which selector names we've seen (in the destination field tags),
- // and whether a destination for that selector has been chosen.
- selectorSeen := make(map[string]bool)
- for i := 0; i < structType.NumField(); i++ {
- // Find information about this field.
- tag := structType.Field(i).Tag.Get("tls")
- fieldInfo, err := fieldTagToFieldInfo(tag, structType.Field(i).Name)
- if err != nil {
- return offset, err
- }
- destination := v.Field(i)
- if fieldInfo.selector != "" {
- // This is a possible select(Enum) destination, so first check that the referenced
- // selector field has already been seen earlier in the struct.
- choice, ok := enums[fieldInfo.selector]
- if !ok {
- return offset, structuralError{fieldInfo.name, "selector not seen: " + fieldInfo.selector}
- }
- if structType.Field(i).Type.Kind() != reflect.Ptr {
- return offset, structuralError{fieldInfo.name, "choice field not a pointer type"}
- }
- // Is this the first mention of the selector field name? If so, remember it.
- seen, ok := selectorSeen[fieldInfo.selector]
- if !ok {
- selectorSeen[fieldInfo.selector] = false
- }
- if choice != fieldInfo.val {
- // This destination field was not the chosen one, so make it nil (we checked
- // it was a pointer above).
- v.Field(i).Set(reflect.Zero(structType.Field(i).Type))
- continue
- }
- if seen {
- // We already saw a different destination field receive the value for this
- // selector value, which indicates a badly annotated structure.
- return offset, structuralError{fieldInfo.name, "duplicate selector value for " + fieldInfo.selector}
- }
- selectorSeen[fieldInfo.selector] = true
- // Make an object of the pointed-to type and parse into that.
- v.Field(i).Set(reflect.New(structType.Field(i).Type.Elem()))
- destination = v.Field(i).Elem()
- }
- offset, err = parseField(destination, data, offset, fieldInfo)
- if err != nil {
- return offset, err
- }
- // Remember any possible tls.Enum values encountered in case they are selectors.
- if structType.Field(i).Type.Kind() == enumType.Kind() {
- enums[structType.Field(i).Name] = v.Field(i).Uint()
- }
- }
- // Now we have seen all fields in the structure, check that all select(Enum) {..} selector
- // fields found a destination to put their data in.
- for selector, seen := range selectorSeen {
- if !seen {
- return offset, syntaxError{info.fieldName(), selector + ": unhandled value for selector"}
- }
- }
- return offset, nil
- case reflect.Array:
- datalen := v.Len()
- if datalen > len(rest) {
- return offset, syntaxError{info.fieldName(), "truncated array"}
- }
- inner := rest[:datalen]
- offset += datalen
- if fieldType.Elem().Kind() != reflect.Uint8 {
- // Only byte/uint8 arrays are supported
- return offset, structuralError{info.fieldName(), "unsupported array type: " + v.Type().String()}
- }
- reflect.Copy(v, reflect.ValueOf(inner))
- return offset, nil
- case reflect.Slice:
- sliceType := fieldType
- // Slices represent variable-length vectors, which are prefixed by a length field.
- // The fieldInfo indicates the size of that length field.
- varlen, err := readVarUint(rest, info)
- if err != nil {
- return offset, err
- }
- datalen := int(varlen)
- offset += int(info.count)
- rest = rest[info.count:]
- if datalen > len(rest) {
- return offset, syntaxError{info.fieldName(), "truncated slice"}
- }
- inner := rest[:datalen]
- offset += datalen
- if fieldType.Elem().Kind() == reflect.Uint8 {
- // Fast version for []byte
- v.Set(reflect.MakeSlice(sliceType, datalen, datalen))
- reflect.Copy(v, reflect.ValueOf(inner))
- return offset, nil
- }
- v.Set(reflect.MakeSlice(sliceType, 0, datalen))
- single := reflect.New(sliceType.Elem())
- for innerOffset := 0; innerOffset < len(inner); {
- var err error
- innerOffset, err = parseField(single.Elem(), inner, innerOffset, nil)
- if err != nil {
- return offset, err
- }
- v.Set(reflect.Append(v, single.Elem()))
- }
- return offset, nil
- default:
- return offset, structuralError{info.fieldName(), fmt.Sprintf("unsupported type: %s of kind %s", fieldType, v.Kind())}
- }
- }
- // Marshal returns the TLS encoding of val.
- func Marshal(val interface{}) ([]byte, error) {
- return MarshalWithParams(val, "")
- }
- // MarshalWithParams returns the TLS encoding of val, and allows field
- // parameters to be specified for the top-level element. The form
- // of the params is the same as the field tags.
- func MarshalWithParams(val interface{}, params string) ([]byte, error) {
- info, err := fieldTagToFieldInfo(params, "")
- if err != nil {
- return nil, err
- }
- var out bytes.Buffer
- v := reflect.ValueOf(val)
- if err := marshalField(&out, v, info); err != nil {
- return nil, err
- }
- return out.Bytes(), err
- }
- func marshalField(out *bytes.Buffer, v reflect.Value, info *fieldInfo) error {
- var prefix string
- if info != nil && len(info.name) > 0 {
- prefix = info.name + ": "
- }
- fieldType := v.Type()
- // First look for known fixed types.
- switch fieldType {
- case uint8Type:
- out.WriteByte(byte(v.Uint()))
- return nil
- case uint16Type:
- scratch := make([]byte, 2)
- binary.BigEndian.PutUint16(scratch, uint16(v.Uint()))
- out.Write(scratch)
- return nil
- case uint24Type:
- i := v.Uint()
- if i > 0xffffff {
- return structuralError{info.fieldName(), fmt.Sprintf("uint24 overflow %d", i)}
- }
- scratch := make([]byte, 4)
- binary.BigEndian.PutUint32(scratch, uint32(i))
- out.Write(scratch[1:])
- return nil
- case uint32Type:
- scratch := make([]byte, 4)
- binary.BigEndian.PutUint32(scratch, uint32(v.Uint()))
- out.Write(scratch)
- return nil
- case uint64Type:
- scratch := make([]byte, 8)
- binary.BigEndian.PutUint64(scratch, uint64(v.Uint()))
- out.Write(scratch)
- return nil
- }
- // Now deal with user-defined types.
- switch v.Kind() {
- case enumType.Kind():
- i := v.Uint()
- if info == nil {
- return structuralError{info.fieldName(), "enum field tag missing"}
- }
- if err := info.check(i, prefix); err != nil {
- return err
- }
- scratch := make([]byte, 8)
- binary.BigEndian.PutUint64(scratch, uint64(i))
- out.Write(scratch[(8 - info.count):])
- return nil
- case reflect.Struct:
- structType := fieldType
- enums := make(map[string]uint64) // Values of any Enum fields
- // The comment parseField() describes the mapping of the TLS select(Enum) {..} construct;
- // here we have selector and source (rather than destination) fields.
- // Track which selector names we've seen (in the source field tags), and whether a source
- // value for that selector has been processed.
- selectorSeen := make(map[string]bool)
- for i := 0; i < structType.NumField(); i++ {
- // Find information about this field.
- tag := structType.Field(i).Tag.Get("tls")
- fieldInfo, err := fieldTagToFieldInfo(tag, structType.Field(i).Name)
- if err != nil {
- return err
- }
- source := v.Field(i)
- if fieldInfo.selector != "" {
- // This field is a possible source for a select(Enum) {..}. First check
- // the selector field name has been seen.
- choice, ok := enums[fieldInfo.selector]
- if !ok {
- return structuralError{fieldInfo.name, "selector not seen: " + fieldInfo.selector}
- }
- if structType.Field(i).Type.Kind() != reflect.Ptr {
- return structuralError{fieldInfo.name, "choice field not a pointer type"}
- }
- // Is this the first mention of the selector field name? If so, remember it.
- seen, ok := selectorSeen[fieldInfo.selector]
- if !ok {
- selectorSeen[fieldInfo.selector] = false
- }
- if choice != fieldInfo.val {
- // This source was not chosen; police that it should be nil.
- if v.Field(i).Pointer() != uintptr(0) {
- return structuralError{fieldInfo.name, "unchosen field is non-nil"}
- }
- continue
- }
- if seen {
- // We already saw a different source field generate the value for this
- // selector value, which indicates a badly annotated structure.
- return structuralError{fieldInfo.name, "duplicate selector value for " + fieldInfo.selector}
- }
- selectorSeen[fieldInfo.selector] = true
- if v.Field(i).Pointer() == uintptr(0) {
- return structuralError{fieldInfo.name, "chosen field is nil"}
- }
- // Marshal from the pointed-to source object.
- source = v.Field(i).Elem()
- }
- var fieldData bytes.Buffer
- if err := marshalField(&fieldData, source, fieldInfo); err != nil {
- return err
- }
- out.Write(fieldData.Bytes())
- // Remember any tls.Enum values encountered in case they are selectors.
- if structType.Field(i).Type.Kind() == enumType.Kind() {
- enums[structType.Field(i).Name] = v.Field(i).Uint()
- }
- }
- // Now we have seen all fields in the structure, check that all select(Enum) {..} selector
- // fields found a source field get get their data from.
- for selector, seen := range selectorSeen {
- if !seen {
- return syntaxError{info.fieldName(), selector + ": unhandled value for selector"}
- }
- }
- return nil
- case reflect.Array:
- datalen := v.Len()
- arrayType := fieldType
- if arrayType.Elem().Kind() != reflect.Uint8 {
- // Only byte/uint8 arrays are supported
- return structuralError{info.fieldName(), "unsupported array type"}
- }
- bytes := make([]byte, datalen)
- for i := 0; i < datalen; i++ {
- bytes[i] = uint8(v.Index(i).Uint())
- }
- _, err := out.Write(bytes)
- return err
- case reflect.Slice:
- if info == nil {
- return structuralError{info.fieldName(), "slice field tag missing"}
- }
- sliceType := fieldType
- if sliceType.Elem().Kind() == reflect.Uint8 {
- // Fast version for []byte: first write the length as info.count bytes.
- datalen := v.Len()
- scratch := make([]byte, 8)
- binary.BigEndian.PutUint64(scratch, uint64(datalen))
- out.Write(scratch[(8 - info.count):])
- if err := info.check(uint64(datalen), prefix); err != nil {
- return err
- }
- // Then just write the data.
- bytes := make([]byte, datalen)
- for i := 0; i < datalen; i++ {
- bytes[i] = uint8(v.Index(i).Uint())
- }
- _, err := out.Write(bytes)
- return err
- }
- // General version: use a separate Buffer to write the slice entries into.
- var innerBuf bytes.Buffer
- for i := 0; i < v.Len(); i++ {
- if err := marshalField(&innerBuf, v.Index(i), nil); err != nil {
- return err
- }
- }
- // Now insert (and check) the size.
- size := uint64(innerBuf.Len())
- if err := info.check(size, prefix); err != nil {
- return err
- }
- scratch := make([]byte, 8)
- binary.BigEndian.PutUint64(scratch, size)
- out.Write(scratch[(8 - info.count):])
- // Then copy the data.
- _, err := out.Write(innerBuf.Bytes())
- return err
- default:
- return structuralError{info.fieldName(), fmt.Sprintf("unsupported type: %s of kind %s", fieldType, v.Kind())}
- }
- }
|