// Copyright (c) 2026 Alibaba Group and its affiliates

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package tdx provides TDX quote generation and verification functionality without CGO dependency
package tdx

import (
	"crypto/ecdh"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/sha256"
	"crypto/x509"
	"encoding/asn1"
	"encoding/pem"
	"fmt"
	"math/big"
	"strings"
)

// VerifyECDSASignature verifies an ECDSA signature using the provided public key
func VerifyECDSASignature(publicKey *ecdsa.PublicKey, message, signature []byte) error {
	// Hash the message
	hash := sha256.Sum256(message)

	// If the signature is 64 bytes, it's likely in P1363 format, convert to DER
	if len(signature) == 64 {
		r := new(big.Int).SetBytes(signature[:32])
		s := new(big.Int).SetBytes(signature[32:])
		var err error
		signature, err = asn1.Marshal(struct {
			R, S *big.Int
		}{r, s})
		if err != nil {
			return fmt.Errorf("failed to convert P1363 to DER: %w", err)
		}
	}

	// Verify the signature
	if !ecdsa.VerifyASN1(publicKey, hash[:], signature) {
		return fmt.Errorf("signature verification failed")
	}

	return nil
}

// ParseECDSAPublicKey parses an ECDSA public key from raw bytes
func ParseECDSAPublicKey(rawKey []byte) (*ecdsa.PublicKey, error) {
	// Ensure input is 64 bytes
	if len(rawKey) != 64 {
		return nil, fmt.Errorf("raw key must be 64 bytes long")
	}

	// Create uncompressed point format (0x04 prefix + x + y coordinates)
	uncompressed := make([]byte, 65)
	uncompressed[0] = 0x04
	copy(uncompressed[1:], rawKey)

	// Use the modern crypto/ecdh package for validation (replaces deprecated elliptic.Unmarshal)
	_, err := ecdh.P256().NewPublicKey(uncompressed)
	if err != nil {
		return nil, fmt.Errorf("failed to parse public key: %w", err)
	}

	// Extract coordinates manually to create ecdsa.PublicKey
	x := new(big.Int).SetBytes(uncompressed[1:33])
	y := new(big.Int).SetBytes(uncompressed[33:65])
	return &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}, nil
}

// ParseCertChain parses PEM/DER encoded certificate data into an EcdsaCertChain
// Based on Intel DCAP QVL: AttestationLibrary/src/CertVerification/CertificateChain.cpp:42-133 (CertificateChain::parse)
func ParseCertChain(certData []byte) (*EcdsaCertChain, error) {
	// Create certificate chain structure
	chain := &EcdsaCertChain{}

	// First, split PEM certificates as per DCAP QVL: CertificateChain.cpp:44 (splitChain)
	var certStrs [][]byte
	rest := certData
	for len(rest) > 0 {
		var block *pem.Block
		block, rest = pem.Decode(rest)
		if block == nil {
			break
		}
		if block.Type == "CERTIFICATE" {
			certStrs = append(certStrs, block.Bytes)
		}
	}

	// If no PEM certificates found, try parsing as raw DER
	if len(certStrs) == 0 {
		_, err := x509.ParseCertificate(certData)
		if err != nil {
			return nil, fmt.Errorf("failed to parse certificate as DER: %w", err)
		}
		certStrs = [][]byte{certData}
	}

	// Parse certificates and identify root certificate during parsing as per DCAP QVL: CertificateChain.cpp:47-58
	var certificates []*x509.Certificate
	for _, certBytes := range certStrs {
		cert, err := x509.ParseCertificate(certBytes)
		if err != nil {
			return nil, fmt.Errorf("failed to parse certificate: %w", err)
		}

		// Identify root certificate during parsing as per DCAP QVL: CertificateChain.cpp:52-55
		if cert.Subject.String() == cert.Issuer.String() {
			chain.RootCA = cert
		}

		certificates = append(certificates, cert)
	}

	if len(certificates) == 0 {
		return nil, fmt.Errorf("no certificates found in certification data")
	}

	chain.Certificates = certificates

	// Second loop to identify topmost certificate and PCK certificate as per DCAP QVL: CertificateChain.cpp:96-124
	for _, cert := range certificates {
		// Identify topmost certificate as per DCAP QVL: CertificateChain.cpp:96-106
		// Find the certificate that is not used to sign any other certificate in the chain
		isTopmost := true
		for _, otherCert := range certificates {
			if otherCert.Subject.String() != cert.Subject.String() &&
				otherCert.Issuer.String() == cert.Subject.String() {
				isTopmost = false
				break
			}
		}
		if isTopmost {
			chain.TopMostCert = cert
		}

		// Identify PCK certificate as per DCAP QVL: CertificateChain.cpp:107-123
		if strings.Contains(cert.Subject.CommonName, SGX_PCK_CN_PHRASE) {
			chain.PCKCert = cert
		}
	}

	return chain, nil
}

