Copyright 2009 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package asn1

import (
	
	
	
	
	
	
	
	
)

var (
	byte00Encoder encoder = byteEncoder(0x00)
	byteFFEncoder encoder = byteEncoder(0xff)
)
encoder represents an ASN.1 element that is waiting to be marshaled.
Len returns the number of bytes needed to marshal this element.
Encode encodes this element by writing Len() bytes to dst.
	Encode(dst []byte)
}

type byteEncoder byte

func ( byteEncoder) () int {
	return 1
}

func ( byteEncoder) ( []byte) {
	[0] = byte()
}

type bytesEncoder []byte

func ( bytesEncoder) () int {
	return len()
}

func ( bytesEncoder) ( []byte) {
	if copy(, ) != len() {
		panic("internal error")
	}
}

type stringEncoder string

func ( stringEncoder) () int {
	return len()
}

func ( stringEncoder) ( []byte) {
	if copy(, ) != len() {
		panic("internal error")
	}
}

type multiEncoder []encoder

func ( multiEncoder) () int {
	var  int
	for ,  := range  {
		 += .Len()
	}
	return 
}

func ( multiEncoder) ( []byte) {
	var  int
	for ,  := range  {
		.Encode([:])
		 += .Len()
	}
}

type setEncoder []encoder

func ( setEncoder) () int {
	var  int
	for ,  := range  {
		 += .Len()
	}
	return 
}

Per X690 Section 11.6: The encodings of the component values of a set-of value shall appear in ascending order, the encodings being compared as octet strings with the shorter components being padded at their trailing end with 0-octets. First we encode each element to its TLV encoding and then use octetSort to get the ordering expected by X690 DER rules before writing the sorted encodings out to dst.
	 := make([][]byte, len())
	for ,  := range  {
		[] = make([]byte, .Len())
		.Encode([])
	}

Since we are using bytes.Compare to compare TLV encodings we don't need to right pad s[i] and s[j] to the same length as suggested in X690. If len(s[i]) < len(s[j]) the length octet of s[i], which is the first determining byte, will inherently be smaller than the length octet of s[j]. This lets us skip the padding step.
		return bytes.Compare([], []) < 0
	})

	var  int
	for ,  := range  {
		copy([:], )
		 += len()
	}
}

scratch contains temporary space for encoding the tag and length of an element in order to avoid extra allocations.
	scratch [8]byte
	tag     encoder
	body    encoder
}

func ( *taggedEncoder) () int {
	return .tag.Len() + .body.Len()
}

func ( *taggedEncoder) ( []byte) {
	.tag.Encode()
	.body.Encode([.tag.Len():])
}

type int64Encoder int64

func ( int64Encoder) () int {
	 := 1

	for  > 127 {
		++
		 >>= 8
	}

	for  < -128 {
		++
		 >>= 8
	}

	return 
}

func ( int64Encoder) ( []byte) {
	 := .Len()

	for  := 0;  < ; ++ {
		[] = byte( >> uint((-1-)*8))
	}
}

func ( int64) int {
	if  == 0 {
		return 1
	}

	 := 0
	for  := ;  > 0;  >>= 7 {
		++
	}

	return 
}

func ( []byte,  int64) []byte {
	 := base128IntLength()

	for  :=  - 1;  >= 0; -- {
		 := byte( >> uint(*7))
		 &= 0x7f
		if  != 0 {
			 |= 0x80
		}

		 = append(, )
	}

	return 
}

func ( *big.Int) (encoder, error) {
	if  == nil {
		return nil, StructuralError{"empty integer"}
	}

A negative number has to be converted to two's-complement form. So we'll invert and subtract 1. If the most-significant-bit isn't set then we'll need to pad the beginning with 0xff in order to keep the number negative.
		 := new(big.Int).Neg()
		.Sub(, bigOne)
		 := .Bytes()
		for  := range  {
			[] ^= 0xff
		}
		if len() == 0 || [0]&0x80 == 0 {
			return multiEncoder([]encoder{byteFFEncoder, bytesEncoder()}), nil
		}
		return bytesEncoder(), nil
Zero is written as a single 0 zero rather than no bytes.
		return byte00Encoder, nil
	} else {
		 := .Bytes()
We'll have to pad this with 0x00 in order to stop it looking like a negative number.
			return multiEncoder([]encoder{byte00Encoder, bytesEncoder()}), nil
		}
		return bytesEncoder(), nil
	}
}

