libgo: update to go1.9
[official-gcc.git] / libgo / go / encoding / asn1 / marshal.go
blobfdadb3996efcf8afbf9f6c11beec3b20f7abb47c
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.
5 package asn1
7 import (
8 "errors"
9 "fmt"
10 "math/big"
11 "reflect"
12 "time"
13 "unicode/utf8"
16 var (
17 byte00Encoder encoder = byteEncoder(0x00)
18 byteFFEncoder encoder = byteEncoder(0xff)
21 // encoder represents a ASN.1 element that is waiting to be marshaled.
22 type encoder interface {
23 // Len returns the number of bytes needed to marshal this element.
24 Len() int
25 // Encode encodes this element by writing Len() bytes to dst.
26 Encode(dst []byte)
29 type byteEncoder byte
31 func (c byteEncoder) Len() int {
32 return 1
35 func (c byteEncoder) Encode(dst []byte) {
36 dst[0] = byte(c)
39 type bytesEncoder []byte
41 func (b bytesEncoder) Len() int {
42 return len(b)
45 func (b bytesEncoder) Encode(dst []byte) {
46 if copy(dst, b) != len(b) {
47 panic("internal error")
51 type stringEncoder string
53 func (s stringEncoder) Len() int {
54 return len(s)
57 func (s stringEncoder) Encode(dst []byte) {
58 if copy(dst, s) != len(s) {
59 panic("internal error")
63 type multiEncoder []encoder
65 func (m multiEncoder) Len() int {
66 var size int
67 for _, e := range m {
68 size += e.Len()
70 return size
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()
81 type taggedEncoder struct {
82 // scratch contains temporary space for encoding the tag and length of
83 // an element in order to avoid extra allocations.
84 scratch [8]byte
85 tag encoder
86 body encoder
89 func (t *taggedEncoder) Len() int {
90 return t.tag.Len() + t.body.Len()
93 func (t *taggedEncoder) Encode(dst []byte) {
94 t.tag.Encode(dst)
95 t.body.Encode(dst[t.tag.Len():])
98 type int64Encoder int64
100 func (i int64Encoder) Len() int {
101 n := 1
103 for i > 127 {
105 i >>= 8
108 for i < -128 {
110 i >>= 8
113 return n
116 func (i int64Encoder) Encode(dst []byte) {
117 n := i.Len()
119 for j := 0; j < n; j++ {
120 dst[j] = byte(i >> uint((n-1-j)*8))
124 func base128IntLength(n int64) int {
125 if n == 0 {
126 return 1
129 l := 0
130 for i := n; i > 0; i >>= 7 {
134 return l
137 func appendBase128Int(dst []byte, n int64) []byte {
138 l := base128IntLength(n)
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
147 dst = append(dst, o)
150 return dst
153 func makeBigInt(n *big.Int) (encoder, error) {
154 if n == nil {
155 return nil, StructuralError{"empty integer"}
158 if n.Sign() < 0 {
159 // A negative number has to be converted to two's-complement
160 // form. So we'll invert and subtract 1. If the
161 // most-significant-bit isn't set then we'll need to pad the
162 // beginning with 0xff in order to keep the number negative.
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
169 if len(bytes) == 0 || bytes[0]&0x80 == 0 {
170 return multiEncoder([]encoder{byteFFEncoder, bytesEncoder(bytes)}), nil
172 return bytesEncoder(bytes), nil
173 } else if n.Sign() == 0 {
174 // Zero is written as a single 0 zero rather than no bytes.
175 return byte00Encoder, nil
176 } else {
177 bytes := n.Bytes()
178 if len(bytes) > 0 && bytes[0]&0x80 != 0 {
179 // We'll have to pad this with 0x00 in order to stop it
180 // looking like a negative number.
181 return multiEncoder([]encoder{byte00Encoder, bytesEncoder(bytes)}), nil
183 return bytesEncoder(bytes), nil
187 func appendLength(dst []byte, i int) []byte {
188 n := lengthLength(i)
190 for ; n > 0; n-- {
191 dst = append(dst, byte(i>>uint((n-1)*8)))
194 return dst
197 func lengthLength(i int) (numBytes int) {
198 numBytes = 1
199 for i > 255 {
200 numBytes++
201 i >>= 8
203 return
206 func appendTagAndLength(dst []byte, t tagAndLength) []byte {
207 b := uint8(t.class) << 6
208 if t.isCompound {
209 b |= 0x20
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)
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))
228 return dst
231 type bitStringEncoder BitString
233 func (b bitStringEncoder) Len() int {
234 return len(b.Bytes) + 1
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")
244 type oidEncoder []int
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]))
251 return l
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]))
261 func makeObjectIdentifier(oid []int) (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"}
266 return oidEncoder(oid), nil
269 func makePrintableString(s string) (e encoder, err error) {
270 for i := 0; i < len(s); i++ {
271 if !isPrintable(s[i]) {
272 return nil, StructuralError{"PrintableString contains invalid character"}
276 return stringEncoder(s), nil
279 func makeIA5String(s string) (e encoder, err error) {
280 for i := 0; i < len(s); i++ {
281 if s[i] > 127 {
282 return nil, StructuralError{"IA5String contains invalid character"}
286 return stringEncoder(s), nil
289 func makeUTF8String(s string) encoder {
290 return stringEncoder(s)
293 func appendTwoDigits(dst []byte, v int) []byte {
294 return append(dst, byte('0'+(v/10)%10), byte('0'+v%10))
297 func appendFourDigits(dst []byte, v int) []byte {
298 var bytes [4]byte
299 for i := range bytes {
300 bytes[3-i] = '0' + byte(v%10)
301 v /= 10
303 return append(dst, bytes[:]...)
306 func outsideUTCRange(t time.Time) bool {
307 year := t.Year()
308 return year < 1950 || year >= 2050
311 func makeUTCTime(t time.Time) (e encoder, err error) {
312 dst := make([]byte, 0, 18)
314 dst, err = appendUTCTime(dst, t)
315 if err != nil {
316 return nil, err
319 return bytesEncoder(dst), nil
322 func makeGeneralizedTime(t time.Time) (e encoder, err error) {
323 dst := make([]byte, 0, 20)
325 dst, err = appendGeneralizedTime(dst, t)
326 if err != nil {
327 return nil, err
330 return bytesEncoder(dst), nil
333 func appendUTCTime(dst []byte, t time.Time) (ret []byte, err error) {
334 year := t.Year()
336 switch {
337 case 1950 <= year && year < 2000:
338 dst = appendTwoDigits(dst, year-1900)
339 case 2000 <= year && year < 2050:
340 dst = appendTwoDigits(dst, year-2000)
341 default:
342 return nil, StructuralError{"cannot represent time as UTCTime"}
345 return appendTimeCommon(dst, t), nil
348 func appendGeneralizedTime(dst []byte, t time.Time) (ret []byte, err error) {
349 year := t.Year()
350 if year < 0 || year > 9999 {
351 return nil, StructuralError{"cannot represent time as GeneralizedTime"}
354 dst = appendFourDigits(dst, year)
356 return appendTimeCommon(dst, t), nil
359 func appendTimeCommon(dst []byte, t time.Time) []byte {
360 _, month, day := t.Date()
362 dst = appendTwoDigits(dst, int(month))
363 dst = appendTwoDigits(dst, day)
365 hour, min, sec := t.Clock()
367 dst = appendTwoDigits(dst, hour)
368 dst = appendTwoDigits(dst, min)
369 dst = appendTwoDigits(dst, sec)
371 _, offset := t.Zone()
373 switch {
374 case offset/60 == 0:
375 return append(dst, 'Z')
376 case offset > 0:
377 dst = append(dst, '+')
378 case offset < 0:
379 dst = append(dst, '-')
382 offsetMinutes := offset / 60
383 if offsetMinutes < 0 {
384 offsetMinutes = -offsetMinutes
387 dst = appendTwoDigits(dst, offsetMinutes/60)
388 dst = appendTwoDigits(dst, offsetMinutes%60)
390 return dst
393 func stripTagAndLength(in []byte) []byte {
394 _, offset, err := parseTagAndLength(in, 0)
395 if err != nil {
396 return in
398 return in[offset:]
401 func makeBody(value reflect.Value, params fieldParameters) (e encoder, err error) {
402 switch value.Type() {
403 case flagType:
404 return bytesEncoder(nil), nil
405 case timeType:
406 t := value.Interface().(time.Time)
407 if params.timeType == TagGeneralizedTime || outsideUTCRange(t) {
408 return makeGeneralizedTime(t)
410 return makeUTCTime(t)
411 case bitStringType:
412 return bitStringEncoder(value.Interface().(BitString)), nil
413 case objectIdentifierType:
414 return makeObjectIdentifier(value.Interface().(ObjectIdentifier))
415 case bigIntType:
416 return makeBigInt(value.Interface().(*big.Int))
419 switch v := value; v.Kind() {
420 case reflect.Bool:
421 if v.Bool() {
422 return byteFFEncoder, nil
424 return byte00Encoder, nil
425 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
426 return int64Encoder(v.Int()), nil
427 case reflect.Struct:
428 t := v.Type()
430 for i := 0; i < t.NumField(); i++ {
431 if t.Field(i).PkgPath != "" {
432 return nil, StructuralError{"struct contains unexported fields"}
436 startingField := 0
438 n := t.NumField()
439 if n == 0 {
440 return bytesEncoder(nil), nil
443 // If the first element of the structure is a non-empty
444 // RawContents, then we don't bother serializing the rest.
445 if t.Field(0).Type == rawContentsType {
446 s := v.Field(0)
447 if s.Len() > 0 {
448 bytes := s.Bytes()
449 /* The RawContents will contain the tag and
450 * length fields but we'll also be writing
451 * those ourselves, so we strip them out of
452 * bytes */
453 return bytesEncoder(stripTagAndLength(bytes)), nil
456 startingField = 1
459 switch n1 := n - startingField; n1 {
460 case 0:
461 return bytesEncoder(nil), nil
462 case 1:
463 return makeField(v.Field(startingField), parseFieldParameters(t.Field(startingField).Tag.Get("asn1")))
464 default:
465 m := make([]encoder, n1)
466 for i := 0; i < n1; i++ {
467 m[i], err = makeField(v.Field(i+startingField), parseFieldParameters(t.Field(i+startingField).Tag.Get("asn1")))
468 if err != nil {
469 return nil, err
473 return multiEncoder(m), nil
475 case reflect.Slice:
476 sliceType := v.Type()
477 if sliceType.Elem().Kind() == reflect.Uint8 {
478 return bytesEncoder(v.Bytes()), nil
481 var fp fieldParameters
483 switch l := v.Len(); l {
484 case 0:
485 return bytesEncoder(nil), nil
486 case 1:
487 return makeField(v.Index(0), fp)
488 default:
489 m := make([]encoder, l)
491 for i := 0; i < l; i++ {
492 m[i], err = makeField(v.Index(i), fp)
493 if err != nil {
494 return nil, err
498 return multiEncoder(m), nil
500 case reflect.String:
501 switch params.stringType {
502 case TagIA5String:
503 return makeIA5String(v.String())
504 case TagPrintableString:
505 return makePrintableString(v.String())
506 default:
507 return makeUTF8String(v.String()), nil
511 return nil, StructuralError{"unknown Go type"}
514 func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) {
515 if !v.IsValid() {
516 return nil, fmt.Errorf("asn1: cannot marshal nil value")
518 // If the field is an interface{} then recurse into it.
519 if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
520 return makeField(v.Elem(), params)
523 if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty {
524 return bytesEncoder(nil), nil
527 if params.optional && params.defaultValue != nil && canHaveDefaultValue(v.Kind()) {
528 defaultValue := reflect.New(v.Type()).Elem()
529 defaultValue.SetInt(*params.defaultValue)
531 if reflect.DeepEqual(v.Interface(), defaultValue.Interface()) {
532 return bytesEncoder(nil), nil
536 // If no default value is given then the zero value for the type is
537 // assumed to be the default value. This isn't obviously the correct
538 // behavior, but it's what Go has traditionally done.
539 if params.optional && params.defaultValue == nil {
540 if reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
541 return bytesEncoder(nil), nil
545 if v.Type() == rawValueType {
546 rv := v.Interface().(RawValue)
547 if len(rv.FullBytes) != 0 {
548 return bytesEncoder(rv.FullBytes), nil
551 t := new(taggedEncoder)
553 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound}))
554 t.body = bytesEncoder(rv.Bytes)
556 return t, nil
559 tag, isCompound, ok := getUniversalType(v.Type())
560 if !ok {
561 return nil, StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
563 class := ClassUniversal
565 if params.timeType != 0 && tag != TagUTCTime {
566 return nil, StructuralError{"explicit time type given to non-time member"}
569 if params.stringType != 0 && tag != TagPrintableString {
570 return nil, StructuralError{"explicit string type given to non-string member"}
573 switch tag {
574 case TagPrintableString:
575 if params.stringType == 0 {
576 // This is a string without an explicit string type. We'll use
577 // a PrintableString if the character set in the string is
578 // sufficiently limited, otherwise we'll use a UTF8String.
579 for _, r := range v.String() {
580 if r >= utf8.RuneSelf || !isPrintable(byte(r)) {
581 if !utf8.ValidString(v.String()) {
582 return nil, errors.New("asn1: string not valid UTF-8")
584 tag = TagUTF8String
585 break
588 } else {
589 tag = params.stringType
591 case TagUTCTime:
592 if params.timeType == TagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) {
593 tag = TagGeneralizedTime
597 if params.set {
598 if tag != TagSequence {
599 return nil, StructuralError{"non sequence tagged as set"}
601 tag = TagSet
604 t := new(taggedEncoder)
606 t.body, err = makeBody(v, params)
607 if err != nil {
608 return nil, err
611 bodyLen := t.body.Len()
613 if params.explicit {
614 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{class, tag, bodyLen, isCompound}))
616 tt := new(taggedEncoder)
618 tt.body = t
620 tt.tag = bytesEncoder(appendTagAndLength(tt.scratch[:0], tagAndLength{
621 class: ClassContextSpecific,
622 tag: *params.tag,
623 length: bodyLen + t.tag.Len(),
624 isCompound: true,
627 return tt, nil
630 if params.tag != nil {
631 // implicit tag.
632 tag = *params.tag
633 class = ClassContextSpecific
636 t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{class, tag, bodyLen, isCompound}))
638 return t, nil
641 // Marshal returns the ASN.1 encoding of val.
643 // In addition to the struct tags recognised by Unmarshal, the following can be
644 // used:
646 // ia5: causes strings to be marshaled as ASN.1, IA5String values
647 // omitempty: causes empty slices to be skipped
648 // printable: causes strings to be marshaled as ASN.1, PrintableString values
649 // utf8: causes strings to be marshaled as ASN.1, UTF8String values
650 // utc: causes time.Time to be marshaled as ASN.1, UTCTime values
651 // generalized: causes time.Time to be marshaled as ASN.1, GeneralizedTime values
652 func Marshal(val interface{}) ([]byte, error) {
653 e, err := makeField(reflect.ValueOf(val), fieldParameters{})
654 if err != nil {
655 return nil, err
657 b := make([]byte, e.Len())
658 e.Encode(b)
659 return b, nil