// 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.

// Package asn1 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 ber // 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 ( ) // We start by dealing with each of the primitive types in turn. // BOOLEAN func parseBool( []byte) ( bool, error) { if len() != 1 { = asn1.SyntaxError{Msg: "invalid boolean"} return } // DER demands that "If the encoding represents the boolean value TRUE, // its single contents octet shall have all eight bits set to one." // Thus only 0 and 255 are valid encoded values. switch [0] { case 0: = false case 0xff: = true default: = asn1.SyntaxError{Msg: "invalid boolean"} } return } // INTEGER // checkInteger returns nil if the given bytes are a valid DER-encoded // INTEGER and an error otherwise. func checkInteger( []byte) error { if len() == 0 { return asn1.StructuralError{Msg: "empty integer"} } if len() == 1 { return nil } if ([0] == 0 && [1]&0x80 == 0) || ([0] == 0xff && [1]&0x80 == 0x80) { return asn1.StructuralError{Msg: "integer not minimally-encoded"} } return nil } // parseInt64 treats the given bytes as a big-endian, signed integer and // returns the result. func parseInt64( []byte) ( int64, error) { = checkInteger() if != nil { return } if len() > 8 { // We'll overflow an int64 in this case. = asn1.StructuralError{Msg: "integer too large"} return } for := 0; < len(); ++ { <<= 8 |= int64([]) } // Shift up and down in order to sign extend the result. <<= 64 - uint8(len())*8 >>= 64 - uint8(len())*8 return } // parseInt treats the given bytes as a big-endian, signed integer and returns // the result. func parseInt32( []byte) (int32, error) { if := checkInteger(); != nil { return 0, } , := parseInt64() if != nil { return 0, } if != int64(int32()) { return 0, asn1.StructuralError{Msg: "integer too large"} } return int32(), nil } var bigOne = big.NewInt(1) // parseBigInt treats the given bytes as a big-endian, signed integer and returns // the result. func parseBigInt( []byte) (*big.Int, error) { if := checkInteger(); != nil { return nil, } := new(big.Int) if len() > 0 && [0]&0x80 == 0x80 { // This is a negative number. := make([]byte, len()) for := range { [] = ^[] } .SetBytes() .Add(, bigOne) .Neg() return , nil } .SetBytes() return , nil } // BIT STRING // parseBitString parses an ASN.1 bit string from the given byte slice and returns it. func parseBitString( []byte) ( asn1.BitString, error) { if len() == 0 { = asn1.SyntaxError{Msg: "zero length BIT STRING"} return } := int([0]) if > 7 || len() == 1 && > 0 || [len()-1]&((1<<[0])-1) != 0 { = asn1.SyntaxError{Msg: "invalid padding bits in BIT STRING"} return } .BitLength = (len()-1)*8 - .Bytes = [1:] return } // OBJECT IDENTIFIER // parseObjectIdentifier parses an OBJECT IDENTIFIER from the given bytes and // returns it. An object identifier is a sequence of variable length integers // that are assigned in a hierarchy. func parseObjectIdentifier( []byte) ( asn1.ObjectIdentifier, error) { if len() == 0 { = asn1.SyntaxError{Msg: "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. = make([]int, len()+1) // The first varint is 40*value1 + value2: // According to this packing, value1 can take the values 0, 1 and 2 only. // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2, // then there are no restrictions on value2. , , := _parseBase128Int(, 0) if != nil { return } if < 80 { [0] = / 40 [1] = % 40 } else { [0] = 2 [1] = - 80 } := 2 for ; < len(); ++ { , , = _parseBase128Int(, ) if != nil { return } [] = } = [0:] return } // parseBase128Int parses a base-128 encoded int from the given offset in the // given byte slice. It returns the value and the new offset. func parseBase128Int( []byte, int) (, int, error) { = var int64 for := 0; < len(); ++ { // 5 * 7 bits per byte == 35 bits of data // Thus the representation is either non-minimal or too large for an int32 if == 5 { = asn1.StructuralError{Msg: "base 128 integer too large"} return } <<= 7 := [] |= int64( & 0x7f) ++ if &0x80 == 0 { = int() // Ensure that the returned value fits in an int on all platforms if > math.MaxInt32 { = asn1.StructuralError{Msg: "base 128 integer too large"} } return } } = asn1.SyntaxError{Msg: "truncated base 128 integer"} return } func _parseBase128Int( []byte, int) (, int, error) { = for := 0; < len(); ++ { <<= 7 := [] |= int( & 0x7f) ++ if &0x80 == 0 { return } } = asn1.SyntaxError{Msg: "truncated base 128 integer"} return } // UTCTime func parseUTCTime( []byte) ( time.Time, error) { := string() := "0601021504Z0700" , = time.Parse(, ) if != nil { = "060102150405Z0700" , = time.Parse(, ) } if != nil { return } if := .Format(); != { = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", , ) return } if .Year() >= 2050 { // UTCTime only encodes times prior to 2050. See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 = .AddDate(-100, 0, 0) } return } // parseGeneralizedTime parses the GeneralizedTime from the given byte slice // and returns the resulting time. func parseGeneralizedTime( []byte) ( time.Time, error) { const = "20060102150405Z0700" := string() if , = time.Parse(, ); != nil { return } if := .Format(); != { = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", , ) } return } // NumericString // parseNumericString parses an ASN.1 NumericString from the given byte array // and returns it. func parseNumericString( []byte) ( string, error) { for , := range { if !isNumeric() { return "", asn1.SyntaxError{Msg: "NumericString contains invalid character"} } } return string(), nil } // isNumeric reports whether the given b is in the ASN.1 NumericString set. func isNumeric( byte) bool { return '0' <= && <= '9' || == ' ' } // PrintableString // parsePrintableString parses an ASN.1 PrintableString from the given byte // array and returns it. func parsePrintableString( []byte) ( string, error) { for , := range { if !isPrintable(, allowAsterisk, allowAmpersand) { = asn1.SyntaxError{Msg: "PrintableString contains invalid character"} return } } = string() return } type asteriskFlag bool type ampersandFlag bool const ( allowAsterisk asteriskFlag = true rejectAsterisk asteriskFlag = false allowAmpersand ampersandFlag = true rejectAmpersand ampersandFlag = false ) // isPrintable reports whether the given b is in the ASN.1 PrintableString set. // If asterisk is allowAsterisk then '*' is also allowed, reflecting existing // practice. If ampersand is allowAmpersand then '&' is allowed as well. func isPrintable( byte, asteriskFlag, ampersandFlag) bool { return 'a' <= && <= 'z' || 'A' <= && <= 'Z' || '0' <= && <= '9' || '\'' <= && <= ')' || '+' <= && <= '/' || == ' ' || == ':' || == '=' || == '?' || // This is technically not allowed in a PrintableString. // However, x509 certificates with wildcard strings don't // always use the correct string type so we permit it. (bool() && == '*') || // This is not technically allowed either. However, not // only is it relatively common, but there are also a // handful of CA certificates that contain it. At least // one of which will not expire until 2027. (bool() && == '&') } // IA5String // parseIA5String parses an ASN.1 IA5String (ASCII string) from the given // byte slice and returns it. func parseIA5String( []byte) ( string, error) { for , := range { if >= utf8.RuneSelf { = asn1.SyntaxError{Msg: "IA5String contains invalid character"} return } } = string() return } // T61String // parseT61String parses an ASN.1 T61String (8-bit clean string) from the given // byte slice and returns it. func parseT61String( []byte) ( string, error) { return string(), nil } // UTF8String // parseUTF8String parses an ASN.1 UTF8String (raw UTF-8) from the given byte // array and returns it. func parseUTF8String( []byte) ( string, error) { if !utf8.Valid() { return "", errors.New("asn1: invalid UTF-8 string") } return string(), nil } // BMPString // parseBMPString parses an ASN.1 BMPString (Basic Multilingual Plane of // ISO/IEC/ITU 10646-1) from the given byte slice and returns it. func parseBMPString( []byte) (string, error) { if len()%2 != 0 { return "", errors.New("pkcs12: odd-length BMP string") } // Strip terminator if present. if := len(); >= 2 && [-1] == 0 && [-2] == 0 { = [:-2] } := make([]uint16, 0, len()/2) for len() > 0 { = append(, uint16([0])<<8+uint16([1])) = [2:] } return string(utf16.Decode()), nil } // Tagging // parseTagAndLength parses an ASN.1 tag and length pair from the given offset // into a byte slice. 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( []byte, int) ( tagAndLength, int, error) { = // parseTagAndLength should not be called without at least a single // byte to read. Thus this check is for robustness: if >= len() { = errors.New("asn1: internal error in parseTagAndLength") return } := [] ++ .class = int( >> 6) .isCompound = &0x20 == 0x20 .tag = int( & 0x1f) // If the bottom five bits are set, then the tag number is actually base 128 // encoded afterwards if .tag == 0x1f { .tag, , = parseBase128Int(, ) if != nil { return } // Tags should be encoded in minimal form. if .tag < 0x1f { = asn1.SyntaxError{Msg: "non-minimal tag"} return } } if >= len() { = asn1.SyntaxError{Msg: "truncated tag or length"} return } = [] ++ if &0x80 == 0 { // The length is encoded in the bottom 7 bits. .length = int( & 0x7f) } else { // Bottom 7 bits give the number of length bytes to follow. := int( & 0x7f) if == 0 { // TODO: Fix this for BER as it should be allowed. Not seen this in // the wild with SNMP devices though. = asn1.SyntaxError{Msg: "indefinite length found (not DER)"} return } .length = 0 for := 0; < ; ++ { if >= len() { = asn1.SyntaxError{Msg: "truncated tag or length"} return } = [] ++ if .length >= 1<<23 { // We can't shift ret.length up without // overflowing. = asn1.StructuralError{Msg: "length too large"} return } .length <<= 8 .length |= int() } } 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 slice and returns them as a // slice of Go values of the given type. func parseSequenceOf( []byte, reflect.Type, reflect.Type) ( reflect.Value, error) { , , , := getUniversalType() if ! { = asn1.StructuralError{Msg: "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. := 0 for := 0; < len(); { var tagAndLength , , = parseTagAndLength(, ) if != nil { return } switch .tag { case tagIA5String, tagGeneralString, tagT61String, tagUTF8String, tagNumericString, tagBMPString: // We pretend that various other string types are // PRINTABLE STRINGs so that a sequence of them can be // parsed into a []string. .tag = tagPrintableString case tagGeneralizedTime, tagUTCTime: // Likewise, both time types are treated the same. .tag = tagUTCTime } if ! && (.class != classUniversal || .isCompound != || .tag != ) { = asn1.StructuralError{Msg: "sequence tag mismatch"} return } if invalidLength(, .length, len()) { = asn1.SyntaxError{Msg: "truncated sequence"} return } += .length ++ } = reflect.MakeSlice(, , ) := fieldParameters{} := 0 for := 0; < ; ++ { , = parseField(.Index(), , , ) if != nil { return } } return } var ( bitStringType = reflect.TypeOf(asn1.BitString{}) objectIdentifierType = reflect.TypeOf(asn1.ObjectIdentifier{}) enumeratedType = reflect.TypeOf(asn1.Enumerated(0)) flagType = reflect.TypeOf(asn1.Flag(false)) timeType = reflect.TypeOf(time.Time{}) rawValueType = reflect.TypeOf(asn1.RawValue{}) rawContentsType = reflect.TypeOf(asn1.RawContent(nil)) bigIntType = reflect.TypeOf(new(big.Int)) ) // invalidLength reports whether offset + length > sliceLength, or if the // addition would overflow. func invalidLength(, , int) bool { return + < || + > } // parseField is the main parsing function. Given a byte slice 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( reflect.Value, []byte, int, fieldParameters) ( int, error) { = := .Type() // If we have run out of data, it may be that there are optional elements at the end. if == len() { if !setDefaultValue(, ) { = asn1.SyntaxError{Msg: "sequence truncated"} } return } // Deal with the ANY type. if := ; .Kind() == reflect.Interface && .NumMethod() == 0 { var tagAndLength , , = parseTagAndLength(, ) if != nil { return } if invalidLength(, .length, len()) { = asn1.SyntaxError{Msg: "data truncated"} return } var interface{} if !.isCompound && .class == classUniversal { := [ : +.length] switch .tag { case tagPrintableString: , = parsePrintableString() case tagNumericString: , = parseNumericString() case tagIA5String: , = parseIA5String() case tagT61String: , = parseT61String() case tagUTF8String: , = parseUTF8String() case tagInteger: , = parseInt64() case tagBitString: , = parseBitString() case tagOID: , = parseObjectIdentifier() case tagUTCTime: , = parseUTCTime() case tagGeneralizedTime: , = parseGeneralizedTime() case tagOctetString: = case tagBMPString: , = parseBMPString() default: // If we don't know how to handle the type, we just leave Value as nil. } } += .length if != nil { return } if != nil { .Set(reflect.ValueOf()) } return } , , := parseTagAndLength(, ) if != nil { return } if .explicit { := classContextSpecific if .application { = classApplication } if == len() { = asn1.StructuralError{Msg: "explicit tag has no child"} return } if .class == && .tag == *.tag && (.length == 0 || .isCompound) { if == rawValueType { // The inner element should not be parsed for RawValues. } else if .length > 0 { , , = parseTagAndLength(, ) if != nil { return } } else { if != flagType { = asn1.StructuralError{Msg: "zero length explicit tag was not an asn1.Flag"} return } .SetBool(true) return } } else { // The tags didn't match, it might be an optional element. := setDefaultValue(, ) if { = } else { = asn1.StructuralError{Msg: "explicitly tagged member didn't match"} } return } } , , , := getUniversalType() if ! { = asn1.StructuralError{Msg: fmt.Sprintf("unknown Go type: %v", )} return } // Special case for strings: all the ASN.1 string types map to the Go // type string. getUniversalType returns the tag for PrintableString // when it sees a string, so if we see a different string type on the // wire, we change the universal type to match. if == tagPrintableString { if .class == classUniversal { switch .tag { case tagIA5String, tagGeneralString, tagT61String, tagUTF8String, tagNumericString, tagBMPString: = .tag } } else if .stringType != 0 { = .stringType } } // Special case for time: UTCTime and GeneralizedTime both map to the // Go type time.Time. if == tagUTCTime && .tag == tagGeneralizedTime && .class == classUniversal { = tagGeneralizedTime } if .set { = tagSet } := := classUniversal := if !.explicit && .tag != nil { = classContextSpecific = *.tag = false } if !.explicit && .application && .tag != nil { = classApplication = *.tag = false } if !.explicit && .private && .tag != nil { = classPrivate = *.tag = false } // We have unwrapped any explicit tagging at this point. if ! && (.class != || .tag != ) || (! && .isCompound != ) { // Tags don't match. Again, it could be an optional element. := setDefaultValue(, ) if { = } else { = asn1.StructuralError{Msg: fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", , , , .Name(), )} } return } if invalidLength(, .length, len()) { = asn1.SyntaxError{Msg: "data truncated"} return } := [ : +.length] += .length // We deal with the structures defined in this package first. switch { case rawValueType: := asn1.RawValue{.class, .tag, .isCompound, , [:]} .Set(reflect.ValueOf()) return case objectIdentifierType: , := parseObjectIdentifier() .Set(reflect.MakeSlice(.Type(), len(), len())) if == nil { reflect.Copy(, reflect.ValueOf()) } = return case bitStringType: , := parseBitString() if == nil { .Set(reflect.ValueOf()) } = return case timeType: var time.Time var error if == tagUTCTime { , = parseUTCTime() } else { , = parseGeneralizedTime() } if == nil { .Set(reflect.ValueOf()) } = return case enumeratedType: , := parseInt32() if == nil { .SetInt(int64()) } = return case flagType: .SetBool(true) return case bigIntType: , := parseBigInt() if == nil { .Set(reflect.ValueOf()) } = return } switch := ; .Kind() { case reflect.Bool: , := parseBool() if == nil { .SetBool() } = return case reflect.Int, reflect.Int32, reflect.Int64: if .Type().Size() == 4 { , := parseInt32() if == nil { .SetInt(int64()) } = } else { , := parseInt64() if == nil { .SetInt() } = } return // TODO(dfc) Add support for the remaining integer types case reflect.Struct: := for := 0; < .NumField(); ++ { if .Field().PkgPath != "" { = asn1.StructuralError{Msg: "struct contains unexported fields"} return } } if .NumField() > 0 && .Field(0).Type == rawContentsType { := [:] .Field(0).Set(reflect.ValueOf(asn1.RawContent())) } := 0 for := 0; < .NumField(); ++ { := .Field() if == 0 && .Type == rawContentsType { continue } , = (.Field(), , , parseFieldParameters(.Tag.Get("asn1"))) if != 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: := if .Elem().Kind() == reflect.Uint8 { .Set(reflect.MakeSlice(, len(), len())) reflect.Copy(, reflect.ValueOf()) return } , := parseSequenceOf(, , .Elem()) if == nil { .Set() } = return case reflect.String: var string switch { case tagPrintableString: , = parsePrintableString() case tagNumericString: , = parseNumericString() case tagIA5String: , = parseIA5String() case tagT61String: , = parseT61String() case tagUTF8String: , = parseUTF8String() 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. , = parseT61String() case tagBMPString: , = parseBMPString() default: = asn1.SyntaxError{Msg: fmt.Sprintf("internal error: unknown string type %d", )} } if == nil { .SetString() } return } = asn1.StructuralError{Msg: "unsupported: " + .Type().String()} return } // canHaveDefaultValue reports whether k is a Kind that we will set a default // value for. (A signed integer, essentially.) func canHaveDefaultValue( reflect.Kind) bool { switch { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return true } return false } // setDefaultValue is used to install a default value, from a tag string, into // a Value. It is successful if the field was optional, even if a default value // wasn't provided or it failed to install it into the Value. func setDefaultValue( reflect.Value, fieldParameters) ( bool) { if !.optional { return } = true if .defaultValue == nil { return } if canHaveDefaultValue(.Kind()) { .SetInt(*.defaultValue) } return } // Unmarshal parses the BER-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, int32, int64, // or *big.Int (from the math/big package). // 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, IA5String, or NumericString 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: // // application specifies that an APPLICATION tag is used // private specifies that a PRIVATE tag is used // default:x sets the default value for optional integer fields (only used if optional is also present) // explicit specifies that an additional, explicit tag wraps the implicit one // optional marks the field as ASN.1 OPTIONAL // set causes a SET, rather than a SEQUENCE type to be expected // tag:x specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC // // 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. // // If the type name of a slice element ends with "SET" then it's treated as if // the "set" tag was set on it. This can be used with nested slices where a // struct tag cannot be given. // // Other ASN.1 types are not supported; if it encounters them, // Unmarshal returns a parse error. func ( []byte, interface{}) ( []byte, error) { return UnmarshalWithParams(, , "") } // 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 ( []byte, interface{}, string) ( []byte, error) { := reflect.ValueOf().Elem() , := parseField(, , 0, parseFieldParameters()) if != nil { return nil, } return [:], nil }