// getIntermediateCert returns the intermediate CA certificate from chain
// Based on Intel DCAP QVL: AttestationLibrary/src/CertVerification/CertificateChain.cpp:153-165 (getIntermediateCert)
func getIntermediateCert(chain *EcdsaCertChain) *x509.Certificate {
	for _, cert := range chain.Certificates {
		// Find certificate that is not self-signed and contains "CA" in CN
		if cert.Subject.String() != cert.Issuer.String() && strings.Contains(cert.Subject.CommonName, SGX_INTERMEDIATE_CN_PHRASE) {
			return cert
		}
	}
	return nil
}

// ExtractQuoteSignedData extracts the signed portion of quote (header + report) for quote signature verification
// Based on Intel DCAP QVL: getDataToSignatureVerification() method in Quote.cpp:404-410
func ExtractQuoteSignedData(rawQuote []byte) ([]byte, error) {
	if len(rawQuote) < 48 {
		return nil, fmt.Errorf("quote too short to extract signed data")
	}

	// Parse header to determine the structure
	version := uint16(rawQuote[0]) | uint16(rawQuote[1])<<8
	teeType := uint32(rawQuote[4]) | uint32(rawQuote[5])<<8 | uint32(rawQuote[6])<<16 | uint32(rawQuote[7])<<24

	// Calculate signed data size based on DCAP QVL logic
	// Based on Intel DCAP QVL: Quote.cpp lines 84, 97, 110, 125, 134
	var signedDataSize int

	if version == QUOTE_VERSION_5 {
		// V5 quotes have body descriptor: Header + Body + Report
		signedDataSize = 48 + 6 // Header + Body descriptor

		if len(rawQuote) < 50 {
			return nil, fmt.Errorf("quote too short to read body descriptor")
		}
		bodyType := uint16(rawQuote[48]) | uint16(rawQuote[49])<<8
		switch bodyType {
		case BODY_TD_REPORT10_TYPE:
			signedDataSize += 584 // TD Report 1.0
		case BODY_TD_REPORT15_TYPE:
			signedDataSize += 648 // TD Report 1.5
		case BODY_SGX_ENCLAVE_REPORT_TYPE:
			signedDataSize += 384 // SGX Enclave Report
		default:
			return nil, fmt.Errorf("unsupported body type: %d", bodyType)
		}
	} else {
		// V3/V4 quotes: Header + Report (no body descriptor)
		signedDataSize = 48 // Header

		switch teeType {
		case TEE_TYPE_SGX:
			signedDataSize += 384 // SGX Enclave Report
		case TEE_TYPE_TDX:
			signedDataSize += 584 // TD Report 1.0 (V4 only supports TD1.0)
		default:
			return nil, fmt.Errorf("unsupported TEE type: %d", teeType)
		}
	}

	// Extract signed data
	if signedDataSize > len(rawQuote) {
		return nil, fmt.Errorf("quote too short for signed data extraction: need %d bytes, have %d", signedDataSize, len(rawQuote))
	}

	signedData := make([]byte, signedDataSize)
	copy(signedData, rawQuote[:signedDataSize])
	return signedData, nil
}

// ExtractQeReportBytes extracts QE Report raw bytes (384 bytes) from original quote for QE Report signature verification
// Based on Intel DCAP QVL: copyAndAdvance(qeReport, from, ENCLAVE_REPORT_BYTE_LEN, end) in QuoteStructures.cpp:272
func ExtractQeReportBytes(rawQuote []byte, quote *TdxEcdsaQuote) ([]byte, error) {
	// Calculate offset to QeReportCertificationData based on quote structure
	offset := 48 // Header size

	// Add body descriptor size for v5 quotes
	if quote.Header.Version == QUOTE_VERSION_5 {
		offset += 6 // TdQuoteBodyDescriptor size
	}

	// Add report size based on report type
	switch quote.Report.(type) {
	case EnclaveReportBody:
		offset += 384 // SGX Enclave Report size
	case TdReport10:
		offset += 584 // TD Report 1.0 size
	case TdReport15:
		offset += 648 // TD Report 1.5 size
	default:
		return nil, fmt.Errorf("unsupported report type for QE Report extraction: %T", quote.Report)
	}

	// Skip signature data components to reach QeReportCertificationData
	offset += 4  // SignatureDataLen
	offset += 64 // QuoteSignature
	offset += 64 // EcdsaAttestationKey

	// Skip outer QeCertificationData header (type=2 bytes, size=4 bytes)
	offset += 6

	// Now we're at the start of QeReportCertificationData
	// QE Report is the first 384 bytes
	if offset+384 > len(rawQuote) {
		return nil, fmt.Errorf("quote too short to extract QE Report: need %d bytes, have %d", offset+384, len(rawQuote))
	}

	qeReportBytes := make([]byte, 384)
	copy(qeReportBytes, rawQuote[offset:offset+384])
	return qeReportBytes, nil
}

// ExtractSgxExtensions extracts FMSPC and PCEID from PCK certificate SGX extensions
// Based on Intel DCAP QVL: AttestationLibrary/src/AttestationParsers/src/X509/PckCertificate.cpp
func ExtractSgxExtensions(pckCert *x509.Certificate) (fmspc, pceId []byte, err error) {
	// Look for SGX extension in certificate extensions
	// SGX extension OID: 1.2.840.113741.1.13.1
	for _, ext := range pckCert.Extensions {
		if ext.Id.Equal(OIDSGXExtension) {
			// Parse SGX extension to find FMSPC and PCEID
			fmspc, pceId, err := parseSgxExtensionData(ext.Value)
			if err != nil {
				return nil, nil, fmt.Errorf("failed to parse SGX extension data: %w", err)
			}

			return fmspc, pceId, nil
		}
	}

	return nil, nil, fmt.Errorf("SGX extension not found in PCK certificate")
}

// ExtractPCKCertificateFlags extracts configuration flags from PCK certificate SGX extensions
// Based on Intel DCAP QVL: AttestationLibrary/src/AttestationParsers/src/X509/PckCertificate.cpp
func ExtractPCKCertificateFlags(pckCert *x509.Certificate) (*PCKCertificateFlags, error) {
	flags := &PCKCertificateFlags{
		DynamicPlatform: 0, // PCK_FLAG_UNDEFINED
		CachedKeys:      0, // PCK_FLAG_UNDEFINED
		SmtEnabled:      0, // PCK_FLAG_UNDEFINED
	}

	// Look for SGX extension in certificate extensions
	for _, ext := range pckCert.Extensions {
		if ext.Id.Equal(OIDSGXExtension) {
			// Parse SGX extension to find configuration flags
			err := parsePCKConfigurationFlags(ext.Value, flags)
			if err != nil {
				return nil, fmt.Errorf("failed to parse PCK configuration flags: %w", err)
			}
			return flags, nil
		}
	}

	// Return default flags if no SGX extension found (this is normal)
	return flags, nil
}