func ( []byte,  int) []byte {
	 := lengthLength()

	for ;  > 0; -- {
		 = append(, byte(>>uint((-1)*8)))
	}

	return 
}

func ( int) ( int) {
	 = 1
	for  > 255 {
		++
		 >>= 8
	}
	return
}

func ( []byte,  tagAndLength) []byte {
	 := uint8(.class) << 6
	if .isCompound {
		 |= 0x20
	}
	if .tag >= 31 {
		 |= 0x1f
		 = append(, )
		 = appendBase128Int(, int64(.tag))
	} else {
		 |= uint8(.tag)
		 = append(, )
	}

	if .length >= 128 {
		 := lengthLength(.length)
		 = append(, 0x80|byte())
		 = appendLength(, .length)
	} else {
		 = append(, byte(.length))
	}

	return 
}

type bitStringEncoder BitString

func ( bitStringEncoder) () int {
	return len(.Bytes) + 1
}

func ( bitStringEncoder) ( []byte) {
	[0] = byte((8 - .BitLength%8) % 8)
	if copy([1:], .Bytes) != len(.Bytes) {
		panic("internal error")
	}
}

type oidEncoder []int

func ( oidEncoder) () int {
	 := base128IntLength(int64([0]*40 + [1]))
	for  := 2;  < len(); ++ {
		 += base128IntLength(int64([]))
	}
	return 
}

func ( oidEncoder) ( []byte) {
	 = appendBase128Int([:0], int64([0]*40+[1]))
	for  := 2;  < len(); ++ {
		 = appendBase128Int(, int64([]))
	}
}

func ( []int) ( encoder,  error) {
	if len() < 2 || [0] > 2 || ([0] < 2 && [1] >= 40) {
		return nil, StructuralError{"invalid object identifier"}
	}

	return oidEncoder(), nil
}

func ( string) ( encoder,  error) {
The asterisk is often used in PrintableString, even though it is invalid. If a PrintableString was specifically requested then the asterisk is permitted by this code. Ampersand is allowed in parsing due a handful of CA certificates, however when making new certificates it is rejected.
		if !isPrintable([], allowAsterisk, rejectAmpersand) {
			return nil, StructuralError{"PrintableString contains invalid character"}
		}
	}

	return stringEncoder(), nil
}

func ( string) ( encoder,  error) {
	for  := 0;  < len(); ++ {
		if [] > 127 {
			return nil, StructuralError{"IA5String contains invalid character"}
		}
	}

	return stringEncoder(), nil
}

func ( string) ( encoder,  error) {
	for  := 0;  < len(); ++ {
		if !isNumeric([]) {
			return nil, StructuralError{"NumericString contains invalid character"}
		}
	}

	return stringEncoder(), nil
}

func ( string) encoder {
	return stringEncoder()
}

func ( []byte,  int) []byte {
	return append(, byte('0'+(/10)%10), byte('0'+%10))
}

func ( []byte,  int) []byte {
	var  [4]byte
	for  := range  {
		[3-] = '0' + byte(%10)
		 /= 10
	}
	return append(, [:]...)
}

func ( time.Time) bool {
	 := .Year()
	return  < 1950 ||  >= 2050
}

func ( time.Time) ( encoder,  error) {
	 := make([]byte, 0, 18)

	,  = appendUTCTime(, )
	if  != nil {
		return nil, 
	}

	return bytesEncoder(), nil
}

func ( time.Time) ( encoder,  error) {
	 := make([]byte, 0, 20)

	,  = appendGeneralizedTime(, )
	if  != nil {
		return nil, 
	}

	return bytesEncoder(), nil
}

func ( []byte,  time.Time) ( []byte,  error) {
	 := .Year()

	switch {
	case 1950 <=  &&  < 2000:
		 = appendTwoDigits(, -1900)
	case 2000 <=  &&  < 2050:
		 = appendTwoDigits(, -2000)
	default:
		return nil, StructuralError{"cannot represent time as UTCTime"}
	}

	return appendTimeCommon(, ), nil
}

func ( []byte,  time.Time) ( []byte,  error) {
	 := .Year()
	if  < 0 ||  > 9999 {
		return nil, StructuralError{"cannot represent time as GeneralizedTime"}
	}

	 = appendFourDigits(, )

	return appendTimeCommon(, ), nil
}

