]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/asn1: Improved control of flags and times
authorRichard Barnes <rlb@ipv.sx>
Thu, 12 Feb 2015 07:35:16 +0000 (23:35 -0800)
committerAdam Langley <agl@golang.org>
Tue, 28 Apr 2015 16:35:13 +0000 (16:35 +0000)
This change corrects the serialization of asn1.Flag values, so that
when set, they serialize to an empty value, and when unset, they are
omitted. It also adds a format parameter that allows calling code
to control whether time.Time values are serialized as UTCTime or
GeneralizedTime.

Change-Id: I6d97abf009ea317338dab30c80f35a2de7e07104
Reviewed-on: https://go-review.googlesource.com/5970
Reviewed-by: Adam Langley <agl@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>

src/encoding/asn1/asn1.go
src/encoding/asn1/asn1_test.go
src/encoding/asn1/common.go
src/encoding/asn1/marshal.go
src/encoding/asn1/marshal_test.go

index aa99ca5cc5847417b7e6834e53bd44e805149729..7172c1c78601783bddee303d43ab43d71b520113 100644 (file)
@@ -579,6 +579,8 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
                                result, err = parseObjectIdentifier(innerBytes)
                        case tagUTCTime:
                                result, err = parseUTCTime(innerBytes)
+                       case tagGeneralizedTime:
+                               result, err = parseGeneralizedTime(innerBytes)
                        case tagOctetString:
                                result = innerBytes
                        default:
index 4e864d08ac0a96ba42dd45ce5c94efb4f48d1914..1a2ae2569f8fb6def8f8b7a17889cb96cd055cad 100644 (file)
@@ -358,6 +358,8 @@ func newBool(b bool) *bool { return &b }
 var parseFieldParametersTestData []parseFieldParametersTest = []parseFieldParametersTest{
        {"", fieldParameters{}},
        {"ia5", fieldParameters{stringType: tagIA5String}},
+       {"generalized", fieldParameters{timeType: tagGeneralizedTime}},
+       {"utc", fieldParameters{timeType: tagUTCTime}},
        {"printable", fieldParameters{stringType: tagPrintableString}},
        {"optional", fieldParameters{optional: true}},
        {"explicit", fieldParameters{explicit: true, tag: new(int)}},
@@ -366,7 +368,7 @@ var parseFieldParametersTestData []parseFieldParametersTest = []parseFieldParame
        {"default:42", fieldParameters{defaultValue: newInt64(42)}},
        {"tag:17", fieldParameters{tag: newInt(17)}},
        {"optional,explicit,default:42,tag:17", fieldParameters{optional: true, explicit: true, defaultValue: newInt64(42), tag: newInt(17)}},
-       {"optional,explicit,default:42,tag:17,rubbish1", fieldParameters{true, true, false, newInt64(42), newInt(17), 0, false, false}},
+       {"optional,explicit,default:42,tag:17,rubbish1", fieldParameters{true, true, false, newInt64(42), newInt(17), 0, 0, false, false}},
        {"set", fieldParameters{set: true}},
 }
 
index 33a117ece195411304421f4ccedac5c6698325d4..ab85e0496ff85171ee05f531eb4559c3694be7c7 100644 (file)
@@ -74,6 +74,7 @@ type fieldParameters struct {
        defaultValue *int64 // a default value for INTEGER typed fields (maybe nil).
        tag          *int   // the EXPLICIT or IMPLICIT tag (maybe nil).
        stringType   int    // the string tag to use when marshaling.
+       timeType     int    // the time tag to use when marshaling.
        set          bool   // true iff this should be encoded as a SET
        omitEmpty    bool   // true iff this should be omitted if empty when marshaling.
 
@@ -94,6 +95,10 @@ func parseFieldParameters(str string) (ret fieldParameters) {
                        if ret.tag == nil {
                                ret.tag = new(int)
                        }
+               case part == "generalized":
+                       ret.timeType = tagGeneralizedTime
+               case part == "utc":
+                       ret.timeType = tagUTCTime
                case part == "ia5":
                        ret.stringType = tagIA5String
                case part == "printable":
index bf92c04c9ff6755fff0980c7a5e2c11ad949c119..67a019db2d40677d68517e2d44330419f12e743b 100644 (file)
@@ -410,9 +410,11 @@ func stripTagAndLength(in []byte) []byte {
 
 func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err error) {
        switch value.Type() {
+       case flagType:
+               return nil
        case timeType:
                t := value.Interface().(time.Time)
-               if outsideUTCRange(t) {
+               if params.timeType == tagGeneralizedTime || outsideUTCRange(t) {
                        return marshalGeneralizedTime(out, t)
                } else {
                        return marshalUTCTime(out, t)
@@ -552,6 +554,10 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
        }
        class := classUniversal
 
+       if params.timeType != 0 && tag != tagUTCTime {
+               return StructuralError{"explicit time type given to non-time member"}
+       }
+
        if params.stringType != 0 && tag != tagPrintableString {
                return StructuralError{"explicit string type given to non-string member"}
        }
@@ -575,7 +581,7 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
                        tag = params.stringType
                }
        case tagUTCTime:
-               if outsideUTCRange(v.Interface().(time.Time)) {
+               if params.timeType == tagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) {
                        tag = tagGeneralizedTime
                }
        }
index 5b0115f28c58f5f99c938503a519fbe44065428d..cdca8aa33638d8eba823a0a730ced38a239c85f3 100644 (file)
@@ -42,6 +42,14 @@ type explicitTagTest struct {
        A int `asn1:"explicit,tag:5"`
 }
 
+type flagTest struct {
+       A Flag `asn1:"tag:0,optional"`
+}
+
+type generalizedTimeTest struct {
+       A time.Time `asn1:"generalized"`
+}
+
 type ia5StringTest struct {
        A string `asn1:"ia5"`
 }
@@ -92,10 +100,13 @@ var marshalTests = []marshalTest{
        {[]byte{1, 2, 3}, "0403010203"},
        {implicitTagTest{64}, "3003850140"},
        {explicitTagTest{64}, "3005a503020140"},
+       {flagTest{true}, "30028000"},
+       {flagTest{false}, "3000"},
        {time.Unix(0, 0).UTC(), "170d3730303130313030303030305a"},
        {time.Unix(1258325776, 0).UTC(), "170d3039313131353232353631365a"},
        {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"},