// parsePCKConfigurationFlags parses SGX extension data to extract configuration flags
func parsePCKConfigurationFlags(extData []byte, flags *PCKCertificateFlags) error {
	if len(extData) < 10 {
		return fmt.Errorf("SGX extension data too short: %d bytes", len(extData))
	}

	// Parse the outer SEQUENCE containing all SGX extension entries
	var entries []SGXExtensionEntry
	_, err := asn1.Unmarshal(extData, &entries)
	if err != nil {
		return fmt.Errorf("failed to parse SGX extension ASN.1: %w", err)
	}

	// Search for configuration flags in the extension entries
	for _, entry := range entries {
		if entry.OID.Equal(OIDSGXDynamicPlatform) {
			if entry.Value.Tag == asn1.TagBoolean {
				if len(entry.Value.Bytes) > 0 && entry.Value.Bytes[0] != 0 {
					flags.DynamicPlatform = 2 // PCK_FLAG_TRUE
				} else {
					flags.DynamicPlatform = 1 // PCK_FLAG_FALSE
				}
			}
		} else if entry.OID.Equal(OIDSGXCachedKeys) {
			if entry.Value.Tag == asn1.TagBoolean {
				if len(entry.Value.Bytes) > 0 && entry.Value.Bytes[0] != 0 {
					flags.CachedKeys = 2 // PCK_FLAG_TRUE
				} else {
					flags.CachedKeys = 1 // PCK_FLAG_FALSE
				}
			}
		} else if entry.OID.Equal(OIDSGXSmtEnabled) {
			if entry.Value.Tag == asn1.TagBoolean {
				if len(entry.Value.Bytes) > 0 && entry.Value.Bytes[0] != 0 {
					flags.SmtEnabled = 2 // PCK_FLAG_TRUE
				} else {
					flags.SmtEnabled = 1 // PCK_FLAG_FALSE
				}
			}
		}
	}

	return nil
}

// parseSgxExtensionData parses SGX extension raw data to extract FMSPC and PCEID
// Based on Intel DCAP QVL SGX extension parsing logic using standard ASN.1 parsing
func parseSgxExtensionData(extData []byte) (fmspc, pceid []byte, err error) {
	if len(extData) < 10 {
		return nil, nil, fmt.Errorf("SGX extension data too short: %d bytes", len(extData))
	}

	// Parse the outer SEQUENCE containing all SGX extension entries
	var entries []SGXExtensionEntry
	_, err = asn1.Unmarshal(extData, &entries)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to parse SGX extension ASN.1: %w", err)
	}

	// Search for FMSPC and PCEID in the extension entries using OIDs from types.go
	for _, entry := range entries {
		if entry.OID.Equal(OIDSGXFmspc) {
			// FMSPC found
			if entry.Value.Tag == asn1.TagOctetString {
				fmspc = entry.Value.Bytes
			}
		} else if entry.OID.Equal(OIDSGXPceid) {
			// PCEID found
			if entry.Value.Tag == asn1.TagOctetString {
				pceid = entry.Value.Bytes
			}
		}
	}

	// Validate that we found both FMSPC and PCEID
	if len(fmspc) == 0 {
		return nil, nil, fmt.Errorf("FMSPC not found in SGX extension")
	}
	if len(pceid) == 0 {
		return nil, nil, fmt.Errorf("PCEID not found in SGX extension")
	}

	// Validate lengths according to SGX specification
	if len(fmspc) != 6 {
		return nil, nil, fmt.Errorf("invalid FMSPC length: expected 6 bytes, got %d", len(fmspc))
	}
	if len(pceid) != 2 {
		return nil, nil, fmt.Errorf("invalid PCEID length: expected 2 bytes, got %d", len(pceid))
	}

	return fmspc, pceid, nil
}

// ExtractCpuSvnFromSgxExtensions extracts CPU SVN from PCK certificate SGX extensions
// Based on Intel DCAP QVL: AttestationLibrary/src/AttestationParsers/src/X509/Tcb.cpp:224-230
func ExtractCpuSvnFromSgxExtensions(pckCert *x509.Certificate) ([]byte, error) {
	// Look for SGX extension in certificate extensions
	for _, ext := range pckCert.Extensions {
		if ext.Id.Equal(OIDSGXExtension) {
			// Parse SGX extension to find CPU SVN using the same method as PCE SVN
			cpuSvn, err := ParseCpuSvnFromTcbInSgxExtension(ext.Value)
			if err != nil {
				return nil, fmt.Errorf("failed to parse CPU SVN from SGX extension: %w", err)
			}
			return cpuSvn, nil
		}
	}

	return nil, fmt.Errorf("SGX extension not found in PCK certificate")
}

// ParseCpuSvnFromTcbInSgxExtension parses CPU SVN from TCB sub-extension within SGX extension
// Based on Intel DCAP QVL: AttestationLibrary/src/AttestationParsers/src/X509/Tcb.cpp:225-230
func ParseCpuSvnFromTcbInSgxExtension(extensionData []byte) ([]byte, error) {
	// Parse the SGX extension as ASN.1 SEQUENCE
	var sgxExt asn1.RawValue
	rest, err := asn1.Unmarshal(extensionData, &sgxExt)
	if err != nil || len(rest) != 0 {
		return nil, fmt.Errorf("failed to parse SGX extension ASN.1: %w", err)
	}

	if sgxExt.Tag != asn1.TagSequence {
		return nil, fmt.Errorf("SGX extension is not a sequence")
	}

	// Parse the sequence content to find TCB sub-extension
	content := sgxExt.Bytes

	for len(content) > 0 {
		// Parse each tuple as a SEQUENCE
		var tuple asn1.RawValue
		rest, err := asn1.Unmarshal(content, &tuple)
		if err != nil {
			break
		}

		if tuple.Tag != asn1.TagSequence {
			content = rest
			continue
		}

		// Parse the tuple content: [OID, Value]
		tupleContent := tuple.Bytes

		// Parse OID
		var oid asn1.ObjectIdentifier
		tupleRest, err := asn1.Unmarshal(tupleContent, &oid)
		if err != nil {
			content = rest
			continue
		}

		// Check if this is the TCB OID
		if oid.Equal(OIDSGXTcb) {
			// Parse the TCB value and extract CPU SVN from it
			cpuSvn, err := ParseCpuSvnFromTcbValue(tupleRest)
			if err == nil {
				return cpuSvn, nil
			}
		}

		content = rest
	}

	return nil, fmt.Errorf("TCB extension not found in SGX extension")
}

// ParseCpuSvnFromTcbValue parses CPU SVN from TCB extension value
// Based on Intel DCAP QVL: AttestationLibrary/src/AttestationParsers/src/X509/Tcb.cpp:225-230
func ParseCpuSvnFromTcbValue(tcbValueData []byte) ([]byte, error) {
	// First parse the TCB value as a SEQUENCE containing all TCB components
	var tcbSequence asn1.RawValue
	rest, err := asn1.Unmarshal(tcbValueData, &tcbSequence)
	if err != nil || len(rest) != 0 {
		return nil, fmt.Errorf("failed to parse TCB sequence: %w", err)
	}

	if tcbSequence.Tag != asn1.TagSequence {
		return nil, fmt.Errorf("TCB value is not a sequence")
	}

	// Now parse the content of the TCB sequence
	content := tcbSequence.Bytes

	for len(content) > 0 {
		// Parse each TCB component as a SEQUENCE
		var component asn1.RawValue
		rest, err := asn1.Unmarshal(content, &component)
		if err != nil {
			break
		}

		if component.Tag != asn1.TagSequence {
			content = rest
			continue
		}

		// Parse the component content: [OID, Value]
		componentContent := component.Bytes

		// Parse OID
		var oid asn1.ObjectIdentifier
		componentRest, err := asn1.Unmarshal(componentContent, &oid)
		if err != nil {
			content = rest
			continue
		}

		// Check if this is the CPU SVN OID
		if oid.Equal(OIDSGXCpuSvn) {
			// Parse the CPU SVN value
			var value asn1.RawValue
			_, err := asn1.Unmarshal(componentRest, &value)
			if err != nil {
				content = rest
				continue
			}

			// CPU SVN should be an OCTET STRING
			if value.Tag == asn1.TagOctetString {
				return value.Bytes, nil
			}
		}

		content = rest
	}

	return nil, fmt.Errorf("CPU SVN not found in TCB extension")
}

