Copyright 2017 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 cryptobyte

import (
	encoding_asn1 
	
	
	
	

	
)
This file contains ASN.1-related methods for String and Builder.
Builder
AddASN1Int64 appends a DER-encoded ASN.1 INTEGER.
AddASN1Int64WithTag appends a DER-encoded ASN.1 INTEGER with the given tag.
func ( *Builder) ( int64,  asn1.Tag) {
	.addASN1Signed(, )
}
AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION.
func ( *Builder) ( int64) {
	.addASN1Signed(asn1.ENUM, )
}

func ( *Builder) ( asn1.Tag,  int64) {
	.AddASN1(, func( *Builder) {
		 := 1
		for  := ;  >= 0x80 ||  < -0x80;  >>= 8 {
			++
		}

		for ;  > 0; -- {
			 :=  >> uint((-1)*8) & 0xff
			.AddUint8(uint8())
		}
	})
}
AddASN1Uint64 appends a DER-encoded ASN.1 INTEGER.
func ( *Builder) ( uint64) {
	.AddASN1(asn1.INTEGER, func( *Builder) {
		 := 1
		for  := ;  >= 0x80;  >>= 8 {
			++
		}

		for ;  > 0; -- {
			 :=  >> uint((-1)*8) & 0xff
			.AddUint8(uint8())
		}
	})
}
AddASN1BigInt appends a DER-encoded ASN.1 INTEGER.
func ( *Builder) ( *big.Int) {
	if .err != nil {
		return
	}

	.AddASN1(asn1.INTEGER, func( *Builder) {
A negative number has to be converted to two's-complement form. So we 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 {
				.add(0xff)
			}
			.add(...)
		} else if .Sign() == 0 {
			.add(0)
		} else {
			 := .Bytes()
			if [0]&0x80 != 0 {
				.add(0)
			}
			.add(...)
		}
	})
}
AddASN1OctetString appends a DER-encoded ASN.1 OCTET STRING.
func ( *Builder) ( []byte) {
	.AddASN1(asn1.OCTET_STRING, func( *Builder) {
		.AddBytes()
	})
}

const generalizedTimeFormatStr = "20060102150405Z0700"
AddASN1GeneralizedTime appends a DER-encoded ASN.1 GENERALIZEDTIME.
func ( *Builder) ( time.Time) {
	if .Year() < 0 || .Year() > 9999 {
		.err = fmt.Errorf("cryptobyte: cannot represent %v as a GeneralizedTime", )
		return
	}
	.AddASN1(asn1.GeneralizedTime, func( *Builder) {
		.AddBytes([]byte(.Format(generalizedTimeFormatStr)))
	})
}
AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not support BIT STRINGs that are not a whole number of bytes.
func ( *Builder) ( []byte) {
	.AddASN1(asn1.BIT_STRING, func( *Builder) {
		.AddUint8(0)
		.AddBytes()
	})
}

func ( *Builder) ( int64) {
	var  int
	if  == 0 {
		 = 1
	} else {
		for  := ;  > 0;  >>= 7 {
			++
		}
	}

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

		.add()
	}
}

func ( encoding_asn1.ObjectIdentifier) bool {
	if len() < 2 {
		return false
	}

	if [0] > 2 || ([0] <= 1 && [1] >= 40) {
		return false
	}

	for ,  := range  {
		if  < 0 {
			return false
		}
	}

	return true
}

func ( *Builder) ( encoding_asn1.ObjectIdentifier) {
	.AddASN1(asn1.OBJECT_IDENTIFIER, func( *Builder) {
		if !isValidOID() {
			.err = fmt.Errorf("cryptobyte: invalid OID: %v", )
			return
		}

		.addBase128Int(int64([0])*40 + int64([1]))
		for ,  := range [2:] {
			.addBase128Int(int64())
		}
	})
}

func ( *Builder) ( bool) {
	.AddASN1(asn1.BOOLEAN, func( *Builder) {
		if  {
			.AddUint8(0xff)
		} else {
			.AddUint8(0)
		}
	})
}

func ( *Builder) () {
	.add(uint8(asn1.NULL), 0)
}
MarshalASN1 calls encoding_asn1.Marshal on its input and appends the result if successful or records an error if one occurred.
NOTE(martinkr): This is somewhat of a hack to allow propagation of encoding_asn1.Marshal errors into Builder.err. N.B. if you call MarshalASN1 with a value embedded into a struct, its tag information is lost.
	if .err != nil {
		return
	}
	,  := encoding_asn1.Marshal()
	if  != nil {
		.err = 
		return
	}
	.AddBytes()
}
AddASN1 appends an ASN.1 object. The object is prefixed with the given tag. Tags greater than 30 are not supported and result in an error (i.e. low-tag-number form only). The child builder passed to the BuilderContinuation can be used to build the content of the ASN.1 object.
func ( *Builder) ( asn1.Tag,  BuilderContinuation) {
	if .err != nil {
		return
Identifiers with the low five bits set indicate high-tag-number format (two or more octets), which we don't support.
	if &0x1f == 0x1f {
		.err = fmt.Errorf("cryptobyte: high-tag number identifier octects not supported: 0x%x", )
		return
	}
	.AddUint8(uint8())
	.addLengthPrefixed(1, true, )
}
String
ReadASN1Boolean decodes an ASN.1 BOOLEAN and converts it to a boolean representation into out and advances. It reports whether the read was successful.
func ( *String) ( *bool) bool {
	var  String
	if !.ReadASN1(&, asn1.BOOLEAN) || len() != 1 {
		return false
	}

	switch [0] {
	case 0:
		* = false
	case 0xff:
		* = true
	default:
		return false
	}

	return true
}

var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem()
ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does not point to an integer or to a big.Int, it panics. It reports whether the read was successful.
func ( *String) ( interface{}) bool {
	if reflect.TypeOf().Kind() != reflect.Ptr {
		panic("out is not a pointer")
	}
	switch reflect.ValueOf().Elem().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		var  int64
		if !.readASN1Int64(&) || reflect.ValueOf().Elem().OverflowInt() {
			return false
		}
		reflect.ValueOf().Elem().SetInt()
		return true
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		var  uint64
		if !.readASN1Uint64(&) || reflect.ValueOf().Elem().OverflowUint() {
			return false
		}
		reflect.ValueOf().Elem().SetUint()
		return true
	case reflect.Struct:
		if reflect.TypeOf().Elem() == bigIntType {
			return .readASN1BigInt(.(*big.Int))
		}
	}
	panic("out does not point to an integer type")
}

func ( []byte) bool {
An INTEGER is encoded with at least one octet.
		return false
	}
	if len() == 1 {
		return true
	}
Value is not minimally encoded.
		return false
	}
	return true
}

var bigOne = big.NewInt(1)

func ( *String) ( *big.Int) bool {
	var  String
	if !.ReadASN1(&, asn1.INTEGER) || !checkASN1Integer() {
		return false
	}
Negative number.
		 := make([]byte, len())
		for ,  := range  {
			[] = ^
		}
		.SetBytes()
		.Add(, bigOne)
		.Neg()
	} else {
		.SetBytes()
	}
	return true
}

func ( *String) ( *int64) bool {
	var  String
	if !.ReadASN1(&, asn1.INTEGER) || !checkASN1Integer() || !asn1Signed(, ) {
		return false
	}
	return true
}

func ( *int64,  []byte) bool {
	 := len()
	if  > 8 {
		return false
	}
	for  := 0;  < ; ++ {
		* <<= 8
		* |= int64([])
Shift up and down in order to sign extend the result.
	* <<= 64 - uint8()*8
	* >>= 64 - uint8()*8
	return true
}

func ( *String) ( *uint64) bool {
	var  String
	if !.ReadASN1(&, asn1.INTEGER) || !checkASN1Integer() || !asn1Unsigned(, ) {
		return false
	}
	return true
}

func ( *uint64,  []byte) bool {
	 := len()
Too large for uint64.
		return false
	}
Negative number.
		return false
	}
	for  := 0;  < ; ++ {
		* <<= 8
		* |= uint64([])
	}
	return true
}
ReadASN1Int64WithTag decodes an ASN.1 INTEGER with the given tag into out and advances. It reports whether the read was successful and resulted in a value that can be represented in an int64.
func ( *String) ( *int64,  asn1.Tag) bool {
	var  String
	return .ReadASN1(&, ) && checkASN1Integer() && asn1Signed(, )
}
ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It reports whether the read was successful.
func ( *String) ( *int) bool {
	var  String
	var  int64
	if !.ReadASN1(&, asn1.ENUM) || !checkASN1Integer() || !asn1Signed(&, ) {
		return false
	}
	if int64(int()) !=  {
		return false
	}
	* = int()
	return true
}

