// Copyright 2021 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 x509

import (
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	

	
	cryptobyte_asn1 
)

// isPrintable reports whether the given b is in the ASN.1 PrintableString set.
// This is a simplified version of encoding/asn1.isPrintable.
func isPrintable( byte) bool {
	return 'a' <=  &&  <= 'z' ||
		'A' <=  &&  <= 'Z' ||
		'0' <=  &&  <= '9' ||
		'\'' <=  &&  <= ')' ||
		'+' <=  &&  <= '/' ||
		 == ' ' ||
		 == ':' ||
		 == '=' ||
		 == '?' ||
		// This is technically not allowed in a PrintableString.
		// However, x509 certificates with wildcard strings don't
		// always use the correct string type so we permit it.
		 == '*' ||
		// This is not technically allowed either. However, not
		// only is it relatively common, but there are also a
		// handful of CA certificates that contain it. At least
		// one of which will not expire until 2027.
		 == '&'
}

// parseASN1String parses the ASN.1 string types T61String, PrintableString,
// UTF8String, BMPString, IA5String, and NumericString. This is mostly copied
// from the respective encoding/asn1.parse... methods, rather than just
// increasing the API surface of that package.
func parseASN1String( cryptobyte_asn1.Tag,  []byte) (string, error) {
	switch  {
	case cryptobyte_asn1.T61String:
		return string(), nil
	case cryptobyte_asn1.PrintableString:
		for ,  := range  {
			if !isPrintable() {
				return "", errors.New("invalid PrintableString")
			}
		}
		return string(), nil
	case cryptobyte_asn1.UTF8String:
		if !utf8.Valid() {
			return "", errors.New("invalid UTF-8 string")
		}
		return string(), nil
	case cryptobyte_asn1.Tag(asn1.TagBMPString):
		if len()%2 != 0 {
			return "", errors.New("invalid BMPString")
		}

		// Strip terminator if present.
		if  := len();  >= 2 && [-1] == 0 && [-2] == 0 {
			 = [:-2]
		}

		 := make([]uint16, 0, len()/2)
		for len() > 0 {
			 = append(, uint16([0])<<8+uint16([1]))
			 = [2:]
		}

		return string(utf16.Decode()), nil
	case cryptobyte_asn1.IA5String:
		 := string()
		if isIA5String() != nil {
			return "", errors.New("invalid IA5String")
		}
		return , nil
	case cryptobyte_asn1.Tag(asn1.TagNumericString):
		for ,  := range  {
			if !('0' <=  &&  <= '9' ||  == ' ') {
				return "", errors.New("invalid NumericString")
			}
		}
		return string(), nil
	}
	return "", fmt.Errorf("unsupported string type: %v", )
}

// parseName parses a DER encoded Name as defined in RFC 5280. We may
// want to export this function in the future for use in crypto/tls.
func parseName( cryptobyte.String) (*pkix.RDNSequence, error) {
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: invalid RDNSequence")
	}

	var  pkix.RDNSequence
	for !.Empty() {
		var  pkix.RelativeDistinguishedNameSET
		var  cryptobyte.String
		if !.ReadASN1(&, cryptobyte_asn1.SET) {
			return nil, errors.New("x509: invalid RDNSequence")
		}
		for !.Empty() {
			var  cryptobyte.String
			if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
				return nil, errors.New("x509: invalid RDNSequence: invalid attribute")
			}
			var  pkix.AttributeTypeAndValue
			if !.ReadASN1ObjectIdentifier(&.Type) {
				return nil, errors.New("x509: invalid RDNSequence: invalid attribute type")
			}
			var  cryptobyte.String
			var  cryptobyte_asn1.Tag
			if !.ReadAnyASN1(&, &) {
				return nil, errors.New("x509: invalid RDNSequence: invalid attribute value")
			}
			var  error
			.Value,  = parseASN1String(, )
			if  != nil {
				return nil, fmt.Errorf("x509: invalid RDNSequence: invalid attribute value: %s", )
			}
			 = append(, )
		}

		 = append(, )
	}

	return &, nil
}

func parseAI( cryptobyte.String) (pkix.AlgorithmIdentifier, error) {
	 := pkix.AlgorithmIdentifier{}
	if !.ReadASN1ObjectIdentifier(&.Algorithm) {
		return , errors.New("x509: malformed OID")
	}
	if .Empty() {
		return , nil
	}
	var  cryptobyte.String
	var  cryptobyte_asn1.Tag
	if !.ReadAnyASN1Element(&, &) {
		return , errors.New("x509: malformed parameters")
	}
	.Parameters.Tag = int()
	.Parameters.FullBytes = 
	return , nil
}

func parseTime( *cryptobyte.String) (time.Time, error) {
	var  time.Time
	switch {
	case .PeekASN1Tag(cryptobyte_asn1.UTCTime):
		if !.ReadASN1UTCTime(&) {
			return , errors.New("x509: malformed UTCTime")
		}
	case .PeekASN1Tag(cryptobyte_asn1.GeneralizedTime):
		if !.ReadASN1GeneralizedTime(&) {
			return , errors.New("x509: malformed GeneralizedTime")
		}
	default:
		return , errors.New("x509: unsupported time format")
	}
	return , nil
}

func parseValidity( cryptobyte.String) (time.Time, time.Time, error) {
	,  := parseTime(&)
	if  != nil {
		return time.Time{}, time.Time{}, 
	}
	,  := parseTime(&)
	if  != nil {
		return time.Time{}, time.Time{}, 
	}

	return , , nil
}

func parseExtension( cryptobyte.String) (pkix.Extension, error) {
	var  pkix.Extension
	if !.ReadASN1ObjectIdentifier(&.Id) {
		return , errors.New("x509: malformed extension OID field")
	}
	if .PeekASN1Tag(cryptobyte_asn1.BOOLEAN) {
		if !.ReadASN1Boolean(&.Critical) {
			return , errors.New("x509: malformed extension critical field")
		}
	}
	var  cryptobyte.String
	if !.ReadASN1(&, cryptobyte_asn1.OCTET_STRING) {
		return , errors.New("x509: malformed extension value field")
	}
	.Value = 
	return , nil
}

func parsePublicKey( *publicKeyInfo) (any, error) {
	 := .Algorithm.Algorithm
	 := .Algorithm.Parameters
	 := cryptobyte.String(.PublicKey.RightAlign())
	switch {
	case .Equal(oidPublicKeyRSA):
		// RSA public keys must have a NULL in the parameters.
		// See RFC 3279, Section 2.3.1.
		if !bytes.Equal(.FullBytes, asn1.NullBytes) {
			return nil, errors.New("x509: RSA key missing NULL parameters")
		}

		 := &pkcs1PublicKey{N: new(big.Int)}
		if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
			return nil, errors.New("x509: invalid RSA public key")
		}
		if !.ReadASN1Integer(.N) {
			return nil, errors.New("x509: invalid RSA modulus")
		}
		if !.ReadASN1Integer(&.E) {
			return nil, errors.New("x509: invalid RSA public exponent")
		}

		if .N.Sign() <= 0 {
			return nil, errors.New("x509: RSA modulus is not a positive number")
		}
		if .E <= 0 {
			return nil, errors.New("x509: RSA public exponent is not a positive number")
		}

		 := &rsa.PublicKey{
			E: .E,
			N: .N,
		}
		return , nil
	case .Equal(oidPublicKeyECDSA):
		 := cryptobyte.String(.FullBytes)
		 := new(asn1.ObjectIdentifier)
		if !.ReadASN1ObjectIdentifier() {
			return nil, errors.New("x509: invalid ECDSA parameters")
		}
		 := namedCurveFromOID(*)
		if  == nil {
			return nil, errors.New("x509: unsupported elliptic curve")
		}
		,  := elliptic.Unmarshal(, )
		if  == nil {
			return nil, errors.New("x509: failed to unmarshal elliptic curve point")
		}
		 := &ecdsa.PublicKey{
			Curve: ,
			X:     ,
			Y:     ,
		}
		return , nil
	case .Equal(oidPublicKeyEd25519):
		// RFC 8410, Section 3
		// > For all of the OIDs, the parameters MUST be absent.
		if len(.FullBytes) != 0 {
			return nil, errors.New("x509: Ed25519 key encoded with illegal parameters")
		}
		if len() != ed25519.PublicKeySize {
			return nil, errors.New("x509: wrong Ed25519 public key size")
		}
		return ed25519.PublicKey(), nil
	case .Equal(oidPublicKeyX25519):
		// RFC 8410, Section 3
		// > For all of the OIDs, the parameters MUST be absent.
		if len(.FullBytes) != 0 {
			return nil, errors.New("x509: X25519 key encoded with illegal parameters")
		}
		return ecdh.X25519().NewPublicKey()
	case .Equal(oidPublicKeyDSA):
		 := new(big.Int)
		if !.ReadASN1Integer() {
			return nil, errors.New("x509: invalid DSA public key")
		}
		 := &dsa.PublicKey{
			Y: ,
			Parameters: dsa.Parameters{
				P: new(big.Int),
				Q: new(big.Int),
				G: new(big.Int),
			},
		}
		 := cryptobyte.String(.FullBytes)
		if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) ||
			!.ReadASN1Integer(.Parameters.P) ||
			!.ReadASN1Integer(.Parameters.Q) ||
			!.ReadASN1Integer(.Parameters.G) {
			return nil, errors.New("x509: invalid DSA parameters")
		}
		if .Y.Sign() <= 0 || .Parameters.P.Sign() <= 0 ||
			.Parameters.Q.Sign() <= 0 || .Parameters.G.Sign() <= 0 {
			return nil, errors.New("x509: zero or negative DSA parameter")
		}
		return , nil
	default:
		return nil, errors.New("x509: unknown public key algorithm")
	}
}

func parseKeyUsageExtension( cryptobyte.String) (KeyUsage, error) {
	var  asn1.BitString
	if !.ReadASN1BitString(&) {
		return 0, errors.New("x509: invalid key usage")
	}

	var  int
	for  := 0;  < 9; ++ {
		if .At() != 0 {
			 |= 1 << uint()
		}
	}
	return KeyUsage(), nil
}

func parseBasicConstraintsExtension( cryptobyte.String) (bool, int, error) {
	var  bool
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return false, 0, errors.New("x509: invalid basic constraints a")
	}
	if .PeekASN1Tag(cryptobyte_asn1.BOOLEAN) {
		if !.ReadASN1Boolean(&) {
			return false, 0, errors.New("x509: invalid basic constraints b")
		}
	}
	 := -1
	if !.Empty() && .PeekASN1Tag(cryptobyte_asn1.INTEGER) {
		if !.ReadASN1Integer(&) {
			return false, 0, errors.New("x509: invalid basic constraints c")
		}
	}

	// TODO: map out.MaxPathLen to 0 if it has the -1 default value? (Issue 19285)
	return , , nil
}

func forEachSAN( cryptobyte.String,  func( int,  []byte) error) error {
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return errors.New("x509: invalid subject alternative names")
	}
	for !.Empty() {
		var  cryptobyte.String
		var  cryptobyte_asn1.Tag
		if !.ReadAnyASN1(&, &) {
			return errors.New("x509: invalid subject alternative name")
		}
		if  := (int(^0x80), );  != nil {
			return 
		}
	}

	return nil
}

func parseSANExtension( cryptobyte.String) (,  []string,  []net.IP,  []*url.URL,  error) {
	 = forEachSAN(, func( int,  []byte) error {
		switch  {
		case nameTypeEmail:
			 := string()
			if  := isIA5String();  != nil {
				return errors.New("x509: SAN rfc822Name is malformed")
			}
			 = append(, )
		case nameTypeDNS:
			 := string()
			if  := isIA5String();  != nil {
				return errors.New("x509: SAN dNSName is malformed")
			}
			 = append(, string())
		case nameTypeURI:
			 := string()
			if  := isIA5String();  != nil {
				return errors.New("x509: SAN uniformResourceIdentifier is malformed")
			}
			,  := url.Parse()
			if  != nil {
				return fmt.Errorf("x509: cannot parse URI %q: %s", , )
			}
			if len(.Host) > 0 {
				if ,  := domainToReverseLabels(.Host); ! {
					return fmt.Errorf("x509: cannot parse URI %q: invalid domain", )
				}
			}
			 = append(, )
		case nameTypeIP:
			switch len() {
			case net.IPv4len, net.IPv6len:
				 = append(, )
			default:
				return errors.New("x509: cannot parse IP address of length " + strconv.Itoa(len()))
			}
		}

		return nil
	})

	return
}

func parseExtKeyUsageExtension( cryptobyte.String) ([]ExtKeyUsage, []asn1.ObjectIdentifier, error) {
	var  []ExtKeyUsage
	var  []asn1.ObjectIdentifier
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return nil, nil, errors.New("x509: invalid extended key usages")
	}
	for !.Empty() {
		var  asn1.ObjectIdentifier
		if !.ReadASN1ObjectIdentifier(&) {
			return nil, nil, errors.New("x509: invalid extended key usages")
		}
		if ,  := extKeyUsageFromOID();  {
			 = append(, )
		} else {
			 = append(, )
		}
	}
	return , , nil
}

func parseCertificatePoliciesExtension( cryptobyte.String) ([]asn1.ObjectIdentifier, error) {
	var  []asn1.ObjectIdentifier
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: invalid certificate policies")
	}
	for !.Empty() {
		var  cryptobyte.String
		if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
			return nil, errors.New("x509: invalid certificate policies")
		}
		var  asn1.ObjectIdentifier
		if !.ReadASN1ObjectIdentifier(&) {
			return nil, errors.New("x509: invalid certificate policies")
		}
		 = append(, )
	}

	return , nil
}

// isValidIPMask reports whether mask consists of zero or more 1 bits, followed by zero bits.
func isValidIPMask( []byte) bool {
	 := false

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

			continue
		}

		switch  {
		case 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe:
			 = true
		case 0xff:
		default:
			return false
		}
	}

	return true
}

func parseNameConstraintsExtension( *Certificate,  pkix.Extension) ( bool,  error) {
	// RFC 5280, 4.2.1.10

	// NameConstraints ::= SEQUENCE {
	//      permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
	//      excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
	//
	// GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
	//
	// GeneralSubtree ::= SEQUENCE {
	//      base                    GeneralName,
	//      minimum         [0]     BaseDistance DEFAULT 0,
	//      maximum         [1]     BaseDistance OPTIONAL }
	//
	// BaseDistance ::= INTEGER (0..MAX)

	 := cryptobyte.String(.Value)
	var , ,  cryptobyte.String
	var ,  bool
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) ||
		!.Empty() ||
		!.ReadOptionalASN1(&, &, cryptobyte_asn1.Tag(0).ContextSpecific().Constructed()) ||
		!.ReadOptionalASN1(&, &, cryptobyte_asn1.Tag(1).ContextSpecific().Constructed()) ||
		!.Empty() {
		return false, errors.New("x509: invalid NameConstraints extension")
	}

	if ! && ! || len() == 0 && len() == 0 {
		// From RFC 5280, Section 4.2.1.10:
		//   “either the permittedSubtrees field
		//   or the excludedSubtrees MUST be
		//   present”
		return false, errors.New("x509: empty name constraints extension")
	}

	 := func( cryptobyte.String) ( []string,  []*net.IPNet, ,  []string,  error) {
		for !.Empty() {
			var ,  cryptobyte.String
			var  cryptobyte_asn1.Tag
			if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) ||
				!.ReadAnyASN1(&, &) {
				return nil, nil, nil, nil, fmt.Errorf("x509: invalid NameConstraints extension")
			}

			var (
				   = cryptobyte_asn1.Tag(2).ContextSpecific()
				 = cryptobyte_asn1.Tag(1).ContextSpecific()
				    = cryptobyte_asn1.Tag(7).ContextSpecific()
				   = cryptobyte_asn1.Tag(6).ContextSpecific()
			)

			switch  {
			case :
				 := string()
				if  := isIA5String();  != nil {
					return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + .Error())
				}

				 := 
				if len() > 0 && [0] == '.' {
					// constraints can have a leading
					// period to exclude the domain
					// itself, but that's not valid in a
					// normal domain name.
					 = [1:]
				}
				if ,  := domainToReverseLabels(); ! {
					return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse dnsName constraint %q", )
				}
				 = append(, )

			case :
				 := len()
				var ,  []byte

				switch  {
				case 8:
					 = [:4]
					 = [4:]

				case 32:
					 = [:16]
					 = [16:]

				default:
					return nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained value of length %d", )
				}

				if !isValidIPMask() {
					return nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained invalid mask %x", )
				}

				 = append(, &net.IPNet{IP: net.IP(), Mask: net.IPMask()})

			case :
				 := string()
				if  := isIA5String();  != nil {
					return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + .Error())
				}

				// If the constraint contains an @ then
				// it specifies an exact mailbox name.
				if strings.Contains(, "@") {
					if ,  := parseRFC2821Mailbox(); ! {
						return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", )
					}
				} else {
					// Otherwise it's a domain name.
					 := 
					if len() > 0 && [0] == '.' {
						 = [1:]
					}
					if ,  := domainToReverseLabels(); ! {
						return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", )
					}
				}
				 = append(, )

			case :
				 := string()
				if  := isIA5String();  != nil {
					return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + .Error())
				}

				if net.ParseIP() != nil {
					return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q: cannot be IP address", )
				}

				 := 
				if len() > 0 && [0] == '.' {
					// constraints can have a leading
					// period to exclude the domain itself,
					// but that's not valid in a normal
					// domain name.
					 = [1:]
				}
				if ,  := domainToReverseLabels(); ! {
					return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q", )
				}
				 = append(, )

			default:
				 = true
			}
		}

		return , , , , nil
	}

	if .PermittedDNSDomains, .PermittedIPRanges, .PermittedEmailAddresses, .PermittedURIDomains,  = ();  != nil {
		return false, 
	}
	if .ExcludedDNSDomains, .ExcludedIPRanges, .ExcludedEmailAddresses, .ExcludedURIDomains,  = ();  != nil {
		return false, 
	}
	.PermittedDNSDomainsCritical = .Critical

	return , nil
}

func processExtensions( *Certificate) error {
	var  error
	for ,  := range .Extensions {
		 := false

		if len(.Id) == 4 && .Id[0] == 2 && .Id[1] == 5 && .Id[2] == 29 {
			switch .Id[3] {
			case 15:
				.KeyUsage,  = parseKeyUsageExtension(.Value)
				if  != nil {
					return 
				}
			case 19:
				.IsCA, .MaxPathLen,  = parseBasicConstraintsExtension(.Value)
				if  != nil {
					return 
				}
				.BasicConstraintsValid = true
				.MaxPathLenZero = .MaxPathLen == 0
			case 17:
				.DNSNames, .EmailAddresses, .IPAddresses, .URIs,  = parseSANExtension(.Value)
				if  != nil {
					return 
				}

				if len(.DNSNames) == 0 && len(.EmailAddresses) == 0 && len(.IPAddresses) == 0 && len(.URIs) == 0 {
					// If we didn't parse anything then we do the critical check, below.
					 = true
				}

			case 30:
				,  = parseNameConstraintsExtension(, )
				if  != nil {
					return 
				}

			case 31:
				// RFC 5280, 4.2.1.13

				// CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
				//
				// DistributionPoint ::= SEQUENCE {
				//     distributionPoint       [0]     DistributionPointName OPTIONAL,
				//     reasons                 [1]     ReasonFlags OPTIONAL,
				//     cRLIssuer               [2]     GeneralNames OPTIONAL }
				//
				// DistributionPointName ::= CHOICE {
				//     fullName                [0]     GeneralNames,
				//     nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
				 := cryptobyte.String(.Value)
				if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
					return errors.New("x509: invalid CRL distribution points")
				}
				for !.Empty() {
					var  cryptobyte.String
					if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
						return errors.New("x509: invalid CRL distribution point")
					}
					var  cryptobyte.String
					var  bool
					if !.ReadOptionalASN1(&, &, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) {
						return errors.New("x509: invalid CRL distribution point")
					}
					if ! {
						continue
					}
					if !.ReadASN1(&, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) {
						return errors.New("x509: invalid CRL distribution point")
					}
					for !.Empty() {
						if !.PeekASN1Tag(cryptobyte_asn1.Tag(6).ContextSpecific()) {
							break
						}
						var  cryptobyte.String
						if !.ReadASN1(&, cryptobyte_asn1.Tag(6).ContextSpecific()) {
							return errors.New("x509: invalid CRL distribution point")
						}
						.CRLDistributionPoints = append(.CRLDistributionPoints, string())
					}
				}

			case 35:
				// RFC 5280, 4.2.1.1
				 := cryptobyte.String(.Value)
				var  cryptobyte.String
				if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
					return errors.New("x509: invalid authority key identifier")
				}
				if .PeekASN1Tag(cryptobyte_asn1.Tag(0).ContextSpecific()) {
					if !.ReadASN1(&, cryptobyte_asn1.Tag(0).ContextSpecific()) {
						return errors.New("x509: invalid authority key identifier")
					}
					.AuthorityKeyId = 
				}
			case 37:
				.ExtKeyUsage, .UnknownExtKeyUsage,  = parseExtKeyUsageExtension(.Value)
				if  != nil {
					return 
				}
			case 14:
				// RFC 5280, 4.2.1.2
				 := cryptobyte.String(.Value)
				var  cryptobyte.String
				if !.ReadASN1(&, cryptobyte_asn1.OCTET_STRING) {
					return errors.New("x509: invalid subject key identifier")
				}
				.SubjectKeyId = 
			case 32:
				.PolicyIdentifiers,  = parseCertificatePoliciesExtension(.Value)
				if  != nil {
					return 
				}
			default:
				// Unknown extensions are recorded if critical.
				 = true
			}
		} else if .Id.Equal(oidExtensionAuthorityInfoAccess) {
			// RFC 5280 4.2.2.1: Authority Information Access
			 := cryptobyte.String(.Value)
			if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
				return errors.New("x509: invalid authority info access")
			}
			for !.Empty() {
				var  cryptobyte.String
				if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
					return errors.New("x509: invalid authority info access")
				}
				var  asn1.ObjectIdentifier
				if !.ReadASN1ObjectIdentifier(&) {
					return errors.New("x509: invalid authority info access")
				}
				if !.PeekASN1Tag(cryptobyte_asn1.Tag(6).ContextSpecific()) {
					continue
				}
				if !.ReadASN1(&, cryptobyte_asn1.Tag(6).ContextSpecific()) {
					return errors.New("x509: invalid authority info access")
				}
				switch {
				case .Equal(oidAuthorityInfoAccessOcsp):
					.OCSPServer = append(.OCSPServer, string())
				case .Equal(oidAuthorityInfoAccessIssuers):
					.IssuingCertificateURL = append(.IssuingCertificateURL, string())
				}
			}
		} else {
			// Unknown extensions are recorded if critical.
			 = true
		}

		if .Critical &&  {
			.UnhandledCriticalExtensions = append(.UnhandledCriticalExtensions, .Id)
		}
	}

	return nil
}

func parseCertificate( []byte) (*Certificate, error) {
	 := &Certificate{}

	 := cryptobyte.String()
	// we read the SEQUENCE including length and tag bytes so that
	// we can populate Certificate.Raw, before unwrapping the
	// SEQUENCE so it can be operated on
	if !.ReadASN1Element(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed certificate")
	}
	.Raw = 
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed certificate")
	}

	var  cryptobyte.String
	// do the same trick again as above to extract the raw
	// bytes for Certificate.RawTBSCertificate
	if !.ReadASN1Element(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed tbs certificate")
	}
	.RawTBSCertificate = 
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed tbs certificate")
	}

	if !.ReadOptionalASN1Integer(&.Version, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific(), 0) {
		return nil, errors.New("x509: malformed version")
	}
	if .Version < 0 {
		return nil, errors.New("x509: malformed version")
	}
	// for backwards compat reasons Version is one-indexed,
	// rather than zero-indexed as defined in 5280
	.Version++
	if .Version > 3 {
		return nil, errors.New("x509: invalid version")
	}

	 := new(big.Int)
	if !.ReadASN1Integer() {
		return nil, errors.New("x509: malformed serial number")
	}
	// we ignore the presence of negative serial numbers because
	// of their prevalence, despite them being invalid
	// TODO(rolandshoemaker): revisit this decision, there are currently
	// only 10 trusted certificates with negative serial numbers
	// according to censys.io.
	.SerialNumber = 

	var  cryptobyte.String
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed signature algorithm identifier")
	}
	// Before parsing the inner algorithm identifier, extract
	// the outer algorithm identifier and make sure that they
	// match.
	var  cryptobyte.String
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed algorithm identifier")
	}
	if !bytes.Equal(, ) {
		return nil, errors.New("x509: inner and outer signature algorithm identifiers don't match")
	}
	,  := parseAI()
	if  != nil {
		return nil, 
	}
	.SignatureAlgorithm = getSignatureAlgorithmFromAI()

	var  cryptobyte.String
	if !.ReadASN1Element(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed issuer")
	}
	.RawIssuer = 
	,  := parseName()
	if  != nil {
		return nil, 
	}
	.Issuer.FillFromRDNSequence()

	var  cryptobyte.String
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed validity")
	}
	.NotBefore, .NotAfter,  = parseValidity()
	if  != nil {
		return nil, 
	}

	var  cryptobyte.String
	if !.ReadASN1Element(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed issuer")
	}
	.RawSubject = 
	,  := parseName()
	if  != nil {
		return nil, 
	}
	.Subject.FillFromRDNSequence()

	var  cryptobyte.String
	if !.ReadASN1Element(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed spki")
	}
	.RawSubjectPublicKeyInfo = 
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed spki")
	}
	var  cryptobyte.String
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed public key algorithm identifier")
	}
	,  := parseAI()
	if  != nil {
		return nil, 
	}
	.PublicKeyAlgorithm = getPublicKeyAlgorithmFromOID(.Algorithm)
	var  asn1.BitString
	if !.ReadASN1BitString(&) {
		return nil, errors.New("x509: malformed subjectPublicKey")
	}
	if .PublicKeyAlgorithm != UnknownPublicKeyAlgorithm {
		.PublicKey,  = parsePublicKey(&publicKeyInfo{
			Algorithm: ,
			PublicKey: ,
		})
		if  != nil {
			return nil, 
		}
	}

	if .Version > 1 {
		if !.SkipOptionalASN1(cryptobyte_asn1.Tag(1).ContextSpecific()) {
			return nil, errors.New("x509: malformed issuerUniqueID")
		}
		if !.SkipOptionalASN1(cryptobyte_asn1.Tag(2).ContextSpecific()) {
			return nil, errors.New("x509: malformed subjectUniqueID")
		}
		if .Version == 3 {
			var  cryptobyte.String
			var  bool
			if !.ReadOptionalASN1(&, &, cryptobyte_asn1.Tag(3).Constructed().ContextSpecific()) {
				return nil, errors.New("x509: malformed extensions")
			}
			if  {
				 := make(map[string]bool)
				if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
					return nil, errors.New("x509: malformed extensions")
				}
				for !.Empty() {
					var  cryptobyte.String
					if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
						return nil, errors.New("x509: malformed extension")
					}
					,  := parseExtension()
					if  != nil {
						return nil, 
					}
					 := .Id.String()
					if [] {
						return nil, errors.New("x509: certificate contains duplicate extensions")
					}
					[] = true
					.Extensions = append(.Extensions, )
				}
				 = processExtensions()
				if  != nil {
					return nil, 
				}
			}
		}
	}

	var  asn1.BitString
	if !.ReadASN1BitString(&) {
		return nil, errors.New("x509: malformed signature")
	}
	.Signature = .RightAlign()

	return , nil
}

