Run Format

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		"bytes"
     9		"errors"
    10		"fmt"
    11		"io"
    12		"math/big"
    13		"reflect"
    14		"time"
    15		"unicode/utf8"
    16	)
    17	
    18	// A forkableWriter is an in-memory buffer that can be
    19	// 'forked' to create new forkableWriters that bracket the
    20	// original.  After
    21	//    pre, post := w.fork();
    22	// the overall sequence of bytes represented is logically w+pre+post.
    23	type forkableWriter struct {
    24		*bytes.Buffer
    25		pre, post *forkableWriter
    26	}
    27	
    28	func newForkableWriter() *forkableWriter {
    29		return &forkableWriter{new(bytes.Buffer), nil, nil}
    30	}
    31	
    32	func (f *forkableWriter) fork() (pre, post *forkableWriter) {
    33		if f.pre != nil || f.post != nil {
    34			panic("have already forked")
    35		}
    36		f.pre = newForkableWriter()
    37		f.post = newForkableWriter()
    38		return f.pre, f.post
    39	}
    40	
    41	func (f *forkableWriter) Len() (l int) {
    42		l += f.Buffer.Len()
    43		if f.pre != nil {
    44			l += f.pre.Len()
    45		}
    46		if f.post != nil {
    47			l += f.post.Len()
    48		}
    49		return
    50	}
    51	
    52	func (f *forkableWriter) writeTo(out io.Writer) (n int, err error) {
    53		n, err = out.Write(f.Bytes())
    54		if err != nil {
    55			return
    56		}
    57	
    58		var nn int
    59	
    60		if f.pre != nil {
    61			nn, err = f.pre.writeTo(out)
    62			n += nn
    63			if err != nil {
    64				return
    65			}
    66		}
    67	
    68		if f.post != nil {
    69			nn, err = f.post.writeTo(out)
    70			n += nn
    71		}
    72		return
    73	}
    74	
    75	func marshalBase128Int(out *forkableWriter, n int64) (err error) {
    76		if n == 0 {
    77			err = out.WriteByte(0)
    78			return
    79		}
    80	
    81		l := 0
    82		for i := n; i > 0; i >>= 7 {
    83			l++
    84		}
    85	
    86		for i := l - 1; i >= 0; i-- {
    87			o := byte(n >> uint(i*7))
    88			o &= 0x7f
    89			if i != 0 {
    90				o |= 0x80
    91			}
    92			err = out.WriteByte(o)
    93			if err != nil {
    94				return
    95			}
    96		}
    97	
    98		return nil
    99	}
   100	
   101	func marshalInt64(out *forkableWriter, i int64) (err error) {
   102		n := int64Length(i)
   103	
   104		for ; n > 0; n-- {
   105			err = out.WriteByte(byte(i >> uint((n-1)*8)))
   106			if err != nil {
   107				return
   108			}
   109		}
   110	
   111		return nil
   112	}
   113	
   114	func int64Length(i int64) (numBytes int) {
   115		numBytes = 1
   116	
   117		for i > 127 {
   118			numBytes++
   119			i >>= 8
   120		}
   121	
   122		for i < -128 {
   123			numBytes++
   124			i >>= 8
   125		}
   126	
   127		return
   128	}
   129	
   130	func marshalBigInt(out *forkableWriter, n *big.Int) (err error) {
   131		if n.Sign() < 0 {
   132			// A negative number has to be converted to two's-complement
   133			// form. So we'll subtract 1 and invert. If the
   134			// most-significant-bit isn't set then we'll need to pad the
   135			// beginning with 0xff in order to keep the number negative.
   136			nMinus1 := new(big.Int).Neg(n)
   137			nMinus1.Sub(nMinus1, bigOne)
   138			bytes := nMinus1.Bytes()
   139			for i := range bytes {
   140				bytes[i] ^= 0xff
   141			}
   142			if len(bytes) == 0 || bytes[0]&0x80 == 0 {
   143				err = out.WriteByte(0xff)
   144				if err != nil {
   145					return
   146				}
   147			}
   148			_, err = out.Write(bytes)
   149		} else if n.Sign() == 0 {
   150			// Zero is written as a single 0 zero rather than no bytes.
   151			err = out.WriteByte(0x00)
   152		} else {
   153			bytes := n.Bytes()
   154			if len(bytes) > 0 && bytes[0]&0x80 != 0 {
   155				// We'll have to pad this with 0x00 in order to stop it
   156				// looking like a negative number.
   157				err = out.WriteByte(0)
   158				if err != nil {
   159					return
   160				}
   161			}
   162			_, err = out.Write(bytes)
   163		}
   164		return
   165	}
   166	
   167	func marshalLength(out *forkableWriter, i int) (err error) {
   168		n := lengthLength(i)
   169	
   170		for ; n > 0; n-- {
   171			err = out.WriteByte(byte(i >> uint((n-1)*8)))
   172			if err != nil {
   173				return
   174			}
   175		}
   176	
   177		return nil
   178	}
   179	
   180	func lengthLength(i int) (numBytes int) {
   181		numBytes = 1
   182		for i > 255 {
   183			numBytes++
   184			i >>= 8
   185		}
   186		return
   187	}
   188	
   189	func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err error) {
   190		b := uint8(t.class) << 6
   191		if t.isCompound {
   192			b |= 0x20
   193		}
   194		if t.tag >= 31 {
   195			b |= 0x1f
   196			err = out.WriteByte(b)
   197			if err != nil {
   198				return
   199			}
   200			err = marshalBase128Int(out, int64(t.tag))
   201			if err != nil {
   202				return
   203			}
   204		} else {
   205			b |= uint8(t.tag)
   206			err = out.WriteByte(b)
   207			if err != nil {
   208				return
   209			}
   210		}
   211	
   212		if t.length >= 128 {
   213			l := lengthLength(t.length)
   214			err = out.WriteByte(0x80 | byte(l))
   215			if err != nil {
   216				return
   217			}
   218			err = marshalLength(out, t.length)
   219			if err != nil {
   220				return
   221			}
   222		} else {
   223			err = out.WriteByte(byte(t.length))
   224			if err != nil {
   225				return
   226			}
   227		}
   228	
   229		return nil
   230	}
   231	
   232	func marshalBitString(out *forkableWriter, b BitString) (err error) {
   233		paddingBits := byte((8 - b.BitLength%8) % 8)
   234		err = out.WriteByte(paddingBits)
   235		if err != nil {
   236			return
   237		}
   238		_, err = out.Write(b.Bytes)
   239		return
   240	}
   241	
   242	func marshalObjectIdentifier(out *forkableWriter, oid []int) (err error) {
   243		if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
   244			return StructuralError{"invalid object identifier"}
   245		}
   246	
   247		err = marshalBase128Int(out, int64(oid[0]*40+oid[1]))
   248		if err != nil {
   249			return
   250		}
   251		for i := 2; i < len(oid); i++ {
   252			err = marshalBase128Int(out, int64(oid[i]))
   253			if err != nil {
   254				return
   255			}
   256		}
   257	
   258		return
   259	}
   260	
   261	func marshalPrintableString(out *forkableWriter, s string) (err error) {
   262		b := []byte(s)
   263		for _, c := range b {
   264			if !isPrintable(c) {
   265				return StructuralError{"PrintableString contains invalid character"}
   266			}
   267		}
   268	
   269		_, err = out.Write(b)
   270		return
   271	}
   272	
   273	func marshalIA5String(out *forkableWriter, s string) (err error) {
   274		b := []byte(s)
   275		for _, c := range b {
   276			if c > 127 {
   277				return StructuralError{"IA5String contains invalid character"}
   278			}
   279		}
   280	
   281		_, err = out.Write(b)
   282		return
   283	}
   284	
   285	func marshalUTF8String(out *forkableWriter, s string) (err error) {
   286		_, err = out.Write([]byte(s))
   287		return
   288	}
   289	
   290	func marshalTwoDigits(out *forkableWriter, v int) (err error) {
   291		err = out.WriteByte(byte('0' + (v/10)%10))
   292		if err != nil {
   293			return
   294		}
   295		return out.WriteByte(byte('0' + v%10))
   296	}
   297	
   298	func marshalUTCTime(out *forkableWriter, t time.Time) (err error) {
   299		year, month, day := t.Date()
   300	
   301		switch {
   302		case 1950 <= year && year < 2000:
   303			err = marshalTwoDigits(out, int(year-1900))
   304		case 2000 <= year && year < 2050:
   305			err = marshalTwoDigits(out, int(year-2000))
   306		default:
   307			return StructuralError{"cannot represent time as UTCTime"}
   308		}
   309		if err != nil {
   310			return
   311		}
   312	
   313		err = marshalTwoDigits(out, int(month))
   314		if err != nil {
   315			return
   316		}
   317	
   318		err = marshalTwoDigits(out, day)
   319		if err != nil {
   320			return
   321		}
   322	
   323		hour, min, sec := t.Clock()
   324	
   325		err = marshalTwoDigits(out, hour)
   326		if err != nil {
   327			return
   328		}
   329	
   330		err = marshalTwoDigits(out, min)
   331		if err != nil {
   332			return
   333		}
   334	
   335		err = marshalTwoDigits(out, sec)
   336		if err != nil {
   337			return
   338		}
   339	
   340		_, offset := t.Zone()
   341	
   342		switch {
   343		case offset/60 == 0:
   344			err = out.WriteByte('Z')
   345			return
   346		case offset > 0:
   347			err = out.WriteByte('+')
   348		case offset < 0:
   349			err = out.WriteByte('-')
   350		}
   351	
   352		if err != nil {
   353			return
   354		}
   355	
   356		offsetMinutes := offset / 60
   357		if offsetMinutes < 0 {
   358			offsetMinutes = -offsetMinutes
   359		}
   360	
   361		err = marshalTwoDigits(out, offsetMinutes/60)
   362		if err != nil {
   363			return
   364		}
   365	
   366		err = marshalTwoDigits(out, offsetMinutes%60)
   367		return
   368	}
   369	
   370	func stripTagAndLength(in []byte) []byte {
   371		_, offset, err := parseTagAndLength(in, 0)
   372		if err != nil {
   373			return in
   374		}
   375		return in[offset:]
   376	}
   377	
   378	func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err error) {
   379		switch value.Type() {
   380		case timeType:
   381			return marshalUTCTime(out, value.Interface().(time.Time))
   382		case bitStringType:
   383			return marshalBitString(out, value.Interface().(BitString))
   384		case objectIdentifierType:
   385			return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier))
   386		case bigIntType:
   387			return marshalBigInt(out, value.Interface().(*big.Int))
   388		}
   389	
   390		switch v := value; v.Kind() {
   391		case reflect.Bool:
   392			if v.Bool() {
   393				return out.WriteByte(255)
   394			} else {
   395				return out.WriteByte(0)
   396			}
   397		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   398			return marshalInt64(out, int64(v.Int()))
   399		case reflect.Struct:
   400			t := v.Type()
   401	
   402			startingField := 0
   403	
   404			// If the first element of the structure is a non-empty
   405			// RawContents, then we don't bother serializing the rest.
   406			if t.NumField() > 0 && t.Field(0).Type == rawContentsType {
   407				s := v.Field(0)
   408				if s.Len() > 0 {
   409					bytes := make([]byte, s.Len())
   410					for i := 0; i < s.Len(); i++ {
   411						bytes[i] = uint8(s.Index(i).Uint())
   412					}
   413					/* The RawContents will contain the tag and
   414					 * length fields but we'll also be writing
   415					 * those ourselves, so we strip them out of
   416					 * bytes */
   417					_, err = out.Write(stripTagAndLength(bytes))
   418					return
   419				} else {
   420					startingField = 1
   421				}
   422			}
   423	
   424			for i := startingField; i < t.NumField(); i++ {
   425				var pre *forkableWriter
   426				pre, out = out.fork()
   427				err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag.Get("asn1")))
   428				if err != nil {
   429					return
   430				}
   431			}
   432			return
   433		case reflect.Slice:
   434			sliceType := v.Type()
   435			if sliceType.Elem().Kind() == reflect.Uint8 {
   436				bytes := make([]byte, v.Len())
   437				for i := 0; i < v.Len(); i++ {
   438					bytes[i] = uint8(v.Index(i).Uint())
   439				}
   440				_, err = out.Write(bytes)
   441				return
   442			}
   443	
   444			var fp fieldParameters
   445			for i := 0; i < v.Len(); i++ {
   446				var pre *forkableWriter
   447				pre, out = out.fork()
   448				err = marshalField(pre, v.Index(i), fp)
   449				if err != nil {
   450					return
   451				}
   452			}
   453			return
   454		case reflect.String:
   455			switch params.stringType {
   456			case tagIA5String:
   457				return marshalIA5String(out, v.String())
   458			case tagPrintableString:
   459				return marshalPrintableString(out, v.String())
   460			default:
   461				return marshalUTF8String(out, v.String())
   462			}
   463		}
   464	
   465		return StructuralError{"unknown Go type"}
   466	}
   467	
   468	func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err error) {
   469		// If the field is an interface{} then recurse into it.
   470		if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
   471			return marshalField(out, v.Elem(), params)
   472		}
   473	
   474		if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty {
   475			return
   476		}
   477	
   478		if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
   479			return
   480		}
   481	
   482		if v.Type() == rawValueType {
   483			rv := v.Interface().(RawValue)
   484			if len(rv.FullBytes) != 0 {
   485				_, err = out.Write(rv.FullBytes)
   486			} else {
   487				err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
   488				if err != nil {
   489					return
   490				}
   491				_, err = out.Write(rv.Bytes)
   492			}
   493			return
   494		}
   495	
   496		tag, isCompound, ok := getUniversalType(v.Type())
   497		if !ok {
   498			err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
   499			return
   500		}
   501		class := classUniversal
   502	
   503		if params.stringType != 0 && tag != tagPrintableString {
   504			return StructuralError{"explicit string type given to non-string member"}
   505		}
   506	
   507		if tag == tagPrintableString {
   508			if params.stringType == 0 {
   509				// This is a string without an explicit string type. We'll use
   510				// a PrintableString if the character set in the string is
   511				// sufficiently limited, otherwise we'll use a UTF8String.
   512				for _, r := range v.String() {
   513					if r >= utf8.RuneSelf || !isPrintable(byte(r)) {
   514						if !utf8.ValidString(v.String()) {
   515							return errors.New("asn1: string not valid UTF-8")
   516						}
   517						tag = tagUTF8String
   518						break
   519					}
   520				}
   521			} else {
   522				tag = params.stringType
   523			}
   524		}
   525	
   526		if params.set {
   527			if tag != tagSequence {
   528				return StructuralError{"non sequence tagged as set"}
   529			}
   530			tag = tagSet
   531		}
   532	
   533		tags, body := out.fork()
   534	
   535		err = marshalBody(body, v, params)
   536		if err != nil {
   537			return
   538		}
   539	
   540		bodyLen := body.Len()
   541	
   542		var explicitTag *forkableWriter
   543		if params.explicit {
   544			explicitTag, tags = tags.fork()
   545		}
   546	
   547		if !params.explicit && params.tag != nil {
   548			// implicit tag.
   549			tag = *params.tag
   550			class = classContextSpecific
   551		}
   552	
   553		err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound})
   554		if err != nil {
   555			return
   556		}
   557	
   558		if params.explicit {
   559			err = marshalTagAndLength(explicitTag, tagAndLength{
   560				class:      classContextSpecific,
   561				tag:        *params.tag,
   562				length:     bodyLen + tags.Len(),
   563				isCompound: true,
   564			})
   565		}
   566	
   567		return nil
   568	}
   569	
   570	// Marshal returns the ASN.1 encoding of val.
   571	func Marshal(val interface{}) ([]byte, error) {
   572		var out bytes.Buffer
   573		v := reflect.ValueOf(val)
   574		f := newForkableWriter()
   575		err := marshalField(f, v, fieldParameters{})
   576		if err != nil {
   577			return nil, err
   578		}
   579		_, err = f.writeTo(&out)
   580		return out.Bytes(), nil
   581	}

View as plain text