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