diff options
Diffstat (limited to 'src/cmd/fix/testdata/reflect.asn1.go.out')
-rw-r--r-- | src/cmd/fix/testdata/reflect.asn1.go.out | 814 |
1 files changed, 0 insertions, 814 deletions
diff --git a/src/cmd/fix/testdata/reflect.asn1.go.out b/src/cmd/fix/testdata/reflect.asn1.go.out deleted file mode 100644 index ba6224e6d..000000000 --- a/src/cmd/fix/testdata/reflect.asn1.go.out +++ /dev/null @@ -1,814 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// The asn1 package implements parsing of DER-encoded ASN.1 data structures, -// as defined in ITU-T Rec X.690. -// -// See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,'' -// http://luca.ntop.org/Teaching/Appunti/asn1.html. -package asn1 - -// ASN.1 is a syntax for specifying abstract objects and BER, DER, PER, XER etc -// are different encoding formats for those objects. Here, we'll be dealing -// with DER, the Distinguished Encoding Rules. DER is used in X.509 because -// it's fast to parse and, unlike BER, has a unique encoding for every object. -// When calculating hashes over objects, it's important that the resulting -// bytes be the same at both ends and DER removes this margin of error. -// -// ASN.1 is very complex and this package doesn't attempt to implement -// everything by any means. - -import ( - "fmt" - "os" - "reflect" - "time" -) - -// A StructuralError suggests that the ASN.1 data is valid, but the Go type -// which is receiving it doesn't match. -type StructuralError struct { - Msg string -} - -func (e StructuralError) String() string { return "ASN.1 structure error: " + e.Msg } - -// A SyntaxError suggests that the ASN.1 data is invalid. -type SyntaxError struct { - Msg string -} - -func (e SyntaxError) String() string { return "ASN.1 syntax error: " + e.Msg } - -// We start by dealing with each of the primitive types in turn. - -// BOOLEAN - -func parseBool(bytes []byte) (ret bool, err os.Error) { - if len(bytes) != 1 { - err = SyntaxError{"invalid boolean"} - return - } - - return bytes[0] != 0, nil -} - -// INTEGER - -// parseInt64 treats the given bytes as a big-endian, signed integer and -// returns the result. -func parseInt64(bytes []byte) (ret int64, err os.Error) { - if len(bytes) > 8 { - // We'll overflow an int64 in this case. - err = StructuralError{"integer too large"} - return - } - for bytesRead := 0; bytesRead < len(bytes); bytesRead++ { - ret <<= 8 - ret |= int64(bytes[bytesRead]) - } - - // Shift up and down in order to sign extend the result. - ret <<= 64 - uint8(len(bytes))*8 - ret >>= 64 - uint8(len(bytes))*8 - return -} - -// parseInt treats the given bytes as a big-endian, signed integer and returns -// the result. -func parseInt(bytes []byte) (int, os.Error) { - ret64, err := parseInt64(bytes) - if err != nil { - return 0, err - } - if ret64 != int64(int(ret64)) { - return 0, StructuralError{"integer too large"} - } - return int(ret64), nil -} - -// BIT STRING - -// BitString is the structure to use when you want an ASN.1 BIT STRING type. A -// bit string is padded up to the nearest byte in memory and the number of -// valid bits is recorded. Padding bits will be zero. -type BitString struct { - Bytes []byte // bits packed into bytes. - BitLength int // length in bits. -} - -// At returns the bit at the given index. If the index is out of range it -// returns false. -func (b BitString) At(i int) int { - if i < 0 || i >= b.BitLength { - return 0 - } - x := i / 8 - y := 7 - uint(i%8) - return int(b.Bytes[x]>>y) & 1 -} - -// RightAlign returns a slice where the padding bits are at the beginning. The -// slice may share memory with the BitString. -func (b BitString) RightAlign() []byte { - shift := uint(8 - (b.BitLength % 8)) - if shift == 8 || len(b.Bytes) == 0 { - return b.Bytes - } - - a := make([]byte, len(b.Bytes)) - a[0] = b.Bytes[0] >> shift - for i := 1; i < len(b.Bytes); i++ { - a[i] = b.Bytes[i-1] << (8 - shift) - a[i] |= b.Bytes[i] >> shift - } - - return a -} - -// parseBitString parses an ASN.1 bit string from the given byte array and returns it. -func parseBitString(bytes []byte) (ret BitString, err os.Error) { - if len(bytes) == 0 { - err = SyntaxError{"zero length BIT STRING"} - return - } - paddingBits := int(bytes[0]) - if paddingBits > 7 || - len(bytes) == 1 && paddingBits > 0 || - bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 { - err = SyntaxError{"invalid padding bits in BIT STRING"} - return - } - ret.BitLength = (len(bytes)-1)*8 - paddingBits - ret.Bytes = bytes[1:] - return -} - -// OBJECT IDENTIFIER - -// An ObjectIdentifier represents an ASN.1 OBJECT IDENTIFIER. -type ObjectIdentifier []int - -// Equal returns true iff oi and other represent the same identifier. -func (oi ObjectIdentifier) Equal(other ObjectIdentifier) bool { - if len(oi) != len(other) { - return false - } - for i := 0; i < len(oi); i++ { - if oi[i] != other[i] { - return false - } - } - - return true -} - -// parseObjectIdentifier parses an OBJECT IDENTIFER from the given bytes and -// returns it. An object identifer is a sequence of variable length integers -// that are assigned in a hierarachy. -func parseObjectIdentifier(bytes []byte) (s []int, err os.Error) { - if len(bytes) == 0 { - err = SyntaxError{"zero length OBJECT IDENTIFIER"} - return - } - - // In the worst case, we get two elements from the first byte (which is - // encoded differently) and then every varint is a single byte long. - s = make([]int, len(bytes)+1) - - // The first byte is 40*value1 + value2: - s[0] = int(bytes[0]) / 40 - s[1] = int(bytes[0]) % 40 - i := 2 - for offset := 1; offset < len(bytes); i++ { - var v int - v, offset, err = parseBase128Int(bytes, offset) - if err != nil { - return - } - s[i] = v - } - s = s[0:i] - return -} - -// ENUMERATED - -// An Enumerated is represented as a plain int. -type Enumerated int - -// FLAG - -// A Flag accepts any data and is set to true if present. -type Flag bool - -// parseBase128Int parses a base-128 encoded int from the given offset in the -// given byte array. It returns the value and the new offset. -func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err os.Error) { - offset = initOffset - for shifted := 0; offset < len(bytes); shifted++ { - if shifted > 4 { - err = StructuralError{"base 128 integer too large"} - return - } - ret <<= 7 - b := bytes[offset] - ret |= int(b & 0x7f) - offset++ - if b&0x80 == 0 { - return - } - } - err = SyntaxError{"truncated base 128 integer"} - return -} - -// UTCTime - -func parseUTCTime(bytes []byte) (ret *time.Time, err os.Error) { - s := string(bytes) - ret, err = time.Parse("0601021504Z0700", s) - if err == nil { - return - } - ret, err = time.Parse("060102150405Z0700", s) - return -} - -// parseGeneralizedTime parses the GeneralizedTime from the given byte array -// and returns the resulting time. -func parseGeneralizedTime(bytes []byte) (ret *time.Time, err os.Error) { - return time.Parse("20060102150405Z0700", string(bytes)) -} - -// PrintableString - -// parsePrintableString parses a ASN.1 PrintableString from the given byte -// array and returns it. -func parsePrintableString(bytes []byte) (ret string, err os.Error) { - for _, b := range bytes { - if !isPrintable(b) { - err = SyntaxError{"PrintableString contains invalid character"} - return - } - } - ret = string(bytes) - return -} - -// isPrintable returns true iff the given b is in the ASN.1 PrintableString set. -func isPrintable(b byte) bool { - return 'a' <= b && b <= 'z' || - 'A' <= b && b <= 'Z' || - '0' <= b && b <= '9' || - '\'' <= b && b <= ')' || - '+' <= b && b <= '/' || - b == ' ' || - b == ':' || - b == '=' || - b == '?' || - // This is techincally not allowed in a PrintableString. - // However, x509 certificates with wildcard strings don't - // always use the correct string type so we permit it. - b == '*' -} - -// IA5String - -// parseIA5String parses a ASN.1 IA5String (ASCII string) from the given -// byte array and returns it. -func parseIA5String(bytes []byte) (ret string, err os.Error) { - for _, b := range bytes { - if b >= 0x80 { - err = SyntaxError{"IA5String contains invalid character"} - return - } - } - ret = string(bytes) - return -} - -// T61String - -// parseT61String parses a ASN.1 T61String (8-bit clean string) from the given -// byte array and returns it. -func parseT61String(bytes []byte) (ret string, err os.Error) { - return string(bytes), nil -} - -// A RawValue represents an undecoded ASN.1 object. -type RawValue struct { - Class, Tag int - IsCompound bool - Bytes []byte - FullBytes []byte // includes the tag and length -} - -// RawContent is used to signal that the undecoded, DER data needs to be -// preserved for a struct. To use it, the first field of the struct must have -// this type. It's an error for any of the other fields to have this type. -type RawContent []byte - -// Tagging - -// parseTagAndLength parses an ASN.1 tag and length pair from the given offset -// into a byte array. It returns the parsed data and the new offset. SET and -// SET OF (tag 17) are mapped to SEQUENCE and SEQUENCE OF (tag 16) since we -// don't distinguish between ordered and unordered objects in this code. -func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err os.Error) { - offset = initOffset - b := bytes[offset] - offset++ - ret.class = int(b >> 6) - ret.isCompound = b&0x20 == 0x20 - ret.tag = int(b & 0x1f) - - // If the bottom five bits are set, then the tag number is actually base 128 - // encoded afterwards - if ret.tag == 0x1f { - ret.tag, offset, err = parseBase128Int(bytes, offset) - if err != nil { - return - } - } - if offset >= len(bytes) { - err = SyntaxError{"truncated tag or length"} - return - } - b = bytes[offset] - offset++ - if b&0x80 == 0 { - // The length is encoded in the bottom 7 bits. - ret.length = int(b & 0x7f) - } else { - // Bottom 7 bits give the number of length bytes to follow. - numBytes := int(b & 0x7f) - // We risk overflowing a signed 32-bit number if we accept more than 3 bytes. - if numBytes > 3 { - err = StructuralError{"length too large"} - return - } - if numBytes == 0 { - err = SyntaxError{"indefinite length found (not DER)"} - return - } - ret.length = 0 - for i := 0; i < numBytes; i++ { - if offset >= len(bytes) { - err = SyntaxError{"truncated tag or length"} - return - } - b = bytes[offset] - offset++ - ret.length <<= 8 - ret.length |= int(b) - } - } - - return -} - -// parseSequenceOf is used for SEQUENCE OF and SET OF values. It tries to parse -// a number of ASN.1 values from the given byte array and returns them as a -// slice of Go values of the given type. -func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err os.Error) { - expectedTag, compoundType, ok := getUniversalType(elemType) - if !ok { - err = StructuralError{"unknown Go type for slice"} - return - } - - // First we iterate over the input and count the number of elements, - // checking that the types are correct in each case. - numElements := 0 - for offset := 0; offset < len(bytes); { - var t tagAndLength - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - // We pretend that GENERAL STRINGs are PRINTABLE STRINGs so - // that a sequence of them can be parsed into a []string. - if t.tag == tagGeneralString { - t.tag = tagPrintableString - } - if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag { - err = StructuralError{"sequence tag mismatch"} - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"truncated sequence"} - return - } - offset += t.length - numElements++ - } - ret = reflect.MakeSlice(sliceType, numElements, numElements) - params := fieldParameters{} - offset := 0 - for i := 0; i < numElements; i++ { - offset, err = parseField(ret.Index(i), bytes, offset, params) - if err != nil { - return - } - } - return -} - -var ( - bitStringType = reflect.TypeOf(BitString{}) - objectIdentifierType = reflect.TypeOf(ObjectIdentifier{}) - enumeratedType = reflect.TypeOf(Enumerated(0)) - flagType = reflect.TypeOf(Flag(false)) - timeType = reflect.TypeOf(&time.Time{}) - rawValueType = reflect.TypeOf(RawValue{}) - rawContentsType = reflect.TypeOf(RawContent(nil)) -) - -// invalidLength returns true iff offset + length > sliceLength, or if the -// addition would overflow. -func invalidLength(offset, length, sliceLength int) bool { - return offset+length < offset || offset+length > sliceLength -} - -// parseField is the main parsing function. Given a byte array and an offset -// into the array, it will try to parse a suitable ASN.1 value out and store it -// in the given Value. -func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err os.Error) { - offset = initOffset - fieldType := v.Type() - - // If we have run out of data, it may be that there are optional elements at the end. - if offset == len(bytes) { - if !setDefaultValue(v, params) { - err = SyntaxError{"sequence truncated"} - } - return - } - - // Deal with raw values. - if fieldType == rawValueType { - var t tagAndLength - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"data truncated"} - return - } - result := RawValue{t.class, t.tag, t.isCompound, bytes[offset : offset+t.length], bytes[initOffset : offset+t.length]} - offset += t.length - v.Set(reflect.ValueOf(result)) - return - } - - // Deal with the ANY type. - if ifaceType := fieldType; ifaceType.Kind() == reflect.Interface && ifaceType.NumMethod() == 0 { - ifaceValue := v - var t tagAndLength - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"data truncated"} - return - } - var result interface{} - if !t.isCompound && t.class == classUniversal { - innerBytes := bytes[offset : offset+t.length] - switch t.tag { - case tagPrintableString: - result, err = parsePrintableString(innerBytes) - case tagIA5String: - result, err = parseIA5String(innerBytes) - case tagT61String: - result, err = parseT61String(innerBytes) - case tagInteger: - result, err = parseInt64(innerBytes) - case tagBitString: - result, err = parseBitString(innerBytes) - case tagOID: - result, err = parseObjectIdentifier(innerBytes) - case tagUTCTime: - result, err = parseUTCTime(innerBytes) - case tagOctetString: - result = innerBytes - default: - // If we don't know how to handle the type, we just leave Value as nil. - } - } - offset += t.length - if err != nil { - return - } - if result != nil { - ifaceValue.Set(reflect.ValueOf(result)) - } - return - } - universalTag, compoundType, ok1 := getUniversalType(fieldType) - if !ok1 { - err = StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)} - return - } - - t, offset, err := parseTagAndLength(bytes, offset) - if err != nil { - return - } - if params.explicit { - expectedClass := classContextSpecific - if params.application { - expectedClass = classApplication - } - if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) { - if t.length > 0 { - t, offset, err = parseTagAndLength(bytes, offset) - if err != nil { - return - } - } else { - if fieldType != flagType { - err = StructuralError{"Zero length explicit tag was not an asn1.Flag"} - return - } - - flagValue := v - flagValue.SetBool(true) - return - } - } else { - // The tags didn't match, it might be an optional element. - ok := setDefaultValue(v, params) - if ok { - offset = initOffset - } else { - err = StructuralError{"explicitly tagged member didn't match"} - } - return - } - } - - // Special case for strings: PrintableString and IA5String both map to - // the Go type string. getUniversalType returns the tag for - // PrintableString when it sees a string so, if we see an IA5String on - // the wire, we change the universal type to match. - if universalTag == tagPrintableString && t.tag == tagIA5String { - universalTag = tagIA5String - } - // Likewise for GeneralString - if universalTag == tagPrintableString && t.tag == tagGeneralString { - universalTag = tagGeneralString - } - - // Special case for time: UTCTime and GeneralizedTime both map to the - // Go type time.Time. - if universalTag == tagUTCTime && t.tag == tagGeneralizedTime { - universalTag = tagGeneralizedTime - } - - expectedClass := classUniversal - expectedTag := universalTag - - if !params.explicit && params.tag != nil { - expectedClass = classContextSpecific - expectedTag = *params.tag - } - - if !params.explicit && params.application && params.tag != nil { - expectedClass = classApplication - expectedTag = *params.tag - } - - // We have unwrapped any explicit tagging at this point. - if t.class != expectedClass || t.tag != expectedTag || t.isCompound != compoundType { - // Tags don't match. Again, it could be an optional element. - ok := setDefaultValue(v, params) - if ok { - offset = initOffset - } else { - err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", expectedTag, t, params, fieldType.Name(), offset)} - } - return - } - if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"data truncated"} - return - } - innerBytes := bytes[offset : offset+t.length] - offset += t.length - - // We deal with the structures defined in this package first. - switch fieldType { - case objectIdentifierType: - newSlice, err1 := parseObjectIdentifier(innerBytes) - sliceValue := v - sliceValue.Set(reflect.MakeSlice(sliceValue.Type(), len(newSlice), len(newSlice))) - if err1 == nil { - reflect.Copy(sliceValue, reflect.ValueOf(newSlice)) - } - err = err1 - return - case bitStringType: - structValue := v - bs, err1 := parseBitString(innerBytes) - if err1 == nil { - structValue.Set(reflect.ValueOf(bs)) - } - err = err1 - return - case timeType: - ptrValue := v - var time *time.Time - var err1 os.Error - if universalTag == tagUTCTime { - time, err1 = parseUTCTime(innerBytes) - } else { - time, err1 = parseGeneralizedTime(innerBytes) - } - if err1 == nil { - ptrValue.Set(reflect.ValueOf(time)) - } - err = err1 - return - case enumeratedType: - parsedInt, err1 := parseInt(innerBytes) - enumValue := v - if err1 == nil { - enumValue.SetInt(int64(parsedInt)) - } - err = err1 - return - case flagType: - flagValue := v - flagValue.SetBool(true) - return - } - switch val := v; val.Kind() { - case reflect.Bool: - parsedBool, err1 := parseBool(innerBytes) - if err1 == nil { - val.SetBool(parsedBool) - } - err = err1 - return - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - switch val.Type().Kind() { - case reflect.Int: - parsedInt, err1 := parseInt(innerBytes) - if err1 == nil { - val.SetInt(int64(parsedInt)) - } - err = err1 - return - case reflect.Int64: - parsedInt, err1 := parseInt64(innerBytes) - if err1 == nil { - val.SetInt(parsedInt) - } - err = err1 - return - } - case reflect.Struct: - structType := fieldType - - if structType.NumField() > 0 && - structType.Field(0).Type == rawContentsType { - bytes := bytes[initOffset:offset] - val.Field(0).Set(reflect.ValueOf(RawContent(bytes))) - } - - innerOffset := 0 - for i := 0; i < structType.NumField(); i++ { - field := structType.Field(i) - if i == 0 && field.Type == rawContentsType { - continue - } - innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag)) - if err != nil { - return - } - } - // We allow extra bytes at the end of the SEQUENCE because - // adding elements to the end has been used in X.509 as the - // version numbers have increased. - return - case reflect.Slice: - sliceType := fieldType - if sliceType.Elem().Kind() == reflect.Uint8 { - val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes))) - reflect.Copy(val, reflect.ValueOf(innerBytes)) - return - } - newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem()) - if err1 == nil { - val.Set(newSlice) - } - err = err1 - return - case reflect.String: - var v string - switch universalTag { - case tagPrintableString: - v, err = parsePrintableString(innerBytes) - case tagIA5String: - v, err = parseIA5String(innerBytes) - case tagT61String: - v, err = parseT61String(innerBytes) - case tagGeneralString: - // GeneralString is specified in ISO-2022/ECMA-35, - // A brief review suggests that it includes structures - // that allow the encoding to change midstring and - // such. We give up and pass it as an 8-bit string. - v, err = parseT61String(innerBytes) - default: - err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)} - } - if err == nil { - val.SetString(v) - } - return - } - err = StructuralError{"unknown Go type"} - return -} - -// setDefaultValue is used to install a default value, from a tag string, into -// a Value. It is successful is the field was optional, even if a default value -// wasn't provided or it failed to install it into the Value. -func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) { - if !params.optional { - return - } - ok = true - if params.defaultValue == nil { - return - } - switch val := v; val.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - val.SetInt(*params.defaultValue) - } - return -} - -// Unmarshal parses the DER-encoded ASN.1 data structure 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 upper case field names. -// -// An ASN.1 INTEGER can be written to an int or int64. -// If the encoded value does not fit in the Go type, -// Unmarshal returns a parse error. -// -// An ASN.1 BIT STRING can be written to a BitString. -// -// An ASN.1 OCTET STRING can be written to a []byte. -// -// An ASN.1 OBJECT IDENTIFIER can be written to an -// ObjectIdentifier. -// -// An ASN.1 ENUMERATED can be written to an Enumerated. -// -// An ASN.1 UTCTIME or GENERALIZEDTIME can be written to a *time.Time. -// -// An ASN.1 PrintableString or IA5String can be written to a string. -// -// Any of the above ASN.1 values can be written to an interface{}. -// The value stored in the interface has the corresponding Go type. -// For integers, that type is int64. -// -// An ASN.1 SEQUENCE OF x or SET OF x can be written -// to a slice if an x can be written to the slice's element type. -// -// An ASN.1 SEQUENCE or SET can be written to a struct -// if each of the elements in the sequence can be -// written to the corresponding element in the struct. -// -// The following tags on struct fields have special meaning to Unmarshal: -// -// optional marks the field as ASN.1 OPTIONAL -// [explicit] tag:x specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC -// default:x sets the default value for optional integer fields -// -// If the type of the first field of a structure is RawContent then the raw -// ASN1 contents of the struct will be stored in it. -// -// Other ASN.1 types are not supported; if it encounters them, -// Unmarshal returns a parse error. -func Unmarshal(b []byte, val interface{}) (rest []byte, err os.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) (rest []byte, err os.Error) { - v := reflect.ValueOf(val).Elem() - offset, err := parseField(v, b, 0, parseFieldParameters(params)) - if err != nil { - return nil, err - } - return b[offset:], nil -} |