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 var bytes [4]byte
359 for i := range bytes {
360 bytes[3-i] = '0' + byte(v%10)
361 v /= 10
362 }
363 return append(dst, bytes[:]...)
364 }
365
366 func outsideUTCRange(t time.Time) bool {
367 year := t.Year()
368 return year < 1950 || year >= 2050
369 }
370
371 func makeUTCTime(t time.Time) (e encoder, err error) {
372 dst := make([]byte, 0, 18)
373
374 dst, err = appendUTCTime(dst, t)
375 if err != nil {
376 return nil, err
377 }
378
379 return bytesEncoder(dst), nil
380 }
381
382 func makeGeneralizedTime(t time.Time) (e encoder, err error) {
383 dst := make([]byte, 0, 20)
384
385 dst, err = appendGeneralizedTime(dst, t)
386 if err != nil {
387 return nil, err
388 }
389
390 return bytesEncoder(dst), nil
391 }
392
393 func appendUTCTime(dst []byte, t time.Time) (ret []byte, err error) {
394 year := t.Year()
395
396 switch {
397 case 1950 <= year && year < 2000:
398 dst = appendTwoDigits(dst, year-1900)
399 case 2000 <= year && year < 2050:
400 dst = appendTwoDigits(dst, year-2000)
401 default:
402 return nil, StructuralError{"cannot represent time as UTCTime"}
403 }
404
405 return appendTimeCommon(dst, t), nil
406 }
407
408 func appendGeneralizedTime(dst []byte, t time.Time) (ret []byte, err error) {
409 year := t.Year()
410 if year < 0 || year > 9999 {
411 return nil, StructuralError{"cannot represent time as GeneralizedTime"}
412 }
413
414 dst = appendFourDigits(dst, year)
415
416 return appendTimeCommon(dst, t), nil
417 }
418
419 func appendTimeCommon(dst []byte, t time.Time) []byte {
420 _, month, day := t.Date()
421
422 dst = appendTwoDigits(dst, int(month))
423 dst = appendTwoDigits(dst, day)
424
425 hour, min, sec := t.Clock()
426
427 dst = appendTwoDigits(dst, hour)
428 dst = appendTwoDigits(dst, min)
429 dst = appendTwoDigits(dst, sec)
430
431 _, offset := t.Zone()
432
433 switch {
434 case offset/60 == 0:
435 return append(dst, 'Z')
436 case offset > 0:
437 dst = append(dst, '+')
438 case offset < 0:
439 dst = append(dst, '-')
440 }
441
442 offsetMinutes := offset / 60
443 if offsetMinutes < 0 {
444 offsetMinutes = -offsetMinutes
445 }
446
447 dst = appendTwoDigits(dst, offsetMinutes/60)
448 dst = appendTwoDigits(dst, offsetMinutes%60)
449
450 return dst
451 }
452
453 func stripTagAndLength(in []byte) []byte {
454 _, offset, err := parseTagAndLength(in, 0)
455 if err != nil {
456 return in
457 }
458 return in[offset:]
459 }
460
461 func makeBody(value reflect.Value, params fieldParameters) (e encoder, err error) {
462 switch value.Type() {
463 case flagType:
464 return bytesEncoder(nil), nil
465 case timeType:
466 t := value.Interface().(time.Time)
467 if params.timeType == TagGeneralizedTime || outsideUTCRange(t) {
468 return makeGeneralizedTime(t)
469 }
470 return makeUTCTime(t)
471 case bitStringType:
472 return bitStringEncoder(value.Interface().(BitString)), nil
473 case objectIdentifierType:
474 return makeObjectIdentifier(value.Interface().(ObjectIdentifier))
475 case bigIntType:
476 return makeBigInt(value.Interface().(*big.Int))
477 }
478
479 switch v := value; v.Kind() {
480 case reflect.Bool:
481 if v.Bool() {
482 return byteFFEncoder, nil
483 }
484 return byte00Encoder, nil
485 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
486 return int64Encoder(v.Int()), nil
487 case reflect.Struct:
488 t := v.Type()
489
490 for i := 0; i < t.NumField(); i++ {
491 if !t.Field(i).IsExported() {
492 return nil, StructuralError{"struct contains unexported fields"}
493 }
494 }
495
496 startingField := 0
497
498 n := t.NumField()
499 if n == 0 {
500 return bytesEncoder(nil), nil
501 }
502
503
504
505 if t.Field(0).Type == rawContentsType {
506 s := v.Field(0)
507 if s.Len() > 0 {
508 bytes := s.Bytes()
509
513 return bytesEncoder(stripTagAndLength(bytes)), nil
514 }
515
516 startingField = 1
517 }
518
519 switch n1 := n - startingField; n1 {
520 case 0:
521 return bytesEncoder(nil), nil
522 case 1:
523 return makeField(v.Field(startingField), parseFieldParameters(t.Field(startingField).Tag.Get("asn1")))
524 default:
525 m := make([]encoder, n1)
526 for i := 0; i < n1; i++ {
527 m[i], err = makeField(v.Field(i+startingField), parseFieldParameters(t.Field(i+startingField).Tag.Get("asn1")))
528 if err != nil {
529 return nil, err
530 }
531 }
532
533 return multiEncoder(m), nil
534 }
535 case reflect.Slice:
536 sliceType := v.Type()
537 if sliceType.Elem().Kind() == reflect.Uint8 {
538 return bytesEncoder(v.Bytes()), nil
539 }
540
541 var fp fieldParameters
542
543 switch l := v.Len(); l {
544 case 0:
545 return bytesEncoder(nil), nil
546 case 1:
547 return makeField(v.Index(0), fp)
548 default:
549 m := make([]encoder, l)
550
551 for i := 0; i < l; i++ {
552 m[i], err = makeField(v.Index(i), fp)
553 if err != nil {
554 return nil, err
555 }
556 }
557
558 if params.set {
559 return setEncoder(m), nil
560 }
561 return multiEncoder(m), nil
562 }
563 case reflect.String:
564 switch params.stringType {
565 case TagIA5String:
566 return makeIA5String(v.String())
567 case TagPrintableString:
568 return makePrintableString(v.String())
569 case TagNumericString:
570 return makeNumericString(v.String())
571 default:
572 return makeUTF8String(v.String()), nil
573 }
574 }
575
576 return nil, StructuralError{"unknown Go type"}
577 }
578
579 func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) {
580 if !v.IsValid() {
581 return nil, fmt.Errorf("asn1: cannot marshal nil value")
582 }
583
584 if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
585 return makeField(v.Elem(), params)
586 }
587
588 if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty {
589 return bytesEncoder(nil), nil
590 }
591
592 if params.optional && params.defaultValue != nil && canHaveDefaultValue(v.Kind()) {
593 defaultValue := reflect.New(v.Type()).Elem()
594 defaultValue.SetInt(*params.defaultValue)
595
596 if reflect.DeepEqual(v.Interface(), defaultValue.Interface()) {
597 return bytesEncoder(nil), nil
598 }
599 }
600
601
602
603
604 if params.optional && params.defaultValue == nil {
605 if reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
606 return bytesEncoder(nil), nil
607 }
608 }
609
610 if v.Type() == rawValueType {
611 rv := v.Interface().(RawValue)
612 if len(rv.FullBytes) != 0 {
613 return bytesEncoder(rv.FullBytes), nil
614 }
615
616 t := new(taggedEncoder)
617
618 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound}))
619 t.body = bytesEncoder(rv.Bytes)
620
621 return t, nil
622 }
623
624 matchAny, tag, isCompound, ok := getUniversalType(v.Type())
625 if !ok || matchAny {
626 return nil, StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
627 }
628
629 if params.timeType != 0 && tag != TagUTCTime {
630 return nil, StructuralError{"explicit time type given to non-time member"}
631 }
632
633 if params.stringType != 0 && tag != TagPrintableString {
634 return nil, StructuralError{"explicit string type given to non-string member"}
635 }
636
637 switch tag {
638 case TagPrintableString:
639 if params.stringType == 0 {
640
641
642
643 for _, r := range v.String() {
644 if r >= utf8.RuneSelf || !isPrintable(byte(r), rejectAsterisk, rejectAmpersand) {
645 if !utf8.ValidString(v.String()) {
646 return nil, errors.New("asn1: string not valid UTF-8")
647 }
648 tag = TagUTF8String
649 break
650 }
651 }
652 } else {
653 tag = params.stringType
654 }
655 case TagUTCTime:
656 if params.timeType == TagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) {
657 tag = TagGeneralizedTime
658 }
659 }
660
661 if params.set {
662 if tag != TagSequence {
663 return nil, StructuralError{"non sequence tagged as set"}
664 }
665 tag = TagSet
666 }
667
668
669
670
671
672
673 if tag == TagSet && !params.set {
674 params.set = true
675 }
676
677 t := new(taggedEncoder)
678
679 t.body, err = makeBody(v, params)
680 if err != nil {
681 return nil, err
682 }
683
684 bodyLen := t.body.Len()
685
686 class := ClassUniversal
687 if params.tag != nil {
688 if params.application {
689 class = ClassApplication
690 } else if params.private {
691 class = ClassPrivate
692 } else {
693 class = ClassContextSpecific
694 }
695
696 if params.explicit {
697 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{ClassUniversal, tag, bodyLen, isCompound}))
698
699 tt := new(taggedEncoder)
700
701 tt.body = t
702
703 tt.tag = bytesEncoder(appendTagAndLength(tt.scratch[:0], tagAndLength{
704 class: class,
705 tag: *params.tag,
706 length: bodyLen + t.tag.Len(),
707 isCompound: true,
708 }))
709
710 return tt, nil
711 }
712
713
714 tag = *params.tag
715 }
716
717 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{class, tag, bodyLen, isCompound}))
718
719 return t, nil
720 }
721
722
723
724
725
726
727
728
729
730
731
732
733 func Marshal(val any) ([]byte, error) {
734 return MarshalWithParams(val, "")
735 }
736
737
738
739 func MarshalWithParams(val any, params string) ([]byte, error) {
740 e, err := makeField(reflect.ValueOf(val), parseFieldParameters(params))
741 if err != nil {
742 return nil, err
743 }
744 b := make([]byte, e.Len())
745 e.Encode(b)
746 return b, nil
747 }
748
View as plain text