1
2
3
4
5
6
7
8
9
10 package asn1
11
12
13
14
15
16
17
18
19
20
21
22 import (
23 "errors"
24 "fmt"
25 "math"
26 "math/big"
27 "reflect"
28 "strconv"
29 "strings"
30 "time"
31 "unicode/utf16"
32 "unicode/utf8"
33 )
34
35
36
37 type StructuralError struct {
38 Msg string
39 }
40
41 func (e StructuralError) Error() string { return "asn1: structure error: " + e.Msg }
42
43
44 type SyntaxError struct {
45 Msg string
46 }
47
48 func (e SyntaxError) Error() string { return "asn1: syntax error: " + e.Msg }
49
50
51
52
53
54 func parseBool(bytes []byte) (ret bool, err error) {
55 if len(bytes) != 1 {
56 err = SyntaxError{"invalid boolean"}
57 return
58 }
59
60
61
62
63 switch bytes[0] {
64 case 0:
65 ret = false
66 case 0xff:
67 ret = true
68 default:
69 err = SyntaxError{"invalid boolean"}
70 }
71
72 return
73 }
74
75
76
77
78
79 func checkInteger(bytes []byte) error {
80 if len(bytes) == 0 {
81 return StructuralError{"empty integer"}
82 }
83 if len(bytes) == 1 {
84 return nil
85 }
86 if (bytes[0] == 0 && bytes[1]&0x80 == 0) || (bytes[0] == 0xff && bytes[1]&0x80 == 0x80) {
87 return StructuralError{"integer not minimally-encoded"}
88 }
89 return nil
90 }
91
92
93
94 func parseInt64(bytes []byte) (ret int64, err error) {
95 err = checkInteger(bytes)
96 if err != nil {
97 return
98 }
99 if len(bytes) > 8 {
100
101 err = StructuralError{"integer too large"}
102 return
103 }
104 for bytesRead := 0; bytesRead < len(bytes); bytesRead++ {
105 ret <<= 8
106 ret |= int64(bytes[bytesRead])
107 }
108
109
110 ret <<= 64 - uint8(len(bytes))*8
111 ret >>= 64 - uint8(len(bytes))*8
112 return
113 }
114
115
116
117 func parseInt32(bytes []byte) (int32, error) {
118 if err := checkInteger(bytes); err != nil {
119 return 0, err
120 }
121 ret64, err := parseInt64(bytes)
122 if err != nil {
123 return 0, err
124 }
125 if ret64 != int64(int32(ret64)) {
126 return 0, StructuralError{"integer too large"}
127 }
128 return int32(ret64), nil
129 }
130
131 var bigOne = big.NewInt(1)
132
133
134
135 func parseBigInt(bytes []byte) (*big.Int, error) {
136 if err := checkInteger(bytes); err != nil {
137 return nil, err
138 }
139 ret := new(big.Int)
140 if len(bytes) > 0 && bytes[0]&0x80 == 0x80 {
141
142 notBytes := make([]byte, len(bytes))
143 for i := range notBytes {
144 notBytes[i] = ^bytes[i]
145 }
146 ret.SetBytes(notBytes)
147 ret.Add(ret, bigOne)
148 ret.Neg(ret)
149 return ret, nil
150 }
151 ret.SetBytes(bytes)
152 return ret, nil
153 }
154
155
156
157
158
159
160 type BitString struct {
161 Bytes []byte
162 BitLength int
163 }
164
165
166
167 func (b BitString) At(i int) int {
168 if i < 0 || i >= b.BitLength {
169 return 0
170 }
171 x := i / 8
172 y := 7 - uint(i%8)
173 return int(b.Bytes[x]>>y) & 1
174 }
175
176
177
178 func (b BitString) RightAlign() []byte {
179 shift := uint(8 - (b.BitLength % 8))
180 if shift == 8 || len(b.Bytes) == 0 {
181 return b.Bytes
182 }
183
184 a := make([]byte, len(b.Bytes))
185 a[0] = b.Bytes[0] >> shift
186 for i := 1; i < len(b.Bytes); i++ {
187 a[i] = b.Bytes[i-1] << (8 - shift)
188 a[i] |= b.Bytes[i] >> shift
189 }
190
191 return a
192 }
193
194
195 func parseBitString(bytes []byte) (ret BitString, err error) {
196 if len(bytes) == 0 {
197 err = SyntaxError{"zero length BIT STRING"}
198 return
199 }
200 paddingBits := int(bytes[0])
201 if paddingBits > 7 ||
202 len(bytes) == 1 && paddingBits > 0 ||
203 bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 {
204 err = SyntaxError{"invalid padding bits in BIT STRING"}
205 return
206 }
207 ret.BitLength = (len(bytes)-1)*8 - paddingBits
208 ret.Bytes = bytes[1:]
209 return
210 }
211
212
213
214
215 var NullRawValue = RawValue{Tag: TagNull}
216
217
218 var NullBytes = []byte{TagNull, 0}
219
220
221
222
223 type ObjectIdentifier []int
224
225
226 func (oi ObjectIdentifier) Equal(other ObjectIdentifier) bool {
227 if len(oi) != len(other) {
228 return false
229 }
230 for i := 0; i < len(oi); i++ {
231 if oi[i] != other[i] {
232 return false
233 }
234 }
235
236 return true
237 }
238
239 func (oi ObjectIdentifier) String() string {
240 var s strings.Builder
241 s.Grow(32)
242
243 buf := make([]byte, 0, 19)
244 for i, v := range oi {
245 if i > 0 {
246 s.WriteByte('.')
247 }
248 s.Write(strconv.AppendInt(buf, int64(v), 10))
249 }
250
251 return s.String()
252 }
253
254
255
256
257 func parseObjectIdentifier(bytes []byte) (s ObjectIdentifier, err error) {
258 if len(bytes) == 0 {
259 err = SyntaxError{"zero length OBJECT IDENTIFIER"}
260 return
261 }
262
263
264
265 s = make([]int, len(bytes)+1)
266
267
268
269
270
271 v, offset, err := parseBase128Int(bytes, 0)
272 if err != nil {
273 return
274 }
275 if v < 80 {
276 s[0] = v / 40
277 s[1] = v % 40
278 } else {
279 s[0] = 2
280 s[1] = v - 80
281 }
282
283 i := 2
284 for ; offset < len(bytes); i++ {
285 v, offset, err = parseBase128Int(bytes, offset)
286 if err != nil {
287 return
288 }
289 s[i] = v
290 }
291 s = s[0:i]
292 return
293 }
294
295
296
297
298 type Enumerated int
299
300
301
302
303 type Flag bool
304
305
306
307 func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) {
308 offset = initOffset
309 var ret64 int64
310 for shifted := 0; offset < len(bytes); shifted++ {
311
312
313 if shifted == 5 {
314 err = StructuralError{"base 128 integer too large"}
315 return
316 }
317 ret64 <<= 7
318 b := bytes[offset]
319
320
321 if shifted == 0 && b == 0x80 {
322 err = SyntaxError{"integer is not minimally encoded"}
323 return
324 }
325 ret64 |= int64(b & 0x7f)
326 offset++
327 if b&0x80 == 0 {
328 ret = int(ret64)
329
330 if ret64 > math.MaxInt32 {
331 err = StructuralError{"base 128 integer too large"}
332 }
333 return
334 }
335 }
336 err = SyntaxError{"truncated base 128 integer"}
337 return
338 }
339
340
341
342 func parseUTCTime(bytes []byte) (ret time.Time, err error) {
343 s := string(bytes)
344
345 formatStr := "0601021504Z0700"
346 ret, err = time.Parse(formatStr, s)
347 if err != nil {
348 formatStr = "060102150405Z0700"
349 ret, err = time.Parse(formatStr, s)
350 }
351 if err != nil {
352 return
353 }
354
355 if serialized := ret.Format(formatStr); serialized != s {
356 err = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", s, serialized)
357 return
358 }
359
360 if ret.Year() >= 2050 {
361
362 ret = ret.AddDate(-100, 0, 0)
363 }
364
365 return
366 }
367
368
369
370 func parseGeneralizedTime(bytes []byte) (ret time.Time, err error) {
371 const formatStr = "20060102150405.999999999Z0700"
372 s := string(bytes)
373
374 if ret, err = time.Parse(formatStr, s); err != nil {
375 return
376 }
377
378 if serialized := ret.Format(formatStr); serialized != s {
379 err = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", s, serialized)
380 }
381
382 return
383 }
384
385
386
387
388
389 func parseNumericString(bytes []byte) (ret string, err error) {
390 for _, b := range bytes {
391 if !isNumeric(b) {
392 return "", SyntaxError{"NumericString contains invalid character"}
393 }
394 }
395 return string(bytes), nil
396 }
397
398
399 func isNumeric(b byte) bool {
400 return '0' <= b && b <= '9' ||
401 b == ' '
402 }
403
404
405
406
407
408 func parsePrintableString(bytes []byte) (ret string, err error) {
409 for _, b := range bytes {
410 if !isPrintable(b, allowAsterisk, allowAmpersand) {
411 err = SyntaxError{"PrintableString contains invalid character"}
412 return
413 }
414 }
415 ret = string(bytes)
416 return
417 }
418
419 type asteriskFlag bool
420 type ampersandFlag bool
421
422 const (
423 allowAsterisk asteriskFlag = true
424 rejectAsterisk asteriskFlag = false
425
426 allowAmpersand ampersandFlag = true
427 rejectAmpersand ampersandFlag = false
428 )
429
430
431
432
433 func isPrintable(b byte, asterisk asteriskFlag, ampersand ampersandFlag) bool {
434 return 'a' <= b && b <= 'z' ||
435 'A' <= b && b <= 'Z' ||
436 '0' <= b && b <= '9' ||
437 '\'' <= b && b <= ')' ||
438 '+' <= b && b <= '/' ||
439 b == ' ' ||
440 b == ':' ||
441 b == '=' ||
442 b == '?' ||
443
444
445
446 (bool(asterisk) && b == '*') ||
447
448
449
450
451 (bool(ampersand) && b == '&')
452 }
453
454
455
456
457
458 func parseIA5String(bytes []byte) (ret string, err error) {
459 for _, b := range bytes {
460 if b >= utf8.RuneSelf {
461 err = SyntaxError{"IA5String contains invalid character"}
462 return
463 }
464 }
465 ret = string(bytes)
466 return
467 }
468
469
470
471
472
473 func parseT61String(bytes []byte) (ret string, err error) {
474 return string(bytes), nil
475 }
476
477
478
479
480
481 func parseUTF8String(bytes []byte) (ret string, err error) {
482 if !utf8.Valid(bytes) {
483 return "", errors.New("asn1: invalid UTF-8 string")
484 }
485 return string(bytes), nil
486 }
487
488
489
490
491
492 func parseBMPString(bmpString []byte) (string, error) {
493 if len(bmpString)%2 != 0 {
494 return "", errors.New("pkcs12: odd-length BMP string")
495 }
496
497
498 if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 {
499 bmpString = bmpString[:l-2]
500 }
501
502 s := make([]uint16, 0, len(bmpString)/2)
503 for len(bmpString) > 0 {
504 s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1]))
505 bmpString = bmpString[2:]
506 }
507
508 return string(utf16.Decode(s)), nil
509 }
510
511
512 type RawValue struct {
513 Class, Tag int
514 IsCompound bool
515 Bytes []byte
516 FullBytes []byte
517 }
518
519
520
521
522 type RawContent []byte
523
524
525
526
527
528
529
530 func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err error) {
531 offset = initOffset
532
533
534 if offset >= len(bytes) {
535 err = errors.New("asn1: internal error in parseTagAndLength")
536 return
537 }
538 b := bytes[offset]
539 offset++
540 ret.class = int(b >> 6)
541 ret.isCompound = b&0x20 == 0x20
542 ret.tag = int(b & 0x1f)
543
544
545
546 if ret.tag == 0x1f {
547 ret.tag, offset, err = parseBase128Int(bytes, offset)
548 if err != nil {
549 return
550 }
551
552 if ret.tag < 0x1f {
553 err = SyntaxError{"non-minimal tag"}
554 return
555 }
556 }
557 if offset >= len(bytes) {
558 err = SyntaxError{"truncated tag or length"}
559 return
560 }
561 b = bytes[offset]
562 offset++
563 if b&0x80 == 0 {
564
565 ret.length = int(b & 0x7f)
566 } else {
567
568 numBytes := int(b & 0x7f)
569 if numBytes == 0 {
570 err = SyntaxError{"indefinite length found (not DER)"}
571 return
572 }
573 ret.length = 0
574 for i := 0; i < numBytes; i++ {
575 if offset >= len(bytes) {
576 err = SyntaxError{"truncated tag or length"}
577 return
578 }
579 b = bytes[offset]
580 offset++
581 if ret.length >= 1<<23 {
582
583
584 err = StructuralError{"length too large"}
585 return
586 }
587 ret.length <<= 8
588 ret.length |= int(b)
589 if ret.length == 0 {
590
591 err = StructuralError{"superfluous leading zeros in length"}
592 return
593 }
594 }
595
596 if ret.length < 0x80 {
597 err = StructuralError{"non-minimal length"}
598 return
599 }
600 }
601
602 return
603 }
604
605
606
607
608 func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err error) {
609 matchAny, expectedTag, compoundType, ok := getUniversalType(elemType)
610 if !ok {
611 err = StructuralError{"unknown Go type for slice"}
612 return
613 }
614
615
616
617 numElements := 0
618 for offset := 0; offset < len(bytes); {
619 var t tagAndLength
620 t, offset, err = parseTagAndLength(bytes, offset)
621 if err != nil {
622 return
623 }
624 switch t.tag {
625 case TagIA5String, TagGeneralString, TagT61String, TagUTF8String, TagNumericString, TagBMPString:
626
627
628
629 t.tag = TagPrintableString
630 case TagGeneralizedTime, TagUTCTime:
631
632 t.tag = TagUTCTime
633 }
634
635 if !matchAny && (t.class != ClassUniversal || t.isCompound != compoundType || t.tag != expectedTag) {
636 err = StructuralError{"sequence tag mismatch"}
637 return
638 }
639 if invalidLength(offset, t.length, len(bytes)) {
640 err = SyntaxError{"truncated sequence"}
641 return
642 }
643 offset += t.length
644 numElements++
645 }
646 ret = reflect.MakeSlice(sliceType, numElements, numElements)
647 params := fieldParameters{}
648 offset := 0
649 for i := 0; i < numElements; i++ {
650 offset, err = parseField(ret.Index(i), bytes, offset, params)
651 if err != nil {
652 return
653 }
654 }
655 return
656 }
657
658 var (
659 bitStringType = reflect.TypeFor[BitString]()
660 objectIdentifierType = reflect.TypeFor[ObjectIdentifier]()
661 enumeratedType = reflect.TypeFor[Enumerated]()
662 flagType = reflect.TypeFor[Flag]()
663 timeType = reflect.TypeFor[time.Time]()
664 rawValueType = reflect.TypeFor[RawValue]()
665 rawContentsType = reflect.TypeFor[RawContent]()
666 bigIntType = reflect.TypeFor[*big.Int]()
667 )
668
669
670
671 func invalidLength(offset, length, sliceLength int) bool {
672 return offset+length < offset || offset+length > sliceLength
673 }
674
675
676
677
678 func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err error) {
679 offset = initOffset
680 fieldType := v.Type()
681
682
683 if offset == len(bytes) {
684 if !setDefaultValue(v, params) {
685 err = SyntaxError{"sequence truncated"}
686 }
687 return
688 }
689
690
691 if ifaceType := fieldType; ifaceType.Kind() == reflect.Interface && ifaceType.NumMethod() == 0 {
692 var t tagAndLength
693 t, offset, err = parseTagAndLength(bytes, offset)
694 if err != nil {
695 return
696 }
697 if invalidLength(offset, t.length, len(bytes)) {
698 err = SyntaxError{"data truncated"}
699 return
700 }
701 var result any
702 if !t.isCompound && t.class == ClassUniversal {
703 innerBytes := bytes[offset : offset+t.length]
704 switch t.tag {
705 case TagPrintableString:
706 result, err = parsePrintableString(innerBytes)
707 case TagNumericString:
708 result, err = parseNumericString(innerBytes)
709 case TagIA5String:
710 result, err = parseIA5String(innerBytes)
711 case TagT61String:
712 result, err = parseT61String(innerBytes)
713 case TagUTF8String:
714 result, err = parseUTF8String(innerBytes)
715 case TagInteger:
716 result, err = parseInt64(innerBytes)
717 case TagBitString:
718 result, err = parseBitString(innerBytes)
719 case TagOID:
720 result, err = parseObjectIdentifier(innerBytes)
721 case TagUTCTime:
722 result, err = parseUTCTime(innerBytes)
723 case TagGeneralizedTime:
724 result, err = parseGeneralizedTime(innerBytes)
725 case TagOctetString:
726 result = innerBytes
727 case TagBMPString:
728 result, err = parseBMPString(innerBytes)
729 default:
730
731 }
732 }
733 offset += t.length
734 if err != nil {
735 return
736 }
737 if result != nil {
738 v.Set(reflect.ValueOf(result))
739 }
740 return
741 }
742
743 t, offset, err := parseTagAndLength(bytes, offset)
744 if err != nil {
745 return
746 }
747 if params.explicit {
748 expectedClass := ClassContextSpecific
749 if params.application {
750 expectedClass = ClassApplication
751 }
752 if offset == len(bytes) {
753 err = StructuralError{"explicit tag has no child"}
754 return
755 }
756 if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) {
757 if fieldType == rawValueType {
758
759 } else if t.length > 0 {
760 t, offset, err = parseTagAndLength(bytes, offset)
761 if err != nil {
762 return
763 }
764 } else {
765 if fieldType != flagType {
766 err = StructuralError{"zero length explicit tag was not an asn1.Flag"}
767 return
768 }
769 v.SetBool(true)
770 return
771 }
772 } else {
773
774 ok := setDefaultValue(v, params)
775 if ok {
776 offset = initOffset
777 } else {
778 err = StructuralError{"explicitly tagged member didn't match"}
779 }
780 return
781 }
782 }
783
784 matchAny, universalTag, compoundType, ok1 := getUniversalType(fieldType)
785 if !ok1 {
786 err = StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)}
787 return
788 }
789
790
791
792
793
794 if universalTag == TagPrintableString {
795 if t.class == ClassUniversal {
796 switch t.tag {
797 case TagIA5String, TagGeneralString, TagT61String, TagUTF8String, TagNumericString, TagBMPString:
798 universalTag = t.tag
799 }
800 } else if params.stringType != 0 {
801 universalTag = params.stringType
802 }
803 }
804
805
806
807 if universalTag == TagUTCTime && t.tag == TagGeneralizedTime && t.class == ClassUniversal {
808 universalTag = TagGeneralizedTime
809 }
810
811 if params.set {
812 universalTag = TagSet
813 }
814
815 matchAnyClassAndTag := matchAny
816 expectedClass := ClassUniversal
817 expectedTag := universalTag
818
819 if !params.explicit && params.tag != nil {
820 expectedClass = ClassContextSpecific
821 expectedTag = *params.tag
822 matchAnyClassAndTag = false
823 }
824
825 if !params.explicit && params.application && params.tag != nil {
826 expectedClass = ClassApplication
827 expectedTag = *params.tag
828 matchAnyClassAndTag = false
829 }
830
831 if !params.explicit && params.private && params.tag != nil {
832 expectedClass = ClassPrivate
833 expectedTag = *params.tag
834 matchAnyClassAndTag = false
835 }
836
837
838 if !matchAnyClassAndTag && (t.class != expectedClass || t.tag != expectedTag) ||
839 (!matchAny && t.isCompound != compoundType) {
840
841 ok := setDefaultValue(v, params)
842 if ok {
843 offset = initOffset
844 } else {
845 err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", expectedTag, t, params, fieldType.Name(), offset)}
846 }
847 return
848 }
849 if invalidLength(offset, t.length, len(bytes)) {
850 err = SyntaxError{"data truncated"}
851 return
852 }
853 innerBytes := bytes[offset : offset+t.length]
854 offset += t.length
855
856
857 switch v := v.Addr().Interface().(type) {
858 case *RawValue:
859 *v = RawValue{t.class, t.tag, t.isCompound, innerBytes, bytes[initOffset:offset]}
860 return
861 case *ObjectIdentifier:
862 *v, err = parseObjectIdentifier(innerBytes)
863 return
864 case *BitString:
865 *v, err = parseBitString(innerBytes)
866 return
867 case *time.Time:
868 if universalTag == TagUTCTime {
869 *v, err = parseUTCTime(innerBytes)
870 return
871 }
872 *v, err = parseGeneralizedTime(innerBytes)
873 return
874 case *Enumerated:
875 parsedInt, err1 := parseInt32(innerBytes)
876 if err1 == nil {
877 *v = Enumerated(parsedInt)
878 }
879 err = err1
880 return
881 case *Flag:
882 *v = true
883 return
884 case **big.Int:
885 parsedInt, err1 := parseBigInt(innerBytes)
886 if err1 == nil {
887 *v = parsedInt
888 }
889 err = err1
890 return
891 }
892 switch val := v; val.Kind() {
893 case reflect.Bool:
894 parsedBool, err1 := parseBool(innerBytes)
895 if err1 == nil {
896 val.SetBool(parsedBool)
897 }
898 err = err1
899 return
900 case reflect.Int, reflect.Int32, reflect.Int64:
901 if val.Type().Size() == 4 {
902 parsedInt, err1 := parseInt32(innerBytes)
903 if err1 == nil {
904 val.SetInt(int64(parsedInt))
905 }
906 err = err1
907 } else {
908 parsedInt, err1 := parseInt64(innerBytes)
909 if err1 == nil {
910 val.SetInt(parsedInt)
911 }
912 err = err1
913 }
914 return
915
916 case reflect.Struct:
917 structType := fieldType
918
919 for i := 0; i < structType.NumField(); i++ {
920 if !structType.Field(i).IsExported() {
921 err = StructuralError{"struct contains unexported fields"}
922 return
923 }
924 }
925
926 if structType.NumField() > 0 &&
927 structType.Field(0).Type == rawContentsType {
928 bytes := bytes[initOffset:offset]
929 val.Field(0).Set(reflect.ValueOf(RawContent(bytes)))
930 }
931
932 innerOffset := 0
933 for i := 0; i < structType.NumField(); i++ {
934 field := structType.Field(i)
935 if i == 0 && field.Type == rawContentsType {
936 continue
937 }
938 innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag.Get("asn1")))
939 if err != nil {
940 return
941 }
942 }
943
944
945
946 return
947 case reflect.Slice:
948 sliceType := fieldType
949 if sliceType.Elem().Kind() == reflect.Uint8 {
950 val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes)))
951 reflect.Copy(val, reflect.ValueOf(innerBytes))
952 return
953 }
954 newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem())
955 if err1 == nil {
956 val.Set(newSlice)
957 }
958 err = err1
959 return
960 case reflect.String:
961 var v string
962 switch universalTag {
963 case TagPrintableString:
964 v, err = parsePrintableString(innerBytes)
965 case TagNumericString:
966 v, err = parseNumericString(innerBytes)
967 case TagIA5String:
968 v, err = parseIA5String(innerBytes)
969 case TagT61String:
970 v, err = parseT61String(innerBytes)
971 case TagUTF8String:
972 v, err = parseUTF8String(innerBytes)
973 case TagGeneralString:
974
975
976
977
978 v, err = parseT61String(innerBytes)
979 case TagBMPString:
980 v, err = parseBMPString(innerBytes)
981
982 default:
983 err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)}
984 }
985 if err == nil {
986 val.SetString(v)
987 }
988 return
989 }
990 err = StructuralError{"unsupported: " + v.Type().String()}
991 return
992 }
993
994
995
996 func canHaveDefaultValue(k reflect.Kind) bool {
997 switch k {
998 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
999 return true
1000 }
1001
1002 return false
1003 }
1004
1005
1006
1007
1008 func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
1009 if !params.optional {
1010 return
1011 }
1012 ok = true
1013 if params.defaultValue == nil {
1014 return
1015 }
1016 if canHaveDefaultValue(v.Kind()) {
1017 v.SetInt(*params.defaultValue)
1018 }
1019 return
1020 }
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091 func Unmarshal(b []byte, val any) (rest []byte, err error) {
1092 return UnmarshalWithParams(b, val, "")
1093 }
1094
1095
1096
1097 type invalidUnmarshalError struct {
1098 Type reflect.Type
1099 }
1100
1101 func (e *invalidUnmarshalError) Error() string {
1102 if e.Type == nil {
1103 return "asn1: Unmarshal recipient value is nil"
1104 }
1105
1106 if e.Type.Kind() != reflect.Pointer {
1107 return "asn1: Unmarshal recipient value is non-pointer " + e.Type.String()
1108 }
1109 return "asn1: Unmarshal recipient value is nil " + e.Type.String()
1110 }
1111
1112
1113
1114 func UnmarshalWithParams(b []byte, val any, params string) (rest []byte, err error) {
1115 v := reflect.ValueOf(val)
1116 if v.Kind() != reflect.Pointer || v.IsNil() {
1117 return nil, &invalidUnmarshalError{reflect.TypeOf(val)}
1118 }
1119 offset, err := parseField(v.Elem(), b, 0, parseFieldParameters(params))
1120 if err != nil {
1121 return nil, err
1122 }
1123 return b[offset:], nil
1124 }
1125
View as plain text