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