// ExtractPceSvnFromSgxExtensions extracts PCE SVN from PCK certificate SGX extensions
// Based on Intel DCAP QVL: AttestationLibrary/src/AttestationParsers/src/X509/PckCertificate.cpp:166-168
// PCE SVN is stored within the TCB sub-extension inside the SGX extension
func ExtractPceSvnFromSgxExtensions(pckCert *x509.Certificate) (uint16, error) {
	// Look for SGX extension in certificate extensions
	// SGX extension OID: 1.2.840.113741.1.13.1
	for _, ext := range pckCert.Extensions {
		if ext.Id.Equal(OIDSGXExtension) {
			// Parse SGX extension ASN.1 structure to find TCB sub-extension
			pceSvn, err := ParsePceSvnFromTcbInSgxExtension(ext.Value)
			if err != nil {
				continue // Try next extension if parsing fails
			}
			return pceSvn, nil
		}
	}
	return 0, fmt.Errorf("SGX extension not found in certificate")
}

// ParsePceSvnFromTcbInSgxExtension parses PCE SVN from TCB sub-extension within SGX extension
// Based on Intel DCAP QVL: AttestationLibrary/src/AttestationParsers/src/X509/PckCertificate.cpp:126-189
func ParsePceSvnFromTcbInSgxExtension(extensionData []byte) (uint16, error) {
	// Parse the SGX extension as ASN.1 SEQUENCE
	var sgxExt asn1.RawValue
	rest, err := asn1.Unmarshal(extensionData, &sgxExt)
	if err != nil || len(rest) != 0 {
		return 0, fmt.Errorf("failed to parse SGX extension ASN.1: %w", err)
	}

	if sgxExt.Tag != asn1.TagSequence {
		return 0, fmt.Errorf("SGX extension is not a sequence")
	}

	// Parse the sequence content to find TCB sub-extension
	// Each sub-extension is a tuple: [OID, Value]
	content := sgxExt.Bytes

	for len(content) > 0 {
		// Parse each tuple as a SEQUENCE
		var tuple asn1.RawValue
		rest, err := asn1.Unmarshal(content, &tuple)
		if err != nil {
			break
		}

		if tuple.Tag != asn1.TagSequence {
			content = rest
			continue
		}

		// Parse the tuple content: [OID, Value]
		tupleContent := tuple.Bytes

		// Parse OID
		var oid asn1.ObjectIdentifier
		tupleRest, err := asn1.Unmarshal(tupleContent, &oid)
		if err != nil {
			content = rest
			continue
		}

		// Check if this is the TCB OID
		// Based on DCAP QVL: oids::TCB
		if oid.Equal(OIDSGXTcb) {
			// Parse the TCB value and extract PCE SVN from it
			pceSvn, err := ParsePceSvnFromTcbValue(tupleRest)
			if err == nil {
				return pceSvn, nil
			}
		}

		// Also check for direct PCE SVN OID (in case it's not nested in TCB)
		if oid.Equal(OIDSGXPceSvn) {
			// Parse the PCE SVN value directly
			var value asn1.RawValue
			_, err := asn1.Unmarshal(tupleRest, &value)
			if err == nil && value.Tag == asn1.TagInteger {
				var pceSvn int
				_, err := asn1.Unmarshal(value.FullBytes, &pceSvn)
				if err == nil {
					return uint16(pceSvn), nil
				}
			}
		}

		content = rest
	}

	return 0, fmt.Errorf("TCB extension not found in SGX extension")
}

// ParsePceSvnFromTcbValue parses PCE SVN from TCB extension value
// Based on Intel DCAP QVL: AttestationLibrary/src/AttestationParsers/src/X509/Tcb.cpp:219-224
func ParsePceSvnFromTcbValue(tcbValueData []byte) (uint16, error) {
	// First parse the TCB value as a SEQUENCE containing all TCB components
	var tcbSequence asn1.RawValue
	rest, err := asn1.Unmarshal(tcbValueData, &tcbSequence)
	if err != nil || len(rest) != 0 {
		return 0, fmt.Errorf("failed to parse TCB sequence: %w", err)
	}

	if tcbSequence.Tag != asn1.TagSequence {
		return 0, fmt.Errorf("TCB value is not a sequence")
	}

	// Now parse the content of the TCB sequence
	content := tcbSequence.Bytes

	for len(content) > 0 {
		// Parse each TCB component as a SEQUENCE
		var component asn1.RawValue
		rest, err := asn1.Unmarshal(content, &component)
		if err != nil {
			break
		}

		if component.Tag != asn1.TagSequence {
			content = rest
			continue
		}

		// Parse the component content: [OID, Value]
		componentContent := component.Bytes

		// Parse OID
		var oid asn1.ObjectIdentifier
		componentRest, err := asn1.Unmarshal(componentContent, &oid)
		if err != nil {
			content = rest
			continue
		}

		// Check if this is the PCE SVN OID
		if oid.Equal(OIDSGXPceSvn) {
			// Parse the PCE SVN value
			var value asn1.RawValue
			_, err := asn1.Unmarshal(componentRest, &value)
			if err != nil {
				content = rest
				continue
			}

			// PCE SVN should be an INTEGER
			if value.Tag == asn1.TagInteger {
				var pceSvn int
				_, err := asn1.Unmarshal(value.FullBytes, &pceSvn)
				if err != nil {
					return 0, fmt.Errorf("failed to parse PCE SVN integer: %w", err)
				}
				return uint16(pceSvn), nil
			}
		}

		content = rest
	}

	return 0, fmt.Errorf("PCE SVN not found in TCB extension")
}

// bytesToUint16 converts 2 bytes to uint16 (little endian)
func bytesToUint16(bytes []byte) uint16 {
	if len(bytes) < 2 {
		return 0
	}
	return uint16(bytes[0]) | uint16(bytes[1])<<8
}

// bytesToUint32 converts 4 bytes to uint32 (little endian)
func bytesToUint32(bytes []byte) uint32 {
	if len(bytes) < 4 {
		return 0
	}
	return uint32(bytes[0]) | uint32(bytes[1])<<8 | uint32(bytes[2])<<16 | uint32(bytes[3])<<24
}

// applyMask applies a byte mask to a byte array
func applyMask(data []byte, mask []byte) []byte {
	result := make([]byte, len(data))
	for i := 0; i < len(data) && i < len(mask); i++ {
		result[i] = data[i] & mask[i]
	}
	return result
}

// ExtractPlatformInstanceIdFromCert extracts Platform Instance ID (16 bytes) from Platform PCK certificate
// Based on Intel DCAP QVL: AttestationParsers/src/X509/PlatformPckCertificate.cpp:111-116
func ExtractPlatformInstanceIdFromCert(pckCert *x509.Certificate) ([]byte, error) {
	for _, ext := range pckCert.Extensions {
		if ext.Id.Equal(OIDSGXPlatformInstanceID) {
			var rv asn1.RawValue
			if _, err := asn1.Unmarshal(ext.Value, &rv); err != nil {
				return nil, fmt.Errorf("failed to parse PlatformInstanceID ASN.1: %w", err)
			}
			if rv.Tag != asn1.TagOctetString {
				return nil, fmt.Errorf("PlatformInstanceID is not an OCTET STRING")
			}
			if len(rv.Bytes) != 16 {
				return nil, fmt.Errorf("PlatformInstanceID length invalid: %d", len(rv.Bytes))
			}
			cp := make([]byte, 16)
			copy(cp, rv.Bytes)
			return cp, nil
		}
	}
	return nil, fmt.Errorf("PlatformInstanceID extension not found")
}

// certChainDates holds the date information extracted from a certificate chain
type certChainDates struct {
	earliestIssue      int64
	earliestExpiration int64
	latestIssue        int64
	latestExpiration   int64
}

