1
2
3
4
5 package asn1
6
7 import (
8 "bytes"
9 "errors"
10 "fmt"
11 "math/big"
12 "reflect"
13 "sort"
14 "time"
15 "unicode/utf8"
16 )
17
18 var (
19 byte00Encoder encoder = byteEncoder(0x00)
20 byteFFEncoder encoder = byteEncoder(0xff)
21 )
22
23
24 type encoder interface {
25
26 Len() int
27
28 Encode(dst []byte)
29 }
30
31 type byteEncoder byte
32
33 func (c byteEncoder) Len() int {
34 return 1
35 }
36
37 func (c byteEncoder) Encode(dst []byte) {
38 dst[0] = byte(c)
39 }
40
41 type bytesEncoder []byte
42
43 func (b bytesEncoder) Len() int {
44 return len(b)
45 }
46
47 func (b bytesEncoder) Encode(dst []byte) {
48 if copy(dst, b) != len(b) {
49 panic("internal error")
50 }
51 }
52
53 type stringEncoder string
54
55 func (s stringEncoder) Len() int {
56 return len(s)
57 }
58
59 func (s stringEncoder) Encode(dst []byte) {
60 if copy(dst, s) != len(s) {
61 panic("internal error")
62 }
63 }
64
65 type multiEncoder []encoder
66
67 func (m multiEncoder) Len() int {
68 var size int
69 for _, e := range m {
70 size += e.Len()
71 }
72 return size
73 }
74
75 func (m multiEncoder) Encode(dst []byte) {
76 var off int
77 for _, e := range m {
78 e.Encode(dst[off:])
79 off += e.Len()
80 }
81 }
82
83 type setEncoder []encoder
84
85 func (s setEncoder) Len() int {
86 var size int
87 for _, e := range s {
88 size += e.Len()
89 }
90 return size
91 }
92
93 func (s setEncoder) Encode(dst []byte) {
94
95
96
97
98
99
100
101
102 l := make([][]byte, len(s))
103 for i, e := range s {
104 l[i] = make([]byte, e.Len())
105 e.Encode(l[i])
106 }
107
108 sort.Slice(l, func(i, j int) bool {
109
110
111
112
113
114
115 return bytes.Compare(l[i], l[j]) < 0
116 })
117
118 var off int
119 for _, b := range l {
120 copy(dst[off:], b)
121 off += len(b)
122 }
123 }
124
125 type taggedEncoder struct {
126
127
128 scratch [8]byte
129 tag encoder
130 body encoder
131 }
132
133 func (t *taggedEncoder) Len() int {
134 return t.tag.Len() + t.body.Len()
135 }
136
137 func (t *taggedEncoder) Encode(dst []byte) {
138 t.tag.Encode(dst)
139 t.body.Encode(dst[t.tag.Len():])
140 }
141
142 type int64Encoder int64
143
144 func (i int64Encoder) Len() int {
145 n := 1
146
147 for i > 127 {
148 n++
149 i >>= 8
150 }
151
152 for i < -128 {
153 n++
154 i >>= 8
155 }
156
157 return n
158 }
159
160 func (i int64Encoder) Encode(dst []byte) {
161 n := i.Len()
162
163 for j := 0; j < n; j++ {
164 dst[j] = byte(i >> uint((n-1-j)*8))
165 }
166 }
167
168 func base128IntLength(n int64) int {
169 if n == 0 {
170 return 1
171 }
172
173 l := 0
174 for i := n; i > 0; i >>= 7 {
175 l++
176 }
177
178 return l
179 }
180
181 func appendBase128Int(dst []byte, n int64) []byte {
182 l := base128IntLength(n)
183
184 for i := l - 1; i >= 0; i-- {
185 o := byte(n >> uint(i*7))
186 o &= 0x7f
187 if i != 0 {
188 o |= 0x80
189 }
190
191 dst = append(dst, o)
192 }
193
194 return dst
195 }
196
197 func makeBigInt(n *big.Int) (encoder, error) {
198 if n == nil {
199 return nil, StructuralError{"empty integer"}
200 }
201
202 if n.Sign() < 0 {
203
204
205
206
207 nMinus1 := new(big.Int).Neg(n)
208 nMinus1.Sub(nMinus1, bigOne)
209 bytes := nMinus1.Bytes()
210 for i := range bytes {
211 bytes[i] ^= 0xff
212 }
213 if len(bytes) == 0 || bytes[0]&0x80 == 0 {
214 return multiEncoder([]encoder{byteFFEncoder, bytesEncoder(bytes)}), nil
215 }
216 return bytesEncoder(bytes), nil
217 } else if n.Sign() == 0 {
218
219 return byte00Encoder, nil
220 } else {
221 bytes := n.Bytes()
222 if len(bytes) > 0 && bytes[0]&0x80 != 0 {
223
224
225 return multiEncoder([]encoder{byte00Encoder, bytesEncoder(bytes)}), nil
226 }
227 return bytesEncoder(bytes), nil
228 }
229 }
230
231 func appendLength(dst []byte, i int) []byte {
232 n := lengthLength(i)
233
234 for ; n > 0; n-- {
235 dst = append(dst, byte(i>>uint((n-1)*8)))
236 }
237
238 return dst
239 }
240
241 func lengthLength(i int) (numBytes int) {
242 numBytes = 1
243 for i > 255 {
244 numBytes++
245 i >>= 8
246 }
247 return
248 }
249
250 func appendTagAndLength(dst []byte, t tagAndLength) []byte {
251 b := uint8(t.class) << 6
252 if t.isCompound {
253 b |= 0x20
254 }
255 if t.tag >= 31 {
256 b |= 0x1f
257 dst = append(dst, b)
258 dst = appendBase128Int(dst, int64(t.tag))
259 } else {
260 b |= uint8(t.tag)
261 dst = append(dst, b)
262 }
263
264 if t.length >= 128 {
265 l := lengthLength(t.length)
266 dst = append(dst, 0x80|byte(l))
267 dst = appendLength(dst, t.length)
268 } else {
269 dst = append(dst, byte(t.length))
270 }
271
272 return dst
273 }
274
275 type bitStringEncoder BitString
276
277 func (b bitStringEncoder) Len() int {
278 return len(b.Bytes) + 1
279 }
280
281 func (b bitStringEncoder) Encode(dst []byte) {
282 dst[0] = byte((8 - b.BitLength%8) % 8)
283 if copy(dst[1:], b.Bytes) != len(b.Bytes) {
284 panic("internal error")
285 }
286 }
287
288 type oidEncoder []int
289
290 func (oid oidEncoder) Len() int {
291 l := base128IntLength(int64(oid[0]*40 + oid[1]))
292 for i := 2; i < len(oid); i++ {
293 l += base128IntLength(int64(oid[i]))
294 }
295 return l
296 }
297
298 func (oid oidEncoder) Encode(dst []byte) {
299 dst = appendBase128Int(dst[:0], int64(oid[0]*40+oid[1]))
300 for i := 2; i < len(oid); i++ {
301 dst = appendBase128Int(dst, int64(oid[i]))
302 }
303 }
304
305 func makeObjectIdentifier(oid []int) (e encoder, err error) {
306 if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
307 return nil, StructuralError{"invalid object identifier"}
308 }
309
310 return oidEncoder(oid), nil
311 }
312
313 func makePrintableString(s string) (e encoder, err error) {
314 for i := 0; i < len(s); i++ {
315
316
317
318
319
320
321 if !isPrintable(s[i], allowAsterisk, rejectAmpersand) {
322 return nil, StructuralError{"PrintableString contains invalid character"}
323 }
324 }
325
326 return stringEncoder(s), nil
327 }
328
329 func makeIA5String(s string) (e encoder, err error) {
330 for i := 0; i < len(s); i++ {
331 if s[i] > 127 {
332 return nil, StructuralError{"IA5String contains invalid character"}
333 }
334 }
335
336 return stringEncoder(s), nil
337 }
338
339 func makeNumericString(s string) (e encoder, err error) {
340 for i := 0; i < len(s); i++ {
341 if !isNumeric(s[i]) {
342 return nil, StructuralError{"NumericString contains invalid character"}
343 }
344 }
345
346 return stringEncoder(s), nil
347 }
348
349 func makeUTF8String(s string) encoder {
350 return stringEncoder(s)
351 }
352
353 func appendTwoDigits(dst []byte, v int) []byte {
354 return append(dst, byte('0'+(v/10)%10), byte('0'+v%10))
355 }
356
357 func appendFourDigits(dst []byte, v int) []byte {
358 return append(dst,
359 byte('0'+(v/1000)%10),
360 byte('0'+(v/100)%10),
361 byte('0'+(v/10)%10),
362 byte('0'+v%10))
363 }
364
365 func outsideUTCRange(t time.Time) bool {
366 year := t.Year()
367 return year < 1950 || year >= 2050
368 }
369
370 func makeUTCTime(t time.Time) (e encoder, err error) {
371 dst := make([]byte, 0, 18)
372
373 dst, err = appendUTCTime(dst, t)
374 if err != nil {
375 return nil, err
376 }
377
378 return bytesEncoder(dst), nil
379 }
380
381 func makeGeneralizedTime(t time.Time) (e encoder, err error) {
382 dst := make([]byte, 0, 20)
383
384 dst, err = appendGeneralizedTime(dst, t)
385 if err != nil {
386 return nil, err
387 }
388
389 return bytesEncoder(dst), nil
390 }
391
392 func appendUTCTime(dst []byte, t time.Time) (ret []byte, err error) {
393 year := t.Year()
394
395 switch {
396 case 1950 <= year && year < 2000:
397 dst = appendTwoDigits(dst, year-1900)
398 case 2000 <= year && year < 2050:
399 dst = appendTwoDigits(dst, year-2000)
400 default:
401 return nil, StructuralError{"cannot represent time as UTCTime"}
402 }
403
404 return appendTimeCommon(dst, t), nil
405 }
406
407 func appendGeneralizedTime(dst []byte, t time.Time) (ret []byte, err error) {
408 year := t.Year()
409 if year < 0 || year > 9999 {
410 return nil, StructuralError{"cannot represent time as GeneralizedTime"}
411 }
412
413 dst = appendFourDigits(dst, year)
414
415 return appendTimeCommon(dst, t), nil
416 }
417
418 func appendTimeCommon(dst []byte, t time.Time) []byte {
419 _, month, day := t.Date()
420
421 dst = appendTwoDigits(dst, int(month))
422 dst = appendTwoDigits(dst, day)
423
424 hour, min, sec := t.Clock()
425
426 dst = appendTwoDigits(dst, hour)
427 dst = appendTwoDigits(dst, min)
428 dst = appendTwoDigits(dst, sec)
429
430 _, offset := t.Zone()
431
432 switch {
433 case offset/60 == 0:
434 return append(dst, 'Z')
435 case offset > 0:
436 dst = append(dst, '+')
437 case offset < 0:
438 dst = append(dst, '-')
439 }
440
441 offsetMinutes := offset / 60
442 if offsetMinutes < 0 {
443 offsetMinutes = -offsetMinutes
444 }
445
446 dst = appendTwoDigits(dst, offsetMinutes/60)
447 dst = appendTwoDigits(dst, offsetMinutes%60)
448
449 return dst
450 }
451
452 func stripTagAndLength(in []byte) []byte {
453 _, offset, err := parseTagAndLength(in, 0)
454 if err != nil {
455 return in
456 }
457 return in[offset:]
458 }
459
460 func makeBody(value reflect.Value, params fieldParameters) (e encoder, err error) {
461 switch value.Type() {
462 case flagType:
463 return bytesEncoder(nil), nil
464 case timeType:
465 t := value.Interface().(time.Time)
466 if params.timeType == TagGeneralizedTime || outsideUTCRange(t) {
467 return makeGeneralizedTime(t)
468 }
469 return makeUTCTime(t)
470 case bitStringType:
471 return bitStringEncoder(value.Interface().(BitString)), nil
472 case objectIdentifierType:
473 return makeObjectIdentifier(value.Interface().(ObjectIdentifier))
474 case bigIntType:
475 return makeBigInt(value.Interface().(*big.Int))
476 }
477
478 switch v := value; v.Kind() {
479 case reflect.Bool:
480 if v.Bool() {
481 return byteFFEncoder, nil
482 }
483 return byte00Encoder, nil
484 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
485 return int64Encoder(v.Int()), nil
486 case reflect.Struct:
487 t := v.Type()
488
489 for i := 0; i < t.NumField(); i++ {
490 if !t.Field(i).IsExported() {
491 return nil, StructuralError{"struct contains unexported fields"}
492 }
493 }
494
495 startingField := 0
496
497 n := t.NumField()
498 if n == 0 {
499 return bytesEncoder(nil), nil
500 }
501
502
503
504 if t.Field(0).Type == rawContentsType {
505 s := v.Field(0)
506 if s.Len() > 0 {
507 bytes := s.Bytes()
508
512 return bytesEncoder(stripTagAndLength(bytes)), nil
513 }
514
515 startingField = 1
516 }
517
518 switch n1 := n - startingField; n1 {
519 case 0:
520 return bytesEncoder(nil), nil
521 case 1:
522 return makeField(v.Field(startingField), parseFieldParameters(t.Field(startingField).Tag.Get("asn1")))
523 default:
524 m := make([]encoder, n1)
525 for i := 0; i < n1; i++ {
526 m[i], err = makeField(v.Field(i+startingField), parseFieldParameters(t.Field(i+startingField).Tag.Get("asn1")))
527 if err != nil {
528 return nil, err
529 }
530 }
531
532 return multiEncoder(m), nil
533 }
534 case reflect.Slice:
535 sliceType := v.Type()
536 if sliceType.Elem().Kind() == reflect.Uint8 {
537 return bytesEncoder(v.Bytes()), nil
538 }
539
540 var fp fieldParameters
541
542 switch l := v.Len(); l {
543 case 0:
544 return bytesEncoder(nil), nil
545 case 1:
546 return makeField(v.Index(0), fp)
547 default:
548 m := make([]encoder, l)
549
550 for i := 0; i < l; i++ {
551 m[i], err = makeField(v.Index(i), fp)
552 if err != nil {
553 return nil, err
554 }
555 }
556
557 if params.set {
558 return setEncoder(m), nil
559 }
560 return multiEncoder(m), nil
561 }
562 case reflect.String:
563 switch params.stringType {
564 case TagIA5String:
565 return makeIA5String(v.String())
566 case TagPrintableString:
567 return makePrintableString(v.String())
568 case TagNumericString:
569 return makeNumericString(v.String())
570 default:
571 return makeUTF8String(v.String()), nil
572 }
573 }
574
575 return nil, StructuralError{"unknown Go type"}
576 }
577
578 func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) {
579 if !v.IsValid() {
580 return nil, fmt.Errorf("asn1: cannot marshal nil value")
581 }
582
583 if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
584 return makeField(v.Elem(), params)
585 }
586
587 if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty {
588 return bytesEncoder(nil), nil
589 }
590
591 if params.optional && params.defaultValue != nil && canHaveDefaultValue(v.Kind()) {
592 defaultValue := reflect.New(v.Type()).Elem()
593 defaultValue.SetInt(*params.defaultValue)
594
595 if reflect.DeepEqual(v.Interface(), defaultValue.Interface()) {
596 return bytesEncoder(nil), nil
597 }
598 }
599
600
601
602
603 if params.optional && params.defaultValue == nil {
604 if reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
605 return bytesEncoder(nil), nil
606 }
607 }
608
609 if v.Type() == rawValueType {
610 rv := v.Interface().(RawValue)
611 if len(rv.FullBytes) != 0 {
612 return bytesEncoder(rv.FullBytes), nil
613 }
614
615 t := new(taggedEncoder)
616
617 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound}))
618 t.body = bytesEncoder(rv.Bytes)
619
620 return t, nil
621 }
622
623 matchAny, tag, isCompound, ok := getUniversalType(v.Type())
624 if !ok || matchAny {
625 return nil, StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
626 }
627
628 if params.timeType != 0 && tag != TagUTCTime {
629 return nil, StructuralError{"explicit time type given to non-time member"}
630 }
631
632 if params.stringType != 0 && tag != TagPrintableString {
633 return nil, StructuralError{"explicit string type given to non-string member"}
634 }
635
636 switch tag {
637 case TagPrintableString:
638 if params.stringType == 0 {
639
640
641
642 for _, r := range v.String() {
643 if r >= utf8.RuneSelf || !isPrintable(byte(r), rejectAsterisk, rejectAmpersand) {
644 if !utf8.ValidString(v.String()) {
645 return nil, errors.New("asn1: string not valid UTF-8")
646 }
647 tag = TagUTF8String
648 break
649 }
650 }
651 } else {
652 tag = params.stringType
653 }
654 case TagUTCTime:
655 if params.timeType == TagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) {
656 tag = TagGeneralizedTime
657 }
658 }
659
660 if params.set {
661 if tag != TagSequence {
662 return nil, StructuralError{"non sequence tagged as set"}
663 }
664 tag = TagSet
665 }
666
667
668
669
670
671
672 if tag == TagSet && !params.set {
673 params.set = true
674 }
675
676 t := new(taggedEncoder)
677
678 t.body, err = makeBody(v, params)
679 if err != nil {
680 return nil, err
681 }
682
683 bodyLen := t.body.Len()
684
685 class := ClassUniversal
686 if params.tag != nil {
687 if params.application {
688 class = ClassApplication
689 } else if params.private {
690 class = ClassPrivate
691 } else {
692 class = ClassContextSpecific
693 }
694
695 if params.explicit {
696 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{ClassUniversal, tag, bodyLen, isCompound}))
697
698 tt := new(taggedEncoder)
699
700 tt.body = t
701
702 tt.tag = bytesEncoder(appendTagAndLength(tt.scratch[:0], tagAndLength{
703 class: class,
704 tag: *params.tag,
705 length: bodyLen + t.tag.Len(),
706 isCompound: true,
707 }))
708
709 return tt, nil
710 }
711
712
713 tag = *params.tag
714 }
715
716 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{class, tag, bodyLen, isCompound}))
717
718 return t, nil
719 }
720
721
722
723
724
725
726
727
728
729
730
731
732 func Marshal(val any) ([]byte, error) {
733 return MarshalWithParams(val, "")
734 }
735
736
737
738 func MarshalWithParams(val any, params string) ([]byte, error) {
739 e, err := makeField(reflect.ValueOf(val), parseFieldParameters(params))
740 if err != nil {
741 return nil, err
742 }
743 b := make([]byte, e.Len())
744 e.Encode(b)
745 return b, nil
746 }
747
View as plain text