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