From 8a079b0f104467ae795de8df6e7da4a5ce6f0c9b Mon Sep 17 00:00:00 2001 From: InfiniteLoopSpace <35842605+InfiniteLoopSpace@users.noreply.github.com> Date: Wed, 14 Nov 2018 13:12:15 +0100 Subject: [PATCH] Use exported types from "encoding/asn1" to retain compatibility. --- asn1/asn1.go | 236 +++++++++++++++++++++---------------------- asn1/asn1_test.go | 111 ++++++++++---------- asn1/marshal.go | 35 +++---- asn1/marshal_test.go | 27 ++--- 4 files changed, 206 insertions(+), 203 deletions(-) diff --git a/asn1/asn1.go b/asn1/asn1.go index cade975..a027e11 100644 --- a/asn1/asn1.go +++ b/asn1/asn1.go @@ -20,31 +20,31 @@ package asn1 // everything by any means. import ( + "encoding/asn1" "errors" "fmt" "log" "math" "math/big" "reflect" - "strconv" "time" "unicode/utf8" ) // 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 -} +//type StructuralError struct { +// Msg string +//} -func (e StructuralError) Error() string { return "asn1: structure error: " + e.Msg } +//func (e StructuralError) Error() string { return "asn1: structure error: " + e.Msg } // A SyntaxError suggests that the ASN.1 data is invalid. -type SyntaxError struct { - Msg string -} +//type SyntaxError struct { +// Msg string +//} -func (e SyntaxError) Error() string { return "asn1: syntax error: " + e.Msg } +//func (e SyntaxError) Error() string { return "asn1: syntax error: " + e.Msg } // We start by dealing with each of the primitive types in turn. @@ -52,7 +52,7 @@ func (e SyntaxError) Error() string { return "asn1: syntax error: " + e.Msg } func parseBool(bytes []byte) (ret bool, err error) { if len(bytes) != 1 { - err = SyntaxError{"invalid boolean"} + err = asn1.SyntaxError{"invalid boolean"} return } @@ -65,7 +65,7 @@ func parseBool(bytes []byte) (ret bool, err error) { case 0xff: ret = true default: - err = SyntaxError{"invalid boolean"} + err = asn1.SyntaxError{"invalid boolean"} } return @@ -77,13 +77,13 @@ func parseBool(bytes []byte) (ret bool, err error) { // INTEGER and an error otherwise. func checkInteger(bytes []byte) error { if len(bytes) == 0 { - return StructuralError{"empty integer"} + return asn1.StructuralError{"empty integer"} } if len(bytes) == 1 { return nil } if (bytes[0] == 0 && bytes[1]&0x80 == 0) || (bytes[0] == 0xff && bytes[1]&0x80 == 0x80) { - return StructuralError{"integer not minimally-encoded"} + return asn1.StructuralError{"integer not minimally-encoded"} } return nil } @@ -97,7 +97,7 @@ func parseInt64(bytes []byte) (ret int64, err error) { } if len(bytes) > 8 { // We'll overflow an int64 in this case. - err = StructuralError{"integer too large"} + err = asn1.StructuralError{"integer too large"} return } for bytesRead := 0; bytesRead < len(bytes); bytesRead++ { @@ -122,7 +122,7 @@ func parseInt32(bytes []byte) (int32, error) { return 0, err } if ret64 != int64(int32(ret64)) { - return 0, StructuralError{"integer too large"} + return 0, asn1.StructuralError{"integer too large"} } return int32(ret64), nil } @@ -156,51 +156,51 @@ func parseBigInt(bytes []byte) (*big.Int, error) { // 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. -} +//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 -} +//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 -} +//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 slice and returns it. -func parseBitString(bytes []byte) (ret BitString, err error) { +func parseBitString(bytes []byte) (ret asn1.BitString, err error) { if len(bytes) == 0 { - err = SyntaxError{"zero length BIT STRING"} + err = asn1.SyntaxError{"zero length BIT STRING"} return } paddingBits := int(bytes[0]) if paddingBits > 7 || len(bytes) == 1 && paddingBits > 0 || bytes[len(bytes)-1]&((1< 0 { - s += "." - } - s += strconv.Itoa(v) - } - - return s -} +//func (oi ObjectIdentifier) String() string { +// var s string +// +// for i, v := range oi { +// if i > 0 { +// s += "." +// } +// s += strconv.Itoa(v) +// } +// +// return s +//} // 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(bytes []byte) (s ObjectIdentifier, err error) { +func parseObjectIdentifier(bytes []byte) (s asn1.ObjectIdentifier, err error) { if len(bytes) == 0 { - err = SyntaxError{"zero length OBJECT IDENTIFIER"} + err = asn1.SyntaxError{"zero length OBJECT IDENTIFIER"} return } @@ -292,12 +292,12 @@ func parseObjectIdentifier(bytes []byte) (s ObjectIdentifier, err error) { // ENUMERATED // An Enumerated is represented as a plain int. -type Enumerated int +//type Enumerated int // FLAG // A Flag accepts any data and is set to true if present. -type Flag bool +//type Flag bool // parseBase128Int parses a base-128 encoded int from the given offset in the // given byte slice. It returns the value and the new offset. @@ -308,7 +308,7 @@ func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) // 5 * 7 bits per byte == 35 bits of data // Thus the representation is either non-minimal or too large for an int32 if shifted == 5 { - err = StructuralError{"base 128 integer too large"} + err = asn1.StructuralError{"base 128 integer too large"} return } ret64 <<= 7 @@ -319,12 +319,12 @@ func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) ret = int(ret64) // Ensure that the returned value fits in an int on all platforms if ret64 > math.MaxInt32 { - err = StructuralError{"base 128 integer too large"} + err = asn1.StructuralError{"base 128 integer too large"} } return } } - err = SyntaxError{"truncated base 128 integer"} + err = asn1.SyntaxError{"truncated base 128 integer"} return } @@ -380,7 +380,7 @@ func parseGeneralizedTime(bytes []byte) (ret time.Time, err error) { func parseNumericString(bytes []byte) (ret string, err error) { for _, b := range bytes { if !isNumeric(b) { - return "", SyntaxError{"NumericString contains invalid character"} + return "", asn1.SyntaxError{"NumericString contains invalid character"} } } return string(bytes), nil @@ -399,7 +399,7 @@ func isNumeric(b byte) bool { func parsePrintableString(bytes []byte) (ret string, err error) { for _, b := range bytes { if !isPrintable(b, allowAsterisk, allowAmpersand) { - err = SyntaxError{"PrintableString contains invalid character"} + err = asn1.SyntaxError{"PrintableString contains invalid character"} return } } @@ -449,7 +449,7 @@ func isPrintable(b byte, asterisk asteriskFlag, ampersand ampersandFlag) bool { func parseIA5String(bytes []byte) (ret string, err error) { for _, b := range bytes { if b >= utf8.RuneSelf { - err = SyntaxError{"IA5String contains invalid character"} + err = asn1.SyntaxError{"IA5String contains invalid character"} return } } @@ -477,17 +477,17 @@ func parseUTF8String(bytes []byte) (ret string, err error) { } // 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 -} +//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 +//type RawContent []byte // Tagging @@ -518,12 +518,12 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i } // Tags should be encoded in minimal form. if ret.tag < 0x1f { - err = SyntaxError{"non-minimal tag"} + err = asn1.SyntaxError{"non-minimal tag"} return } } if offset >= len(bytes) { - err = SyntaxError{"truncated tag or length"} + err = asn1.SyntaxError{"truncated tag or length"} return } b = bytes[offset] @@ -563,13 +563,13 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i } log.Println("indefinite length found (not DER)") } - err = SyntaxError{"indefinite length found (not DER)"} + err = asn1.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"} + err = asn1.SyntaxError{"truncated tag or length"} return } b = bytes[offset] @@ -577,20 +577,20 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i if ret.length >= 1<<23 { // We can't shift ret.length up without // overflowing. - err = StructuralError{"length too large"} + err = asn1.StructuralError{"length too large"} return } ret.length <<= 8 ret.length |= int(b) if ret.length == 0 { // DER requires that lengths be minimal. - err = StructuralError{"superfluous leading zeros in length"} + err = asn1.StructuralError{"superfluous leading zeros in length"} return } } // Short lengths must be encoded in short form. if ret.length < 0x80 { - err = StructuralError{"non-minimal length"} + err = asn1.StructuralError{"non-minimal length"} return } } @@ -604,7 +604,7 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type, params fieldParameters) (ret reflect.Value, err error) { matchAny, expectedTag, compoundType, ok := getUniversalType(elemType) if !ok { - err = StructuralError{"unknown Go type for slice"} + err = asn1.StructuralError{"unknown Go type for slice"} return } @@ -629,11 +629,11 @@ func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type } if !matchAny && (t.class != ClassUniversal || t.isCompound != compoundType || t.tag != expectedTag) && !params.choice { - err = StructuralError{"sequence tag mismatch"} + err = asn1.StructuralError{"sequence tag mismatch"} return } if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"truncated sequence"} + err = asn1.SyntaxError{"truncated sequence"} return } offset += t.length @@ -652,13 +652,13 @@ func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type } var ( - bitStringType = reflect.TypeOf(BitString{}) - objectIdentifierType = reflect.TypeOf(ObjectIdentifier{}) - enumeratedType = reflect.TypeOf(Enumerated(0)) - flagType = reflect.TypeOf(Flag(false)) + 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(RawValue{}) - rawContentsType = reflect.TypeOf(RawContent(nil)) + rawValueType = reflect.TypeOf(asn1.RawValue{}) + rawContentsType = reflect.TypeOf(asn1.RawContent(nil)) bigIntType = reflect.TypeOf(new(big.Int)) ) @@ -678,7 +678,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam // 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"} + err = asn1.SyntaxError{"sequence truncated"} } return } @@ -691,7 +691,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam return } if invalidLength(offset, t.length, len(bytes)) { - err = SyntaxError{"data truncated"} + err = asn1.SyntaxError{"data truncated"} return } var result interface{} @@ -744,7 +744,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam expectedClass = ClassApplication } if offset == len(bytes) { - err = StructuralError{"explicit tag has no child"} + err = asn1.StructuralError{"explicit tag has no child"} return } if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) { @@ -757,7 +757,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam } } else { if fieldType != flagType { - err = StructuralError{"zero length explicit tag was not an asn1.Flag"} + err = asn1.StructuralError{"zero length explicit tag was not an asn1.Flag"} return } v.SetBool(true) @@ -769,7 +769,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam if ok { offset = initOffset } else { - err = StructuralError{"explicitly tagged member didn't match"} + err = asn1.StructuralError{"explicitly tagged member didn't match"} } return } @@ -777,7 +777,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam matchAny, universalTag, compoundType, ok1 := getUniversalType(fieldType) if !ok1 { - err = StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)} + err = asn1.StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)} return } @@ -836,12 +836,12 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam 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)} + err = asn1.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"} + err = asn1.SyntaxError{"data truncated"} return } innerBytes := bytes[offset : offset+t.length] @@ -850,7 +850,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam // We deal with the structures defined in this package first. switch fieldType { case rawValueType: - result := RawValue{t.class, t.tag, t.isCompound, innerBytes, bytes[initOffset:offset]} + result := asn1.RawValue{t.class, t.tag, t.isCompound, innerBytes, bytes[initOffset:offset]} v.Set(reflect.ValueOf(result)) return case objectIdentifierType: @@ -928,7 +928,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam for i := 0; i < structType.NumField(); i++ { if structType.Field(i).PkgPath != "" { - err = StructuralError{"struct contains unexported fields"} + err = asn1.StructuralError{"struct contains unexported fields"} return } } @@ -936,7 +936,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam if structType.NumField() > 0 && structType.Field(0).Type == rawContentsType { bytes := bytes[initOffset:offset] - val.Field(0).Set(reflect.ValueOf(RawContent(bytes))) + val.Field(0).Set(reflect.ValueOf(asn1.RawContent(bytes))) } innerOffset := 0 @@ -998,14 +998,14 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam // 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)} + err = asn1.SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)} } if err == nil { val.SetString(v) } return } - err = StructuralError{"unsupported: " + v.Type().String()} + err = asn1.StructuralError{"unsupported: " + v.Type().String()} return } diff --git a/asn1/asn1_test.go b/asn1/asn1_test.go index f0a54e0..6dbc83b 100644 --- a/asn1/asn1_test.go +++ b/asn1/asn1_test.go @@ -6,6 +6,7 @@ package asn1 import ( "bytes" + "encoding/asn1" "fmt" "math" "math/big" @@ -178,7 +179,7 @@ func TestBitString(t *testing.T) { } func TestBitStringAt(t *testing.T) { - bs := BitString{[]byte{0x82, 0x40}, 16} + bs := asn1.BitString{[]byte{0x82, 0x40}, 16} if bs.At(0) != 1 { t.Error("#1: Failed") } @@ -216,7 +217,7 @@ var bitStringRightAlignTests = []bitStringRightAlignTest{ func TestBitStringRightAlign(t *testing.T) { for i, test := range bitStringRightAlignTests { - bs := BitString{test.in, test.inlen} + bs := asn1.BitString{test.in, test.inlen} out := bs.RightAlign() if !bytes.Equal(out, test.out) { t.Errorf("#%d got: %x want: %x", i, out, test.out) @@ -227,7 +228,7 @@ func TestBitStringRightAlign(t *testing.T) { type objectIdentifierTest struct { in []byte ok bool - out ObjectIdentifier // has base type[]int + out asn1.ObjectIdentifier // has base type[]int } var objectIdentifierTestData = []objectIdentifierTest{ @@ -252,7 +253,7 @@ func TestObjectIdentifier(t *testing.T) { } } - if s := ObjectIdentifier([]int{1, 2, 3, 4}).String(); s != "1.2.3.4" { + if s := asn1.ObjectIdentifier([]int{1, 2, 3, 4}).String(); s != "1.2.3.4" { t.Errorf("bad ObjectIdentifier.String(). Got %s, want 1.2.3.4", s) } } @@ -447,7 +448,7 @@ func TestParseFieldParameters(t *testing.T) { } type TestObjectIdentifierStruct struct { - OID ObjectIdentifier + OID asn1.ObjectIdentifier } type TestContextSpecificTags struct { @@ -481,17 +482,17 @@ var unmarshalTestData = []struct { out interface{} }{ {[]byte{0x02, 0x01, 0x42}, newInt(0x42)}, - {[]byte{0x05, 0x00}, &RawValue{0, 5, false, []byte{}, []byte{0x05, 0x00}}}, + {[]byte{0x05, 0x00}, &asn1.RawValue{0, 5, false, []byte{}, []byte{0x05, 0x00}}}, {[]byte{0x30, 0x08, 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d}, &TestObjectIdentifierStruct{[]int{1, 2, 840, 113549}}}, - {[]byte{0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0}, &BitString{[]byte{110, 93, 192}, 18}}, + {[]byte{0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0}, &asn1.BitString{[]byte{110, 93, 192}, 18}}, {[]byte{0x30, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &[]int{1, 2, 3}}, {[]byte{0x02, 0x01, 0x10}, newInt(16)}, {[]byte{0x13, 0x04, 't', 'e', 's', 't'}, newString("test")}, {[]byte{0x16, 0x04, 't', 'e', 's', 't'}, newString("test")}, // Ampersand is allowed in PrintableString due to mistakes by major CAs. {[]byte{0x13, 0x05, 't', 'e', 's', 't', '&'}, newString("test&")}, - {[]byte{0x16, 0x04, 't', 'e', 's', 't'}, &RawValue{0, 22, false, []byte("test"), []byte("\x16\x04test")}}, - {[]byte{0x04, 0x04, 1, 2, 3, 4}, &RawValue{0, 4, false, []byte{1, 2, 3, 4}, []byte{4, 4, 1, 2, 3, 4}}}, + {[]byte{0x16, 0x04, 't', 'e', 's', 't'}, &asn1.RawValue{0, 22, false, []byte("test"), []byte("\x16\x04test")}}, + {[]byte{0x04, 0x04, 1, 2, 3, 4}, &asn1.RawValue{0, 4, false, []byte{1, 2, 3, 4}, []byte{4, 4, 1, 2, 3, 4}}}, {[]byte{0x30, 0x03, 0x81, 0x01, 0x01}, &TestContextSpecificTags{1}}, {[]byte{0x30, 0x08, 0xa1, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}, &TestContextSpecificTags2{1, 2}}, {[]byte{0x30, 0x03, 0x81, 0x01, '@'}, &TestContextSpecificTags3{"@"}}, @@ -520,12 +521,12 @@ func TestUnmarshal(t *testing.T) { type Certificate struct { TBSCertificate TBSCertificate SignatureAlgorithm AlgorithmIdentifier - SignatureValue BitString + SignatureValue asn1.BitString } type TBSCertificate struct { Version int `asn1:"optional,explicit,default:0,tag:0"` - SerialNumber RawValue + SerialNumber asn1.RawValue SignatureAlgorithm AlgorithmIdentifier Issuer RDNSequence Validity Validity @@ -534,7 +535,7 @@ type TBSCertificate struct { } type AlgorithmIdentifier struct { - Algorithm ObjectIdentifier + Algorithm asn1.ObjectIdentifier } type RDNSequence []RelativeDistinguishedNameSET @@ -542,7 +543,7 @@ type RDNSequence []RelativeDistinguishedNameSET type RelativeDistinguishedNameSET []AttributeTypeAndValue type AttributeTypeAndValue struct { - Type ObjectIdentifier + Type asn1.ObjectIdentifier Value interface{} } @@ -552,7 +553,7 @@ type Validity struct { type PublicKeyInfo struct { Algorithm AlgorithmIdentifier - PublicKey BitString + PublicKey asn1.BitString } func TestCertificate(t *testing.T) { @@ -577,7 +578,7 @@ func TestCertificateWithNUL(t *testing.T) { } type rawStructTest struct { - Raw RawContent + Raw asn1.RawContent A int } @@ -603,25 +604,25 @@ func TestRawStructs(t *testing.T) { } type oiEqualTest struct { - first ObjectIdentifier - second ObjectIdentifier + first asn1.ObjectIdentifier + second asn1.ObjectIdentifier same bool } var oiEqualTests = []oiEqualTest{ { - ObjectIdentifier{1, 2, 3}, - ObjectIdentifier{1, 2, 3}, + asn1.ObjectIdentifier{1, 2, 3}, + asn1.ObjectIdentifier{1, 2, 3}, true, }, { - ObjectIdentifier{1}, - ObjectIdentifier{1, 2, 3}, + asn1.ObjectIdentifier{1}, + asn1.ObjectIdentifier{1, 2, 3}, false, }, { - ObjectIdentifier{1, 2, 3}, - ObjectIdentifier{10, 11, 12}, + asn1.ObjectIdentifier{1, 2, 3}, + asn1.ObjectIdentifier{10, 11, 12}, false, }, } @@ -637,31 +638,31 @@ func TestObjectIdentifierEqual(t *testing.T) { var derEncodedSelfSignedCert = Certificate{ TBSCertificate: TBSCertificate{ Version: 0, - SerialNumber: RawValue{Class: 0, Tag: 2, IsCompound: false, Bytes: []uint8{0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}, FullBytes: []byte{2, 9, 0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}}, - SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}}, + SerialNumber: asn1.RawValue{Class: 0, Tag: 2, IsCompound: false, Bytes: []uint8{0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}, FullBytes: []byte{2, 9, 0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}}, + SignatureAlgorithm: AlgorithmIdentifier{Algorithm: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}}, Issuer: RDNSequence{ - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: asn1.ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: asn1.ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: asn1.ObjectIdentifier{2, 5, 4, 7}, Value: "City"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: asn1.ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: asn1.ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}}, }, Validity: Validity{ NotBefore: time.Date(2009, 10, 8, 00, 25, 53, 0, time.UTC), NotAfter: time.Date(2010, 10, 8, 00, 25, 53, 0, time.UTC), }, Subject: RDNSequence{ - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}}, - RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: asn1.ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: asn1.ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: asn1.ObjectIdentifier{2, 5, 4, 7}, Value: "City"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: asn1.ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: asn1.ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}}, + RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}}, }, PublicKey: PublicKeyInfo{ - Algorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}}, - PublicKey: BitString{ + Algorithm: AlgorithmIdentifier{Algorithm: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}}, + PublicKey: asn1.BitString{ Bytes: []uint8{ 0x30, 0x48, 0x2, 0x41, 0x0, 0xcd, 0xb7, 0x63, 0x9c, 0x32, 0x78, 0xf0, 0x6, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42, @@ -675,8 +676,8 @@ var derEncodedSelfSignedCert = Certificate{ }, }, }, - SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}}, - SignatureValue: BitString{ + SignatureAlgorithm: AlgorithmIdentifier{Algorithm: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}}, + SignatureValue: asn1.BitString{ Bytes: []uint8{ 0xa6, 0x7b, 0x6, 0xec, 0x5e, 0xce, 0x92, 0x77, 0x2c, 0xa4, 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c, @@ -996,7 +997,7 @@ type exported struct { } func TestUnexportedStructField(t *testing.T) { - want := StructuralError{"struct contains unexported fields"} + want := asn1.StructuralError{"struct contains unexported fields"} _, err := Marshal(unexported{X: 5, y: 1}) if err != want { @@ -1015,34 +1016,34 @@ func TestUnexportedStructField(t *testing.T) { } func TestNull(t *testing.T) { - marshaled, err := Marshal(NullRawValue) + marshaled, err := Marshal(asn1.NullRawValue) if err != nil { t.Fatal(err) } - if !bytes.Equal(NullBytes, marshaled) { - t.Errorf("Expected Marshal of NullRawValue to yield %x, got %x", NullBytes, marshaled) + if !bytes.Equal(asn1.NullBytes, marshaled) { + t.Errorf("Expected Marshal of NullRawValue to yield %x, got %x", asn1.NullBytes, marshaled) } - unmarshaled := RawValue{} - if _, err := Unmarshal(NullBytes, &unmarshaled); err != nil { + unmarshaled := asn1.RawValue{} + if _, err := Unmarshal(asn1.NullBytes, &unmarshaled); err != nil { t.Fatal(err) } - unmarshaled.FullBytes = NullRawValue.FullBytes + unmarshaled.FullBytes = asn1.NullRawValue.FullBytes if len(unmarshaled.Bytes) == 0 { // DeepEqual considers a nil slice and an empty slice to be different. - unmarshaled.Bytes = NullRawValue.Bytes + unmarshaled.Bytes = asn1.NullRawValue.Bytes } - if !reflect.DeepEqual(NullRawValue, unmarshaled) { - t.Errorf("Expected Unmarshal of NullBytes to yield %v, got %v", NullRawValue, unmarshaled) + if !reflect.DeepEqual(asn1.NullRawValue, unmarshaled) { + t.Errorf("Expected Unmarshal of NullBytes to yield %v, got %v", asn1.NullRawValue, unmarshaled) } } func TestExplicitTagRawValueStruct(t *testing.T) { type foo struct { - A RawValue `asn1:"optional,explicit,tag:5"` - B []byte `asn1:"optional,explicit,tag:6"` + A asn1.RawValue `asn1:"optional,explicit,tag:5"` + B []byte `asn1:"optional,explicit,tag:6"` } before := foo{B: []byte{1, 2, 3}} derBytes, err := Marshal(before) @@ -1064,10 +1065,10 @@ func TestExplicitTagRawValueStruct(t *testing.T) { func TestTaggedRawValue(t *testing.T) { type taggedRawValue struct { - A RawValue `asn1:"tag:5"` + A asn1.RawValue `asn1:"tag:5"` } type untaggedRawValue struct { - A RawValue + A asn1.RawValue } const isCompound = 0x20 const tag = 5 diff --git a/asn1/marshal.go b/asn1/marshal.go index 1f15548..e396706 100644 --- a/asn1/marshal.go +++ b/asn1/marshal.go @@ -5,6 +5,7 @@ package asn1 import ( + "encoding/asn1" "errors" "fmt" "math/big" @@ -152,7 +153,7 @@ func appendBase128Int(dst []byte, n int64) []byte { func makeBigInt(n *big.Int) (encoder, error) { if n == nil { - return nil, StructuralError{"empty integer"} + return nil, asn1.StructuralError{"empty integer"} } if n.Sign() < 0 { @@ -228,7 +229,7 @@ func appendTagAndLength(dst []byte, t tagAndLength) []byte { return dst } -type bitStringEncoder BitString +type bitStringEncoder asn1.BitString func (b bitStringEncoder) Len() int { return len(b.Bytes) + 1 @@ -260,7 +261,7 @@ func (oid oidEncoder) Encode(dst []byte) { func makeObjectIdentifier(oid []int) (e encoder, err error) { if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) { - return nil, StructuralError{"invalid object identifier"} + return nil, asn1.StructuralError{"invalid object identifier"} } return oidEncoder(oid), nil @@ -275,7 +276,7 @@ func makePrintableString(s string) (e encoder, err error) { // certificates, however when making new certificates // it is rejected. if !isPrintable(s[i], allowAsterisk, rejectAmpersand) { - return nil, StructuralError{"PrintableString contains invalid character"} + return nil, asn1.StructuralError{"PrintableString contains invalid character"} } } @@ -285,7 +286,7 @@ func makePrintableString(s string) (e encoder, err error) { func makeIA5String(s string) (e encoder, err error) { for i := 0; i < len(s); i++ { if s[i] > 127 { - return nil, StructuralError{"IA5String contains invalid character"} + return nil, asn1.StructuralError{"IA5String contains invalid character"} } } @@ -295,7 +296,7 @@ func makeIA5String(s string) (e encoder, err error) { func makeNumericString(s string) (e encoder, err error) { for i := 0; i < len(s); i++ { if !isNumeric(s[i]) { - return nil, StructuralError{"NumericString contains invalid character"} + return nil, asn1.StructuralError{"NumericString contains invalid character"} } } @@ -355,7 +356,7 @@ func appendUTCTime(dst []byte, t time.Time) (ret []byte, err error) { case 2000 <= year && year < 2050: dst = appendTwoDigits(dst, year-2000) default: - return nil, StructuralError{"cannot represent time as UTCTime"} + return nil, asn1.StructuralError{"cannot represent time as UTCTime"} } return appendTimeCommon(dst, t), nil @@ -364,7 +365,7 @@ func appendUTCTime(dst []byte, t time.Time) (ret []byte, err error) { func appendGeneralizedTime(dst []byte, t time.Time) (ret []byte, err error) { year := t.Year() if year < 0 || year > 9999 { - return nil, StructuralError{"cannot represent time as GeneralizedTime"} + return nil, asn1.StructuralError{"cannot represent time as GeneralizedTime"} } dst = appendFourDigits(dst, year) @@ -425,9 +426,9 @@ func makeBody(value reflect.Value, params fieldParameters) (e encoder, err error } return makeUTCTime(t) case bitStringType: - return bitStringEncoder(value.Interface().(BitString)), nil + return bitStringEncoder(value.Interface().(asn1.BitString)), nil case objectIdentifierType: - return makeObjectIdentifier(value.Interface().(ObjectIdentifier)) + return makeObjectIdentifier(value.Interface().(asn1.ObjectIdentifier)) case bigIntType: return makeBigInt(value.Interface().(*big.Int)) } @@ -445,7 +446,7 @@ func makeBody(value reflect.Value, params fieldParameters) (e encoder, err error for i := 0; i < t.NumField(); i++ { if t.Field(i).PkgPath != "" { - return nil, StructuralError{"struct contains unexported fields"} + return nil, asn1.StructuralError{"struct contains unexported fields"} } } @@ -534,7 +535,7 @@ func makeBody(value reflect.Value, params fieldParameters) (e encoder, err error } } - return nil, StructuralError{"unknown Go type"} + return nil, asn1.StructuralError{"unknown Go type"} } func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) { @@ -569,7 +570,7 @@ func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) { } if v.Type() == rawValueType { - rv := v.Interface().(RawValue) + rv := v.Interface().(asn1.RawValue) if len(rv.FullBytes) != 0 { return bytesEncoder(rv.FullBytes), nil } @@ -584,15 +585,15 @@ func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) { matchAny, tag, isCompound, ok := getUniversalType(v.Type()) if !ok || matchAny { - return nil, StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())} + return nil, asn1.StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())} } if params.timeType != 0 && tag != TagUTCTime { - return nil, StructuralError{"explicit time type given to non-time member"} + return nil, asn1.StructuralError{"explicit time type given to non-time member"} } if params.stringType != 0 && tag != TagPrintableString { - return nil, StructuralError{"explicit string type given to non-string member"} + return nil, asn1.StructuralError{"explicit string type given to non-string member"} } switch tag { @@ -621,7 +622,7 @@ func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) { if params.set { if tag != TagSequence { - return nil, StructuralError{"non sequence tagged as set"} + return nil, asn1.StructuralError{"non sequence tagged as set"} } tag = TagSet } diff --git a/asn1/marshal_test.go b/asn1/marshal_test.go index a77826a..b64a090 100644 --- a/asn1/marshal_test.go +++ b/asn1/marshal_test.go @@ -6,6 +6,7 @@ package asn1 import ( "bytes" + "encoding/asn1" "encoding/hex" "math/big" "reflect" @@ -32,7 +33,7 @@ type nestedStruct struct { } type rawContentsStruct struct { - Raw RawContent + Raw asn1.RawContent A int } @@ -45,7 +46,7 @@ type explicitTagTest struct { } type flagTest struct { - A Flag `asn1:"tag:0,optional"` + A asn1.Flag `asn1:"tag:0,optional"` } type generalizedTimeTest struct { @@ -65,7 +66,7 @@ type genericStringTest struct { } type optionalRawValueTest struct { - A RawValue `asn1:"optional"` + A asn1.RawValue `asn1:"optional"` } type omitEmptyTest struct { @@ -129,11 +130,11 @@ var marshalTests = []marshalTest{ {time.Unix(1258325776, 0).In(PST), "17113039313131353134353631362d30383030"}, {farFuture(), "180f32313030303430353132303130315a"}, {generalizedTimeTest{time.Unix(1258325776, 0).UTC()}, "3011180f32303039313131353232353631365a"}, - {BitString{[]byte{0x80}, 1}, "03020780"}, - {BitString{[]byte{0x81, 0xf0}, 12}, "03030481f0"}, - {ObjectIdentifier([]int{1, 2, 3, 4}), "06032a0304"}, - {ObjectIdentifier([]int{1, 2, 840, 133549, 1, 1, 5}), "06092a864888932d010105"}, - {ObjectIdentifier([]int{2, 100, 3}), "0603813403"}, + {asn1.BitString{[]byte{0x80}, 1}, "03020780"}, + {asn1.BitString{[]byte{0x81, 0xf0}, 12}, "03030481f0"}, + {asn1.ObjectIdentifier([]int{1, 2, 3, 4}), "06032a0304"}, + {asn1.ObjectIdentifier([]int{1, 2, 840, 133549, 1, 1, 5}), "06092a864888932d010105"}, + {asn1.ObjectIdentifier([]int{2, 100, 3}), "0603813403"}, {"test", "130474657374"}, { "" + @@ -168,7 +169,7 @@ var marshalTests = []marshalTest{ {genericStringTest{"test&"}, "30070c057465737426"}, {rawContentsStruct{nil, 64}, "3003020140"}, {rawContentsStruct{[]byte{0x30, 3, 1, 2, 3}, 64}, "3003010203"}, - {RawValue{Tag: 1, Class: 2, IsCompound: false, Bytes: []byte{1, 2, 3}}, "8103010203"}, + {asn1.RawValue{Tag: 1, Class: 2, IsCompound: false, Bytes: []byte{1, 2, 3}}, "8103010203"}, {testSET([]int{10}), "310302010a"}, {omitEmptyTest{[]string{}}, "3000"}, {omitEmptyTest{[]string{"1"}}, "30053003130131"}, @@ -258,9 +259,9 @@ func TestMarshalOID(t *testing.T) { var marshalTestsOID = []marshalTest{ {[]byte("\x06\x01\x30"), "0403060130"}, // bytes format returns a byte sequence \x04 // {ObjectIdentifier([]int{0}), "060100"}, // returns an error as OID 0.0 has the same encoding - {[]byte("\x06\x010"), "0403060130"}, // same as above "\x06\x010" = "\x06\x01" + "0" - {ObjectIdentifier([]int{2, 999, 3}), "0603883703"}, // Example of ITU-T X.690 - {ObjectIdentifier([]int{0, 0}), "060100"}, // zero OID + {[]byte("\x06\x010"), "0403060130"}, // same as above "\x06\x010" = "\x06\x01" + "0" + {asn1.ObjectIdentifier([]int{2, 999, 3}), "0603883703"}, // Example of ITU-T X.690 + {asn1.ObjectIdentifier([]int{0, 0}), "060100"}, // zero OID } for i, test := range marshalTestsOID { data, err := Marshal(test.in) @@ -283,7 +284,7 @@ func TestIssue11130(t *testing.T) { t.Errorf("%v", err) return } - if reflect.TypeOf(v).String() != reflect.TypeOf(ObjectIdentifier{}).String() { + if reflect.TypeOf(v).String() != reflect.TypeOf(asn1.ObjectIdentifier{}).String() { t.Errorf("marshal OID returned an invalid type") return }