func ( *String) ( *int) bool {
	 := 0
	for  := 0; len(*) > 0; ++ {
		if  == 4 {
			return false
		}
		 <<= 7
		 := .read(1)[0]
		 |= int( & 0x7f)
		if &0x80 == 0 {
			* = 
			return true
		}
	}
	return false // truncated
}
ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and advances. It reports whether the read was successful.
func ( *String) ( *encoding_asn1.ObjectIdentifier) bool {
	var  String
	if !.ReadASN1(&, asn1.OBJECT_IDENTIFIER) || len() == 0 {
		return false
	}
In the worst case, we get two elements from the first byte (which is encoded differently) and then every varint is a single byte long.
	 := make([]int, len()+1)
The first varint is 40*value1 + value2: According to this packing, value1 can take the values 0, 1 and 2 only. When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2, then there are no restrictions on value2.
	var  int
	if !.readBase128Int(&) {
		return false
	}
	if  < 80 {
		[0] =  / 40
		[1] =  % 40
	} else {
		[0] = 2
		[1] =  - 80
	}

	 := 2
	for ; len() > 0; ++ {
		if !.readBase128Int(&) {
			return false
		}
		[] = 
	}
	* = [:]
	return true
}
ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and advances. It reports whether the read was successful.
func ( *String) ( *time.Time) bool {
	var  String
	if !.ReadASN1(&, asn1.GeneralizedTime) {
		return false
	}
	 := string()
	,  := time.Parse(generalizedTimeFormatStr, )
	if  != nil {
		return false
	}
	if  := .Format(generalizedTimeFormatStr);  !=  {
		return false
	}
	* = 
	return true
}
ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It reports whether the read was successful.
func ( *String) ( *encoding_asn1.BitString) bool {
	var  String
	if !.ReadASN1(&, asn1.BIT_STRING) || len() == 0 ||
		len()*8/8 != len() {
		return false
	}

	 := uint8([0])
	 = [1:]
	if  > 7 ||
		len() == 0 &&  != 0 ||
		len() > 0 && [len()-1]&(1<<-1) != 0 {
		return false
	}

	.BitLength = len()*8 - int()
	.Bytes = 
	return true
}
ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It is an error if the BIT STRING is not a whole number of bytes. It reports whether the read was successful.
func ( *String) ( *[]byte) bool {
	var  String
	if !.ReadASN1(&, asn1.BIT_STRING) || len() == 0 {
		return false
	}

	 := uint8([0])
	if  != 0 {
		return false
	}
	* = [1:]
	return true
}
ReadASN1Bytes reads the contents of a DER-encoded ASN.1 element (not including tag and length bytes) into out, and advances. The element must match the given tag. It reports whether the read was successful.
func ( *String) ( *[]byte,  asn1.Tag) bool {
	return .ReadASN1((*String)(), )
}
ReadASN1 reads the contents of a DER-encoded ASN.1 element (not including tag and length bytes) into out, and advances. The element must match the given tag. It reports whether the read was successful. Tags greater than 30 are not supported (i.e. low-tag-number format only).
func ( *String) ( *String,  asn1.Tag) bool {
	var  asn1.Tag
	if !.ReadAnyASN1(, &) ||  !=  {
		return false
	}
	return true
}
ReadASN1Element reads the contents of a DER-encoded ASN.1 element (including tag and length bytes) into out, and advances. The element must match the given tag. It reports whether the read was successful. Tags greater than 30 are not supported (i.e. low-tag-number format only).
func ( *String) ( *String,  asn1.Tag) bool {
	var  asn1.Tag
	if !.ReadAnyASN1Element(, &) ||  !=  {
		return false
	}
	return true
}
ReadAnyASN1 reads the contents of a DER-encoded ASN.1 element (not including tag and length bytes) into out, sets outTag to its tag, and advances. It reports whether the read was successful. Tags greater than 30 are not supported (i.e. low-tag-number format only).
func ( *String) ( *String,  *asn1.Tag) bool {
	return .readASN1(, , true /* skip header */)
}
ReadAnyASN1Element reads the contents of a DER-encoded ASN.1 element (including tag and length bytes) into out, sets outTag to is tag, and advances. It reports whether the read was successful. Tags greater than 30 are not supported (i.e. low-tag-number format only).
func ( *String) ( *String,  *asn1.Tag) bool {
	return .readASN1(, , false /* include header */)
}
PeekASN1Tag reports whether the next ASN.1 value on the string starts with the given tag.
func ( String) ( asn1.Tag) bool {
	if len() == 0 {
		return false
	}
	return asn1.Tag([0]) == 
}
SkipASN1 reads and discards an ASN.1 element with the given tag. It reports whether the operation was successful.
func ( *String) ( asn1.Tag) bool {
	var  String
	return .ReadASN1(&, )
}
ReadOptionalASN1 attempts to read the contents of a DER-encoded ASN.1 element (not including tag and length bytes) tagged with the given tag into out. It stores whether an element with the tag was found in outPresent, unless outPresent is nil. It reports whether the read was successful.
func ( *String) ( *String,  *bool,  asn1.Tag) bool {
	 := .PeekASN1Tag()
	if  != nil {
		* = 
	}
	if  && !.ReadASN1(, ) {
		return false
	}
	return true
}
SkipOptionalASN1 advances s over an ASN.1 element with the given tag, or else leaves s unchanged. It reports whether the operation was successful.
func ( *String) ( asn1.Tag) bool {
	if !.PeekASN1Tag() {
		return true
	}
	var  String
	return .ReadASN1(&, )
}
ReadOptionalASN1Integer attempts to read an optional ASN.1 INTEGER explicitly tagged with tag into out and advances. If no element with a matching tag is present, it writes defaultValue into out instead. If out does not point to an integer or to a big.Int, it panics. It reports whether the read was successful.
func ( *String) ( interface{},  asn1.Tag,  interface{}) bool {
	if reflect.TypeOf().Kind() != reflect.Ptr {
		panic("out is not a pointer")
	}
	var  bool
	var  String
	if !.ReadOptionalASN1(&, &, ) {
		return false
	}
	if ! {
		switch reflect.ValueOf().Elem().Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			reflect.ValueOf().Elem().Set(reflect.ValueOf())
		case reflect.Struct:
			if reflect.TypeOf().Elem() != bigIntType {
				panic("invalid integer type")
			}
			if reflect.TypeOf().Kind() != reflect.Ptr ||
				reflect.TypeOf().Elem() != bigIntType {
				panic("out points to big.Int, but defaultValue does not")
			}
			.(*big.Int).Set(.(*big.Int))
		default:
			panic("invalid integer type")
		}
		return true
	}
	if !.ReadASN1Integer() || !.Empty() {
		return false
	}
	return true
}
ReadOptionalASN1OctetString attempts to read an optional ASN.1 OCTET STRING explicitly tagged with tag into out and advances. If no element with a matching tag is present, it sets "out" to nil instead. It reports whether the read was successful.
func ( *String) ( *[]byte,  *bool,  asn1.Tag) bool {
	var  bool
	var  String
	if !.ReadOptionalASN1(&, &, ) {
		return false
	}
	if  != nil {
		* = 
	}
	if  {
		var  String
		if !.ReadASN1(&, asn1.OCTET_STRING) || !.Empty() {
			return false
		}
		* = 
	} else {
		* = nil
	}
	return true
}
ReadOptionalASN1Boolean sets *out to the value of the next ASN.1 BOOLEAN or, if the next bytes are not an ASN.1 BOOLEAN, to the value of defaultValue. It reports whether the operation was successful.
func ( *String) ( *bool,  bool) bool {
	var  bool
	var  String
	if !.ReadOptionalASN1(&, &, asn1.BOOLEAN) {
		return false
	}

	if ! {
		* = 
		return true
	}

	return .ReadASN1Boolean()
}

