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