// 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< 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 isDigit(b byte) bool { return '0' <= b && b <= '9' } // twoDigits returns the value of two, base 10 digits. func twoDigits(bytes []byte, max int) (int, bool) { for i := 0; i < 2; i++ { if !isDigit(bytes[i]) { return 0, false } } value := (int(bytes[0])-'0')*10 + int(bytes[1]-'0'); if value > max { return 0, false } return value, true; } // parseUTCTime parses the UTCTime from the given byte array and returns the // resulting time. func parseUTCTime(bytes []byte) (ret *time.Time, err os.Error) { // A UTCTime can take the following formats: // // 1111111 // 01234567890123456 // // YYMMDDhhmmZ // YYMMDDhhmm+hhmm // YYMMDDhhmm-hhmm // YYMMDDhhmmssZ // YYMMDDhhmmss+hhmm // YYMMDDhhmmss-hhmm if len(bytes) < 11 { err = SyntaxError{"UTCTime too short"}; return; } ret = new(time.Time); var ok1, ok2, ok3, ok4, ok5 bool; year, ok1 := twoDigits(bytes[0:2], 99); // RFC 5280, section 5.1.2.4 says that years 2050 or later use another date // scheme. if year >= 50 { ret.Year = 1900 + int64(year) } else { ret.Year = 2000 + int64(year) } ret.Month, ok2 = twoDigits(bytes[2:4], 12); ret.Day, ok3 = twoDigits(bytes[4:6], 31); ret.Hour, ok4 = twoDigits(bytes[6:8], 23); ret.Minute, ok5 = twoDigits(bytes[8:10], 59); if !ok1 || !ok2 || !ok3 || !ok4 || !ok5 { goto Error } bytes = bytes[10:]; switch bytes[0] { case '0', '1', '2', '3', '4', '5', '6': if len(bytes) < 3 { goto Error } ret.Second, ok1 = twoDigits(bytes[0:2], 60); // 60, not 59, because of leap seconds. if !ok1 { goto Error } bytes = bytes[2:]; } if len(bytes) == 0 { goto Error } switch bytes[0] { case 'Z': if len(bytes) != 1 { goto Error } return; case '-', '+': if len(bytes) != 5 { goto Error } hours, ok1 := twoDigits(bytes[1:3], 12); minutes, ok2 := twoDigits(bytes[3:5], 59); if !ok1 || !ok2 { goto Error } sign := 1; if bytes[0] == '-' { sign = -1 } ret.ZoneOffset = sign * (60 * (hours*60 + minutes)); default: goto Error } return; Error: err = SyntaxError{"invalid UTCTime"}; return; } // 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 == '?' } // 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; } // A RawValue represents an undecoded ASN.1 object. type RawValue struct { Class, Tag int; IsCompound bool; Bytes []byte; } // 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); } } // We magically map SET and SET OF to SEQUENCE and SEQUENCE OF // because we treat everything as ordered. if ret.tag == tagSet { ret.tag = tagSequence } 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.SliceType, elemType reflect.Type) (ret *reflect.SliceValue, 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 } 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.Elem(i), bytes, offset, params); if err != nil { return } } return; } var ( bitStringType = reflect.Typeof(BitString{}); objectIdentifierType = reflect.Typeof(ObjectIdentifier{}); 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]}; offset += t.length; v.(*reflect.StructValue).Set(reflect.NewValue(result).(*reflect.StructValue)); return; } // Deal with the ANY type. if ifaceType, ok := fieldType.(*reflect.InterfaceType); ok && ifaceType.NumMethod() == 0 { ifaceValue := v.(*reflect.InterfaceValue); 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 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.NewValue(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 { if t.class == classContextSpecific && t.tag == *params.tag && t.isCompound { t, offset, err = parseTagAndLength(bytes, offset); if err != nil { 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 } expectedClass := classUniversal; expectedTag := universalTag; if !params.explicit && params.tag != nil { expectedClass = classContextSpecific; 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]; // We deal with the structures defined in this package first. switch fieldType { case objectIdentifierType: newSlice, err1 := parseObjectIdentifier(innerBytes); sliceValue := v.(*reflect.SliceValue); sliceValue.Set(reflect.MakeSlice(sliceValue.Type().(*reflect.SliceType), len(newSlice), len(newSlice))); if err1 == nil { reflect.ArrayCopy(sliceValue, reflect.NewValue(newSlice).(reflect.ArrayOrSliceValue)) } offset += t.length; err = err1; return; case bitStringType: structValue := v.(*reflect.StructValue); bs, err1 := parseBitString(innerBytes); offset += t.length; if err1 == nil { structValue.Set(reflect.NewValue(bs).(*reflect.StructValue)) } err = err1; return; case timeType: ptrValue := v.(*reflect.PtrValue); time, err1 := parseUTCTime(innerBytes); offset += t.length; if err1 == nil { ptrValue.Set(reflect.NewValue(time).(*reflect.PtrValue)) } err = err1; return; } switch val := v.(type) { case *reflect.BoolValue: parsedBool, err1 := parseBool(innerBytes); offset += t.length; if err1 == nil { val.Set(parsedBool) } err = err1; return; case *reflect.IntValue: parsedInt, err1 := parseInt(innerBytes); offset += t.length; if err1 == nil { val.Set(parsedInt) } err = err1; return; case *reflect.Int64Value: parsedInt, err1 := parseInt64(innerBytes); offset += t.length; if err1 == nil { val.Set(parsedInt) } err = err1; return; case *reflect.StructValue: structType := fieldType.(*reflect.StructType); if structType.NumField() > 0 && structType.Field(0).Type == rawContentsType { bytes := bytes[initOffset : offset+t.length]; val.Field(0).SetValue(reflect.NewValue(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 } } offset += t.length; // 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.SliceValue: sliceType := fieldType.(*reflect.SliceType); if _, ok := sliceType.Elem().(*reflect.Uint8Type); ok { val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes))); reflect.ArrayCopy(val, reflect.NewValue(innerBytes).(reflect.ArrayOrSliceValue)); return; } newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem()); offset += t.length; if err1 == nil { val.Set(newSlice) } err = err1; return; case *reflect.StringValue: var v string; switch universalTag { case tagPrintableString: v, err = parsePrintableString(innerBytes) case tagIA5String: v, err = parseIA5String(innerBytes) default: err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)} } if err == nil { val.Set(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.(type) { case *reflect.IntValue: val.Set(int(*params.defaultValue)) case *reflect.Int64Value: val.Set(int64(*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 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(val interface{}, b []byte) (rest []byte, err os.Error) { v := reflect.NewValue(val).(*reflect.PtrValue).Elem(); offset, err := parseField(v, b, 0, fieldParameters{}); if err != nil { return nil, err } return b[offset:], nil; }