func ( *String) ( *String,  *asn1.Tag,  bool) bool {
	if len(*) < 2 {
		return false
	}
	,  := (*)[0], (*)[1]

ITU-T X.690 section 8.1.2 An identifier octet with a tag part of 0x1f indicates a high-tag-number form identifier with two or more octets. We only support tags less than 31 (i.e. low-tag-number form, single octet identifier).
		return false
	}

	if  != nil {
		* = asn1.Tag()
	}
ITU-T X.690 section 8.1.3 Bit 8 of the first length byte indicates whether the length is short- or long-form.
	var ,  uint32 // length includes headerLen
Short-form length (section 8.1.3.4), encoded in bits 1-7.
		 = uint32() + 2
		 = 2
Long-form length (section 8.1.3.5). Bits 1-7 encode the number of octets used to encode the length.
		 :=  & 0x7f
		var  uint32

		if  == 0 ||  > 4 || len(*) < int(2+) {
			return false
		}

		 := String((*)[2 : 2+])
		if !.readUnsigned(&, int()) {
			return false
		}
ITU-T X.690 section 10.1 (DER length forms) requires encoding the length with the minimum number of octets.
Length should have used short-form encoding.
			return false
		}
Leading octet is 0. Length should have been at least one byte shorter.
			return false
		}

		 = 2 + uint32()
Overflow.
			return false
		}
		 =  + 
	}

	if int() < 0 || !.ReadBytes((*[]byte)(), int()) {
		return false
	}
	if  && !.Skip(int()) {
		panic("cryptobyte: internal error")
	}

	return true