func ( []byte,  time.Time) []byte {
	, ,  := .Date()

	 = appendTwoDigits(, int())
	 = appendTwoDigits(, )

	, ,  := .Clock()

	 = appendTwoDigits(, )
	 = appendTwoDigits(, )
	 = appendTwoDigits(, )

	,  := .Zone()

	switch {
	case /60 == 0:
		return append(, 'Z')
	case  > 0:
		 = append(, '+')
	case  < 0:
		 = append(, '-')
	}

	 :=  / 60
	if  < 0 {
		 = -
	}

	 = appendTwoDigits(, /60)
	 = appendTwoDigits(, %60)

	return 
}

func ( []byte) []byte {
	, ,  := parseTagAndLength(, 0)
	if  != nil {
		return 
	}
	return [:]
}

func ( reflect.Value,  fieldParameters) ( encoder,  error) {
	switch .Type() {
	case flagType:
		return bytesEncoder(nil), nil
	case timeType:
		 := .Interface().(time.Time)
		if .timeType == TagGeneralizedTime || outsideUTCRange() {
			return makeGeneralizedTime()
		}
		return makeUTCTime()
	case bitStringType:
		return bitStringEncoder(.Interface().(BitString)), nil
	case objectIdentifierType:
		return makeObjectIdentifier(.Interface().(ObjectIdentifier))
	case bigIntType:
		return makeBigInt(.Interface().(*big.Int))
	}

	switch  := ; .Kind() {
	case reflect.Bool:
		if .Bool() {
			return byteFFEncoder, nil
		}
		return byte00Encoder, nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return int64Encoder(.Int()), nil
	case reflect.Struct:
		 := .Type()

		for  := 0;  < .NumField(); ++ {
			if .Field().PkgPath != "" {
				return nil, StructuralError{"struct contains unexported fields"}
			}
		}

		 := 0

		 := .NumField()
		if  == 0 {
			return bytesEncoder(nil), nil
		}
If the first element of the structure is a non-empty RawContents, then we don't bother serializing the rest.
		if .Field(0).Type == rawContentsType {
			 := .Field(0)
			if .Len() > 0 {
The RawContents will contain the tag and * length fields but we'll also be writing * those ourselves, so we strip them out of * bytes
				return bytesEncoder(stripTagAndLength()), nil
			}

			 = 1
		}

		switch  :=  - ;  {
		case 0:
			return bytesEncoder(nil), nil
		case 1:
			return makeField(.Field(), parseFieldParameters(.Field().Tag.Get("asn1")))
		default:
			 := make([]encoder, )
			for  := 0;  < ; ++ {
				[],  = makeField(.Field(+), parseFieldParameters(.Field(+).Tag.Get("asn1")))
				if  != nil {
					return nil, 
				}
			}

			return multiEncoder(), nil
		}
	case reflect.Slice:
		 := .Type()
		if .Elem().Kind() == reflect.Uint8 {
			return bytesEncoder(.Bytes()), nil
		}

		var  fieldParameters

		switch  := .Len();  {
		case 0:
			return bytesEncoder(nil), nil
		case 1:
			return makeField(.Index(0), )
		default:
			 := make([]encoder, )

			for  := 0;  < ; ++ {
				[],  = makeField(.Index(), )
				if  != nil {
					return nil, 
				}
			}

			if .set {
				return setEncoder(), nil
			}
			return multiEncoder(), nil
		}
	case reflect.String:
		switch .stringType {
		case TagIA5String:
			return makeIA5String(.String())
		case TagPrintableString:
			return makePrintableString(.String())
		case TagNumericString:
			return makeNumericString(.String())
		default:
			return makeUTF8String(.String()), nil
		}
	}

	return nil, StructuralError{"unknown Go type"}
}

func ( reflect.Value,  fieldParameters) ( encoder,  error) {
	if !.IsValid() {
		return nil, fmt.Errorf("asn1: cannot marshal nil value")
If the field is an interface{} then recurse into it.
	if .Kind() == reflect.Interface && .Type().NumMethod() == 0 {
		return (.Elem(), )
	}

	if .Kind() == reflect.Slice && .Len() == 0 && .omitEmpty {
		return bytesEncoder(nil), nil
	}

	if .optional && .defaultValue != nil && canHaveDefaultValue(.Kind()) {
		 := reflect.New(.Type()).Elem()
		.SetInt(*.defaultValue)

		if reflect.DeepEqual(.Interface(), .Interface()) {
			return bytesEncoder(nil), nil
		}
	}
If no default value is given then the zero value for the type is assumed to be the default value. This isn't obviously the correct behavior, but it's what Go has traditionally done.
	if .optional && .defaultValue == nil {
		if reflect.DeepEqual(.Interface(), reflect.Zero(.Type()).Interface()) {
			return bytesEncoder(nil), nil
		}
	}

	if .Type() == rawValueType {
		 := .Interface().(RawValue)
		if len(.FullBytes) != 0 {
			return bytesEncoder(.FullBytes), nil
		}

		 := new(taggedEncoder)

		.tag = bytesEncoder(appendTagAndLength(.scratch[:0], tagAndLength{.Class, .Tag, len(.Bytes), .IsCompound}))
		.body = bytesEncoder(.Bytes)

		return , nil
	}

	, , ,  := getUniversalType(.Type())
	if ! ||  {
		return nil, StructuralError{fmt.Sprintf("unknown Go type: %v", .Type())}
	}

	if .timeType != 0 &&  != TagUTCTime {
		return nil, StructuralError{"explicit time type given to non-time member"}
	}

	if .stringType != 0 &&  != TagPrintableString {
		return nil, StructuralError{"explicit string type given to non-string member"}
	}

	switch  {
	case TagPrintableString:
This is a string without an explicit string type. We'll use a PrintableString if the character set in the string is sufficiently limited, otherwise we'll use a UTF8String.
			for ,  := range .String() {
				if  >= utf8.RuneSelf || !isPrintable(byte(), rejectAsterisk, rejectAmpersand) {
					if !utf8.ValidString(.String()) {
						return nil, errors.New("asn1: string not valid UTF-8")
					}
					 = TagUTF8String
					break
				}
			}
		} else {
			 = .stringType
		}
	case TagUTCTime:
		if .timeType == TagGeneralizedTime || outsideUTCRange(.Interface().(time.Time)) {
			 = TagGeneralizedTime
		}
	}

	if .set {
		if  != TagSequence {
			return nil, StructuralError{"non sequence tagged as set"}
		}
		 = TagSet
	}
makeField can be called for a slice that should be treated as a SET but doesn't have params.set set, for instance when using a slice with the SET type name suffix. In this case getUniversalType returns TagSet, but makeBody doesn't know about that so will treat the slice as a sequence. To work around this we set params.set.
	if  == TagSet && !.set {
		.set = true
	}

	 := new(taggedEncoder)

	.body,  = makeBody(, )
	if  != nil {
		return nil, 
	}

	 := .body.Len()

	 := ClassUniversal
	if .tag != nil {
		if .application {
			 = ClassApplication
		} else if .private {
			 = ClassPrivate
		} else {
			 = ClassContextSpecific
		}

		if .explicit {
			.tag = bytesEncoder(appendTagAndLength(.scratch[:0], tagAndLength{ClassUniversal, , , }))

			 := new(taggedEncoder)

			.body = 

			.tag = bytesEncoder(appendTagAndLength(.scratch[:0], tagAndLength{
				class:      ,
				tag:        *.tag,
				length:      + .tag.Len(),
				isCompound: true,
			}))

			return , nil
		}
implicit tag.
		 = *.tag
	}

	.tag = bytesEncoder(appendTagAndLength(.scratch[:0], tagAndLength{, , , }))

	return , nil
}
Marshal returns the ASN.1 encoding of val. In addition to the struct tags recognised by Unmarshal, the following can be used: ia5: causes strings to be marshaled as ASN.1, IA5String values omitempty: causes empty slices to be skipped printable: causes strings to be marshaled as ASN.1, PrintableString values utf8: causes strings to be marshaled as ASN.1, UTF8String values utc: causes time.Time to be marshaled as ASN.1, UTCTime values generalized: causes time.Time to be marshaled as ASN.1, GeneralizedTime values
func ( interface{}) ([]byte, error) {
	return MarshalWithParams(, "")
}
MarshalWithParams allows field parameters to be specified for the top-level element. The form of the params is the same as the field tags.
func ( interface{},  string) ([]byte, error) {
	,  := makeField(reflect.ValueOf(), parseFieldParameters())
	if  != nil {
		return nil, 
	}
	 := make([]byte, .Len())
	.Encode()
	return , nil