Skip to content

Commit

Permalink
encoding/asn1: fix explicitly tagged Times.
Browse files Browse the repository at this point in the history
https://golang.org/cl/153770043/ tried to fix the case where a
implicitly tagged Time, that happened to have the same tag as
GENERALIZEDTIME, shouldn't be parsed as a GENERALIZEDTIME.

It did so, mistakenly, by testing whether params.tag != nil. But
explicitly tagged values also have a non-nil tag and there the inner
tag actually does encode the type of the value.

This change instead tests whether the tag class is UNIVERSAL before
assuming that the tag contains type information.

LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/152380044
  • Loading branch information
agl committed Oct 10, 2014
1 parent eeb2211 commit 1fd042c
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/encoding/asn1/asn1.go
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
// 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 {
if params.tag == nil {
if t.class == classUniversal {
switch t.tag {
case tagIA5String, tagGeneralString, tagT61String, tagUTF8String:
universalTag = t.tag
Expand All @@ -652,7 +652,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam

// Special case for time: UTCTime and GeneralizedTime both map to the
// Go type time.Time.
if universalTag == tagUTCTime && params.tag == nil && t.tag == tagGeneralizedTime {
if universalTag == tagUTCTime && t.tag == tagGeneralizedTime && t.class == classUniversal {
universalTag = tagGeneralizedTime
}

Expand Down
48 changes: 48 additions & 0 deletions src/encoding/asn1/asn1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -817,3 +817,51 @@ func TestStringSlice(t *testing.T) {
}
}
}

type explicitTaggedTimeTest struct {
Time time.Time `asn1:"explicit,tag:0"`
}

var explicitTaggedTimeTestData = []struct {
in []byte
out explicitTaggedTimeTest
}{
{[]byte{0x30, 0x11, 0xa0, 0xf, 0x17, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'},
explicitTaggedTimeTest{time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC)}},
{[]byte{0x30, 0x17, 0xa0, 0xf, 0x18, 0x13, '2', '0', '1', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '+', '0', '6', '0', '7'},
explicitTaggedTimeTest{time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))}},
}

func TestExplicitTaggedTime(t *testing.T) {
// Test that a time.Time will match either tagUTCTime or
// tagGeneralizedTime.
for i, test := range explicitTaggedTimeTestData {
var got explicitTaggedTimeTest
_, err := Unmarshal(test.in, &got)
if err != nil {
t.Errorf("Unmarshal failed at index %d %v", i, err)
}
if !got.Time.Equal(test.out.Time) {
t.Errorf("#%d: got %v, want %v", i, got.Time, test.out.Time)
}
}
}

type implicitTaggedTimeTest struct {
Time time.Time `asn1:"tag:24"`
}

func TestImplicitTaggedTime(t *testing.T) {
// An implicitly tagged time value, that happens to have an implicit
// tag equal to a GENERALIZEDTIME, should still be parsed as a UTCTime.
// (There's no "timeType" in fieldParameters to determine what type of
// time should be expected when implicitly tagged.)
der := []byte{0x30, 0x0f, 0x80 | 24, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'}
var result implicitTaggedTimeTest
if _, err := Unmarshal(der, &result); err != nil {
t.Fatalf("Error while parsing: %s", err)
}
if expected := time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC); !result.Time.Equal(expected) {
t.Errorf("Wrong result. Got %v, want %v", result.Time, expected)
}
}

0 comments on commit 1fd042c

Please sign in to comment.