1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package asn1
6
7import (
8	"bytes"
9	"fmt"
10	"math"
11	"math/big"
12	"reflect"
13	"strings"
14	"testing"
15	"time"
16)
17
18type boolTest struct {
19	in  []byte
20	ok  bool
21	out bool
22}
23
24var boolTestData = []boolTest{
25	{[]byte{0x00}, true, false},
26	{[]byte{0xff}, true, true},
27	{[]byte{0x00, 0x00}, false, false},
28	{[]byte{0xff, 0xff}, false, false},
29	{[]byte{0x01}, false, false},
30}
31
32func TestParseBool(t *testing.T) {
33	for i, test := range boolTestData {
34		ret, err := parseBool(test.in)
35		if (err == nil) != test.ok {
36			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
37		}
38		if test.ok && ret != test.out {
39			t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
40		}
41	}
42}
43
44type int64Test struct {
45	in  []byte
46	ok  bool
47	out int64
48}
49
50var int64TestData = []int64Test{
51	{[]byte{0x00}, true, 0},
52	{[]byte{0x7f}, true, 127},
53	{[]byte{0x00, 0x80}, true, 128},
54	{[]byte{0x01, 0x00}, true, 256},
55	{[]byte{0x80}, true, -128},
56	{[]byte{0xff, 0x7f}, true, -129},
57	{[]byte{0xff}, true, -1},
58	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, true, -9223372036854775808},
59	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, false, 0},
60	{[]byte{}, false, 0},
61	{[]byte{0x00, 0x7f}, false, 0},
62	{[]byte{0xff, 0xf0}, false, 0},
63}
64
65func TestParseInt64(t *testing.T) {
66	for i, test := range int64TestData {
67		ret, err := parseInt64(test.in)
68		if (err == nil) != test.ok {
69			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
70		}
71		if test.ok && ret != test.out {
72			t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
73		}
74	}
75}
76
77type int32Test struct {
78	in  []byte
79	ok  bool
80	out int32
81}
82
83var int32TestData = []int32Test{
84	{[]byte{0x00}, true, 0},
85	{[]byte{0x7f}, true, 127},
86	{[]byte{0x00, 0x80}, true, 128},
87	{[]byte{0x01, 0x00}, true, 256},
88	{[]byte{0x80}, true, -128},
89	{[]byte{0xff, 0x7f}, true, -129},
90	{[]byte{0xff}, true, -1},
91	{[]byte{0x80, 0x00, 0x00, 0x00}, true, -2147483648},
92	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00}, false, 0},
93	{[]byte{}, false, 0},
94	{[]byte{0x00, 0x7f}, false, 0},
95	{[]byte{0xff, 0xf0}, false, 0},
96}
97
98func TestParseInt32(t *testing.T) {
99	for i, test := range int32TestData {
100		ret, err := parseInt32(test.in)
101		if (err == nil) != test.ok {
102			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
103		}
104		if test.ok && int32(ret) != test.out {
105			t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
106		}
107	}
108}
109
110var bigIntTests = []struct {
111	in     []byte
112	ok     bool
113	base10 string
114}{
115	{[]byte{0xff}, true, "-1"},
116	{[]byte{0x00}, true, "0"},
117	{[]byte{0x01}, true, "1"},
118	{[]byte{0x00, 0xff}, true, "255"},
119	{[]byte{0xff, 0x00}, true, "-256"},
120	{[]byte{0x01, 0x00}, true, "256"},
121	{[]byte{}, false, ""},
122	{[]byte{0x00, 0x7f}, false, ""},
123	{[]byte{0xff, 0xf0}, false, ""},
124}
125
126func TestParseBigInt(t *testing.T) {
127	for i, test := range bigIntTests {
128		ret, err := parseBigInt(test.in)
129		if (err == nil) != test.ok {
130			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
131		}
132		if test.ok {
133			if ret.String() != test.base10 {
134				t.Errorf("#%d: bad result from %x, got %s want %s", i, test.in, ret.String(), test.base10)
135			}
136			e, err := makeBigInt(ret)
137			if err != nil {
138				t.Errorf("%d: err=%q", i, err)
139				continue
140			}
141			result := make([]byte, e.Len())
142			e.Encode(result)
143			if !bytes.Equal(result, test.in) {
144				t.Errorf("#%d: got %x from marshaling %s, want %x", i, result, ret, test.in)
145			}
146		}
147	}
148}
149
150type bitStringTest struct {
151	in        []byte
152	ok        bool
153	out       []byte
154	bitLength int
155}
156
157var bitStringTestData = []bitStringTest{
158	{[]byte{}, false, []byte{}, 0},
159	{[]byte{0x00}, true, []byte{}, 0},
160	{[]byte{0x07, 0x00}, true, []byte{0x00}, 1},
161	{[]byte{0x07, 0x01}, false, []byte{}, 0},
162	{[]byte{0x07, 0x40}, false, []byte{}, 0},
163	{[]byte{0x08, 0x00}, false, []byte{}, 0},
164}
165
166func TestBitString(t *testing.T) {
167	for i, test := range bitStringTestData {
168		ret, err := parseBitString(test.in)
169		if (err == nil) != test.ok {
170			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
171		}
172		if err == nil {
173			if test.bitLength != ret.BitLength || !bytes.Equal(ret.Bytes, test.out) {
174				t.Errorf("#%d: Bad result: %v (expected %v %v)", i, ret, test.out, test.bitLength)
175			}
176		}
177	}
178}
179
180func TestBitStringAt(t *testing.T) {
181	bs := BitString{[]byte{0x82, 0x40}, 16}
182	if bs.At(0) != 1 {
183		t.Error("#1: Failed")
184	}
185	if bs.At(1) != 0 {
186		t.Error("#2: Failed")
187	}
188	if bs.At(6) != 1 {
189		t.Error("#3: Failed")
190	}
191	if bs.At(9) != 1 {
192		t.Error("#4: Failed")
193	}
194	if bs.At(-1) != 0 {
195		t.Error("#5: Failed")
196	}
197	if bs.At(17) != 0 {
198		t.Error("#6: Failed")
199	}
200}
201
202type bitStringRightAlignTest struct {
203	in    []byte
204	inlen int
205	out   []byte
206}
207
208var bitStringRightAlignTests = []bitStringRightAlignTest{
209	{[]byte{0x80}, 1, []byte{0x01}},
210	{[]byte{0x80, 0x80}, 9, []byte{0x01, 0x01}},
211	{[]byte{}, 0, []byte{}},
212	{[]byte{0xce}, 8, []byte{0xce}},
213	{[]byte{0xce, 0x47}, 16, []byte{0xce, 0x47}},
214	{[]byte{0x34, 0x50}, 12, []byte{0x03, 0x45}},
215}
216
217func TestBitStringRightAlign(t *testing.T) {
218	for i, test := range bitStringRightAlignTests {
219		bs := BitString{test.in, test.inlen}
220		out := bs.RightAlign()
221		if !bytes.Equal(out, test.out) {
222			t.Errorf("#%d got: %x want: %x", i, out, test.out)
223		}
224	}
225}
226
227type objectIdentifierTest struct {
228	in  []byte
229	ok  bool
230	out []int
231}
232
233var objectIdentifierTestData = []objectIdentifierTest{
234	{[]byte{}, false, []int{}},
235	{[]byte{85}, true, []int{2, 5}},
236	{[]byte{85, 0x02}, true, []int{2, 5, 2}},
237	{[]byte{85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}},
238	{[]byte{0x81, 0x34, 0x03}, true, []int{2, 100, 3}},
239	{[]byte{85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}},
240}
241
242func TestObjectIdentifier(t *testing.T) {
243	for i, test := range objectIdentifierTestData {
244		ret, err := parseObjectIdentifier(test.in)
245		if (err == nil) != test.ok {
246			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
247		}
248		if err == nil {
249			if !reflect.DeepEqual(test.out, ret) {
250				t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
251			}
252		}
253	}
254
255	if s := ObjectIdentifier([]int{1, 2, 3, 4}).String(); s != "1.2.3.4" {
256		t.Errorf("bad ObjectIdentifier.String(). Got %s, want 1.2.3.4", s)
257	}
258}
259
260type timeTest struct {
261	in  string
262	ok  bool
263	out time.Time
264}
265
266var utcTestData = []timeTest{
267	{"910506164540-0700", true, time.Date(1991, 05, 06, 16, 45, 40, 0, time.FixedZone("", -7*60*60))},
268	{"910506164540+0730", true, time.Date(1991, 05, 06, 16, 45, 40, 0, time.FixedZone("", 7*60*60+30*60))},
269	{"910506234540Z", true, time.Date(1991, 05, 06, 23, 45, 40, 0, time.UTC)},
270	{"9105062345Z", true, time.Date(1991, 05, 06, 23, 45, 0, 0, time.UTC)},
271	{"5105062345Z", true, time.Date(1951, 05, 06, 23, 45, 0, 0, time.UTC)},
272	{"a10506234540Z", false, time.Time{}},
273	{"91a506234540Z", false, time.Time{}},
274	{"9105a6234540Z", false, time.Time{}},
275	{"910506a34540Z", false, time.Time{}},
276	{"910506334a40Z", false, time.Time{}},
277	{"91050633444aZ", false, time.Time{}},
278	{"910506334461Z", false, time.Time{}},
279	{"910506334400Za", false, time.Time{}},
280	/* These are invalid times. However, the time package normalises times
281	 * and they were accepted in some versions. See #11134. */
282	{"000100000000Z", false, time.Time{}},
283	{"101302030405Z", false, time.Time{}},
284	{"100002030405Z", false, time.Time{}},
285	{"100100030405Z", false, time.Time{}},
286	{"100132030405Z", false, time.Time{}},
287	{"100231030405Z", false, time.Time{}},
288	{"100102240405Z", false, time.Time{}},
289	{"100102036005Z", false, time.Time{}},
290	{"100102030460Z", false, time.Time{}},
291	{"-100102030410Z", false, time.Time{}},
292	{"10-0102030410Z", false, time.Time{}},
293	{"10-0002030410Z", false, time.Time{}},
294	{"1001-02030410Z", false, time.Time{}},
295	{"100102-030410Z", false, time.Time{}},
296	{"10010203-0410Z", false, time.Time{}},
297	{"1001020304-10Z", false, time.Time{}},
298}
299
300func TestUTCTime(t *testing.T) {
301	for i, test := range utcTestData {
302		ret, err := parseUTCTime([]byte(test.in))
303		if err != nil {
304			if test.ok {
305				t.Errorf("#%d: parseUTCTime(%q) = error %v", i, test.in, err)
306			}
307			continue
308		}
309		if !test.ok {
310			t.Errorf("#%d: parseUTCTime(%q) succeeded, should have failed", i, test.in)
311			continue
312		}
313		const format = "Jan _2 15:04:05 -0700 2006" // ignore zone name, just offset
314		have := ret.Format(format)
315		want := test.out.Format(format)
316		if have != want {
317			t.Errorf("#%d: parseUTCTime(%q) = %s, want %s", i, test.in, have, want)
318		}
319	}
320}
321
322var generalizedTimeTestData = []timeTest{
323	{"20100102030405Z", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.UTC)},
324	{"20100102030405", false, time.Time{}},
325	{"20100102030405+0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))},
326	{"20100102030405-0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", -6*60*60-7*60))},
327	/* These are invalid times. However, the time package normalises times
328	 * and they were accepted in some versions. See #11134. */
329	{"00000100000000Z", false, time.Time{}},
330	{"20101302030405Z", false, time.Time{}},
331	{"20100002030405Z", false, time.Time{}},
332	{"20100100030405Z", false, time.Time{}},
333	{"20100132030405Z", false, time.Time{}},
334	{"20100231030405Z", false, time.Time{}},
335	{"20100102240405Z", false, time.Time{}},
336	{"20100102036005Z", false, time.Time{}},
337	{"20100102030460Z", false, time.Time{}},
338	{"-20100102030410Z", false, time.Time{}},
339	{"2010-0102030410Z", false, time.Time{}},
340	{"2010-0002030410Z", false, time.Time{}},
341	{"201001-02030410Z", false, time.Time{}},
342	{"20100102-030410Z", false, time.Time{}},
343	{"2010010203-0410Z", false, time.Time{}},
344	{"201001020304-10Z", false, time.Time{}},
345}
346
347func TestGeneralizedTime(t *testing.T) {
348	for i, test := range generalizedTimeTestData {
349		ret, err := parseGeneralizedTime([]byte(test.in))
350		if (err == nil) != test.ok {
351			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
352		}
353		if err == nil {
354			if !reflect.DeepEqual(test.out, ret) {
355				t.Errorf("#%d: Bad result: %q → %v (expected %v)", i, test.in, ret, test.out)
356			}
357		}
358	}
359}
360
361type tagAndLengthTest struct {
362	in  []byte
363	ok  bool
364	out tagAndLength
365}
366
367var tagAndLengthData = []tagAndLengthTest{
368	{[]byte{0x80, 0x01}, true, tagAndLength{2, 0, 1, false}},
369	{[]byte{0xa0, 0x01}, true, tagAndLength{2, 0, 1, true}},
370	{[]byte{0x02, 0x00}, true, tagAndLength{0, 2, 0, false}},
371	{[]byte{0xfe, 0x00}, true, tagAndLength{3, 30, 0, true}},
372	{[]byte{0x1f, 0x1f, 0x00}, true, tagAndLength{0, 31, 0, false}},
373	{[]byte{0x1f, 0x81, 0x00, 0x00}, true, tagAndLength{0, 128, 0, false}},
374	{[]byte{0x1f, 0x81, 0x80, 0x01, 0x00}, true, tagAndLength{0, 0x4001, 0, false}},
375	{[]byte{0x00, 0x81, 0x80}, true, tagAndLength{0, 0, 128, false}},
376	{[]byte{0x00, 0x82, 0x01, 0x00}, true, tagAndLength{0, 0, 256, false}},
377	{[]byte{0x00, 0x83, 0x01, 0x00}, false, tagAndLength{}},
378	{[]byte{0x1f, 0x85}, false, tagAndLength{}},
379	{[]byte{0x30, 0x80}, false, tagAndLength{}},
380	// Superfluous zeros in the length should be an error.
381	{[]byte{0xa0, 0x82, 0x00, 0xff}, false, tagAndLength{}},
382	// Lengths up to the maximum size of an int should work.
383	{[]byte{0xa0, 0x84, 0x7f, 0xff, 0xff, 0xff}, true, tagAndLength{2, 0, 0x7fffffff, true}},
384	// Lengths that would overflow an int should be rejected.
385	{[]byte{0xa0, 0x84, 0x80, 0x00, 0x00, 0x00}, false, tagAndLength{}},
386	// Long length form may not be used for lengths that fit in short form.
387	{[]byte{0xa0, 0x81, 0x7f}, false, tagAndLength{}},
388	// Tag numbers which would overflow int32 are rejected. (The value below is 2^31.)
389	{[]byte{0x1f, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00}, false, tagAndLength{}},
390	// Tag numbers that fit in an int32 are valid. (The value below is 2^31 - 1.)
391	{[]byte{0x1f, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x00}, true, tagAndLength{tag: math.MaxInt32}},
392	// Long tag number form may not be used for tags that fit in short form.
393	{[]byte{0x1f, 0x1e, 0x00}, false, tagAndLength{}},
394}
395
396func TestParseTagAndLength(t *testing.T) {
397	for i, test := range tagAndLengthData {
398		tagAndLength, _, err := parseTagAndLength(test.in, 0)
399		if (err == nil) != test.ok {
400			t.Errorf("#%d: Incorrect error result (did pass? %v, expected: %v)", i, err == nil, test.ok)
401		}
402		if err == nil && !reflect.DeepEqual(test.out, tagAndLength) {
403			t.Errorf("#%d: Bad result: %v (expected %v)", i, tagAndLength, test.out)
404		}
405	}
406}
407
408type parseFieldParametersTest struct {
409	in  string
410	out fieldParameters
411}
412
413func newInt(n int) *int { return &n }
414
415func newInt64(n int64) *int64 { return &n }
416
417func newString(s string) *string { return &s }
418
419func newBool(b bool) *bool { return &b }
420
421var parseFieldParametersTestData []parseFieldParametersTest = []parseFieldParametersTest{
422	{"", fieldParameters{}},
423	{"ia5", fieldParameters{stringType: TagIA5String}},
424	{"generalized", fieldParameters{timeType: TagGeneralizedTime}},
425	{"utc", fieldParameters{timeType: TagUTCTime}},
426	{"printable", fieldParameters{stringType: TagPrintableString}},
427	{"numeric", fieldParameters{stringType: TagNumericString}},
428	{"optional", fieldParameters{optional: true}},
429	{"explicit", fieldParameters{explicit: true, tag: new(int)}},
430	{"application", fieldParameters{application: true, tag: new(int)}},
431	{"optional,explicit", fieldParameters{optional: true, explicit: true, tag: new(int)}},
432	{"default:42", fieldParameters{defaultValue: newInt64(42)}},
433	{"tag:17", fieldParameters{tag: newInt(17)}},
434	{"optional,explicit,default:42,tag:17", fieldParameters{optional: true, explicit: true, defaultValue: newInt64(42), tag: newInt(17)}},
435	{"optional,explicit,default:42,tag:17,rubbish1", fieldParameters{true, true, false, newInt64(42), newInt(17), 0, 0, false, false}},
436	{"set", fieldParameters{set: true}},
437}
438
439func TestParseFieldParameters(t *testing.T) {
440	for i, test := range parseFieldParametersTestData {
441		f := parseFieldParameters(test.in)
442		if !reflect.DeepEqual(f, test.out) {
443			t.Errorf("#%d: Bad result: %v (expected %v)", i, f, test.out)
444		}
445	}
446}
447
448type TestObjectIdentifierStruct struct {
449	OID ObjectIdentifier
450}
451
452type TestContextSpecificTags struct {
453	A int `asn1:"tag:1"`
454}
455
456type TestContextSpecificTags2 struct {
457	A int `asn1:"explicit,tag:1"`
458	B int
459}
460
461type TestContextSpecificTags3 struct {
462	S string `asn1:"tag:1,utf8"`
463}
464
465type TestElementsAfterString struct {
466	S    string
467	A, B int
468}
469
470type TestBigInt struct {
471	X *big.Int
472}
473
474type TestSet struct {
475	Ints []int `asn1:"set"`
476}
477
478var unmarshalTestData = []struct {
479	in  []byte
480	out interface{}
481}{
482	{[]byte{0x02, 0x01, 0x42}, newInt(0x42)},
483	{[]byte{0x05, 0x00}, &RawValue{0, 5, false, []byte{}, []byte{0x05, 0x00}}},
484	{[]byte{0x30, 0x08, 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d}, &TestObjectIdentifierStruct{[]int{1, 2, 840, 113549}}},
485	{[]byte{0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0}, &BitString{[]byte{110, 93, 192}, 18}},
486	{[]byte{0x30, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &[]int{1, 2, 3}},
487	{[]byte{0x02, 0x01, 0x10}, newInt(16)},
488	{[]byte{0x13, 0x04, 't', 'e', 's', 't'}, newString("test")},
489	{[]byte{0x16, 0x04, 't', 'e', 's', 't'}, newString("test")},
490	// Ampersand is allowed in PrintableString due to mistakes by major CAs.
491	{[]byte{0x13, 0x05, 't', 'e', 's', 't', '&'}, newString("test&")},
492	{[]byte{0x16, 0x04, 't', 'e', 's', 't'}, &RawValue{0, 22, false, []byte("test"), []byte("\x16\x04test")}},
493	{[]byte{0x04, 0x04, 1, 2, 3, 4}, &RawValue{0, 4, false, []byte{1, 2, 3, 4}, []byte{4, 4, 1, 2, 3, 4}}},
494	{[]byte{0x30, 0x03, 0x81, 0x01, 0x01}, &TestContextSpecificTags{1}},
495	{[]byte{0x30, 0x08, 0xa1, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}, &TestContextSpecificTags2{1, 2}},
496	{[]byte{0x30, 0x03, 0x81, 0x01, '@'}, &TestContextSpecificTags3{"@"}},
497	{[]byte{0x01, 0x01, 0x00}, newBool(false)},
498	{[]byte{0x01, 0x01, 0xff}, newBool(true)},
499	{[]byte{0x30, 0x0b, 0x13, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x22, 0x02, 0x01, 0x33}, &TestElementsAfterString{"foo", 0x22, 0x33}},
500	{[]byte{0x30, 0x05, 0x02, 0x03, 0x12, 0x34, 0x56}, &TestBigInt{big.NewInt(0x123456)}},
501	{[]byte{0x30, 0x0b, 0x31, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &TestSet{Ints: []int{1, 2, 3}}},
502	{[]byte{0x12, 0x0b, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' '}, newString("0123456789 ")},
503}
504
505func TestUnmarshal(t *testing.T) {
506	for i, test := range unmarshalTestData {
507		pv := reflect.New(reflect.TypeOf(test.out).Elem())
508		val := pv.Interface()
509		_, err := Unmarshal(test.in, val)
510		if err != nil {
511			t.Errorf("Unmarshal failed at index %d %v", i, err)
512		}
513		if !reflect.DeepEqual(val, test.out) {
514			t.Errorf("#%d:\nhave %#v\nwant %#v", i, val, test.out)
515		}
516	}
517}
518
519type Certificate struct {
520	TBSCertificate     TBSCertificate
521	SignatureAlgorithm AlgorithmIdentifier
522	SignatureValue     BitString
523}
524
525type TBSCertificate struct {
526	Version            int `asn1:"optional,explicit,default:0,tag:0"`
527	SerialNumber       RawValue
528	SignatureAlgorithm AlgorithmIdentifier
529	Issuer             RDNSequence
530	Validity           Validity
531	Subject            RDNSequence
532	PublicKey          PublicKeyInfo
533}
534
535type AlgorithmIdentifier struct {
536	Algorithm ObjectIdentifier
537}
538
539type RDNSequence []RelativeDistinguishedNameSET
540
541type RelativeDistinguishedNameSET []AttributeTypeAndValue
542
543type AttributeTypeAndValue struct {
544	Type  ObjectIdentifier
545	Value interface{}
546}
547
548type Validity struct {
549	NotBefore, NotAfter time.Time
550}
551
552type PublicKeyInfo struct {
553	Algorithm AlgorithmIdentifier
554	PublicKey BitString
555}
556
557func TestCertificate(t *testing.T) {
558	// This is a minimal, self-signed certificate that should parse correctly.
559	var cert Certificate
560	if _, err := Unmarshal(derEncodedSelfSignedCertBytes, &cert); err != nil {
561		t.Errorf("Unmarshal failed: %v", err)
562	}
563	if !reflect.DeepEqual(cert, derEncodedSelfSignedCert) {
564		t.Errorf("Bad result:\ngot: %+v\nwant: %+v", cert, derEncodedSelfSignedCert)
565	}
566}
567
568func TestCertificateWithNUL(t *testing.T) {
569	// This is the paypal NUL-hack certificate. It should fail to parse because
570	// NUL isn't a permitted character in a PrintableString.
571
572	var cert Certificate
573	if _, err := Unmarshal(derEncodedPaypalNULCertBytes, &cert); err == nil {
574		t.Error("Unmarshal succeeded, should not have")
575	}
576}
577
578type rawStructTest struct {
579	Raw RawContent
580	A   int
581}
582
583func TestRawStructs(t *testing.T) {
584	var s rawStructTest
585	input := []byte{0x30, 0x03, 0x02, 0x01, 0x50}
586
587	rest, err := Unmarshal(input, &s)
588	if len(rest) != 0 {
589		t.Errorf("incomplete parse: %x", rest)
590		return
591	}
592	if err != nil {
593		t.Error(err)
594		return
595	}
596	if s.A != 0x50 {
597		t.Errorf("bad value for A: got %d want %d", s.A, 0x50)
598	}
599	if !bytes.Equal([]byte(s.Raw), input) {
600		t.Errorf("bad value for Raw: got %x want %x", s.Raw, input)
601	}
602}
603
604type oiEqualTest struct {
605	first  ObjectIdentifier
606	second ObjectIdentifier
607	same   bool
608}
609
610var oiEqualTests = []oiEqualTest{
611	{
612		ObjectIdentifier{1, 2, 3},
613		ObjectIdentifier{1, 2, 3},
614		true,
615	},
616	{
617		ObjectIdentifier{1},
618		ObjectIdentifier{1, 2, 3},
619		false,
620	},
621	{
622		ObjectIdentifier{1, 2, 3},
623		ObjectIdentifier{10, 11, 12},
624		false,
625	},
626}
627
628func TestObjectIdentifierEqual(t *testing.T) {
629	for _, o := range oiEqualTests {
630		if s := o.first.Equal(o.second); s != o.same {
631			t.Errorf("ObjectIdentifier.Equal: got: %t want: %t", s, o.same)
632		}
633	}
634}
635
636var derEncodedSelfSignedCert = Certificate{
637	TBSCertificate: TBSCertificate{
638		Version:            0,
639		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}},
640		SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}},
641		Issuer: RDNSequence{
642			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}},
643			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}},
644			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}},
645			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}},
646			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}},
647			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}},
648		},
649		Validity: Validity{
650			NotBefore: time.Date(2009, 10, 8, 00, 25, 53, 0, time.UTC),
651			NotAfter:  time.Date(2010, 10, 8, 00, 25, 53, 0, time.UTC),
652		},
653		Subject: RDNSequence{
654			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}},
655			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}},
656			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}},
657			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}},
658			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}},
659			RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}},
660		},
661		PublicKey: PublicKeyInfo{
662			Algorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}},
663			PublicKey: BitString{
664				Bytes: []uint8{
665					0x30, 0x48, 0x2, 0x41, 0x0, 0xcd, 0xb7,
666					0x63, 0x9c, 0x32, 0x78, 0xf0, 0x6, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42,
667					0x90, 0x2b, 0x59, 0x2d, 0x8c, 0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4,
668					0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea, 0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2,
669					0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88, 0x96, 0x57, 0x72, 0x2a, 0x4f,
670					0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45, 0xdc, 0x8f, 0xde, 0xec,
671					0x35, 0x7d, 0x2, 0x3, 0x1, 0x0, 0x1,
672				},
673				BitLength: 592,
674			},
675		},
676	},
677	SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}},
678	SignatureValue: BitString{
679		Bytes: []uint8{
680			0xa6, 0x7b, 0x6, 0xec, 0x5e, 0xce,
681			0x92, 0x77, 0x2c, 0xa4, 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c,
682			0x7b, 0x45, 0x11, 0xcd, 0x40, 0xa7, 0xf6, 0x59, 0x98, 0x4, 0x2, 0xdf, 0x2b,
683			0x99, 0x8b, 0xb9, 0xa4, 0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8,
684			0xd9, 0x1e, 0xde, 0x14, 0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa,
685			0xfa, 0x88, 0x21, 0x49, 0x4, 0x35,
686		},
687		BitLength: 512,
688	},
689}
690
691var derEncodedSelfSignedCertBytes = []byte{
692	0x30, 0x82, 0x02, 0x18, 0x30,
693	0x82, 0x01, 0xc2, 0x02, 0x09, 0x00, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c,
694	0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
695	0x05, 0x05, 0x00, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
696	0x04, 0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
697	0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
698	0x65, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43,
699	0x69, 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
700	0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
701	0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31,
702	0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c,
703	0x73, 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
704	0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
705	0x01, 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78,
706	0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d,
707	0x30, 0x39, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35, 0x33, 0x5a,
708	0x17, 0x0d, 0x31, 0x30, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35,
709	0x33, 0x5a, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
710	0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
711	0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
712	0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43, 0x69,
713	0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18,
714	0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
715	0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x1a,
716	0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c, 0x73,
717	0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
718	0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
719	0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78, 0x61,
720	0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06,
721	0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
722	0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xcd, 0xb7, 0x63, 0x9c, 0x32, 0x78,
723	0xf0, 0x06, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42, 0x90, 0x2b, 0x59, 0x2d, 0x8c,
724	0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4, 0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea,
725	0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2, 0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88,
726	0x96, 0x57, 0x72, 0x2a, 0x4f, 0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45,
727	0xdc, 0x8f, 0xde, 0xec, 0x35, 0x7d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d,
728	0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
729	0x03, 0x41, 0x00, 0xa6, 0x7b, 0x06, 0xec, 0x5e, 0xce, 0x92, 0x77, 0x2c, 0xa4,
730	0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c, 0x7b, 0x45, 0x11, 0xcd,
731	0x40, 0xa7, 0xf6, 0x59, 0x98, 0x04, 0x02, 0xdf, 0x2b, 0x99, 0x8b, 0xb9, 0xa4,
732	0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8, 0xd9, 0x1e, 0xde, 0x14,
733	0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa, 0xfa, 0x88, 0x21, 0x49,
734	0x04, 0x35,
735}
736
737var derEncodedPaypalNULCertBytes = []byte{
738	0x30, 0x82, 0x06, 0x44, 0x30,
739	0x82, 0x05, 0xad, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x00, 0xf0, 0x9b,
740	0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
741	0x05, 0x00, 0x30, 0x82, 0x01, 0x12, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
742	0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
743	0x04, 0x08, 0x13, 0x09, 0x42, 0x61, 0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61,
744	0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x42, 0x61,
745	0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03,
746	0x55, 0x04, 0x0a, 0x13, 0x20, 0x49, 0x50, 0x53, 0x20, 0x43, 0x65, 0x72, 0x74,
747	0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74,
748	0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x73, 0x2e, 0x6c, 0x2e, 0x31, 0x2e,
749	0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x25, 0x67, 0x65, 0x6e, 0x65,
750	0x72, 0x61, 0x6c, 0x40, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d,
751	0x20, 0x43, 0x2e, 0x49, 0x2e, 0x46, 0x2e, 0x20, 0x20, 0x42, 0x2d, 0x42, 0x36,
752	0x32, 0x32, 0x31, 0x30, 0x36, 0x39, 0x35, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03,
753	0x55, 0x04, 0x0b, 0x13, 0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c,
754	0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
755	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
756	0x69, 0x74, 0x79, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
757	0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41,
758	0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
759	0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31,
760	0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09,
761	0x01, 0x16, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40, 0x69, 0x70,
762	0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39,
763	0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a, 0x17, 0x0d,
764	0x31, 0x31, 0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a,
765	0x30, 0x81, 0x94, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
766	0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
767	0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16,
768	0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0d, 0x53, 0x61, 0x6e, 0x20,
769	0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x31, 0x11, 0x30, 0x0f,
770	0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69,
771	0x74, 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b,
772	0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x55, 0x6e, 0x69, 0x74, 0x31, 0x2f,
773	0x30, 0x2d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x26, 0x77, 0x77, 0x77, 0x2e,
774	0x70, 0x61, 0x79, 0x70, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x73, 0x73,
775	0x6c, 0x2e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
776	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x63, 0x63, 0x30, 0x81, 0x9f, 0x30, 0x0d,
777	0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
778	0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x69,
779	0xfa, 0x6f, 0x3a, 0x00, 0xb4, 0x21, 0x1b, 0xc8, 0xb1, 0x02, 0xd7, 0x3f, 0x19,
780	0xb2, 0xc4, 0x6d, 0xb4, 0x54, 0xf8, 0x8b, 0x8a, 0xcc, 0xdb, 0x72, 0xc2, 0x9e,
781	0x3c, 0x60, 0xb9, 0xc6, 0x91, 0x3d, 0x82, 0xb7, 0x7d, 0x99, 0xff, 0xd1, 0x29,
782	0x84, 0xc1, 0x73, 0x53, 0x9c, 0x82, 0xdd, 0xfc, 0x24, 0x8c, 0x77, 0xd5, 0x41,
783	0xf3, 0xe8, 0x1e, 0x42, 0xa1, 0xad, 0x2d, 0x9e, 0xff, 0x5b, 0x10, 0x26, 0xce,
784	0x9d, 0x57, 0x17, 0x73, 0x16, 0x23, 0x38, 0xc8, 0xd6, 0xf1, 0xba, 0xa3, 0x96,
785	0x5b, 0x16, 0x67, 0x4a, 0x4f, 0x73, 0x97, 0x3a, 0x4d, 0x14, 0xa4, 0xf4, 0xe2,
786	0x3f, 0x8b, 0x05, 0x83, 0x42, 0xd1, 0xd0, 0xdc, 0x2f, 0x7a, 0xe5, 0xb6, 0x10,
787	0xb2, 0x11, 0xc0, 0xdc, 0x21, 0x2a, 0x90, 0xff, 0xae, 0x97, 0x71, 0x5a, 0x49,
788	0x81, 0xac, 0x40, 0xf3, 0x3b, 0xb8, 0x59, 0xb2, 0x4f, 0x02, 0x03, 0x01, 0x00,
789	0x01, 0xa3, 0x82, 0x03, 0x21, 0x30, 0x82, 0x03, 0x1d, 0x30, 0x09, 0x06, 0x03,
790	0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86,
791	0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x06, 0x40,
792	0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x03, 0xf8,
793	0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08,
794	0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1d, 0x06, 0x03, 0x55,
795	0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x61, 0x8f, 0x61, 0x34, 0x43, 0x55, 0x14,
796	0x7f, 0x27, 0x09, 0xce, 0x4c, 0x8b, 0xea, 0x9b, 0x7b, 0x19, 0x25, 0xbc, 0x6e,
797	0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
798	0x0e, 0x07, 0x60, 0xd4, 0x39, 0xc9, 0x1b, 0x5b, 0x5d, 0x90, 0x7b, 0x23, 0xc8,
799	0xd2, 0x34, 0x9d, 0x4a, 0x9a, 0x46, 0x39, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d,
800	0x11, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x1d, 0x12, 0x04,
801	0x15, 0x30, 0x13, 0x81, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40,
802	0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x72, 0x06, 0x09,
803	0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x0d, 0x04, 0x65, 0x16, 0x63,
804	0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
805	0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e,
806	0x4f, 0x54, 0x20, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x45, 0x44, 0x2e,
807	0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x53, 0x65, 0x72, 0x76,
808	0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
809	0x65, 0x20, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x68,
810	0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70,
811	0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x2f, 0x06, 0x09, 0x60,
812	0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x02, 0x04, 0x22, 0x16, 0x20, 0x68,
813	0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70,
814	0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61,
815	0x32, 0x30, 0x30, 0x32, 0x2f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
816	0x86, 0xf8, 0x42, 0x01, 0x04, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70,
817	0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61,
818	0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30,
819	0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x43, 0x4c,
820	0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x46, 0x06, 0x09,
821	0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x03, 0x04, 0x39, 0x16, 0x37,
822	0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69,
823	0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63,
824	0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x72, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74,
825	0x69, 0x6f, 0x6e, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74,
826	0x6d, 0x6c, 0x3f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8,
827	0x42, 0x01, 0x07, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a,
828	0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63,
829	0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f,
830	0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41,
831	0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3f, 0x30, 0x41, 0x06, 0x09, 0x60, 0x86,
832	0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x08, 0x04, 0x34, 0x16, 0x32, 0x68, 0x74,
833	0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73,
834	0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32,
835	0x30, 0x30, 0x32, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x4c, 0x41,
836	0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x30, 0x81, 0x83, 0x06,
837	0x03, 0x55, 0x1d, 0x1f, 0x04, 0x7c, 0x30, 0x7a, 0x30, 0x39, 0xa0, 0x37, 0xa0,
838	0x35, 0x86, 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
839	0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70,
840	0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61,
841	0x32, 0x30, 0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63,
842	0x72, 0x6c, 0x30, 0x3d, 0xa0, 0x3b, 0xa0, 0x39, 0x86, 0x37, 0x68, 0x74, 0x74,
843	0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x69,
844	0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63,
845	0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30,
846	0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c,
847	0x30, 0x32, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04,
848	0x26, 0x30, 0x24, 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
849	0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63,
850	0x73, 0x70, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
851	0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
852	0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x68, 0xee, 0x79, 0x97, 0x97, 0xdd, 0x3b,
853	0xef, 0x16, 0x6a, 0x06, 0xf2, 0x14, 0x9a, 0x6e, 0xcd, 0x9e, 0x12, 0xf7, 0xaa,
854	0x83, 0x10, 0xbd, 0xd1, 0x7c, 0x98, 0xfa, 0xc7, 0xae, 0xd4, 0x0e, 0x2c, 0x9e,
855	0x38, 0x05, 0x9d, 0x52, 0x60, 0xa9, 0x99, 0x0a, 0x81, 0xb4, 0x98, 0x90, 0x1d,
856	0xae, 0xbb, 0x4a, 0xd7, 0xb9, 0xdc, 0x88, 0x9e, 0x37, 0x78, 0x41, 0x5b, 0xf7,
857	0x82, 0xa5, 0xf2, 0xba, 0x41, 0x25, 0x5a, 0x90, 0x1a, 0x1e, 0x45, 0x38, 0xa1,
858	0x52, 0x58, 0x75, 0x94, 0x26, 0x44, 0xfb, 0x20, 0x07, 0xba, 0x44, 0xcc, 0xe5,
859	0x4a, 0x2d, 0x72, 0x3f, 0x98, 0x47, 0xf6, 0x26, 0xdc, 0x05, 0x46, 0x05, 0x07,
860	0x63, 0x21, 0xab, 0x46, 0x9b, 0x9c, 0x78, 0xd5, 0x54, 0x5b, 0x3d, 0x0c, 0x1e,
861	0xc8, 0x64, 0x8c, 0xb5, 0x50, 0x23, 0x82, 0x6f, 0xdb, 0xb8, 0x22, 0x1c, 0x43,
862	0x96, 0x07, 0xa8, 0xbb,
863}
864
865var stringSliceTestData = [][]string{
866	{"foo", "bar"},
867	{"foo", "\\bar"},
868	{"foo", "\"bar\""},
869	{"foo", "åäö"},
870}
871
872func TestStringSlice(t *testing.T) {
873	for _, test := range stringSliceTestData {
874		bs, err := Marshal(test)
875		if err != nil {
876			t.Error(err)
877		}
878
879		var res []string
880		_, err = Unmarshal(bs, &res)
881		if err != nil {
882			t.Error(err)
883		}
884
885		if fmt.Sprintf("%v", res) != fmt.Sprintf("%v", test) {
886			t.Errorf("incorrect marshal/unmarshal; %v != %v", res, test)
887		}
888	}
889}
890
891type explicitTaggedTimeTest struct {
892	Time time.Time `asn1:"explicit,tag:0"`
893}
894
895var explicitTaggedTimeTestData = []struct {
896	in  []byte
897	out explicitTaggedTimeTest
898}{
899	{[]byte{0x30, 0x11, 0xa0, 0xf, 0x17, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'},
900		explicitTaggedTimeTest{time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC)}},
901	{[]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'},
902		explicitTaggedTimeTest{time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))}},
903}
904
905func TestExplicitTaggedTime(t *testing.T) {
906	// Test that a time.Time will match either tagUTCTime or
907	// tagGeneralizedTime.
908	for i, test := range explicitTaggedTimeTestData {
909		var got explicitTaggedTimeTest
910		_, err := Unmarshal(test.in, &got)
911		if err != nil {
912			t.Errorf("Unmarshal failed at index %d %v", i, err)
913		}
914		if !got.Time.Equal(test.out.Time) {
915			t.Errorf("#%d: got %v, want %v", i, got.Time, test.out.Time)
916		}
917	}
918}
919
920type implicitTaggedTimeTest struct {
921	Time time.Time `asn1:"tag:24"`
922}
923
924func TestImplicitTaggedTime(t *testing.T) {
925	// An implicitly tagged time value, that happens to have an implicit
926	// tag equal to a GENERALIZEDTIME, should still be parsed as a UTCTime.
927	// (There's no "timeType" in fieldParameters to determine what type of
928	// time should be expected when implicitly tagged.)
929	der := []byte{0x30, 0x0f, 0x80 | 24, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'}
930	var result implicitTaggedTimeTest
931	if _, err := Unmarshal(der, &result); err != nil {
932		t.Fatalf("Error while parsing: %s", err)
933	}
934	if expected := time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC); !result.Time.Equal(expected) {
935		t.Errorf("Wrong result. Got %v, want %v", result.Time, expected)
936	}
937}
938
939type truncatedExplicitTagTest struct {
940	Test int `asn1:"explicit,tag:0"`
941}
942
943func TestTruncatedExplicitTag(t *testing.T) {
944	// This crashed Unmarshal in the past. See #11154.
945	der := []byte{
946		0x30, // SEQUENCE
947		0x02, // two bytes long
948		0xa0, // context-specific, tag 0
949		0x30, // 48 bytes long
950	}
951
952	var result truncatedExplicitTagTest
953	if _, err := Unmarshal(der, &result); err == nil {
954		t.Error("Unmarshal returned without error")
955	}
956}
957
958type invalidUTF8Test struct {
959	Str string `asn1:"utf8"`
960}
961
962func TestUnmarshalInvalidUTF8(t *testing.T) {
963	data := []byte("0\x05\f\x03a\xc9c")
964	var result invalidUTF8Test
965	_, err := Unmarshal(data, &result)
966
967	const expectedSubstring = "UTF"
968	if err == nil {
969		t.Fatal("Successfully unmarshaled invalid UTF-8 data")
970	} else if !strings.Contains(err.Error(), expectedSubstring) {
971		t.Fatalf("Expected error to mention %q but error was %q", expectedSubstring, err.Error())
972	}
973}
974
975func TestMarshalNilValue(t *testing.T) {
976	nilValueTestData := []interface{}{
977		nil,
978		struct{ V interface{} }{},
979	}
980	for i, test := range nilValueTestData {
981		if _, err := Marshal(test); err == nil {
982			t.Fatalf("#%d: successfully marshaled nil value", i)
983		}
984	}
985}
986
987type unexported struct {
988	X int
989	y int
990}
991
992type exported struct {
993	X int
994	Y int
995}
996
997func TestUnexportedStructField(t *testing.T) {
998	want := StructuralError{"struct contains unexported fields"}
999
1000	_, err := Marshal(unexported{X: 5, y: 1})
1001	if err != want {
1002		t.Errorf("got %v, want %v", err, want)
1003	}
1004
1005	bs, err := Marshal(exported{X: 5, Y: 1})
1006	if err != nil {
1007		t.Fatal(err)
1008	}
1009	var u unexported
1010	_, err = Unmarshal(bs, &u)
1011	if err != want {
1012		t.Errorf("got %v, want %v", err, want)
1013	}
1014}
1015
1016func TestNull(t *testing.T) {
1017	marshaled, err := Marshal(NullRawValue)
1018	if err != nil {
1019		t.Fatal(err)
1020	}
1021	if !bytes.Equal(NullBytes, marshaled) {
1022		t.Errorf("Expected Marshal of NullRawValue to yield %x, got %x", NullBytes, marshaled)
1023	}
1024
1025	unmarshaled := RawValue{}
1026	if _, err := Unmarshal(NullBytes, &unmarshaled); err != nil {
1027		t.Fatal(err)
1028	}
1029
1030	unmarshaled.FullBytes = NullRawValue.FullBytes
1031	if len(unmarshaled.Bytes) == 0 {
1032		// DeepEqual considers a nil slice and an empty slice to be different.
1033		unmarshaled.Bytes = NullRawValue.Bytes
1034	}
1035
1036	if !reflect.DeepEqual(NullRawValue, unmarshaled) {
1037		t.Errorf("Expected Unmarshal of NullBytes to yield %v, got %v", NullRawValue, unmarshaled)
1038	}
1039}
1040
1041func TestExplicitTagRawValueStruct(t *testing.T) {
1042	type foo struct {
1043		A RawValue `asn1:"optional,explicit,tag:5"`
1044		B []byte   `asn1:"optional,explicit,tag:6"`
1045	}
1046	before := foo{B: []byte{1, 2, 3}}
1047	derBytes, err := Marshal(before)
1048	if err != nil {
1049		t.Fatal(err)
1050	}
1051
1052	var after foo
1053	if rest, err := Unmarshal(derBytes, &after); err != nil || len(rest) != 0 {
1054		t.Fatal(err)
1055	}
1056
1057	got := fmt.Sprintf("%#v", after)
1058	want := fmt.Sprintf("%#v", before)
1059	if got != want {
1060		t.Errorf("got %s, want %s (DER: %x)", got, want, derBytes)
1061	}
1062}
1063
1064func TestTaggedRawValue(t *testing.T) {
1065	type taggedRawValue struct {
1066		A RawValue `asn1:"tag:5"`
1067	}
1068	type untaggedRawValue struct {
1069		A RawValue
1070	}
1071	const isCompound = 0x20
1072	const tag = 5
1073
1074	tests := []struct {
1075		shouldMatch bool
1076		derBytes    []byte
1077	}{
1078		{false, []byte{0x30, 3, TagInteger, 1, 1}},
1079		{true, []byte{0x30, 3, (ClassContextSpecific << 6) | tag, 1, 1}},
1080		{true, []byte{0x30, 3, (ClassContextSpecific << 6) | tag | isCompound, 1, 1}},
1081		{false, []byte{0x30, 3, (ClassApplication << 6) | tag | isCompound, 1, 1}},
1082	}
1083
1084	for i, test := range tests {
1085		var tagged taggedRawValue
1086		if _, err := Unmarshal(test.derBytes, &tagged); (err == nil) != test.shouldMatch {
1087			t.Errorf("#%d: unexpected result parsing %x: %s", i, test.derBytes, err)
1088		}
1089
1090		// An untagged RawValue should accept anything.
1091		var untagged untaggedRawValue
1092		if _, err := Unmarshal(test.derBytes, &untagged); err != nil {
1093			t.Errorf("#%d: unexpected failure parsing %x with untagged RawValue: %s", i, test.derBytes, err)
1094		}
1095	}
1096}
1097