Skip to content

Commit fdd921c

Browse files
aglrsc
authored andcommitted
encoding/asn1: be stricter by reserialising parsed times.
The time package does normalisation of times: for example day zero is converted to the last day of the previous month and the 31st of February is moved into March etc. This makes the ASN.1 parsing a little worryingly lax. This change causes the parser to reserialise parsed times to ensure that they round-trip correctly and thus were not normalised. Fixes #11134. Change-Id: I3988bb95153a7b33d64ab861fbe51b1a34a359e9 Reviewed-on: https://go-review.googlesource.com/11094 Run-TryBot: Adam Langley <[email protected]> Reviewed-by: Dmitry Vyukov <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]> Reviewed-by: Russ Cox <[email protected]>
1 parent 85d4d46 commit fdd921c

File tree

2 files changed

+64
-5
lines changed

2 files changed

+64
-5
lines changed

src/encoding/asn1/asn1.go

+27-4
Original file line numberDiff line numberDiff line change
@@ -288,11 +288,23 @@ func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error)
288288

289289
func parseUTCTime(bytes []byte) (ret time.Time, err error) {
290290
s := string(bytes)
291-
ret, err = time.Parse("0601021504Z0700", s)
291+
292+
formatStr := "0601021504Z0700"
293+
ret, err = time.Parse(formatStr, s)
294+
if err != nil {
295+
formatStr = "060102150405Z0700"
296+
ret, err = time.Parse(formatStr, s)
297+
}
292298
if err != nil {
293-
ret, err = time.Parse("060102150405Z0700", s)
299+
return
294300
}
295-
if err == nil && ret.Year() >= 2050 {
301+
302+
if serialized := ret.Format(formatStr); serialized != s {
303+
err = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", s, serialized)
304+
return
305+
}
306+
307+
if ret.Year() >= 2050 {
296308
// UTCTime only encodes times prior to 2050. See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
297309
ret = ret.AddDate(-100, 0, 0)
298310
}
@@ -303,7 +315,18 @@ func parseUTCTime(bytes []byte) (ret time.Time, err error) {
303315
// parseGeneralizedTime parses the GeneralizedTime from the given byte slice
304316
// and returns the resulting time.
305317
func parseGeneralizedTime(bytes []byte) (ret time.Time, err error) {
306-
return time.Parse("20060102150405Z0700", string(bytes))
318+
const formatStr = "20060102150405Z0700"
319+
s := string(bytes)
320+
321+
if ret, err = time.Parse(formatStr, s); err != nil {
322+
return
323+
}
324+
325+
if serialized := ret.Format(formatStr); serialized != s {
326+
err = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", s, serialized)
327+
}
328+
329+
return
307330
}
308331

309332
// PrintableString

src/encoding/asn1/asn1_test.go

+37-1
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,24 @@ var utcTestData = []timeTest{
258258
{"91050633444aZ", false, time.Time{}},
259259
{"910506334461Z", false, time.Time{}},
260260
{"910506334400Za", false, time.Time{}},
261+
/* These are invalid times. However, the time package normalises times
262+
* and they were accepted in some versions. See #11134. */
263+
{"000100000000Z", false, time.Time{}},
264+
{"101302030405Z", false, time.Time{}},
265+
{"100002030405Z", false, time.Time{}},
266+
{"100100030405Z", false, time.Time{}},
267+
{"100132030405Z", false, time.Time{}},
268+
{"100231030405Z", false, time.Time{}},
269+
{"100102240405Z", false, time.Time{}},
270+
{"100102036005Z", false, time.Time{}},
271+
{"100102030460Z", false, time.Time{}},
272+
{"-100102030410Z", false, time.Time{}},
273+
{"10-0102030410Z", false, time.Time{}},
274+
{"10-0002030410Z", false, time.Time{}},
275+
{"1001-02030410Z", false, time.Time{}},
276+
{"100102-030410Z", false, time.Time{}},
277+
{"10010203-0410Z", false, time.Time{}},
278+
{"1001020304-10Z", false, time.Time{}},
261279
}
262280

263281
func TestUTCTime(t *testing.T) {
@@ -287,6 +305,24 @@ var generalizedTimeTestData = []timeTest{
287305
{"20100102030405", false, time.Time{}},
288306
{"20100102030405+0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))},
289307
{"20100102030405-0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", -6*60*60-7*60))},
308+
/* These are invalid times. However, the time package normalises times
309+
* and they were accepted in some versions. See #11134. */
310+
{"00000100000000Z", false, time.Time{}},
311+
{"20101302030405Z", false, time.Time{}},
312+
{"20100002030405Z", false, time.Time{}},
313+
{"20100100030405Z", false, time.Time{}},
314+
{"20100132030405Z", false, time.Time{}},
315+
{"20100231030405Z", false, time.Time{}},
316+
{"20100102240405Z", false, time.Time{}},
317+
{"20100102036005Z", false, time.Time{}},
318+
{"20100102030460Z", false, time.Time{}},
319+
{"-20100102030410Z", false, time.Time{}},
320+
{"2010-0102030410Z", false, time.Time{}},
321+
{"2010-0002030410Z", false, time.Time{}},
322+
{"201001-02030410Z", false, time.Time{}},
323+
{"20100102-030410Z", false, time.Time{}},
324+
{"2010010203-0410Z", false, time.Time{}},
325+
{"201001020304-10Z", false, time.Time{}},
290326
}
291327

292328
func TestGeneralizedTime(t *testing.T) {
@@ -297,7 +333,7 @@ func TestGeneralizedTime(t *testing.T) {
297333
}
298334
if err == nil {
299335
if !reflect.DeepEqual(test.out, ret) {
300-
t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
336+
t.Errorf("#%d: Bad result: %q → %v (expected %v)", i, test.in, ret, test.out)
301337
}
302338
}
303339
}

0 commit comments

Comments
 (0)