Commit 6dd4e5dd authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

encoding/asn1: export tag and class constants

Fixes #9236

Change-Id: I744d7f071e945ea6e6e50203d931f4678c8b545d
Reviewed-on: https://go-review.googlesource.com/17311Reviewed-by: 's avatarAdam Langley <agl@golang.org>
Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 71d2fa8b
...@@ -530,17 +530,17 @@ func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type ...@@ -530,17 +530,17 @@ func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type
return return
} }
switch t.tag { switch t.tag {
case tagIA5String, tagGeneralString, tagT61String, tagUTF8String: case TagIA5String, TagGeneralString, TagT61String, TagUTF8String:
// We pretend that various other string types are // We pretend that various other string types are
// PRINTABLE STRINGs so that a sequence of them can be // PRINTABLE STRINGs so that a sequence of them can be
// parsed into a []string. // parsed into a []string.
t.tag = tagPrintableString t.tag = TagPrintableString
case tagGeneralizedTime, tagUTCTime: case TagGeneralizedTime, TagUTCTime:
// Likewise, both time types are treated the same. // Likewise, both time types are treated the same.
t.tag = tagUTCTime t.tag = TagUTCTime
} }
if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag { if t.class != ClassUniversal || t.isCompound != compoundType || t.tag != expectedTag {
err = StructuralError{"sequence tag mismatch"} err = StructuralError{"sequence tag mismatch"}
return return
} }
...@@ -624,28 +624,28 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam ...@@ -624,28 +624,28 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
return return
} }
var result interface{} var result interface{}
if !t.isCompound && t.class == classUniversal { if !t.isCompound && t.class == ClassUniversal {
innerBytes := bytes[offset : offset+t.length] innerBytes := bytes[offset : offset+t.length]
switch t.tag { switch t.tag {
case tagPrintableString: case TagPrintableString:
result, err = parsePrintableString(innerBytes) result, err = parsePrintableString(innerBytes)
case tagIA5String: case TagIA5String:
result, err = parseIA5String(innerBytes) result, err = parseIA5String(innerBytes)
case tagT61String: case TagT61String:
result, err = parseT61String(innerBytes) result, err = parseT61String(innerBytes)
case tagUTF8String: case TagUTF8String:
result, err = parseUTF8String(innerBytes) result, err = parseUTF8String(innerBytes)
case tagInteger: case TagInteger:
result, err = parseInt64(innerBytes) result, err = parseInt64(innerBytes)
case tagBitString: case TagBitString:
result, err = parseBitString(innerBytes) result, err = parseBitString(innerBytes)
case tagOID: case TagOID:
result, err = parseObjectIdentifier(innerBytes) result, err = parseObjectIdentifier(innerBytes)
case tagUTCTime: case TagUTCTime:
result, err = parseUTCTime(innerBytes) result, err = parseUTCTime(innerBytes)
case tagGeneralizedTime: case TagGeneralizedTime:
result, err = parseGeneralizedTime(innerBytes) result, err = parseGeneralizedTime(innerBytes)
case tagOctetString: case TagOctetString:
result = innerBytes result = innerBytes
default: default:
// If we don't know how to handle the type, we just leave Value as nil. // If we don't know how to handle the type, we just leave Value as nil.
...@@ -671,9 +671,9 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam ...@@ -671,9 +671,9 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
return return
} }
if params.explicit { if params.explicit {
expectedClass := classContextSpecific expectedClass := ClassContextSpecific
if params.application { if params.application {
expectedClass = classApplication expectedClass = ClassApplication
} }
if offset == len(bytes) { if offset == len(bytes) {
err = StructuralError{"explicit tag has no child"} err = StructuralError{"explicit tag has no child"}
...@@ -709,10 +709,10 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam ...@@ -709,10 +709,10 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
// type string. getUniversalType returns the tag for PrintableString // type string. getUniversalType returns the tag for PrintableString
// when it sees a string, so if we see a different string type on the // when it sees a string, so if we see a different string type on the
// wire, we change the universal type to match. // wire, we change the universal type to match.
if universalTag == tagPrintableString { if universalTag == TagPrintableString {
if t.class == classUniversal { if t.class == ClassUniversal {
switch t.tag { switch t.tag {
case tagIA5String, tagGeneralString, tagT61String, tagUTF8String: case TagIA5String, TagGeneralString, TagT61String, TagUTF8String:
universalTag = t.tag universalTag = t.tag
} }
} else if params.stringType != 0 { } else if params.stringType != 0 {
...@@ -722,24 +722,24 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam ...@@ -722,24 +722,24 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
// Special case for time: UTCTime and GeneralizedTime both map to the // Special case for time: UTCTime and GeneralizedTime both map to the
// Go type time.Time. // Go type time.Time.
if universalTag == tagUTCTime && t.tag == tagGeneralizedTime && t.class == classUniversal { if universalTag == TagUTCTime && t.tag == TagGeneralizedTime && t.class == ClassUniversal {
universalTag = tagGeneralizedTime universalTag = TagGeneralizedTime
} }
if params.set { if params.set {
universalTag = tagSet universalTag = TagSet
} }
expectedClass := classUniversal expectedClass := ClassUniversal
expectedTag := universalTag expectedTag := universalTag
if !params.explicit && params.tag != nil { if !params.explicit && params.tag != nil {
expectedClass = classContextSpecific expectedClass = ClassContextSpecific
expectedTag = *params.tag expectedTag = *params.tag
} }
if !params.explicit && params.application && params.tag != nil { if !params.explicit && params.application && params.tag != nil {
expectedClass = classApplication expectedClass = ClassApplication
expectedTag = *params.tag expectedTag = *params.tag
} }
...@@ -781,7 +781,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam ...@@ -781,7 +781,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
case timeType: case timeType:
var time time.Time var time time.Time
var err1 error var err1 error
if universalTag == tagUTCTime { if universalTag == TagUTCTime {
time, err1 = parseUTCTime(innerBytes) time, err1 = parseUTCTime(innerBytes)
} else { } else {
time, err1 = parseGeneralizedTime(innerBytes) time, err1 = parseGeneralizedTime(innerBytes)
...@@ -873,15 +873,15 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam ...@@ -873,15 +873,15 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
case reflect.String: case reflect.String:
var v string var v string
switch universalTag { switch universalTag {
case tagPrintableString: case TagPrintableString:
v, err = parsePrintableString(innerBytes) v, err = parsePrintableString(innerBytes)
case tagIA5String: case TagIA5String:
v, err = parseIA5String(innerBytes) v, err = parseIA5String(innerBytes)
case tagT61String: case TagT61String:
v, err = parseT61String(innerBytes) v, err = parseT61String(innerBytes)
case tagUTF8String: case TagUTF8String:
v, err = parseUTF8String(innerBytes) v, err = parseUTF8String(innerBytes)
case tagGeneralString: case TagGeneralString:
// GeneralString is specified in ISO-2022/ECMA-35, // GeneralString is specified in ISO-2022/ECMA-35,
// A brief review suggests that it includes structures // A brief review suggests that it includes structures
// that allow the encoding to change midstring and // that allow the encoding to change midstring and
......
...@@ -409,10 +409,10 @@ func newBool(b bool) *bool { return &b } ...@@ -409,10 +409,10 @@ func newBool(b bool) *bool { return &b }
var parseFieldParametersTestData []parseFieldParametersTest = []parseFieldParametersTest{ var parseFieldParametersTestData []parseFieldParametersTest = []parseFieldParametersTest{
{"", fieldParameters{}}, {"", fieldParameters{}},
{"ia5", fieldParameters{stringType: tagIA5String}}, {"ia5", fieldParameters{stringType: TagIA5String}},
{"generalized", fieldParameters{timeType: tagGeneralizedTime}}, {"generalized", fieldParameters{timeType: TagGeneralizedTime}},
{"utc", fieldParameters{timeType: tagUTCTime}}, {"utc", fieldParameters{timeType: TagUTCTime}},
{"printable", fieldParameters{stringType: tagPrintableString}}, {"printable", fieldParameters{stringType: TagPrintableString}},
{"optional", fieldParameters{optional: true}}, {"optional", fieldParameters{optional: true}},
{"explicit", fieldParameters{explicit: true, tag: new(int)}}, {"explicit", fieldParameters{explicit: true, tag: new(int)}},
{"application", fieldParameters{application: true, tag: new(int)}}, {"application", fieldParameters{application: true, tag: new(int)}},
......
...@@ -18,29 +18,31 @@ import ( ...@@ -18,29 +18,31 @@ import (
// Here are some standard tags and classes // Here are some standard tags and classes
// ASN.1 tags represent the type of the following object.
const ( const (
tagBoolean = 1 TagBoolean = 1
tagInteger = 2 TagInteger = 2
tagBitString = 3 TagBitString = 3
tagOctetString = 4 TagOctetString = 4
tagOID = 6 TagOID = 6
tagEnum = 10 TagEnum = 10
tagUTF8String = 12 TagUTF8String = 12
tagSequence = 16 TagSequence = 16
tagSet = 17 TagSet = 17
tagPrintableString = 19 TagPrintableString = 19
tagT61String = 20 TagT61String = 20
tagIA5String = 22 TagIA5String = 22
tagUTCTime = 23 TagUTCTime = 23
tagGeneralizedTime = 24 TagGeneralizedTime = 24
tagGeneralString = 27 TagGeneralString = 27
) )
// ASN.1 class types represent the namespace of the tag.
const ( const (
classUniversal = 0 ClassUniversal = 0
classApplication = 1 ClassApplication = 1
classContextSpecific = 2 ClassContextSpecific = 2
classPrivate = 3 ClassPrivate = 3
) )
type tagAndLength struct { type tagAndLength struct {
...@@ -96,15 +98,15 @@ func parseFieldParameters(str string) (ret fieldParameters) { ...@@ -96,15 +98,15 @@ func parseFieldParameters(str string) (ret fieldParameters) {
ret.tag = new(int) ret.tag = new(int)
} }
case part == "generalized": case part == "generalized":
ret.timeType = tagGeneralizedTime ret.timeType = TagGeneralizedTime
case part == "utc": case part == "utc":
ret.timeType = tagUTCTime ret.timeType = TagUTCTime
case part == "ia5": case part == "ia5":
ret.stringType = tagIA5String ret.stringType = TagIA5String
case part == "printable": case part == "printable":
ret.stringType = tagPrintableString ret.stringType = TagPrintableString
case part == "utf8": case part == "utf8":
ret.stringType = tagUTF8String ret.stringType = TagUTF8String
case strings.HasPrefix(part, "default:"): case strings.HasPrefix(part, "default:"):
i, err := strconv.ParseInt(part[8:], 10, 64) i, err := strconv.ParseInt(part[8:], 10, 64)
if err == nil { if err == nil {
...@@ -136,33 +138,33 @@ func parseFieldParameters(str string) (ret fieldParameters) { ...@@ -136,33 +138,33 @@ func parseFieldParameters(str string) (ret fieldParameters) {
func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) { func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
switch t { switch t {
case objectIdentifierType: case objectIdentifierType:
return tagOID, false, true return TagOID, false, true
case bitStringType: case bitStringType:
return tagBitString, false, true return TagBitString, false, true
case timeType: case timeType:
return tagUTCTime, false, true return TagUTCTime, false, true
case enumeratedType: case enumeratedType:
return tagEnum, false, true return TagEnum, false, true
case bigIntType: case bigIntType:
return tagInteger, false, true return TagInteger, false, true
} }
switch t.Kind() { switch t.Kind() {
case reflect.Bool: case reflect.Bool:
return tagBoolean, false, true return TagBoolean, false, true
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return tagInteger, false, true return TagInteger, false, true
case reflect.Struct: case reflect.Struct:
return tagSequence, true, true return TagSequence, true, true
case reflect.Slice: case reflect.Slice:
if t.Elem().Kind() == reflect.Uint8 { if t.Elem().Kind() == reflect.Uint8 {
return tagOctetString, false, true return TagOctetString, false, true
} }
if strings.HasSuffix(t.Name(), "SET") { if strings.HasSuffix(t.Name(), "SET") {
return tagSet, true, true return TagSet, true, true
} }
return tagSequence, true, true return TagSequence, true, true
case reflect.String: case reflect.String:
return tagPrintableString, false, true return TagPrintableString, false, true
} }
return 0, false, false return 0, false, false
} }
...@@ -414,7 +414,7 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter ...@@ -414,7 +414,7 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
return nil return nil
case timeType: case timeType:
t := value.Interface().(time.Time) t := value.Interface().(time.Time)
if params.timeType == tagGeneralizedTime || outsideUTCRange(t) { if params.timeType == TagGeneralizedTime || outsideUTCRange(t) {
return marshalGeneralizedTime(out, t) return marshalGeneralizedTime(out, t)
} else { } else {
return marshalUTCTime(out, t) return marshalUTCTime(out, t)
...@@ -493,9 +493,9 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter ...@@ -493,9 +493,9 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
return return
case reflect.String: case reflect.String:
switch params.stringType { switch params.stringType {
case tagIA5String: case TagIA5String:
return marshalIA5String(out, v.String()) return marshalIA5String(out, v.String())
case tagPrintableString: case TagPrintableString:
return marshalPrintableString(out, v.String()) return marshalPrintableString(out, v.String())
default: default:
return marshalUTF8String(out, v.String()) return marshalUTF8String(out, v.String())
...@@ -555,18 +555,18 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) ...@@ -555,18 +555,18 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())} err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
return return
} }
class := classUniversal class := ClassUniversal
if params.timeType != 0 && tag != tagUTCTime { if params.timeType != 0 && tag != TagUTCTime {
return StructuralError{"explicit time type given to non-time member"} return StructuralError{"explicit time type given to non-time member"}
} }
if params.stringType != 0 && tag != tagPrintableString { if params.stringType != 0 && tag != TagPrintableString {
return StructuralError{"explicit string type given to non-string member"} return StructuralError{"explicit string type given to non-string member"}
} }
switch tag { switch tag {
case tagPrintableString: case TagPrintableString:
if params.stringType == 0 { if params.stringType == 0 {
// This is a string without an explicit string type. We'll use // This is a string without an explicit string type. We'll use
// a PrintableString if the character set in the string is // a PrintableString if the character set in the string is
...@@ -576,24 +576,24 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) ...@@ -576,24 +576,24 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
if !utf8.ValidString(v.String()) { if !utf8.ValidString(v.String()) {
return errors.New("asn1: string not valid UTF-8") return errors.New("asn1: string not valid UTF-8")
} }
tag = tagUTF8String tag = TagUTF8String
break break
} }
} }
} else { } else {
tag = params.stringType tag = params.stringType
} }
case tagUTCTime: case TagUTCTime:
if params.timeType == tagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) { if params.timeType == TagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) {
tag = tagGeneralizedTime tag = TagGeneralizedTime
} }
} }
if params.set { if params.set {
if tag != tagSequence { if tag != TagSequence {
return StructuralError{"non sequence tagged as set"} return StructuralError{"non sequence tagged as set"}
} }
tag = tagSet tag = TagSet
} }
tags, body := out.fork() tags, body := out.fork()
...@@ -613,7 +613,7 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) ...@@ -613,7 +613,7 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
if !params.explicit && params.tag != nil { if !params.explicit && params.tag != nil {
// implicit tag. // implicit tag.
tag = *params.tag tag = *params.tag
class = classContextSpecific class = ClassContextSpecific
} }
err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound}) err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound})
...@@ -623,7 +623,7 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) ...@@ -623,7 +623,7 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
if params.explicit { if params.explicit {
err = marshalTagAndLength(explicitTag, tagAndLength{ err = marshalTagAndLength(explicitTag, tagAndLength{
class: classContextSpecific, class: ClassContextSpecific,
tag: *params.tag, tag: *params.tag,
length: bodyLen + tags.Len(), length: bodyLen + tags.Len(),
isCompound: true, isCompound: true,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment