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