...

Source file src/encoding/asn1/marshal.go

Documentation: encoding/asn1

		 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.
		 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  // encoder represents an ASN.1 element that is waiting to be marshaled.
		24  type encoder interface {
		25  	// Len returns the number of bytes needed to marshal this element.
		26  	Len() int
		27  	// Encode encodes this element by writing Len() bytes to dst.
		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  	// Per X690 Section 11.6: The encodings of the component values of a
		95  	// set-of value shall appear in ascending order, the encodings being
		96  	// compared as octet strings with the shorter components being padded
		97  	// at their trailing end with 0-octets.
		98  	//
		99  	// First we encode each element to its TLV encoding and then use
	 100  	// octetSort to get the ordering expected by X690 DER rules before
	 101  	// writing the sorted encodings out to dst.
	 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  		// Since we are using bytes.Compare to compare TLV encodings we
	 110  		// don't need to right pad s[i] and s[j] to the same length as
	 111  		// suggested in X690. If len(s[i]) < len(s[j]) the length octet of
	 112  		// s[i], which is the first determining byte, will inherently be
	 113  		// smaller than the length octet of s[j]. This lets us skip the
	 114  		// padding step.
	 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  	// scratch contains temporary space for encoding the tag and length of
	 127  	// an element in order to avoid extra allocations.
	 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  		// A negative number has to be converted to two's-complement
	 204  		// form. So we'll invert and subtract 1. If the
	 205  		// most-significant-bit isn't set then we'll need to pad the
	 206  		// beginning with 0xff in order to keep the number negative.
	 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  		// Zero is written as a single 0 zero rather than no bytes.
	 219  		return byte00Encoder, nil
	 220  	} else {
	 221  		bytes := n.Bytes()
	 222  		if len(bytes) > 0 && bytes[0]&0x80 != 0 {
	 223  			// We'll have to pad this with 0x00 in order to stop it
	 224  			// looking like a negative number.
	 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  		// The asterisk is often used in PrintableString, even though
	 316  		// it is invalid. If a PrintableString was specifically
	 317  		// requested then the asterisk is permitted by this code.
	 318  		// Ampersand is allowed in parsing due a handful of CA
	 319  		// certificates, however when making new certificates
	 320  		// it is rejected.
	 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  		// If the first element of the structure is a non-empty
	 504  		// RawContents, then we don't bother serializing the rest.
	 505  		if t.Field(0).Type == rawContentsType {
	 506  			s := v.Field(0)
	 507  			if s.Len() > 0 {
	 508  				bytes := s.Bytes()
	 509  				/* The RawContents will contain the tag and
	 510  				 * length fields but we'll also be writing
	 511  				 * those ourselves, so we strip them out of
	 512  				 * bytes */
	 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  	// If the field is an interface{} then recurse into it.
	 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  	// If no default value is given then the zero value for the type is
	 602  	// assumed to be the default value. This isn't obviously the correct
	 603  	// behavior, but it's what Go has traditionally done.
	 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  			// This is a string without an explicit string type. We'll use
	 641  			// a PrintableString if the character set in the string is
	 642  			// sufficiently limited, otherwise we'll use a UTF8String.
	 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  	// makeField can be called for a slice that should be treated as a SET
	 669  	// but doesn't have params.set set, for instance when using a slice
	 670  	// with the SET type name suffix. In this case getUniversalType returns
	 671  	// TagSet, but makeBody doesn't know about that so will treat the slice
	 672  	// as a sequence. To work around this we set params.set.
	 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  		// implicit tag.
	 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  // Marshal returns the ASN.1 encoding of val.
	 723  //
	 724  // In addition to the struct tags recognised by Unmarshal, the following can be
	 725  // used:
	 726  //
	 727  //	ia5:				 causes strings to be marshaled as ASN.1, IA5String values
	 728  //	omitempty:	 causes empty slices to be skipped
	 729  //	printable:	 causes strings to be marshaled as ASN.1, PrintableString values
	 730  //	utf8:				causes strings to be marshaled as ASN.1, UTF8String values
	 731  //	utc:				 causes time.Time to be marshaled as ASN.1, UTCTime values
	 732  //	generalized: causes time.Time to be marshaled as ASN.1, GeneralizedTime values
	 733  func Marshal(val interface{}) ([]byte, error) {
	 734  	return MarshalWithParams(val, "")
	 735  }
	 736  
	 737  // MarshalWithParams allows field parameters to be specified for the
	 738  // top-level element. The form of the params is the same as the field tags.
	 739  func MarshalWithParams(val interface{}, 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