...
Run Format

Source file src/encoding/asn1/marshal.go

     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		"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	// 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)
    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		// 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
    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) (encoder, error) {
   154		if n == nil {
   155			return nil, StructuralError{"empty integer"}
   156		}
   157	
   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
   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			// 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
   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) (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"}
   264		}
   265	
   266		return oidEncoder(oid), nil
   267	}
   268	
   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"}
   273			}
   274		}
   275	
   276		return stringEncoder(s), nil
   277	}
   278	
   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"}
   283			}
   284		}
   285	
   286		return stringEncoder(s), nil
   287	}
   288	
   289	func makeUTF8String(s string) encoder {
   290		return stringEncoder(s)
   291	}
   292	
   293	func appendTwoDigits(dst []byte, v int) []byte {
   294		return append(dst, byte('0'+(v/10)%10), byte('0'+v%10))
   295	}
   296	
   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
   302		}
   303		return append(dst, bytes[:]...)
   304	}
   305	
   306	func outsideUTCRange(t time.Time) bool {
   307		year := t.Year()
   308		return year < 1950 || year >= 2050
   309	}
   310	
   311	func makeUTCTime(t time.Time) (e encoder, err error) {
   312		dst := make([]byte, 0, 18)
   313	
   314		dst, err = appendUTCTime(dst, t)
   315		if err != nil {
   316			return nil, err
   317		}
   318	
   319		return bytesEncoder(dst), nil
   320	}
   321	
   322	func makeGeneralizedTime(t time.Time) (e encoder, err error) {
   323		dst := make([]byte, 0, 20)
   324	
   325		dst, err = appendGeneralizedTime(dst, t)
   326		if err != nil {
   327			return nil, err
   328		}
   329	
   330		return bytesEncoder(dst), nil
   331	}
   332	
   333	func appendUTCTime(dst []byte, t time.Time) (ret []byte, err error) {
   334		year := t.Year()
   335	
   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"}
   343		}
   344	
   345		return appendTimeCommon(dst, t), nil
   346	}
   347	
   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"}
   352		}
   353	
   354		dst = appendFourDigits(dst, year)
   355	
   356		return appendTimeCommon(dst, t), nil
   357	}
   358	
   359	func appendTimeCommon(dst []byte, t time.Time) []byte {
   360		_, month, day := t.Date()
   361	
   362		dst = appendTwoDigits(dst, int(month))
   363		dst = appendTwoDigits(dst, day)
   364	
   365		hour, min, sec := t.Clock()
   366	
   367		dst = appendTwoDigits(dst, hour)
   368		dst = appendTwoDigits(dst, min)
   369		dst = appendTwoDigits(dst, sec)
   370	
   371		_, offset := t.Zone()
   372	
   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, '-')
   380		}
   381	
   382		offsetMinutes := offset / 60
   383		if offsetMinutes < 0 {
   384			offsetMinutes = -offsetMinutes
   385		}
   386	
   387		dst = appendTwoDigits(dst, offsetMinutes/60)
   388		dst = appendTwoDigits(dst, offsetMinutes%60)
   389	
   390		return dst
   391	}
   392	
   393	func stripTagAndLength(in []byte) []byte {
   394		_, offset, err := parseTagAndLength(in, 0)
   395		if err != nil {
   396			return in
   397		}
   398		return in[offset:]
   399	}
   400	
   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)
   409			}
   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))
   417		}
   418	
   419		switch v := value; v.Kind() {
   420		case reflect.Bool:
   421			if v.Bool() {
   422				return byteFFEncoder, nil
   423			}
   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()
   429	
   430			for i := 0; i < t.NumField(); i++ {
   431				if t.Field(i).PkgPath != "" {
   432					return nil, StructuralError{"struct contains unexported fields"}
   433				}
   434			}
   435	
   436			startingField := 0
   437	
   438			n := t.NumField()
   439			if n == 0 {
   440				return bytesEncoder(nil), nil
   441			}
   442	
   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
   454				}
   455	
   456				startingField = 1
   457			}
   458	
   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
   470					}
   471				}
   472	
   473				return multiEncoder(m), nil
   474			}
   475		case reflect.Slice:
   476			sliceType := v.Type()
   477			if sliceType.Elem().Kind() == reflect.Uint8 {
   478				return bytesEncoder(v.Bytes()), nil
   479			}
   480	
   481			var fp fieldParameters
   482	
   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)
   490	
   491				for i := 0; i < l; i++ {
   492					m[i], err = makeField(v.Index(i), fp)
   493					if err != nil {
   494						return nil, err
   495					}
   496				}
   497	
   498				return multiEncoder(m), nil
   499			}
   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
   508			}
   509		}
   510	
   511		return nil, StructuralError{"unknown Go type"}
   512	}
   513	
   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")
   517		}
   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)
   521		}
   522	
   523		if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty {
   524			return bytesEncoder(nil), nil
   525		}
   526	
   527		if params.optional && params.defaultValue != nil && canHaveDefaultValue(v.Kind()) {
   528			defaultValue := reflect.New(v.Type()).Elem()
   529			defaultValue.SetInt(*params.defaultValue)
   530	
   531			if reflect.DeepEqual(v.Interface(), defaultValue.Interface()) {
   532				return bytesEncoder(nil), nil
   533			}
   534		}
   535	
   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
   542			}
   543		}
   544	
   545		if v.Type() == rawValueType {
   546			rv := v.Interface().(RawValue)
   547			if len(rv.FullBytes) != 0 {
   548				return bytesEncoder(rv.FullBytes), nil
   549			}
   550	
   551			t := new(taggedEncoder)
   552	
   553			t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound}))
   554			t.body = bytesEncoder(rv.Bytes)
   555	
   556			return t, nil
   557		}
   558	
   559		tag, isCompound, ok := getUniversalType(v.Type())
   560		if !ok {
   561			return nil, StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
   562		}
   563		class := ClassUniversal
   564	
   565		if params.timeType != 0 && tag != TagUTCTime {
   566			return nil, StructuralError{"explicit time type given to non-time member"}
   567		}
   568	
   569		if params.stringType != 0 && tag != TagPrintableString {
   570			return nil, StructuralError{"explicit string type given to non-string member"}
   571		}
   572	
   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")
   583						}
   584						tag = TagUTF8String
   585						break
   586					}
   587				}
   588			} else {
   589				tag = params.stringType
   590			}
   591		case TagUTCTime:
   592			if params.timeType == TagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) {
   593				tag = TagGeneralizedTime
   594			}
   595		}
   596	
   597		if params.set {
   598			if tag != TagSequence {
   599				return nil, StructuralError{"non sequence tagged as set"}
   600			}
   601			tag = TagSet
   602		}
   603	
   604		t := new(taggedEncoder)
   605	
   606		t.body, err = makeBody(v, params)
   607		if err != nil {
   608			return nil, err
   609		}
   610	
   611		bodyLen := t.body.Len()
   612	
   613		if params.explicit {
   614			t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{class, tag, bodyLen, isCompound}))
   615	
   616			tt := new(taggedEncoder)
   617	
   618			tt.body = t
   619	
   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,
   625			}))
   626	
   627			return tt, nil
   628		}
   629	
   630		if params.tag != nil {
   631			// implicit tag.
   632			tag = *params.tag
   633			class = ClassContextSpecific
   634		}
   635	
   636		t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{class, tag, bodyLen, isCompound}))
   637	
   638		return t, nil
   639	}
   640	
   641	// Marshal returns the ASN.1 encoding of val.
   642	//
   643	// In addition to the struct tags recognised by Unmarshal, the following can be
   644	// used:
   645	//
   646	//	ia5:		causes strings to be marshaled as ASN.1, IA5 strings
   647	//	omitempty:	causes empty slices to be skipped
   648	//	printable:	causes strings to be marshaled as ASN.1, PrintableString strings.
   649	//	utf8:		causes strings to be marshaled as ASN.1, UTF8 strings
   650	func Marshal(val interface{}) ([]byte, error) {
   651		e, err := makeField(reflect.ValueOf(val), fieldParameters{})
   652		if err != nil {
   653			return nil, err
   654		}
   655		b := make([]byte, e.Len())
   656		e.Encode(b)
   657		return b, nil
   658	}
   659	

View as plain text