// ParseCertificate parses a single certificate from the given ASN.1 DER data.
func ( []byte) (*Certificate, error) {
	,  := parseCertificate()
	if  != nil {
		return nil, 
	}
	if len() != len(.Raw) {
		return nil, errors.New("x509: trailing data")
	}
	return , 
}

// ParseCertificates parses one or more certificates from the given ASN.1 DER
// data. The certificates must be concatenated with no intermediate padding.
func ( []byte) ([]*Certificate, error) {
	var  []*Certificate
	for len() > 0 {
		,  := parseCertificate()
		if  != nil {
			return nil, 
		}
		 = append(, )
		 = [len(.Raw):]
	}
	return , nil
}

// The X.509 standards confusingly 1-indexed the version names, but 0-indexed
// the actual encoded version, so the version for X.509v2 is 1.
const x509v2Version = 1

// ParseRevocationList parses a X509 v2 Certificate Revocation List from the given
// ASN.1 DER data.
func ( []byte) (*RevocationList, error) {
	 := &RevocationList{}

	 := cryptobyte.String()
	// we read the SEQUENCE including length and tag bytes so that
	// we can populate RevocationList.Raw, before unwrapping the
	// SEQUENCE so it can be operated on
	if !.ReadASN1Element(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed crl")
	}
	.Raw = 
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed crl")
	}

	var  cryptobyte.String
	// do the same trick again as above to extract the raw
	// bytes for Certificate.RawTBSCertificate
	if !.ReadASN1Element(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed tbs crl")
	}
	.RawTBSRevocationList = 
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed tbs crl")
	}

	var  int
	if !.PeekASN1Tag(cryptobyte_asn1.INTEGER) {
		return nil, errors.New("x509: unsupported crl version")
	}
	if !.ReadASN1Integer(&) {
		return nil, errors.New("x509: malformed crl")
	}
	if  != x509v2Version {
		return nil, fmt.Errorf("x509: unsupported crl version: %d", )
	}

	var  cryptobyte.String
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed signature algorithm identifier")
	}
	// Before parsing the inner algorithm identifier, extract
	// the outer algorithm identifier and make sure that they
	// match.
	var  cryptobyte.String
	if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed algorithm identifier")
	}
	if !bytes.Equal(, ) {
		return nil, errors.New("x509: inner and outer signature algorithm identifiers don't match")
	}
	,  := parseAI()
	if  != nil {
		return nil, 
	}
	.SignatureAlgorithm = getSignatureAlgorithmFromAI()

	var  asn1.BitString
	if !.ReadASN1BitString(&) {
		return nil, errors.New("x509: malformed signature")
	}
	.Signature = .RightAlign()

	var  cryptobyte.String
	if !.ReadASN1Element(&, cryptobyte_asn1.SEQUENCE) {
		return nil, errors.New("x509: malformed issuer")
	}
	.RawIssuer = 
	,  := parseName()
	if  != nil {
		return nil, 
	}
	.Issuer.FillFromRDNSequence()

	.ThisUpdate,  = parseTime(&)
	if  != nil {
		return nil, 
	}
	if .PeekASN1Tag(cryptobyte_asn1.GeneralizedTime) || .PeekASN1Tag(cryptobyte_asn1.UTCTime) {
		.NextUpdate,  = parseTime(&)
		if  != nil {
			return nil, 
		}
	}

	if .PeekASN1Tag(cryptobyte_asn1.SEQUENCE) {
		var  cryptobyte.String
		if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
			return nil, errors.New("x509: malformed crl")
		}
		for !.Empty() {
			var  cryptobyte.String
			if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
				return nil, errors.New("x509: malformed crl")
			}
			 := pkix.RevokedCertificate{}
			.SerialNumber = new(big.Int)
			if !.ReadASN1Integer(.SerialNumber) {
				return nil, errors.New("x509: malformed serial number")
			}
			.RevocationTime,  = parseTime(&)
			if  != nil {
				return nil, 
			}
			var  cryptobyte.String
			var  bool
			if !.ReadOptionalASN1(&, &, cryptobyte_asn1.SEQUENCE) {
				return nil, errors.New("x509: malformed extensions")
			}
			if  {
				for !.Empty() {
					var  cryptobyte.String
					if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
						return nil, errors.New("x509: malformed extension")
					}
					,  := parseExtension()
					if  != nil {
						return nil, 
					}
					.Extensions = append(.Extensions, )
				}
			}

			.RevokedCertificates = append(.RevokedCertificates, )
		}
	}

	var  cryptobyte.String
	var  bool
	if !.ReadOptionalASN1(&, &, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) {
		return nil, errors.New("x509: malformed extensions")
	}
	if  {
		if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
			return nil, errors.New("x509: malformed extensions")
		}
		for !.Empty() {
			var  cryptobyte.String
			if !.ReadASN1(&, cryptobyte_asn1.SEQUENCE) {
				return nil, errors.New("x509: malformed extension")
			}
			,  := parseExtension()
			if  != nil {
				return nil, 
			}
			if .Id.Equal(oidExtensionAuthorityKeyId) {
				.AuthorityKeyId = .Value
			} else if .Id.Equal(oidExtensionCRLNumber) {
				 := cryptobyte.String(.Value)
				.Number = new(big.Int)
				if !.ReadASN1Integer(.Number) {
					return nil, errors.New("x509: malformed crl number")
				}
			}
			.Extensions = append(.Extensions, )
		}
	}

	return , nil
}