// getCertChainDates extracts issue and expiration dates from a certificate chain
func getCertChainDates(certChain *EcdsaCertChain) certChainDates {
	dates := certChainDates{}

	if certChain.RootCA != nil {
		dates.earliestIssue = certChain.RootCA.NotBefore.Unix()
		dates.earliestExpiration = certChain.RootCA.NotAfter.Unix()
		dates.latestIssue = certChain.RootCA.NotBefore.Unix()
		dates.latestExpiration = certChain.RootCA.NotAfter.Unix()
	}

	intermediateCA := getIntermediateCert(certChain)
	if intermediateCA != nil {
		if intermediateCA.NotBefore.Unix() < dates.earliestIssue || dates.earliestIssue == 0 {
			dates.earliestIssue = intermediateCA.NotBefore.Unix()
		}
		if intermediateCA.NotAfter.Unix() < dates.earliestExpiration || dates.earliestExpiration == 0 {
			dates.earliestExpiration = intermediateCA.NotAfter.Unix()
		}
		if intermediateCA.NotBefore.Unix() > dates.latestIssue {
			dates.latestIssue = intermediateCA.NotBefore.Unix()
		}
		if intermediateCA.NotAfter.Unix() > dates.latestExpiration {
			dates.latestExpiration = intermediateCA.NotAfter.Unix()
		}
	}

	if certChain.PCKCert != nil {
		if certChain.PCKCert.NotBefore.Unix() < dates.earliestIssue || dates.earliestIssue == 0 {
			dates.earliestIssue = certChain.PCKCert.NotBefore.Unix()
		}
		if certChain.PCKCert.NotAfter.Unix() < dates.earliestExpiration || dates.earliestExpiration == 0 {
			dates.earliestExpiration = certChain.PCKCert.NotAfter.Unix()
		}
		if certChain.PCKCert.NotBefore.Unix() > dates.latestIssue {
			dates.latestIssue = certChain.PCKCert.NotBefore.Unix()
		}
		if certChain.PCKCert.NotAfter.Unix() > dates.latestExpiration {
			dates.latestExpiration = certChain.PCKCert.NotAfter.Unix()
		}
	}

	return dates
}

// minElement finds the minimum element in a slice, equivalent to std::min_element
func minElement(slice []int64) int64 {
	if len(slice) == 0 {
		return 0
	}
	min := slice[0]
	for _, val := range slice[1:] {
		if val != 0 && (min == 0 || val < min) {
			min = val
		}
	}
	return min
}

// maxElement finds the maximum element in a slice, equivalent to std::max_element
func maxElement(slice []int64) int64 {
	if len(slice) == 0 {
		return 0
	}
	max := slice[0]
	for _, val := range slice[1:] {
		if val > max {
			max = val
		}
	}
	return max
}

// ParseCertificateChainFromQuote extracts and parses the certificate chain from a quote
// This is a utility function for extracting PCK certificate chain from quote's certification data
func ParseCertificateChainFromQuote(quote *TdxEcdsaQuote) (*EcdsaCertChain, error) {
	if quote.QeCertificationData.CertificationDataType != PCK_ID_QE_REPORT_CERTIFICATION_DATA {
		return nil, fmt.Errorf("unsupported certification data type: %d", quote.QeCertificationData.CertificationDataType)
	}

	// Get QE Report Certification Data from interface
	qeReportCertData, ok := quote.QeCertificationData.CertificationData.(*QeReportCertificationData)
	if !ok {
		return nil, fmt.Errorf("certification data is not QeReportCertificationData type, got %T", quote.QeCertificationData.CertificationData)
	}

	// Get nested certification data (usually PCK cert chain)
	var certData []byte
	if innerCertData, ok := qeReportCertData.QeCertificationData.CertificationData.([]byte); ok {
		certData = innerCertData
	} else {
		return nil, fmt.Errorf("inner certification data is not []byte type, got %T", qeReportCertData.QeCertificationData.CertificationData)
	}

	if len(certData) == 0 {
		return nil, fmt.Errorf("certification data is empty")
	}

	return ParseCertChain(certData)
}
