From 1aa571d38b88142ec604ba20c2f9de611ff6413d Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Wed, 6 Jul 2011 16:25:44 -0400 Subject: asn1: support T61 and UTF8 string. There is no end to the kitchen sink of string types in ASN.1. Fixes #1953. R=golang-dev, gri CC=golang-dev https://golang.org/cl/4672045 --- src/pkg/asn1/asn1.go | 45 +++++++++++++++++++++++++++------------------ src/pkg/asn1/common.go | 1 + 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/pkg/asn1/asn1.go b/src/pkg/asn1/asn1.go index 95f299e63d..6557729317 100644 --- a/src/pkg/asn1/asn1.go +++ b/src/pkg/asn1/asn1.go @@ -149,7 +149,7 @@ func (b BitString) RightAlign() []byte { return a } -// parseBitString parses an ASN.1 bit string from the given byte array and returns it. +// parseBitString parses an ASN.1 bit string from the given byte slice and returns it. func parseBitString(bytes []byte) (ret BitString, err os.Error) { if len(bytes) == 0 { err = SyntaxError{"zero length BIT STRING"} @@ -227,7 +227,7 @@ type Enumerated int 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. +// given byte slice. 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++ { @@ -259,7 +259,7 @@ func parseUTCTime(bytes []byte) (ret *time.Time, err os.Error) { return } -// parseGeneralizedTime parses the GeneralizedTime from the given byte array +// parseGeneralizedTime parses the GeneralizedTime from the given byte slice // and returns the resulting time. func parseGeneralizedTime(bytes []byte) (ret *time.Time, err os.Error) { return time.Parse("20060102150405Z0700", string(bytes)) @@ -300,7 +300,7 @@ func isPrintable(b byte) bool { // IA5String // parseIA5String parses a ASN.1 IA5String (ASCII string) from the given -// byte array and returns it. +// byte slice and returns it. func parseIA5String(bytes []byte) (ret string, err os.Error) { for _, b := range bytes { if b >= 0x80 { @@ -315,11 +315,19 @@ func parseIA5String(bytes []byte) (ret string, err os.Error) { // T61String // parseT61String parses a ASN.1 T61String (8-bit clean string) from the given -// byte array and returns it. +// byte slice and returns it. func parseT61String(bytes []byte) (ret string, err os.Error) { return string(bytes), nil } +// UTF8String + +// parseUTF8String parses a ASN.1 UTF8String (raw UTF-8) from the given byte +// array and returns it. +func parseUTF8String(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 @@ -336,7 +344,7 @@ 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 +// 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(bytes []byte, initOffset int) (ret tagAndLength, offset int, err os.Error) { @@ -393,7 +401,7 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i } // 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 +// 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(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err os.Error) { expectedTag, compoundType, ok := getUniversalType(elemType) @@ -456,7 +464,7 @@ 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 +// 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(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err os.Error) { @@ -573,16 +581,15 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam } } - // 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 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 universalTag == tagPrintableString { + switch t.tag { + case tagIA5String, tagGeneralString, tagT61String, tagUTF8String: + universalTag = t.tag + } } // Special case for time: UTCTime and GeneralizedTime both map to the @@ -738,6 +745,8 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam v, err = parseIA5String(innerBytes) case tagT61String: v, err = parseT61String(innerBytes) + case tagUTF8String: + v, err = parseUTF8String(innerBytes) case tagGeneralString: // GeneralString is specified in ISO-2022/ECMA-35, // A brief review suggests that it includes structures diff --git a/src/pkg/asn1/common.go b/src/pkg/asn1/common.go index 854f4da480..01f4f7b6ec 100644 --- a/src/pkg/asn1/common.go +++ b/src/pkg/asn1/common.go @@ -25,6 +25,7 @@ const ( tagOctetString = 4 tagOID = 6 tagEnum = 10 + tagUTF8String = 12 tagSequence = 16 tagSet = 17 tagPrintableString = 19 -- cgit v1.2.3-54-g00ecf