...

Source file src/pkg/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 an 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			// The asterisk is often used in PrintableString, even though
   272			// it is invalid. If a PrintableString was specifically
   273			// requested then the asterisk is permitted by this code.
   274			// Ampersand is allowed in parsing due a handful of CA
   275			// certificates, however when making new certificates
   276			// it is rejected.
   277			if !isPrintable(s[i], allowAsterisk, rejectAmpersand) {
   278				return nil, StructuralError{"PrintableString contains invalid character"}
   279			}
   280		}
   281	
   282		return stringEncoder(s), nil
   283	}
   284	
   285	func makeIA5String(s 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"}
   289			}
   290		}
   291	
   292		return stringEncoder(s), nil
   293	}
   294	
   295	func makeNumericString(s 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"}
   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) (e encoder, err error) {
   328		dst := make([]byte, 0, 18)
   329	
   330		dst, err = appendUTCTime(dst, t)
   331		if err != nil {
   332			return nil, err
   333		}
   334	
   335		return bytesEncoder(dst), nil
   336	}
   337	
   338	func makeGeneralizedTime(t time.Time) (e encoder, err error) {
   339		dst := make([]byte, 0, 20)
   340	
   341		dst, err = appendGeneralizedTime(dst, t)
   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) (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"}
   359		}
   360	
   361		return appendTimeCommon(dst, t), nil
   362	}
   363	
   364	func appendGeneralizedTime(dst []byte, t time.Time) (ret []byte, err error) {
   365		year := t.Year()
   366		if year < 0 || year > 9999 {
   367			return nil, StructuralError{"cannot represent time as GeneralizedTime"}
   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)
   425			}
   426			return makeUTCTime(t)
   427		case bitStringType:
   428			return bitStringEncoder(value.Interface().(BitString)), nil
   429		case objectIdentifierType:
   430			return makeObjectIdentifier(value.Interface().(ObjectIdentifier))
   431		case bigIntType:
   432			return makeBigInt(value.Interface().(*big.Int))
   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"}
   449				}
   450			}
   451	
   452			startingField := 0
   453	
   454			n := t.NumField()
   455			if n == 0 {
   456				return bytesEncoder(nil), nil
   457			}
   458	
   459			// If the first element of the structure is a non-empty
   460			// RawContents, then we don't bother serializing the rest.
   461			if t.Field(0).Type == rawContentsType {
   462				s := v.Field(0)
   463				if s.Len() > 0 {
   464					bytes := s.Bytes()
   465					/* The RawContents will contain the tag and
   466					 * length fields but we'll also be writing
   467					 * those ourselves, so we strip them out of
   468					 * bytes */
   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())
   520			case TagPrintableString:
   521				return makePrintableString(v.String())
   522			case TagNumericString:
   523				return makeNumericString(v.String())
   524			default:
   525				return makeUTF8String(v.String()), nil
   526			}
   527		}
   528	
   529		return nil, StructuralError{"unknown Go type"}
   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		// If the field is an interface{} then recurse into it.
   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		// If no default value is given then the zero value for the type is
   555		// assumed to be the default value. This isn't obviously the correct
   556		// behavior, but it's what Go has traditionally done.
   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())}
   580		}
   581	
   582		if params.timeType != 0 && tag != TagUTCTime {
   583			return nil, StructuralError{"explicit time type given to non-time member"}
   584		}
   585	
   586		if params.stringType != 0 && tag != TagPrintableString {
   587			return nil, StructuralError{"explicit string type given to non-string member"}
   588		}
   589	
   590		switch tag {
   591		case TagPrintableString:
   592			if params.stringType == 0 {
   593				// This is a string without an explicit string type. We'll use
   594				// a PrintableString if the character set in the string is
   595				// sufficiently limited, otherwise we'll use a UTF8String.
   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"}
   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			// implicit tag.
   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	// Marshal returns the ASN.1 encoding of val.
   667	//
   668	// In addition to the struct tags recognised by Unmarshal, the following can be
   669	// used:
   670	//
   671	//	ia5:         causes strings to be marshaled as ASN.1, IA5String values
   672	//	omitempty:   causes empty slices to be skipped
   673	//	printable:   causes strings to be marshaled as ASN.1, PrintableString values
   674	//	utf8:        causes strings to be marshaled as ASN.1, UTF8String values
   675	//	utc:         causes time.Time to be marshaled as ASN.1, UTCTime values
   676	//	generalized: causes time.Time to be marshaled as ASN.1, GeneralizedTime values
   677	func Marshal(val interface{}) ([]byte, error) {
   678		return MarshalWithParams(val, "")
   679	}
   680	
   681	// MarshalWithParams allows field parameters to be specified for the
   682	// top-level element. The form of the params is the same as the field tags.
   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