diff --git a/Cargo.lock b/Cargo.lock index 0bf6a65..355096c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "actix-codec" @@ -311,6 +311,15 @@ dependencies = [ "libc", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anstyle" version = "1.0.8" @@ -358,6 +367,17 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.3.0" @@ -535,6 +555,29 @@ dependencies = [ "num-traits", ] +[[package]] +name = "bindgen" +version = "0.59.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "clap 2.34.0", + "env_logger", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "which", +] + [[package]] name = "bindgen" version = "0.65.1" @@ -849,6 +892,21 @@ dependencies = [ "libloading", ] +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim 0.8.0", + "textwrap", + "unicode-width", + "vec_map", +] + [[package]] name = "clap" version = "4.5.17" @@ -1486,6 +1544,19 @@ dependencies = [ "syn 2.0.77", ] +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "envy" version = "0.4.2" @@ -1948,6 +2019,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.3.9" @@ -2066,6 +2146,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.30" @@ -2794,7 +2880,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "log", "wasi", @@ -4702,6 +4788,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + [[package]] name = "strsim" version = "0.10.0" @@ -4827,12 +4919,28 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tdx-attest-rs" +version = "0.1.2" +source = "git+https://github.com/intel/SGXDataCenterAttestationPrimitives.git?rev=aa239d25a437a28f3f4de92c38f5b6809faac842#aa239d25a437a28f3f4de92c38f5b6809faac842" +dependencies = [ + "tdx-attest-sys", +] + +[[package]] +name = "tdx-attest-sys" +version = "0.1.0" +source = "git+https://github.com/intel/SGXDataCenterAttestationPrimitives.git?rev=aa239d25a437a28f3f4de92c38f5b6809faac842#aa239d25a437a28f3f4de92c38f5b6809faac842" +dependencies = [ + "bindgen 0.59.2", +] + [[package]] name = "tee-key-preexec" version = "0.3.0" dependencies = [ "anyhow", - "clap", + "clap 4.5.17", "rand", "secp256k1 0.29.1", "teepot", @@ -4846,7 +4954,7 @@ name = "tee-ratls-preexec" version = "0.3.0" dependencies = [ "anyhow", - "clap", + "clap 4.5.17", "rsa", "teepot", "tracing", @@ -4874,7 +4982,7 @@ version = "0.3.0" dependencies = [ "actix-web", "anyhow", - "clap", + "clap 4.5.17", "serde", "teepot", "tracing", @@ -4890,7 +4998,7 @@ dependencies = [ "anyhow", "awc", "bytemuck", - "clap", + "clap 4.5.17", "hex", "rustls 0.22.4", "serde_json", @@ -4909,7 +5017,7 @@ dependencies = [ "actix-web", "anyhow", "awc", - "clap", + "clap 4.5.17", "rustls 0.22.4", "serde_json", "teepot", @@ -4929,7 +5037,7 @@ dependencies = [ "base64 0.22.1", "bytemuck", "bytes", - "clap", + "clap 4.5.17", "const-oid", "enumset", "futures-core", @@ -4948,12 +5056,15 @@ dependencies = [ "serde_with 3.9.0", "sha2", "signature 2.2.0", + "tdx-attest-rs", "teepot-tee-quote-verification-rs", "testaso", "thiserror", + "tokio", "tracing", "tracing-log 0.2.0", "tracing-subscriber", + "tracing-test", "webpki-roots", "x509-cert", "zeroize", @@ -4966,7 +5077,7 @@ dependencies = [ "actix-web", "anyhow", "awc", - "clap", + "clap 4.5.17", "serde_json", "teepot", "tracing", @@ -4989,7 +5100,7 @@ dependencies = [ "actix-web", "anyhow", "awc", - "clap", + "clap 4.5.17", "serde_json", "teepot", "tracing", @@ -5010,6 +5121,15 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "terminal_size" version = "0.3.0" @@ -5026,6 +5146,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63b4d2149a2f578665ca39f8115084635847e9dd6921b5442dcafc7f87bb8e99" +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "thiserror" version = "1.0.63" @@ -5432,6 +5561,27 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "tracing-test" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "557b891436fe0d5e0e363427fc7f217abf9ccd510d5136549847bdcbcd011d68" +dependencies = [ + "tracing-core", + "tracing-subscriber", + "tracing-test-macro", +] + +[[package]] +name = "tracing-test-macro" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" +dependencies = [ + "quote", + "syn 2.0.77", +] + [[package]] name = "try-lock" version = "0.2.5" @@ -5583,7 +5733,7 @@ dependencies = [ "actix-web", "anyhow", "bytemuck", - "clap", + "clap 4.5.17", "hex", "pgp", "serde_json", @@ -5600,7 +5750,7 @@ dependencies = [ "actix-web", "anyhow", "base64 0.22.1", - "clap", + "clap 4.5.17", "serde_json", "teepot", "tracing", @@ -5614,12 +5764,18 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "verify-attestation" version = "0.3.0" dependencies = [ "anyhow", - "clap", + "clap 4.5.17", "hex", "secp256k1 0.29.1", "teepot", @@ -5631,7 +5787,7 @@ name = "verify-era-proof-attestation" version = "0.3.0" dependencies = [ "anyhow", - "clap", + "clap 4.5.17", "ctrlc", "hex", "jsonrpsee-types", diff --git a/Cargo.toml b/Cargo.toml index 7064332..d36677f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,18 +17,15 @@ homepage = "https://github.com/matter-labs/teepot" [workspace.dependencies] actix-http = "3" -actix-tls = "3" actix-web = { version = "4.5", features = ["rustls-0_22"] } anyhow = "1.0.82" awc = { version = "3.4", features = ["rustls-0_22-webpki-roots"] } base64 = "0.22.0" -bitflags = "2.5" bytemuck = { version = "1.15.0", features = ["derive", "min_const_generics", "extern_crate_std"] } bytes = "1" clap = { version = "4.5", features = ["std", "derive", "env", "error-context", "help", "usage", "wrap_help"], default-features = false } const-oid = { version = "0.9", default-features = false } ctrlc = "3.4" -der = "0.7.9" enumset = { version = "1.1", features = ["serde"] } futures-core = { version = "0.3.30", features = ["alloc"], default-features = false } getrandom = "0.2.14" @@ -36,7 +33,6 @@ hex = { version = "0.4.3", features = ["std"], default-features = false } intel-tee-quote-verification-rs = { package = "teepot-tee-quote-verification-rs", path = "crates/teepot-tee-quote-verification-rs", version = "0.3.0" } intel-tee-quote-verification-sys = { version = "0.2.1" } jsonrpsee-types = { version = "0.23", default-features = false } -log = "0.4" num-integer = "0.1.46" num-traits = "0.2.18" p256 = "0.13.2" @@ -44,17 +40,15 @@ pgp = "0.13" pkcs8 = { version = "0.10" } rand = "0.8" reqwest = { version = "0.12", features = ["json"] } -ring = { version = "0.17.8", features = ["std"], default-features = false } rsa = { version = "0.9.6", features = ["sha2", "pem"] } rustls = { version = "0.22" } -rustls-pemfile = "2" -sec1 = { version = "0.7.3", features = ["der"], default-features = false } secp256k1 = { version = "0.29", features = ["rand-std", "global-context"] } serde = { version = "1", features = ["derive", "rc"] } serde_json = "1" serde_with = { version = "3.8", features = ["base64", "hex"] } sha2 = "0.10.8" signature = "2.2.0" +tdx-attest-rs = { version = "0.1.2", git = "https://github.com/intel/SGXDataCenterAttestationPrimitives.git", rev = "aa239d25a437a28f3f4de92c38f5b6809faac842" } teepot = { path = "crates/teepot" } testaso = "0.1.0" thiserror = "1.0.59" @@ -63,6 +57,7 @@ tracing = "0.1" tracing-actix-web = "0.7" tracing-log = "0.2" tracing-subscriber = { version = "0.3", features = ["env-filter"] } +tracing-test = { version = "0.2.5", features = ["no-env-filter"] } url = "2.5.2" webpki-roots = "0.26.1" x509-cert = { version = "0.2", features = ["builder", "signature"] } diff --git a/bin/tee-key-preexec/src/main.rs b/bin/tee-key-preexec/src/main.rs index 6af0c09..70be9c4 100644 --- a/bin/tee-key-preexec/src/main.rs +++ b/bin/tee-key-preexec/src/main.rs @@ -9,9 +9,7 @@ use anyhow::{Context, Result}; use clap::Parser; use secp256k1::{rand, Keypair, PublicKey, Secp256k1, SecretKey}; -use std::ffi::OsString; -use std::os::unix::process::CommandExt; -use std::process::Command; +use std::{ffi::OsString, os::unix::process::CommandExt, process::Command}; use teepot::quote::get_quote; use tracing::error; use tracing_log::LogTracer; @@ -47,15 +45,15 @@ fn main_with_error() -> Result<()> { let verifying_key = PublicKey::from_keypair(&keypair); let verifying_key_bytes = verifying_key.serialize(); let tee_type = match get_quote(verifying_key_bytes.as_ref()) { - Ok(quote) => { + Ok((tee_type, quote)) => { // save quote to file std::fs::write(TEE_QUOTE_FILE, quote)?; - "sgx" + tee_type.to_string() } Err(e) => { error!("Failed to get quote: {}", e); std::fs::write(TEE_QUOTE_FILE, [])?; - "none" + "none".to_string() } }; diff --git a/bin/verify-attestation/src/main.rs b/bin/verify-attestation/src/main.rs index 7f0c380..d799462 100644 --- a/bin/verify-attestation/src/main.rs +++ b/bin/verify-attestation/src/main.rs @@ -9,7 +9,7 @@ use secp256k1::{ecdsa::Signature, Message, PublicKey}; use std::{fs, io::Read, path::PathBuf, str::FromStr, time::UNIX_EPOCH}; use teepot::{ client::TcbLevel, - sgx::{tee_qv_get_collateral, verify_quote_with_collateral, QuoteVerificationResult}, + quote::{error, tee_qv_get_collateral, verify_quote_with_collateral, QuoteVerificationResult}, }; use zksync_basic_types::H256; @@ -84,7 +84,7 @@ fn verify_signature( quote_verification_result: &QuoteVerificationResult, signature_args: &SignatureArgs, ) -> Result<()> { - let reportdata = "e_verification_result.quote.report_body.reportdata; + let reportdata = "e_verification_result.quote.get_report_data(); let public_key = PublicKey::from_slice(reportdata)?; println!("Public key from attestation quote: {}", public_key); let signature_bytes = fs::read(&signature_args.signature_file)?; @@ -103,8 +103,10 @@ fn verify_attestation_quote(attestation_quote_bytes: &[u8]) -> Result, + quote_verification_result: &QuoteVerificationResult, attestation_policy: &AttestationPolicyArgs, node_client: &impl JsonRpcClient, signature: &[u8], @@ -28,7 +29,7 @@ pub async fn verify_batch_proof( let batch_no = batch_number.0; let public_key = PublicKey::from_slice( - "e_verification_result.quote.report_body.reportdata[..PUBLIC_KEY_SIZE], + "e_verification_result.quote.get_report_data()[..PUBLIC_KEY_SIZE], )?; debug!(batch_no, "public key: {}", public_key); @@ -45,8 +46,10 @@ pub async fn verify_batch_proof( } pub fn verify_attestation_quote(attestation_quote_bytes: &[u8]) -> Result { - let collateral = - tee_qv_get_collateral(attestation_quote_bytes).context("Failed to get collateral!")?; + let collateral = QuoteContext::context( + tee_qv_get_collateral(attestation_quote_bytes), + "Failed to get collateral!", + )?; let unix_time: i64 = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH)? .as_secs() as _; @@ -66,17 +69,19 @@ pub fn log_quote_verification_summary(quote_verification_result: &QuoteVerificat warn!("Freshly fetched collateral expired!"); } let tcblevel = TcbLevel::from(*result); + let advisories = if advisories.is_empty() { + "None".to_string() + } else { + advisories + .iter() + .map(ToString::to_string) + .collect::>() + .join(", ") + }; + info!( - "Quote verification result: {}. mrsigner: {}, mrenclave: {}, reportdata: {}. Advisory IDs: {}.", - tcblevel, - hex::encode(quote.report_body.mrsigner), - hex::encode(quote.report_body.mrenclave), - hex::encode(quote.report_body.reportdata), - if advisories.is_empty() { - "None".to_string() - } else { - advisories.iter().map(ToString::to_string).collect::>().join(", ") - } + "Quote verification result: {tcblevel}. {report}. Advisory IDs: {advisories}.", + report = "e.report ); } @@ -88,7 +93,7 @@ fn verify_signature(signature: &[u8], public_key: PublicKey, root_hash: H256) -> fn is_quote_matching_policy( attestation_policy: &AttestationPolicyArgs, - quote_verification_result: &QuoteVerificationResult<'_>, + quote_verification_result: &QuoteVerificationResult, ) -> bool { let quote = "e_verification_result.quote; let tcblevel = TcbLevel::from(quote_verification_result.result); @@ -100,16 +105,20 @@ fn is_quote_matching_policy( ); return false; } - - check_policy( - attestation_policy.sgx_mrsigners.as_deref(), - "e.report_body.mrsigner, - "mrsigner", - ) && check_policy( - attestation_policy.sgx_mrenclaves.as_deref(), - "e.report_body.mrenclave, - "mrenclave", - ) + match "e.report { + Report::SgxEnclave(report_body) => { + check_policy( + attestation_policy.sgx_mrsigners.as_deref(), + &report_body.mr_signer, + "mrsigner", + ) && check_policy( + attestation_policy.sgx_mrenclaves.as_deref(), + &report_body.mr_enclave, + "mrenclave", + ) + } + _ => false, + } } fn check_policy(policy: Option<&str>, actual_value: &[u8], field_name: &str) -> bool { diff --git a/crates/teepot/Cargo.toml b/crates/teepot/Cargo.toml index c33aa89..df20004 100644 --- a/crates/teepot/Cargo.toml +++ b/crates/teepot/Cargo.toml @@ -37,6 +37,7 @@ serde_json.workspace = true serde_with.workspace = true sha2.workspace = true signature.workspace = true +tdx-attest-rs.workspace = true thiserror.workspace = true tracing.workspace = true tracing-log.workspace = true @@ -48,5 +49,6 @@ zeroize.workspace = true [dev-dependencies] anyhow.workspace = true base64.workspace = true -hex.workspace = true testaso.workspace = true +tokio.workspace = true +tracing-test.workspace = true diff --git a/crates/teepot/src/client/mod.rs b/crates/teepot/src/client/mod.rs index 3b21841..284468d 100644 --- a/crates/teepot/src/client/mod.rs +++ b/crates/teepot/src/client/mod.rs @@ -8,12 +8,12 @@ pub mod vault; +pub use crate::quote::verify_quote_with_collateral; +pub use crate::quote::QuoteVerificationResult; +use crate::quote::Report; use crate::server::pki::{RaTlsCollateralExtension, RaTlsQuoteExtension}; use crate::sgx::Quote; -pub use crate::sgx::{ - parse_tcb_levels, sgx_ql_qv_result_t, verify_quote_with_collateral, EnumSet, - QuoteVerificationResult, TcbLevel, -}; +pub use crate::sgx::{parse_tcb_levels, sgx_ql_qv_result_t, EnumSet, TcbLevel}; use actix_web::http::header; use anyhow::Result; use awc::{Client, Connector}; @@ -195,6 +195,10 @@ impl TeeConnection { } = verify_quote_with_collateral(quote_bytes, collateral.as_ref(), current_time) .unwrap(); + let Report::SgxEnclave(report_body) = quote.report else { + return Err(Error::General("TDX quote and not SGX quote".into())); + }; + if collateral_expired || result != sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OK { if collateral_expired { error!( @@ -230,10 +234,10 @@ impl TeeConnection { if let Some(mrsigner) = &self.args.sgx_mrsigner { let mrsigner_bytes = hex::decode(mrsigner) .map_err(|e| Error::General(format!("Failed to decode mrsigner: {}", e)))?; - if quote.report_body.mrsigner[..] != mrsigner_bytes { + if report_body.mr_signer[..] != mrsigner_bytes { return Err(Error::General(format!( "mrsigner mismatch: got {}, expected {}", - hex::encode(quote.report_body.mrsigner), + hex::encode(report_body.mr_signer), &mrsigner ))); } else { @@ -245,10 +249,10 @@ impl TeeConnection { let mrenclave_bytes = hex::decode(mrenclave).map_err(|e| { Error::General(format!("Failed to decode mrenclave: {}", e)) })?; - if quote.report_body.mrenclave[..] != mrenclave_bytes { + if report_body.mr_enclave[..] != mrenclave_bytes { return Err(Error::General(format!( "mrenclave mismatch: got {}, expected {}", - hex::encode(quote.report_body.mrenclave), + hex::encode(report_body.mr_enclave), &mrenclave ))); } else { diff --git a/crates/teepot/src/client/vault.rs b/crates/teepot/src/client/vault.rs index 8d7ef43..fd25d4b 100644 --- a/crates/teepot/src/client/vault.rs +++ b/crates/teepot/src/client/vault.rs @@ -7,26 +7,34 @@ #![deny(clippy::all)] use super::{AttestationArgs, TeeConnection}; -use crate::json::http::{AuthRequest, AuthResponse}; -use crate::server::pki::make_self_signed_cert; -use crate::server::{AnyHowResponseError, HttpResponseError, Status}; -pub use crate::sgx::{ - parse_tcb_levels, sgx_gramine_get_quote, sgx_ql_qv_result_t, tee_qv_get_collateral, - verify_quote_with_collateral, Collateral, EnumSet, QuoteVerificationResult, TcbLevel, +use crate::{ + json::http::{AuthRequest, AuthResponse}, + quote::error::QuoteContext, + server::{pki::make_self_signed_cert, AnyHowResponseError, HttpResponseError, Status}, +}; +pub use crate::{ + quote::{verify_quote_with_collateral, QuoteVerificationResult}, + sgx::{ + parse_tcb_levels, sgx_gramine_get_quote, sgx_ql_qv_result_t, Collateral, EnumSet, TcbLevel, + }, }; use actix_http::error::PayloadError; -use actix_web::http::header; -use actix_web::ResponseError; +use actix_web::{http::header, ResponseError}; use anyhow::{anyhow, bail, Context, Result}; -use awc::error::{SendRequestError, StatusCode}; -use awc::{Client, ClientResponse, Connector}; +use awc::{ + error::{SendRequestError, StatusCode}, + Client, ClientResponse, Connector, +}; use bytes::Bytes; use futures_core::Stream; +use intel_tee_quote_verification_rs::tee_qv_get_collateral; use rustls::ClientConfig; use serde_json::{json, Value}; -use std::fmt::{Display, Formatter}; -use std::sync::Arc; -use std::time; +use std::{ + fmt::{Display, Formatter}, + sync::Arc, + time, +}; use tracing::{debug, error, info, trace}; const VAULT_TOKEN_HEADER: &str = "X-Vault-Token"; diff --git a/crates/teepot/src/lib.rs b/crates/teepot/src/lib.rs index b3bcf16..293ef83 100644 --- a/crates/teepot/src/lib.rs +++ b/crates/teepot/src/lib.rs @@ -8,8 +8,8 @@ pub mod client; pub mod json; -pub mod server; -pub mod sgx; - pub mod log; pub mod quote; +pub mod server; +pub mod sgx; +pub mod tdx; diff --git a/crates/teepot/src/quote/error.rs b/crates/teepot/src/quote/error.rs new file mode 100644 index 0000000..508b5f3 --- /dev/null +++ b/crates/teepot/src/quote/error.rs @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2024 Matter Labs + +//! Quote Error type + +use intel_tee_quote_verification_rs::quote3_error_t; +use std::io; +use tdx_attest_rs::tdx_attest_error_t; +use thiserror::Error; + +/// Quote parsing error +#[derive(Error, Debug)] +#[allow(missing_docs)] +pub enum QuoteError { + #[error("I/O Error")] + IoError { context: String, source: io::Error }, + #[error("parsing bytes")] + ConvertError(#[from] bytemuck::PodCastError), + #[error("unsupported quote version")] + QuoteVersion, + #[error("invalid tee type")] + InvalidTeeType, + #[error("unsupported body type")] + UnsupportedBodyType, + #[error("quote verification error {msg}: {inner:?}")] + Quote3Error { inner: quote3_error_t, msg: String }, + #[error("tdx_att_get_quote error {msg}: {inner:?}")] + TdxAttGetQuote { + inner: tdx_attest_error_t, + msg: String, + }, + #[error("invalid version")] + InvalidVersion, + #[error("report data too long")] + ReportDataSize, + #[error("can't get a quote: unknown TEE")] + UnknownTee, +} + +impl From for QuoteError { + fn from(code: tdx_attest_error_t) -> Self { + Self::TdxAttGetQuote { + inner: code, + msg: "code".to_string(), + } + } +} + +/// Usability trait for easy QuoteError annotation +pub trait QuoteContext { + /// The Ok Type + type Ok; + /// The Context + fn context>(self, msg: I) -> Result; +} + +impl QuoteContext for Result { + type Ok = T; + fn context>(self, msg: I) -> Result { + self.map_err(|e| QuoteError::IoError { + context: msg.into(), + source: e, + }) + } +} + +impl QuoteContext for Result { + type Ok = T; + fn context>(self, msg: I) -> Result { + self.map_err(|e| QuoteError::Quote3Error { + msg: msg.into(), + inner: e, + }) + } +} + +impl QuoteContext for Result { + type Ok = T; + fn context>(self, msg: I) -> Result { + self.map_err(|e| QuoteError::TdxAttGetQuote { + msg: msg.into(), + inner: e, + }) + } +} diff --git a/crates/teepot/src/quote/mod.rs b/crates/teepot/src/quote/mod.rs index 4d8ae51..5f01993 100644 --- a/crates/teepot/src/quote/mod.rs +++ b/crates/teepot/src/quote/mod.rs @@ -1,40 +1,733 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) 2023-2024 Matter Labs +// Parts of it are Copyright (c) 2024 Phala Network +// and copied from https://github.com/Phala-Network/dcap-qvl + //! Get a quote from a TEE +pub mod error; -use crate::sgx::sgx_gramine_get_quote; -use std::io; +use crate::{ + quote::error::{QuoteContext as _, QuoteError}, + sgx::sgx_gramine_get_quote, + tdx::tgx_get_quote, +}; +use bytemuck::{cast_slice, AnyBitPattern}; +use intel_tee_quote_verification_rs::{ + sgx_ql_qv_result_t, sgx_ql_qv_supplemental_t, tee_get_supplemental_data_version_and_size, + tee_supp_data_descriptor_t, tee_verify_quote, Collateral, +}; +use serde::{Deserialize, Serialize}; +use std::{ + ffi::CStr, + fmt::{Display, Formatter}, + io::Read, + mem, + str::FromStr, +}; +use tracing::{trace, warn}; + +pub use intel_tee_quote_verification_rs::tee_qv_get_collateral; -#[derive(Debug, thiserror::Error)] #[allow(missing_docs)] -#[error("{msg}")] -pub struct GetQuoteError { - pub(crate) msg: Box, - #[source] // optional if field name is `source` - pub(crate) source: io::Error, +pub const TEE_TYPE_SGX: u32 = 0x00000000; +#[allow(missing_docs)] +pub const TEE_TYPE_TDX: u32 = 0x00000081; + +#[allow(missing_docs)] +pub const BODY_SGX_ENCLAVE_REPORT_TYPE: u16 = 1; +#[allow(missing_docs)] +pub const BODY_TD_REPORT10_TYPE: u16 = 2; +#[allow(missing_docs)] +pub const BODY_TD_REPORT15_TYPE: u16 = 3; +#[allow(missing_docs)] +pub const ENCLAVE_REPORT_BYTE_LEN: usize = 384; + +#[allow(missing_docs)] +pub const ECDSA_SIGNATURE_BYTE_LEN: usize = 64; +#[allow(missing_docs)] +pub const ECDSA_PUBKEY_BYTE_LEN: usize = 64; +#[allow(missing_docs)] +pub const QE_REPORT_SIG_BYTE_LEN: usize = ECDSA_SIGNATURE_BYTE_LEN; + +mod serde_bytes { + use serde::Deserialize; + + pub(crate) trait FromBytes { + fn from_bytes(bytes: Vec) -> Option + where + Self: Sized; + } + impl FromBytes for Vec { + fn from_bytes(bytes: Vec) -> Option { + Some(bytes) + } + } + impl FromBytes for [u8; N] { + fn from_bytes(bytes: Vec) -> Option { + bytes.try_into().ok() + } + } + + pub(crate) fn serialize( + data: impl AsRef<[u8]>, + serializer: S, + ) -> Result { + let hex_str = hex::encode(data); + serializer.serialize_str(&hex_str) + } + + pub(crate) fn deserialize<'de, D: serde::Deserializer<'de>, T: FromBytes>( + deserializer: D, + ) -> Result { + let hex_str = String::deserialize(deserializer)?; + let bytes = hex::decode(hex_str).map_err(serde::de::Error::custom)?; + T::from_bytes(bytes).ok_or_else(|| serde::de::Error::custom("invalid bytes")) + } +} + +/// Trait that allows zero-copy read of value-references from slices in LE format. +pub trait Decode: Sized { + /// Attempt to deserialise the value from input. + fn decode(input: &mut I) -> Result; +} + +impl Decode for T { + fn decode(input: &mut I) -> Result { + let mut bytes = vec![0u8; size_of::()]; + input.read(&mut bytes).context("parsing bytes")?; + bytemuck::try_pod_read_unaligned(&bytes).map_err(Into::into) + } +} + +#[derive(Debug, Clone)] +#[allow(missing_docs)] +#[repr(C)] +pub struct Data { + pub data: Vec, + _marker: core::marker::PhantomData, +} + +impl Serialize for Data { + fn serialize(&self, serializer: S) -> Result { + serde_bytes::serialize(&self.data, serializer) + } +} + +impl<'de, T> Deserialize<'de> for Data { + fn deserialize>(deserializer: D) -> Result { + let data = serde_bytes::deserialize(deserializer)?; + Ok(Data { + data, + _marker: core::marker::PhantomData, + }) + } +} + +impl> Decode for Data { + fn decode(input: &mut I) -> Result { + let len = T::decode(input)?; + let mut data = vec![0u8; len.into() as usize]; + input.read(&mut data).context("reading bytes")?; + Ok(Data { + data, + _marker: core::marker::PhantomData, + }) + } +} + +#[allow(missing_docs)] +#[derive(AnyBitPattern, Debug, Serialize, Deserialize, Copy, Clone)] +#[repr(C, packed)] +pub struct Header { + pub version: u16, + pub attestation_key_type: u16, + pub tee_type: u32, + pub qe_svn: u16, + pub pce_svn: u16, + #[serde(with = "serde_bytes")] + pub qe_vendor_id: [u8; 16], + #[serde(with = "serde_bytes")] + pub user_data: [u8; 20], +} + +#[derive(AnyBitPattern, Debug, Copy, Clone)] +#[allow(missing_docs)] +#[repr(C, packed)] +pub struct Body { + pub body_type: u16, + pub size: u32, +} + +#[derive(Serialize, Deserialize, AnyBitPattern, Debug, Clone, Copy)] +#[allow(missing_docs)] +#[repr(C, packed)] +pub struct EnclaveReport { + #[serde(with = "serde_bytes")] + pub cpu_svn: [u8; 16], + pub misc_select: u32, + #[serde(with = "serde_bytes")] + pub reserved1: [u8; 28], + #[serde(with = "serde_bytes")] + pub attributes: [u8; 16], + #[serde(with = "serde_bytes")] + pub mr_enclave: [u8; 32], + #[serde(with = "serde_bytes")] + pub reserved2: [u8; 32], + #[serde(with = "serde_bytes")] + pub mr_signer: [u8; 32], + #[serde(with = "serde_bytes")] + pub reserved3: [u8; 96], + pub isv_prod_id: u16, + pub isv_svn: u16, + #[serde(with = "serde_bytes")] + pub reserved4: [u8; 60], + #[serde(with = "serde_bytes")] + pub report_data: [u8; 64], +} + +#[derive(AnyBitPattern, Debug, Copy, Clone, Serialize, Deserialize)] +#[allow(missing_docs)] +#[repr(C, packed)] +pub struct TDReport10 { + #[serde(with = "serde_bytes")] + pub tee_tcb_svn: [u8; 16], + #[serde(with = "serde_bytes")] + pub mr_seam: [u8; 48], + #[serde(with = "serde_bytes")] + pub mr_signer_seam: [u8; 48], + #[serde(with = "serde_bytes")] + pub seam_attributes: [u8; 8], + #[serde(with = "serde_bytes")] + pub td_attributes: [u8; 8], + #[serde(with = "serde_bytes")] + pub xfam: [u8; 8], + #[serde(with = "serde_bytes")] + pub mr_td: [u8; 48], + #[serde(with = "serde_bytes")] + pub mr_config_id: [u8; 48], + #[serde(with = "serde_bytes")] + pub mr_owner: [u8; 48], + #[serde(with = "serde_bytes")] + pub mr_owner_config: [u8; 48], + #[serde(with = "serde_bytes")] + pub rt_mr0: [u8; 48], + #[serde(with = "serde_bytes")] + pub rt_mr1: [u8; 48], + #[serde(with = "serde_bytes")] + pub rt_mr2: [u8; 48], + #[serde(with = "serde_bytes")] + pub rt_mr3: [u8; 48], + #[serde(with = "serde_bytes")] + pub report_data: [u8; 64], +} + +#[derive(AnyBitPattern, Debug, Copy, Clone, Serialize, Deserialize)] +#[allow(missing_docs)] +#[repr(C, packed)] +pub struct TDReport15 { + pub base: TDReport10, + #[serde(with = "serde_bytes")] + pub tee_tcb_svn2: [u8; 16], + #[serde(with = "serde_bytes")] + pub mr_service_td: [u8; 48], +} + +#[allow(missing_docs)] +#[derive(Serialize, Deserialize, Clone)] +#[repr(C)] +pub struct CertificationData { + pub cert_type: u16, + pub body: Data, +} + +impl Decode for CertificationData { + fn decode(input: &mut I) -> Result { + Ok(Self { + cert_type: Decode::decode(input)?, + body: Decode::decode(input)?, + }) + } +} + +impl core::fmt::Debug for CertificationData { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let body_str = String::from_utf8_lossy(&self.body.data); + f.debug_struct("CertificationData") + .field("cert_type", &self.cert_type) + .field("body", &body_str) + .finish() + } +} + +#[derive(Debug, Serialize, Deserialize)] +#[allow(missing_docs)] +#[repr(C)] +pub struct QEReportCertificationData { + #[serde(with = "serde_bytes")] + pub qe_report: [u8; ENCLAVE_REPORT_BYTE_LEN], + #[serde(with = "serde_bytes")] + pub qe_report_signature: [u8; QE_REPORT_SIG_BYTE_LEN], + pub qe_auth_data: Data, + pub certification_data: CertificationData, +} + +impl Decode for QEReportCertificationData { + fn decode(input: &mut I) -> Result { + Ok(Self { + qe_report: Decode::decode(input)?, + qe_report_signature: Decode::decode(input)?, + qe_auth_data: Decode::decode(input)?, + certification_data: Decode::decode(input)?, + }) + } +} + +#[derive(Debug, Serialize, Deserialize)] +#[allow(missing_docs)] +#[repr(C)] +pub struct AuthDataV3 { + #[serde(with = "serde_bytes")] + pub ecdsa_signature: [u8; ECDSA_SIGNATURE_BYTE_LEN], + #[serde(with = "serde_bytes")] + pub ecdsa_attestation_key: [u8; ECDSA_PUBKEY_BYTE_LEN], + #[serde(with = "serde_bytes")] + pub qe_report: [u8; ENCLAVE_REPORT_BYTE_LEN], + #[serde(with = "serde_bytes")] + pub qe_report_signature: [u8; QE_REPORT_SIG_BYTE_LEN], + pub qe_auth_data: Data, + pub certification_data: CertificationData, +} + +impl Decode for AuthDataV3 { + fn decode(input: &mut I) -> Result { + Ok(Self { + ecdsa_signature: Decode::decode(input)?, + ecdsa_attestation_key: Decode::decode(input)?, + qe_report: Decode::decode(input)?, + qe_report_signature: Decode::decode(input)?, + qe_auth_data: Decode::decode(input)?, + certification_data: Decode::decode(input)?, + }) + } +} + +#[derive(Debug, Serialize, Deserialize)] +#[allow(missing_docs)] +#[repr(C)] +pub struct AuthDataV4 { + #[serde(with = "serde_bytes")] + pub ecdsa_signature: [u8; ECDSA_SIGNATURE_BYTE_LEN], + #[serde(with = "serde_bytes")] + pub ecdsa_attestation_key: [u8; ECDSA_PUBKEY_BYTE_LEN], + pub certification_data: CertificationData, + pub qe_report_data: QEReportCertificationData, +} + +impl AuthDataV4 { + #[allow(missing_docs)] + pub fn into_v3(self) -> AuthDataV3 { + AuthDataV3 { + ecdsa_signature: self.ecdsa_signature, + ecdsa_attestation_key: self.ecdsa_attestation_key, + qe_report: self.qe_report_data.qe_report, + qe_report_signature: self.qe_report_data.qe_report_signature, + qe_auth_data: self.qe_report_data.qe_auth_data, + certification_data: self.qe_report_data.certification_data, + } + } +} + +impl Decode for AuthDataV4 { + fn decode(input: &mut I) -> Result { + let ecdsa_signature = Decode::decode(input)?; + let ecdsa_attestation_key = Decode::decode(input)?; + let certification_data: CertificationData = Decode::decode(input)?; + let qe_report_data = + QEReportCertificationData::decode(&mut &certification_data.body.data[..])?; + Ok(AuthDataV4 { + ecdsa_signature, + ecdsa_attestation_key, + certification_data, + qe_report_data, + }) + } +} + +#[derive(Debug, Serialize, Deserialize)] +#[allow(missing_docs)] +#[repr(C)] +pub enum AuthData { + V3(AuthDataV3), + V4(AuthDataV4), +} + +impl AuthData { + #[allow(missing_docs)] + pub fn into_v3(self) -> AuthDataV3 { + match self { + AuthData::V3(data) => data, + AuthData::V4(data) => data.into_v3(), + } + } +} + +fn decode_auth_data(ver: u16, input: &mut &[u8]) -> Result { + match ver { + 3 => { + let auth_data = AuthDataV3::decode(input)?; + Ok(AuthData::V3(auth_data)) + } + 4 => { + let auth_data = AuthDataV4::decode(input)?; + Ok(AuthData::V4(auth_data)) + } + _ => Err(error::QuoteError::QuoteVersion), + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[allow(missing_docs)] +#[repr(C)] +#[non_exhaustive] +pub enum Report { + SgxEnclave(EnclaveReport), + TD10(TDReport10), + TD15(TDReport15), +} + +impl Report { + #[allow(missing_docs)] + pub fn is_sgx(&self) -> bool { + matches!(self, Report::SgxEnclave(_)) + } + + #[allow(missing_docs)] + pub fn as_td10(&self) -> Option<&TDReport10> { + match self { + Report::TD10(report) => Some(report), + Report::TD15(report) => Some(&report.base), + _ => None, + } + } + + #[allow(missing_docs)] + pub fn as_td15(&self) -> Option<&TDReport15> { + match self { + Report::TD15(report) => Some(report), + _ => None, + } + } + + #[allow(missing_docs)] + pub fn as_sgx(&self) -> Option<&EnclaveReport> { + match self { + Report::SgxEnclave(report) => Some(report), + _ => None, + } + } +} + +impl Display for Report { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn space_or_newline(f: &mut Formatter<'_>) -> std::fmt::Result { + if f.alternate() { + writeln!(f) + } else { + write!(f, " ") + } + } + match self { + Report::SgxEnclave(report_body) => { + write!(f, "mrsigner: {}", hex::encode(report_body.mr_signer))?; + space_or_newline(f)?; + write!(f, "mrenclave: {}", hex::encode(report_body.mr_enclave))?; + space_or_newline(f)?; + write!( + f, + "reportdata: {}", + hex::encode(report_body.report_data.as_slice()) + )?; + } + Report::TD10(report_body) => { + write!(f, "mrtd: {}", hex::encode(report_body.mr_td))?; + space_or_newline(f)?; + write!(f, "rtmr0: {}", hex::encode(report_body.rt_mr0))?; + space_or_newline(f)?; + write!(f, "rtmr1: {}", hex::encode(report_body.rt_mr1))?; + space_or_newline(f)?; + write!(f, "rtmr2: {}", hex::encode(report_body.rt_mr2))?; + space_or_newline(f)?; + write!(f, "rtmr3: {}", hex::encode(report_body.rt_mr3))?; + space_or_newline(f)?; + write!( + f, + "reportdata: {}", + hex::encode(report_body.report_data.as_slice()) + )?; + } + Report::TD15(report_body) => { + let report_body = &report_body.base; + write!(f, "mrtd: {}", hex::encode(report_body.mr_td))?; + space_or_newline(f)?; + write!(f, "rtmr0: {}", hex::encode(report_body.rt_mr0))?; + space_or_newline(f)?; + write!(f, "rtmr1: {}", hex::encode(report_body.rt_mr1))?; + space_or_newline(f)?; + write!(f, "rtmr2: {}", hex::encode(report_body.rt_mr2))?; + space_or_newline(f)?; + write!(f, "rtmr3: {}", hex::encode(report_body.rt_mr3))?; + space_or_newline(f)?; + write!( + f, + "reportdata: {}", + hex::encode(report_body.report_data.as_slice()) + )?; + } + } + Ok(()) + } +} + +#[derive(Debug, Serialize, Deserialize)] +#[allow(missing_docs)] +#[repr(C)] +pub struct Quote { + pub header: Header, + pub report: Report, + pub auth_data: AuthData, +} + +impl Decode for Quote { + fn decode(input: &mut I) -> Result { + let header = Header::decode(input)?; + trace!(?header); + let report; + match header.version { + 3 => { + if header.tee_type != TEE_TYPE_SGX { + return Err(error::QuoteError::InvalidTeeType); + } + report = Report::SgxEnclave(EnclaveReport::decode(input)?); + } + 4 => match header.tee_type { + TEE_TYPE_SGX => { + report = Report::SgxEnclave(EnclaveReport::decode(input)?); + } + TEE_TYPE_TDX => { + report = Report::TD10(TDReport10::decode(input)?); + } + _ => return Err(error::QuoteError::InvalidTeeType), + }, + 5 => { + let body = Body::decode(input)?; + match body.body_type { + BODY_SGX_ENCLAVE_REPORT_TYPE => { + report = Report::SgxEnclave(EnclaveReport::decode(input)?); + } + BODY_TD_REPORT10_TYPE => { + report = Report::TD10(TDReport10::decode(input)?); + } + BODY_TD_REPORT15_TYPE => { + report = Report::TD15(TDReport15::decode(input)?); + } + _ => return Err(error::QuoteError::UnsupportedBodyType), + } + } + _ => return Err(error::QuoteError::QuoteVersion), + } + let data = Data::::decode(input)?; + let auth_data = decode_auth_data(header.version, &mut &data.data[..])?; + Ok(Quote { + header, + report, + auth_data, + }) + } +} + +impl Quote { + /// Parse a TEE quote from a byte slice. + pub fn parse(quote: &[u8]) -> Result { + let mut input = quote; + let quote = Quote::decode(&mut input)?; + Ok(quote) + } + + /// Get the report data + pub fn get_report_data(&self) -> &[u8] { + match &self.report { + Report::SgxEnclave(r) => r.report_data.as_slice(), + Report::TD10(r) => r.report_data.as_slice(), + Report::TD15(r) => r.base.report_data.as_slice(), + } + } +} + +/// TEE type +#[non_exhaustive] +pub enum TEEType { + /// Intel SGX + SGX, + /// Intel TDX + TDX, + /// AMD SEV-SNP + SNP, +} + +impl Display for TEEType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let str = match self { + TEEType::SGX => "sgx", + TEEType::TDX => "tdx", + TEEType::SNP => "snp", + }; + write!(f, "{}", str) + } +} + +impl FromStr for TEEType { + type Err = String; + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "sgx" => Ok(TEEType::SGX), + "tdx" => Ok(TEEType::TDX), + "snp" => Ok(TEEType::SNP), + _ => Err("Invalid TEE type".to_string()), + } + } } /// Get the attestation quote from a TEE -pub fn get_quote(report_data: &[u8]) -> Result, GetQuoteError> { +pub fn get_quote(report_data: &[u8]) -> Result<(TEEType, Box<[u8]>), QuoteError> { // check, if we are running in a TEE if std::fs::metadata("/dev/attestation").is_ok() { if report_data.len() > 64 { - return Err(GetQuoteError { - msg: "Report data too long".into(), - source: io::Error::new(io::ErrorKind::Other, "Report data too long"), - }); + return Err(QuoteError::ReportDataSize); } let mut report_data_fixed = [0u8; 64]; report_data_fixed[..report_data.len()].copy_from_slice(report_data); - sgx_gramine_get_quote(&report_data_fixed) + Ok((TEEType::SGX, sgx_gramine_get_quote(&report_data_fixed)?)) + } else if std::fs::metadata("/dev/tdx_guest").is_ok() { + if report_data.len() > 64 { + return Err(QuoteError::ReportDataSize); + } + + let mut report_data_fixed = [0u8; 64]; + report_data_fixed[..report_data.len()].copy_from_slice(report_data); + + Ok((TEEType::TDX, tgx_get_quote(&report_data_fixed)?)) } else { // if not, return an error - Err(GetQuoteError { - msg: "Not running in a TEE".into(), - source: io::Error::new(io::ErrorKind::Other, "Not running in a TEE"), - }) + Err(QuoteError::UnknownTee) } } + +/// The result of the quote verification +pub struct QuoteVerificationResult { + /// the raw result + pub result: sgx_ql_qv_result_t, + /// indicates if the collateral is expired + pub collateral_expired: bool, + /// the earliest expiration date of the collateral + pub earliest_expiration_date: i64, + /// Date of the TCB level + pub tcb_level_date_tag: i64, + /// the advisory string + pub advisories: Vec, + /// the quote + pub quote: Quote, +} + +/// Verifies a quote with optional collateral material +pub fn verify_quote_with_collateral( + quote: &[u8], + collateral: Option<&Collateral>, + current_time: i64, +) -> Result { + let mut supp_data: mem::MaybeUninit = mem::MaybeUninit::zeroed(); + let mut supp_data_desc = tee_supp_data_descriptor_t { + major_version: 0, + data_size: 0, + p_data: supp_data.as_mut_ptr() as *mut u8, + }; + trace!("tee_get_supplemental_data_version_and_size"); + let (_, supp_size) = + tee_get_supplemental_data_version_and_size(quote).map_err(|e| QuoteError::Quote3Error { + msg: "tee_get_supplemental_data_version_and_size".into(), + inner: e, + })?; + + trace!( + "tee_get_supplemental_data_version_and_size supp_size: {}", + supp_size + ); + + if supp_size == mem::size_of::() as u32 { + supp_data_desc.data_size = supp_size; + } else { + supp_data_desc.data_size = 0; + trace!( + "tee_get_supplemental_data_version_and_size supp_size: {}", + supp_size + ); + trace!( + "mem::size_of::(): {}", + mem::size_of::() + ); + warn!("Quote supplemental data size is different between DCAP QVL and QvE, please make sure you installed DCAP QVL and QvE from same release.") + } + + let p_supplemental_data = match supp_data_desc.data_size { + 0 => None, + _ => Some(&mut supp_data_desc), + }; + + let has_sup = p_supplemental_data.is_some(); + + trace!("tee_verify_quote"); + + let (collateral_expiration_status, result) = + tee_verify_quote(quote, collateral, current_time, None, p_supplemental_data) + .context("tee_verify_quote")?; + + trace!("tee_verify_quote end"); + + // check supplemental data if necessary + let (advisories, earliest_expiration_date, tcb_level_date_tag) = if has_sup { + unsafe { + let supp_data = supp_data.assume_init(); + // convert to valid UTF-8 string + let ads = CStr::from_bytes_until_nul(cast_slice(&supp_data.sa_list[..])) + .ok() + .and_then(|s| CStr::to_str(s).ok()) + .into_iter() + .flat_map(|s| s.split(',').map(str::trim).map(String::from)) + .filter(|s| !s.is_empty()) + .collect(); + ( + ads, + supp_data.earliest_expiration_date, + supp_data.tcb_level_date_tag, + ) + } + } else { + (vec![], 0, 0) + }; + + trace!("Quote::parse"); + let quote = Quote::parse(quote)?; + + let res = QuoteVerificationResult { + collateral_expired: collateral_expiration_status != 0, + earliest_expiration_date, + tcb_level_date_tag, + result, + quote, + advisories, + }; + + Ok(res) +} diff --git a/crates/teepot/src/server/attestation.rs b/crates/teepot/src/server/attestation.rs index e390187..9cafb4d 100644 --- a/crates/teepot/src/server/attestation.rs +++ b/crates/teepot/src/server/attestation.rs @@ -3,17 +3,22 @@ //! Common attestation API for all TEEs -use crate::client::AttestationArgs; -use crate::json::http::AttestationResponse; -use crate::sgx::{ - parse_tcb_levels, sgx_gramine_get_quote, tee_qv_get_collateral, verify_quote_with_collateral, - Collateral, EnumSet, QuoteVerificationResult, TcbLevel, +use crate::{ + client::AttestationArgs, + json::http::AttestationResponse, + quote::{ + error::QuoteContext, get_quote, verify_quote_with_collateral, QuoteVerificationResult, + }, + sgx::{parse_tcb_levels, Collateral, EnumSet, TcbLevel}, }; use anyhow::{bail, Context, Result}; use clap::Args; +use intel_tee_quote_verification_rs::tee_qv_get_collateral; use serde::{Deserialize, Serialize}; -use std::sync::{Arc, RwLock}; -use std::time::{Duration, UNIX_EPOCH}; +use std::{ + sync::{Arc, RwLock}, + time::{Duration, UNIX_EPOCH}, +}; use tracing::{debug, error, info, trace, warn}; struct Attestation { @@ -53,7 +58,7 @@ pub fn get_quote_and_collateral( } } - let myquote = sgx_gramine_get_quote(report_data).context("Failed to get own quote")?; + let (_tee_type, myquote) = get_quote(report_data).context("Failed to get own quote")?; let collateral = tee_qv_get_collateral(&myquote).context("Failed to get own collateral")?; let QuoteVerificationResult { @@ -89,8 +94,8 @@ pub fn get_quote_and_collateral( "Earliest expiration in {:?}", Duration::from_secs((earliest_expiration_date - unix_time) as _) ); - info!("mrsigner: {}", hex::encode(quote.report_body.mrsigner)); - info!("mrenclave: {}", hex::encode(quote.report_body.mrenclave)); + + info!("{:#}", quote.report); let quote: Arc<[u8]> = Arc::from(myquote); let collateral = Arc::from(collateral); diff --git a/crates/teepot/src/server/pki.rs b/crates/teepot/src/server/pki.rs index ce3c110..ffa04c3 100644 --- a/crates/teepot/src/server/pki.rs +++ b/crates/teepot/src/server/pki.rs @@ -3,39 +3,38 @@ //! Create a private key and a signed and self-signed certificates -use crate::quote::get_quote; -use crate::sgx::tee_qv_get_collateral; -pub use crate::sgx::{ - parse_tcb_levels, sgx_ql_qv_result_t, verify_quote_with_collateral, EnumSet, - QuoteVerificationResult, TcbLevel, -}; +use crate::quote::{error::QuoteContext, get_quote}; +pub use crate::sgx::{parse_tcb_levels, sgx_ql_qv_result_t, EnumSet, TcbLevel}; use anyhow::{Context, Result}; -use const_oid::db::rfc5280::{ID_KP_CLIENT_AUTH, ID_KP_SERVER_AUTH}; -use const_oid::AssociatedOid; +use const_oid::{ + db::rfc5280::{ID_KP_CLIENT_AUTH, ID_KP_SERVER_AUTH}, + AssociatedOid, +}; use getrandom::getrandom; -use p256::ecdsa::DerSignature; -use p256::pkcs8::EncodePrivateKey; +use intel_tee_quote_verification_rs::tee_qv_get_collateral; +use p256::{ecdsa::DerSignature, pkcs8::EncodePrivateKey}; use pkcs8::der; use rustls::pki_types::PrivatePkcs8KeyDer; use sha2::{Digest, Sha256}; use signature::Signer; -use std::str::FromStr; -use std::time::Duration; +use std::{str::FromStr, time::Duration}; use tracing::debug; -use x509_cert::builder::{Builder, CertificateBuilder, Profile}; -use x509_cert::der::pem::LineEnding; -use x509_cert::der::{asn1::OctetString, Encode as _, EncodePem as _, Length}; -use x509_cert::ext::pkix::name::GeneralNames; -use x509_cert::ext::pkix::{ExtendedKeyUsage, SubjectAltName}; -use x509_cert::ext::{AsExtension, Extension}; -use x509_cert::name::{Name, RdnSequence}; -use x509_cert::serial_number::SerialNumber; -use x509_cert::spki::{ - DynSignatureAlgorithmIdentifier, EncodePublicKey, ObjectIdentifier, SignatureBitStringEncoding, - SubjectPublicKeyInfoOwned, +use x509_cert::{ + builder::{Builder, CertificateBuilder, Profile}, + der::{asn1::OctetString, pem::LineEnding, Encode as _, EncodePem as _, Length}, + ext::{ + pkix::{name::GeneralNames, ExtendedKeyUsage, SubjectAltName}, + AsExtension, Extension, + }, + name::{Name, RdnSequence}, + serial_number::SerialNumber, + spki::{ + DynSignatureAlgorithmIdentifier, EncodePublicKey, ObjectIdentifier, + SignatureBitStringEncoding, SubjectPublicKeyInfoOwned, + }, + time::Validity, + Certificate, }; -use x509_cert::time::Validity; -use x509_cert::Certificate; use zeroize::Zeroizing; /// The OID for the `gramine-ra-tls` quote extension @@ -148,7 +147,7 @@ pub fn make_self_signed_cert( let hash = Sha256::digest(verifying_key_der.as_bytes()); key_hash[..32].copy_from_slice(&hash); - let quote = get_quote(&key_hash)?; + let (_tee_type, quote) = get_quote(&key_hash)?; debug!("quote.len: {:?}", quote.len()); // Create a relative distinguished name. let rdns = RdnSequence::from_str(dn)?; @@ -185,6 +184,7 @@ pub fn make_self_signed_cert( .context("failed to add SubjectAltName")?; } + // FIXME: OID for tee_type builder .add_extension(&RaTlsQuoteExtension { quote: quote.to_vec(), @@ -234,7 +234,7 @@ where let hash = Sha256::digest(verifying_key_der.as_bytes()); key_hash[..32].copy_from_slice(&hash); - let quote = get_quote(&key_hash).context("Failed to get own quote")?; + let (_tee_type, quote) = get_quote(&key_hash).context("Failed to get own quote")?; // Create a relative distinguished name. let subject = Name::from_str(dn)?; @@ -269,6 +269,7 @@ where .context("failed to add SubjectAltName")?; } + // FIXME: oid according to tee_type builder .add_extension(&RaTlsQuoteExtension { quote: quote.to_vec(), diff --git a/crates/teepot/src/sgx/error.rs b/crates/teepot/src/sgx/error.rs deleted file mode 100644 index 492a42a..0000000 --- a/crates/teepot/src/sgx/error.rs +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright (c) 2023 Matter Labs - -//! Intel SGX Enclave error wrapper - -use bytemuck::PodCastError; -use intel_tee_quote_verification_rs::quote3_error_t; -use std::fmt::Formatter; - -/// Wrapper for the quote verification Error -#[derive(Copy, Clone)] -pub struct Quote3Error { - /// error message - pub msg: &'static str, - /// raw error code - pub inner: quote3_error_t, -} - -impl std::fmt::Display for Quote3Error { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}: {:?}", self.msg, self.inner) - } -} - -impl std::fmt::Debug for Quote3Error { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}: {:?}", self.msg, self.inner) - } -} - -impl std::error::Error for Quote3Error {} - -impl From for Quote3Error { - fn from(inner: quote3_error_t) -> Self { - Self { - msg: "Generic", - inner, - } - } -} - -#[derive(Debug, thiserror::Error)] -#[allow(missing_docs)] -pub enum QuoteFromError { - #[error(transparent)] - PodCastError(#[from] PodCastError), - - #[error("Quote version is invalid")] - InvalidVersion, -} diff --git a/crates/teepot/src/sgx/mod.rs b/crates/teepot/src/sgx/mod.rs index 2fc289b..9ae67c6 100644 --- a/crates/teepot/src/sgx/mod.rs +++ b/crates/teepot/src/sgx/mod.rs @@ -5,24 +5,18 @@ //! Intel SGX Enclave report structures. -pub mod error; pub mod sign; pub mod tcblevel; -use bytemuck::{cast_slice, try_from_bytes, AnyBitPattern, PodCastError}; -use intel_tee_quote_verification_rs::{ - quote3_error_t, sgx_ql_qv_supplemental_t, tee_get_supplemental_data_version_and_size, - tee_supp_data_descriptor_t, tee_verify_quote, -}; -use std::ffi::CStr; -use std::fs::OpenOptions; -use std::io::{Read, Write}; -use std::mem; -use tracing::{trace, warn}; - -use crate::quote::GetQuoteError; -pub use error::{Quote3Error, QuoteFromError}; +use crate::quote::error::QuoteContext; +pub use crate::quote::error::QuoteError; +use bytemuck::{try_from_bytes, AnyBitPattern, PodCastError}; pub use intel_tee_quote_verification_rs::{sgx_ql_qv_result_t, Collateral}; +use std::{ + fs::OpenOptions, + io::{Read, Write}, + mem, +}; pub use tcblevel::{parse_tcb_levels, EnumSet, TcbLevel}; /// Structure of a quote @@ -43,13 +37,13 @@ pub struct Quote { impl Quote { /// Creates a quote from a byte slice - pub fn try_from_bytes(bytes: &[u8]) -> Result<&Self, QuoteFromError> { + pub fn try_from_bytes(bytes: &[u8]) -> Result<&Self, QuoteError> { if bytes.len() < mem::size_of::() { return Err(PodCastError::SizeMismatch.into()); } let this: &Self = try_from_bytes(&bytes[..mem::size_of::()])?; if this.version() != 3 { - return Err(QuoteFromError::InvalidVersion); + return Err(QuoteError::InvalidVersion); } Ok(this) } @@ -98,152 +92,26 @@ pub struct ReportBody { pub reportdata: [u8; 64], } -/// The result of the quote verification -pub struct QuoteVerificationResult<'a> { - /// the raw result - pub result: sgx_ql_qv_result_t, - /// indicates if the collateral is expired - pub collateral_expired: bool, - /// the earliest expiration date of the collateral - pub earliest_expiration_date: i64, - /// Date of the TCB level - pub tcb_level_date_tag: i64, - /// the advisory string - pub advisories: Vec, - /// the quote - pub quote: &'a Quote, -} - -/// Verifies a quote with optional collateral material -pub fn verify_quote_with_collateral<'a>( - quote: &'a [u8], - collateral: Option<&Collateral>, - current_time: i64, -) -> Result, Quote3Error> { - let mut supp_data: mem::MaybeUninit = mem::MaybeUninit::zeroed(); - let mut supp_data_desc = tee_supp_data_descriptor_t { - major_version: 0, - data_size: 0, - p_data: supp_data.as_mut_ptr() as *mut u8, - }; - trace!("tee_get_supplemental_data_version_and_size"); - let (_, supp_size) = - tee_get_supplemental_data_version_and_size(quote).map_err(|e| Quote3Error { - msg: "tee_get_supplemental_data_version_and_size", - inner: e, - })?; - - trace!( - "tee_get_supplemental_data_version_and_size supp_size: {}", - supp_size - ); - - if supp_size == mem::size_of::() as u32 { - supp_data_desc.data_size = supp_size; - } else { - supp_data_desc.data_size = 0; - trace!( - "tee_get_supplemental_data_version_and_size supp_size: {}", - supp_size - ); - trace!( - "mem::size_of::(): {}", - mem::size_of::() - ); - warn!("Quote supplemental data size is different between DCAP QVL and QvE, please make sure you installed DCAP QVL and QvE from same release.") - } - - let p_supplemental_data = match supp_data_desc.data_size { - 0 => None, - _ => Some(&mut supp_data_desc), - }; - - let has_sup = p_supplemental_data.is_some(); - - trace!("tee_verify_quote"); - - let (collateral_expiration_status, result) = - tee_verify_quote(quote, collateral, current_time, None, p_supplemental_data).map_err( - |e| Quote3Error { - msg: "tee_verify_quote", - inner: e, - }, - )?; - - // check supplemental data if necessary - let (advisories, earliest_expiration_date, tcb_level_date_tag) = if has_sup { - unsafe { - let supp_data = supp_data.assume_init(); - // convert to valid UTF-8 string - let ads = CStr::from_bytes_until_nul(cast_slice(&supp_data.sa_list[..])) - .ok() - .and_then(|s| CStr::to_str(s).ok()) - .into_iter() - .flat_map(|s| s.split(',').map(str::trim).map(String::from)) - .filter(|s| !s.is_empty()) - .collect(); - ( - ads, - supp_data.earliest_expiration_date, - supp_data.tcb_level_date_tag, - ) - } - } else { - (vec![], 0, 0) - }; - - let quote = Quote::try_from_bytes(quote).map_err(|_| Quote3Error { - msg: "Quote::try_from_bytes", - inner: quote3_error_t::SGX_QL_QUOTE_FORMAT_UNSUPPORTED, - })?; - - let res = QuoteVerificationResult { - collateral_expired: collateral_expiration_status != 0, - earliest_expiration_date, - tcb_level_date_tag, - result, - quote, - advisories, - }; - - Ok(res) -} - /// Get the attestation report in a Gramine enclave -pub fn sgx_gramine_get_quote(report_data: &[u8; 64]) -> Result, GetQuoteError> { +pub fn sgx_gramine_get_quote(report_data: &[u8; 64]) -> Result, QuoteError> { let mut file = OpenOptions::new() .write(true) .open("/dev/attestation/user_report_data") - .map_err(|e| GetQuoteError { - msg: "Failed to open `/dev/attestation/user_report_data`".into(), - source: e, - })?; + .context("opening `/dev/attestation/user_report_data`")?; - file.write(report_data).map_err(|e| GetQuoteError { - msg: "Failed to write `/dev/attestation/user_report_data`".into(), - source: e, - })?; + file.write(report_data) + .context("writing `/dev/attestation/user_report_data`")?; drop(file); let mut file = OpenOptions::new() .read(true) .open("/dev/attestation/quote") - .map_err(|e| GetQuoteError { - msg: "Failed to open `/dev/attestation/quote`".into(), - source: e, - })?; + .context("opening `/dev/attestation/quote`")?; let mut quote = Vec::new(); - file.read_to_end(&mut quote).map_err(|e| GetQuoteError { - msg: "Failed to read `/dev/attestation/quote`".into(), - source: e, - })?; + file.read_to_end(&mut quote) + .context("reading `/dev/attestation/quote`")?; + Ok(quote.into_boxed_slice()) } - -/// Wrapper func for error -/// TODO: move to intel_tee_quote_verification_rs -pub fn tee_qv_get_collateral(quote: &[u8]) -> Result { - intel_tee_quote_verification_rs::tee_qv_get_collateral(quote).map_err(Into::into) -} diff --git a/crates/teepot/src/tdx/mod.rs b/crates/teepot/src/tdx/mod.rs new file mode 100644 index 0000000..37c03de --- /dev/null +++ b/crates/teepot/src/tdx/mod.rs @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2023-2024 Matter Labs + +//! Intel TDX helper functions. + +pub use crate::sgx::tcblevel::{parse_tcb_levels, EnumSet, TcbLevel}; +use crate::sgx::QuoteError; +pub use intel_tee_quote_verification_rs::Collateral; +use tdx_attest_rs::{tdx_att_get_quote, tdx_attest_error_t, tdx_report_data_t}; + +/// Get a TDX quote +pub fn tgx_get_quote(report_data_bytes: &[u8; 64]) -> Result, QuoteError> { + let mut tdx_report_data = tdx_report_data_t { d: [0; 64usize] }; + tdx_report_data.d.copy_from_slice(report_data_bytes); + + let (error, quote) = tdx_att_get_quote(Some(&tdx_report_data), None, None, 0); + + if error == tdx_attest_error_t::TDX_ATTEST_SUCCESS { + if let Some(quote) = quote { + Ok(quote.into()) + } else { + Err(QuoteError::TdxAttGetQuote { + msg: "tdx_att_get_quote: No quote returned".into(), + inner: error, + }) + } + } else { + Err(error.into()) + } +} diff --git a/crates/teepot/tests/sgx_quote_verification.rs b/crates/teepot/tests/sgx_quote_verification.rs index 4f04d2f..27a3d41 100644 --- a/crates/teepot/tests/sgx_quote_verification.rs +++ b/crates/teepot/tests/sgx_quote_verification.rs @@ -2,14 +2,15 @@ // Copyright (c) 2024 Matter Labs mod sgx { - use anyhow::Result; + use anyhow::{Context, Result}; use intel_tee_quote_verification_rs::{sgx_ql_qv_result_t, Collateral}; use std::time::{Duration, UNIX_EPOCH}; - use teepot::sgx::{verify_quote_with_collateral, QuoteVerificationResult}; + use teepot::quote::{verify_quote_with_collateral, QuoteVerificationResult, Report}; + use tracing_test::traced_test; fn check_quote( quote: &[u8], - collateral: &Collateral, + collateral: Option<&Collateral>, current_time: i64, expected_mrsigner: &[u8], expected_reportdata: &[u8], @@ -22,7 +23,7 @@ mod sgx { quote, advisories, tcb_level_date_tag, - } = verify_quote_with_collateral(quote, Some(collateral), current_time).unwrap(); + } = verify_quote_with_collateral(quote, collateral, current_time)?; if collateral_expired || result != sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OK { print!("Attestation failed: "); @@ -67,12 +68,16 @@ mod sgx { println!("tcb_level_date_tag: {:?}", tcb_level_date_tag); assert_eq!(expected_result, result); - let expected_reportdata = hex::encode(expected_reportdata); - let expected_mrsigner = hex::encode(expected_mrsigner); - let actual_reportdata = hex::encode("e.report_body.reportdata[..]); - let actual_mrsigner = hex::encode("e.report_body.mrsigner[..]); - assert_eq!(expected_mrsigner, actual_mrsigner); - assert_eq!(expected_reportdata, actual_reportdata); + + if let Report::SgxEnclave(report_body) = quote.report { + let expected_reportdata = hex::encode(expected_reportdata); + let expected_mrsigner = hex::encode(expected_mrsigner); + let actual_reportdata = hex::encode(&report_body.report_data[..]); + let actual_mrsigner = hex::encode(&report_body.mr_signer[..]); + assert_eq!(expected_mrsigner, actual_mrsigner); + assert_eq!(expected_reportdata, actual_reportdata); + } + Ok(()) } @@ -1132,7 +1137,7 @@ mod sgx { check_quote( "e, - &collateral, + Some(&collateral), current_time, &mrsigner, &report_data, @@ -2203,7 +2208,7 @@ mod sgx { check_quote( "e, - &collateral, + Some(&collateral), current_time, &mrsigner, &report_data, @@ -2560,17 +2565,17 @@ mod sgx { ]; let collateral = Collateral { - major_version: 1, - minor_version: 0, - tee_type: 0, - pck_crl_issuer_chain: "-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n\0".as_bytes().into(), - root_ca_crl: "-----BEGIN X509 CRL-----\nMIIBITCByAIBATAKBggqhkjOPQQDAjBoMRowGAYDVQQDDBFJbnRlbCBTR1ggUm9v\ndCBDQTEaMBgGA1UECgwRSW50ZWwgQ29ycG9yYXRpb24xFDASBgNVBAcMC1NhbnRh\nIENsYXJhMQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMXDTIzMDQwMzEwMjI1MVoX\nDTI0MDQwMjEwMjI1MVqgLzAtMAoGA1UdFAQDAgEBMB8GA1UdIwQYMBaAFCJlDNZa\nnTSJ84O0lVK/UBs5JwasMAoGCCqGSM49BAMCA0gAMEUCIFFXfUfZ+6FXtl8etfRl\ne7xeVsyvc1oD8blj1wSAWrEYAiEAk5AV7BY25+r6X0JsHkAmR8ZzEytoUMq9aM72\nutdoKgM=\n-----END X509 CRL-----\n\0".as_bytes().into(), - pck_crl: "-----BEGIN X509 CRL-----\nMIIKYTCCCggCAQEwCgYIKoZIzj0EAwIwcDEiMCAGA1UEAwwZSW50ZWwgU0dYIFBD\nSyBQbGF0Zm9ybSBDQTEaMBgGA1UECgwRSW50ZWwgQ29ycG9yYXRpb24xFDASBgNV\nBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMXDTIzMDUx\nMzIxMDAwM1oXDTIzMDYxMjIxMDAwM1owggk0MDMCFG/DTlAj5yiSNDXWGqS4PGGB\nZq01Fw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwNAIVAO+ubpcV/KE7h+Mz\n6CYe1tmQqSatFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwNAIVAP1ghkhi\nnLpzB4tNSS9LPqdBrQjNFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwNAIV\nAIr5JBhOHVr93XPD1joS9ei1c35WFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMK\nAQEwNAIVALEleXjPqczdB1mr+MXKcvrjp4qbFw0yMzA1MTMyMTAwMDNaMAwwCgYD\nVR0VBAMKAQEwMwIUdP6mFKlyvg4oQ/IFmDWBHthy+bMXDTIzMDUxMzIxMDAwM1ow\nDDAKBgNVHRUEAwoBATA0AhUA+cTvVrOrSNV34Qi67fS/iAFCFLkXDTIzMDUxMzIx\nMDAwM1owDDAKBgNVHRUEAwoBATAzAhQHHeB3j55fxPKHjzDWsHyaMOazCxcNMjMw\nNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDQCFQDN4kJPlyzqlP8jmTf02AwlAp3W\nCxcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDMCFGwzGeUQm2RQfTzxEyzg\nA0nvUnMZFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwNAIVAN8I11a2anSX\n9DtbtYraBNP096k3Fw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwMwIUKK9I\nW2z2fkCaOdXLWu5FmPeo+nsXDTIzMDUxMzIxMDAwM1owDDAKBgNVHRUEAwoBATA0\nAhUA+4strsCSytqKqbxP8vHCDQNGZowXDTIzMDUxMzIxMDAwM1owDDAKBgNVHRUE\nAwoBATA0AhUAzUhQrFK9zGmmpvBYyLxXu9C1+GQXDTIzMDUxMzIxMDAwM1owDDAK\nBgNVHRUEAwoBATA0AhUAmU3TZm9SdfuAX5XdAr1QyyZ52K0XDTIzMDUxMzIxMDAw\nM1owDDAKBgNVHRUEAwoBATAzAhQHAhNpACUidNkDXu31RXRi+tDvTBcNMjMwNTEz\nMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDMCFGHyv3Pjm04EqifYAb1z0kMZtb+AFw0y\nMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwMwIUOZK+hRuWkC7/OJWebC7/GwZR\npLUXDTIzMDUxMzIxMDAwM1owDDAKBgNVHRUEAwoBATAzAhRjnxOaUED9z/GR6KT7\nG/CG7WA5cRcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDQCFQCVnVM/kknc\nHlE1RM3IML8Zt/HzARcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDMCFA/a\nQ6ALaOp5t8LerqwLSYvfsq+QFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEw\nNAIVAJ1ndTuB5HCQrqdj++xMRUm825kzFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0V\nBAMKAQEwMwIUNL+7eh2cVoFH4Ri2FPe3btPvaN8XDTIzMDUxMzIxMDAwM1owDDAK\nBgNVHRUEAwoBATA0AhUAhdPJOBt3p+BNEZyeWtZ0n/P/q4cXDTIzMDUxMzIxMDAw\nM1owDDAKBgNVHRUEAwoBATA0AhUAk4h8pEEeepI70f7SgZspSfIBtbQXDTIzMDUx\nMzIxMDAwM1owDDAKBgNVHRUEAwoBATAzAhQkmNxig5MJlv2L8jo3rL4mo77UVxcN\nMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDQCFQCKZvGnSUiGZ2icw5A6xUxm\nK3EucxcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDQCFQCvwTYQvdNst5hd\nEGSBqIDToB/aBxcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDQCFQDv4Ess\nM9A2qslspnO/HppHtk1cuxcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDQC\nFQCD2ayNi7UJ0cbICa1xLoQwVZ7X8xcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQD\nCgEBMDMCFHkx/VC1Bxwbv8W3tt7YtFudi4UpFw0yMzA1MTMyMTAwMDNaMAwwCgYD\nVR0VBAMKAQEwMwIUH6IOKXC95dV/e43fgzlITh8dCCMXDTIzMDUxMzIxMDAwM1ow\nDDAKBgNVHRUEAwoBATAzAhQeh7LDsy2NI+QRzvNBl7la8Mit9RcNMjMwNTEzMjEw\nMDAzWjAMMAoGA1UdFQQDCgEBMDQCFQCa/S7pCkc1UKFn2ZaRFDfHUC0fCRcNMjMw\nNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDMCFESBsPEXKKE7aW0+qcdwoLFexY3a\nFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwNAIVAKeFn1eYLvDmfTe8jvLv\nWsg1/xqpFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwMwIUeuN3SKn5EvTG\nO6erB8WTzh0dEYEXDTIzMDUxMzIxMDAwM1owDDAKBgNVHRUEAwoBATAzAhQTiEsz\nJpk4wZWqFw/KddoXdTjfCxcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDMC\nFCw8xv6SedsVFtXOOfKomM2loXXhFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMK\nAQEwMwIUcXlIaHUJI0vpeeS33ObzG+9ktowXDTIzMDUxMzIxMDAwM1owDDAKBgNV\nHRUEAwoBATA0AhUAnXbvLDnBNuhli25zlrHXRFonYx8XDTIzMDUxMzIxMDAwM1ow\nDDAKBgNVHRUEAwoBATA0AhUAw+Al/KmV829ZtIRnk54+NOY2Gm8XDTIzMDUxMzIx\nMDAwM1owDDAKBgNVHRUEAwoBATA0AhUAjF9rMlfaBbF0KeLmG6ll1nMwYGoXDTIz\nMDUxMzIxMDAwM1owDDAKBgNVHRUEAwoBATA0AhUAoXxRci7B4MMnj+i98FIFnL7E\n5kgXDTIzMDUxMzIxMDAwM1owDDAKBgNVHRUEAwoBAaAvMC0wCgYDVR0UBAMCAQEw\nHwYDVR0jBBgwFoAUlW9dzb0b4elAScnU9DPOAVcL3lQwCgYIKoZIzj0EAwIDRwAw\nRAIgFCcExhc9muZCJybEgaDtgH1ZF5s739IHTjXl/JZTDR4CIG5WeLcFCg2nZozP\n5NqC0+MecmYxPN0eubPbpzhsF28z\n-----END X509 CRL-----\n\0".as_bytes().into(), - tcb_info_issuer_chain: "-----BEGIN CERTIFICATE-----\nMIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj\nftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n\0".as_bytes().into(), - tcb_info: "{\"tcbInfo\":{\"id\":\"SGX\",\"version\":3,\"issueDate\":\"2023-05-15T14:08:11Z\",\"nextUpdate\":\"2023-06-14T14:08:11Z\",\"fmspc\":\"00606a000000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":15,\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":11,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":11,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":255},{\"svn\":255},{\"svn\":1},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":13},\"tcbDate\":\"2023-02-15T00:00:00Z\",\"tcbStatus\":\"SWHardeningNeeded\",\"advisoryIDs\":[\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":11,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":11,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":255},{\"svn\":255},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":13},\"tcbDate\":\"2023-02-15T00:00:00Z\",\"tcbStatus\":\"ConfigurationAndSWHardeningNeeded\",\"advisoryIDs\":[\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":7,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":9,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":255},{\"svn\":255},{\"svn\":1},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":13},\"tcbDate\":\"2022-08-10T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00657\",\"INTEL-SA-00730\",\"INTEL-SA-00738\",\"INTEL-SA-00767\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":7,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":9,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":255},{\"svn\":255},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":13},\"tcbDate\":\"2022-08-10T00:00:00Z\",\"tcbStatus\":\"OutOfDateConfigurationNeeded\",\"advisoryIDs\":[\"INTEL-SA-00657\",\"INTEL-SA-00730\",\"INTEL-SA-00738\",\"INTEL-SA-00767\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":4,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":4,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":255},{\"svn\":255},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11},\"tcbDate\":\"2021-11-10T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00586\",\"INTEL-SA-00614\",\"INTEL-SA-00615\",\"INTEL-SA-00657\",\"INTEL-SA-00730\",\"INTEL-SA-00738\",\"INTEL-SA-00767\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":4,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":4,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":255},{\"svn\":255},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":10},\"tcbDate\":\"2020-11-11T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00477\",\"INTEL-SA-00586\",\"INTEL-SA-00614\",\"INTEL-SA-00615\",\"INTEL-SA-00657\",\"INTEL-SA-00730\",\"INTEL-SA-00738\",\"INTEL-SA-00767\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":4,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":4,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":255},{\"svn\":255},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":5},\"tcbDate\":\"2018-01-04T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00106\",\"INTEL-SA-00115\",\"INTEL-SA-00135\",\"INTEL-SA-00203\",\"INTEL-SA-00220\",\"INTEL-SA-00233\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00586\",\"INTEL-SA-00614\",\"INTEL-SA-00615\",\"INTEL-SA-00657\",\"INTEL-SA-00730\",\"INTEL-SA-00738\",\"INTEL-SA-00767\"]}]},\"signature\":\"5fee75684718bcb9191312cd3bf47096a4068f450d2ec9e05b8cd5a3a7cb61b292612a708c4c5a304836c82c3a7191447e3ba691e59287cc9c8943e821734d41\"}\0".as_bytes().into(), - qe_identity_issuer_chain: "-----BEGIN CERTIFICATE-----\nMIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj\nftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n\0".as_bytes().into(), - qe_identity: "{\"enclaveIdentity\":{\"id\":\"QE\",\"version\":2,\"issueDate\":\"2023-05-15T14:48:40Z\",\"nextUpdate\":\"2023-06-14T14:48:40Z\",\"tcbEvaluationDataNumber\":15,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"8C4F5775D796503E96137F77C68A829A0056AC8DED70140B081B094490C57BFF\",\"isvprodid\":1,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":8},\"tcbDate\":\"2023-02-15T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2021-11-10T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00615\"]},{\"tcb\":{\"isvsvn\":5},\"tcbDate\":\"2020-11-11T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00477\",\"INTEL-SA-00615\"]},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2019-11-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00334\",\"INTEL-SA-00477\",\"INTEL-SA-00615\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2019-05-15T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00219\",\"INTEL-SA-00293\",\"INTEL-SA-00334\",\"INTEL-SA-00477\",\"INTEL-SA-00615\"]},{\"tcb\":{\"isvsvn\":1},\"tcbDate\":\"2018-08-15T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00202\",\"INTEL-SA-00219\",\"INTEL-SA-00293\",\"INTEL-SA-00334\",\"INTEL-SA-00477\",\"INTEL-SA-00615\"]}]},\"signature\":\"97ff8957975b40aa51a17765d734363b8cb7557e6657b04f63b67c05f2886be1b7cc14b9c1b889e03b85866e277a102eb9fb85029b7008b41754cdba014a5a8c\"}\0".as_bytes().into(), - }; + major_version: 1, + minor_version: 0, + tee_type: 0, + pck_crl_issuer_chain: "-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n\0".as_bytes().into(), + root_ca_crl: "-----BEGIN X509 CRL-----\nMIIBITCByAIBATAKBggqhkjOPQQDAjBoMRowGAYDVQQDDBFJbnRlbCBTR1ggUm9v\ndCBDQTEaMBgGA1UECgwRSW50ZWwgQ29ycG9yYXRpb24xFDASBgNVBAcMC1NhbnRh\nIENsYXJhMQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMXDTIzMDQwMzEwMjI1MVoX\nDTI0MDQwMjEwMjI1MVqgLzAtMAoGA1UdFAQDAgEBMB8GA1UdIwQYMBaAFCJlDNZa\nnTSJ84O0lVK/UBs5JwasMAoGCCqGSM49BAMCA0gAMEUCIFFXfUfZ+6FXtl8etfRl\ne7xeVsyvc1oD8blj1wSAWrEYAiEAk5AV7BY25+r6X0JsHkAmR8ZzEytoUMq9aM72\nutdoKgM=\n-----END X509 CRL-----\n\0".as_bytes().into(), + pck_crl: "-----BEGIN X509 CRL-----\nMIIKYTCCCggCAQEwCgYIKoZIzj0EAwIwcDEiMCAGA1UEAwwZSW50ZWwgU0dYIFBD\nSyBQbGF0Zm9ybSBDQTEaMBgGA1UECgwRSW50ZWwgQ29ycG9yYXRpb24xFDASBgNV\nBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMXDTIzMDUx\nMzIxMDAwM1oXDTIzMDYxMjIxMDAwM1owggk0MDMCFG/DTlAj5yiSNDXWGqS4PGGB\nZq01Fw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwNAIVAO+ubpcV/KE7h+Mz\n6CYe1tmQqSatFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwNAIVAP1ghkhi\nnLpzB4tNSS9LPqdBrQjNFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwNAIV\nAIr5JBhOHVr93XPD1joS9ei1c35WFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMK\nAQEwNAIVALEleXjPqczdB1mr+MXKcvrjp4qbFw0yMzA1MTMyMTAwMDNaMAwwCgYD\nVR0VBAMKAQEwMwIUdP6mFKlyvg4oQ/IFmDWBHthy+bMXDTIzMDUxMzIxMDAwM1ow\nDDAKBgNVHRUEAwoBATA0AhUA+cTvVrOrSNV34Qi67fS/iAFCFLkXDTIzMDUxMzIx\nMDAwM1owDDAKBgNVHRUEAwoBATAzAhQHHeB3j55fxPKHjzDWsHyaMOazCxcNMjMw\nNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDQCFQDN4kJPlyzqlP8jmTf02AwlAp3W\nCxcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDMCFGwzGeUQm2RQfTzxEyzg\nA0nvUnMZFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwNAIVAN8I11a2anSX\n9DtbtYraBNP096k3Fw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwMwIUKK9I\nW2z2fkCaOdXLWu5FmPeo+nsXDTIzMDUxMzIxMDAwM1owDDAKBgNVHRUEAwoBATA0\nAhUA+4strsCSytqKqbxP8vHCDQNGZowXDTIzMDUxMzIxMDAwM1owDDAKBgNVHRUE\nAwoBATA0AhUAzUhQrFK9zGmmpvBYyLxXu9C1+GQXDTIzMDUxMzIxMDAwM1owDDAK\nBgNVHRUEAwoBATA0AhUAmU3TZm9SdfuAX5XdAr1QyyZ52K0XDTIzMDUxMzIxMDAw\nM1owDDAKBgNVHRUEAwoBATAzAhQHAhNpACUidNkDXu31RXRi+tDvTBcNMjMwNTEz\nMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDMCFGHyv3Pjm04EqifYAb1z0kMZtb+AFw0y\nMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwMwIUOZK+hRuWkC7/OJWebC7/GwZR\npLUXDTIzMDUxMzIxMDAwM1owDDAKBgNVHRUEAwoBATAzAhRjnxOaUED9z/GR6KT7\nG/CG7WA5cRcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDQCFQCVnVM/kknc\nHlE1RM3IML8Zt/HzARcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDMCFA/a\nQ6ALaOp5t8LerqwLSYvfsq+QFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEw\nNAIVAJ1ndTuB5HCQrqdj++xMRUm825kzFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0V\nBAMKAQEwMwIUNL+7eh2cVoFH4Ri2FPe3btPvaN8XDTIzMDUxMzIxMDAwM1owDDAK\nBgNVHRUEAwoBATA0AhUAhdPJOBt3p+BNEZyeWtZ0n/P/q4cXDTIzMDUxMzIxMDAw\nM1owDDAKBgNVHRUEAwoBATA0AhUAk4h8pEEeepI70f7SgZspSfIBtbQXDTIzMDUx\nMzIxMDAwM1owDDAKBgNVHRUEAwoBATAzAhQkmNxig5MJlv2L8jo3rL4mo77UVxcN\nMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDQCFQCKZvGnSUiGZ2icw5A6xUxm\nK3EucxcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDQCFQCvwTYQvdNst5hd\nEGSBqIDToB/aBxcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDQCFQDv4Ess\nM9A2qslspnO/HppHtk1cuxcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDQC\nFQCD2ayNi7UJ0cbICa1xLoQwVZ7X8xcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQD\nCgEBMDMCFHkx/VC1Bxwbv8W3tt7YtFudi4UpFw0yMzA1MTMyMTAwMDNaMAwwCgYD\nVR0VBAMKAQEwMwIUH6IOKXC95dV/e43fgzlITh8dCCMXDTIzMDUxMzIxMDAwM1ow\nDDAKBgNVHRUEAwoBATAzAhQeh7LDsy2NI+QRzvNBl7la8Mit9RcNMjMwNTEzMjEw\nMDAzWjAMMAoGA1UdFQQDCgEBMDQCFQCa/S7pCkc1UKFn2ZaRFDfHUC0fCRcNMjMw\nNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDMCFESBsPEXKKE7aW0+qcdwoLFexY3a\nFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwNAIVAKeFn1eYLvDmfTe8jvLv\nWsg1/xqpFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMKAQEwMwIUeuN3SKn5EvTG\nO6erB8WTzh0dEYEXDTIzMDUxMzIxMDAwM1owDDAKBgNVHRUEAwoBATAzAhQTiEsz\nJpk4wZWqFw/KddoXdTjfCxcNMjMwNTEzMjEwMDAzWjAMMAoGA1UdFQQDCgEBMDMC\nFCw8xv6SedsVFtXOOfKomM2loXXhFw0yMzA1MTMyMTAwMDNaMAwwCgYDVR0VBAMK\nAQEwMwIUcXlIaHUJI0vpeeS33ObzG+9ktowXDTIzMDUxMzIxMDAwM1owDDAKBgNV\nHRUEAwoBATA0AhUAnXbvLDnBNuhli25zlrHXRFonYx8XDTIzMDUxMzIxMDAwM1ow\nDDAKBgNVHRUEAwoBATA0AhUAw+Al/KmV829ZtIRnk54+NOY2Gm8XDTIzMDUxMzIx\nMDAwM1owDDAKBgNVHRUEAwoBATA0AhUAjF9rMlfaBbF0KeLmG6ll1nMwYGoXDTIz\nMDUxMzIxMDAwM1owDDAKBgNVHRUEAwoBATA0AhUAoXxRci7B4MMnj+i98FIFnL7E\n5kgXDTIzMDUxMzIxMDAwM1owDDAKBgNVHRUEAwoBAaAvMC0wCgYDVR0UBAMCAQEw\nHwYDVR0jBBgwFoAUlW9dzb0b4elAScnU9DPOAVcL3lQwCgYIKoZIzj0EAwIDRwAw\nRAIgFCcExhc9muZCJybEgaDtgH1ZF5s739IHTjXl/JZTDR4CIG5WeLcFCg2nZozP\n5NqC0+MecmYxPN0eubPbpzhsF28z\n-----END X509 CRL-----\n\0".as_bytes().into(), + tcb_info_issuer_chain: "-----BEGIN CERTIFICATE-----\nMIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj\nftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n\0".as_bytes().into(), + tcb_info: "{\"tcbInfo\":{\"id\":\"SGX\",\"version\":3,\"issueDate\":\"2023-05-15T14:08:11Z\",\"nextUpdate\":\"2023-06-14T14:08:11Z\",\"fmspc\":\"00606a000000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":15,\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":11,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":11,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":255},{\"svn\":255},{\"svn\":1},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":13},\"tcbDate\":\"2023-02-15T00:00:00Z\",\"tcbStatus\":\"SWHardeningNeeded\",\"advisoryIDs\":[\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":11,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":11,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":255},{\"svn\":255},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":13},\"tcbDate\":\"2023-02-15T00:00:00Z\",\"tcbStatus\":\"ConfigurationAndSWHardeningNeeded\",\"advisoryIDs\":[\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":7,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":9,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":255},{\"svn\":255},{\"svn\":1},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":13},\"tcbDate\":\"2022-08-10T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00657\",\"INTEL-SA-00730\",\"INTEL-SA-00738\",\"INTEL-SA-00767\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":7,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":9,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":255},{\"svn\":255},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":13},\"tcbDate\":\"2022-08-10T00:00:00Z\",\"tcbStatus\":\"OutOfDateConfigurationNeeded\",\"advisoryIDs\":[\"INTEL-SA-00657\",\"INTEL-SA-00730\",\"INTEL-SA-00738\",\"INTEL-SA-00767\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":4,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":4,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":255},{\"svn\":255},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11},\"tcbDate\":\"2021-11-10T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00586\",\"INTEL-SA-00614\",\"INTEL-SA-00615\",\"INTEL-SA-00657\",\"INTEL-SA-00730\",\"INTEL-SA-00738\",\"INTEL-SA-00767\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":4,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":4,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":255},{\"svn\":255},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":10},\"tcbDate\":\"2020-11-11T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00477\",\"INTEL-SA-00586\",\"INTEL-SA-00614\",\"INTEL-SA-00615\",\"INTEL-SA-00657\",\"INTEL-SA-00730\",\"INTEL-SA-00738\",\"INTEL-SA-00767\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":4,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":4,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":255},{\"svn\":255},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":5},\"tcbDate\":\"2018-01-04T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00106\",\"INTEL-SA-00115\",\"INTEL-SA-00135\",\"INTEL-SA-00203\",\"INTEL-SA-00220\",\"INTEL-SA-00233\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00586\",\"INTEL-SA-00614\",\"INTEL-SA-00615\",\"INTEL-SA-00657\",\"INTEL-SA-00730\",\"INTEL-SA-00738\",\"INTEL-SA-00767\"]}]},\"signature\":\"5fee75684718bcb9191312cd3bf47096a4068f450d2ec9e05b8cd5a3a7cb61b292612a708c4c5a304836c82c3a7191447e3ba691e59287cc9c8943e821734d41\"}\0".as_bytes().into(), + qe_identity_issuer_chain: "-----BEGIN CERTIFICATE-----\nMIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj\nftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n\0".as_bytes().into(), + qe_identity: "{\"enclaveIdentity\":{\"id\":\"QE\",\"version\":2,\"issueDate\":\"2023-05-15T14:48:40Z\",\"nextUpdate\":\"2023-06-14T14:48:40Z\",\"tcbEvaluationDataNumber\":15,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"8C4F5775D796503E96137F77C68A829A0056AC8DED70140B081B094490C57BFF\",\"isvprodid\":1,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":8},\"tcbDate\":\"2023-02-15T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2021-11-10T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00615\"]},{\"tcb\":{\"isvsvn\":5},\"tcbDate\":\"2020-11-11T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00477\",\"INTEL-SA-00615\"]},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2019-11-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00334\",\"INTEL-SA-00477\",\"INTEL-SA-00615\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2019-05-15T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00219\",\"INTEL-SA-00293\",\"INTEL-SA-00334\",\"INTEL-SA-00477\",\"INTEL-SA-00615\"]},{\"tcb\":{\"isvsvn\":1},\"tcbDate\":\"2018-08-15T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00202\",\"INTEL-SA-00219\",\"INTEL-SA-00293\",\"INTEL-SA-00334\",\"INTEL-SA-00477\",\"INTEL-SA-00615\"]}]},\"signature\":\"97ff8957975b40aa51a17765d734363b8cb7557e6657b04f63b67c05f2886be1b7cc14b9c1b889e03b85866e277a102eb9fb85029b7008b41754cdba014a5a8c\"}\0".as_bytes().into(), + }; let current_time = 1684165303; @@ -2586,7 +2591,7 @@ mod sgx { check_quote( "e, - &collateral, + Some(&collateral), current_time, &mrsigner, &report_data, @@ -3669,7 +3674,7 @@ mod sgx { check_quote( "e, - &collateral, + Some(&collateral), current_time, &mrsigner, &report_data, @@ -3677,4 +3682,1133 @@ mod sgx { ) .unwrap(); } + + #[tokio::test] + #[traced_test] + async fn tdx_1() -> Result<()> { + let quote = [ + 4, 0, 2, 0, 129, 0, 0, 0, 0, 0, 0, 0, 147, 154, 114, 51, 247, 156, 76, 169, 148, 10, + 13, 179, 149, 127, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 112, 245, 193, 194, 193, 97, 11, 242, + 221, 173, 52, 138, 136, 235, 246, 165, 80, 37, 110, 148, 158, 82, 18, 44, 116, 61, 201, + 124, 222, 80, 204, 175, 173, 47, 197, 146, 125, 21, 15, 48, 127, 186, 59, 140, 162, 24, + 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 16, 0, 0, 0, 0, 231, 0, 6, 0, 0, 0, 0, 0, 93, 86, 8, 14, 185, 239, 140, 224, + 187, 175, 107, 220, 218, 222, 235, 6, 231, 197, 176, 164, 209, 236, 22, 190, 134, 138, + 133, 169, 83, 186, 190, 12, 94, 84, 208, 28, 142, 5, 10, 84, 254, 28, 160, 120, 55, 37, + 48, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 66, 22, 233, 37, 247, 150, 244, 226, 130, 207, 166, 231, 45, 76, 119, 168, 5, 96, + 152, 122, 250, 41, 21, 90, 97, 253, 195, 58, 219, 128, 234, 176, 212, 17, 42, 189, 82, + 56, 126, 94, 37, 166, 13, 238, 251, 138, 82, 135, 117, 24, 106, 53, 86, 81, 215, 130, + 41, 226, 43, 72, 182, 103, 79, 0, 108, 212, 45, 139, 179, 112, 234, 46, 145, 248, 100, + 217, 148, 78, 7, 193, 13, 107, 37, 15, 181, 32, 72, 204, 252, 93, 110, 234, 107, 135, + 143, 164, 209, 17, 30, 60, 72, 25, 158, 84, 78, 146, 66, 178, 218, 227, 55, 134, 247, + 30, 251, 51, 88, 64, 181, 222, 201, 202, 60, 114, 188, 65, 7, 6, 17, 253, 30, 60, 185, + 130, 97, 201, 148, 120, 72, 216, 131, 106, 163, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 16, 0, 0, 173, 106, 32, 109, 219, 200, 128, + 152, 193, 7, 155, 122, 125, 105, 155, 215, 213, 138, 170, 109, 16, 164, 39, 124, 85, + 23, 81, 166, 93, 155, 21, 180, 75, 204, 181, 76, 63, 176, 74, 232, 187, 105, 12, 6, + 252, 251, 184, 232, 245, 64, 217, 15, 193, 251, 48, 39, 120, 210, 6, 165, 79, 192, 101, + 165, 146, 8, 244, 170, 53, 52, 105, 26, 27, 111, 7, 237, 192, 22, 93, 124, 74, 31, 173, + 205, 119, 80, 167, 54, 215, 90, 6, 0, 234, 108, 253, 234, 29, 165, 67, 157, 15, 111, + 174, 243, 248, 207, 172, 69, 217, 220, 251, 85, 85, 184, 153, 126, 192, 253, 143, 167, + 105, 23, 73, 81, 110, 247, 117, 96, 6, 0, 69, 16, 0, 0, 7, 7, 255, 27, 3, 255, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 229, + 163, 167, 181, 216, 48, 194, 149, 59, 152, 83, 76, 108, 89, 163, 163, 79, 220, 52, 233, + 51, 247, 245, 137, 143, 10, 133, 207, 8, 132, 107, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 158, 42, 124, + 111, 148, 143, 23, 71, 78, 52, 167, 252, 67, 237, 3, 15, 124, 21, 99, 241, 186, 189, + 223, 99, 64, 200, 46, 14, 84, 168, 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, + 251, 252, 166, 90, 191, 174, 148, 208, 101, 246, 199, 76, 45, 11, 45, 3, 58, 105, 166, + 8, 54, 250, 244, 81, 54, 176, 166, 141, 248, 70, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 2, 162, 97, 38, 185, + 42, 4, 183, 177, 168, 67, 207, 162, 237, 225, 183, 89, 224, 19, 4, 86, 108, 202, 197, + 108, 151, 18, 255, 142, 246, 86, 143, 11, 27, 240, 45, 133, 132, 182, 25, 177, 123, + 186, 98, 132, 113, 180, 86, 63, 3, 10, 8, 152, 75, 152, 211, 9, 149, 235, 147, 51, 209, + 203, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 0, 93, 14, 0, 0, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, + 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 56, + 68, 67, 67, 66, 74, 97, 103, 65, 119, 73, 66, 65, 103, 73, 85, 89, 71, 99, 82, 76, 89, + 53, 43, 114, 99, 119, 67, 65, 88, 84, 72, 48, 71, 109, 83, 71, 98, 119, 115, 104, 113, + 119, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 99, + 68, 69, 105, 77, 67, 65, 71, 65, 49, 85, 69, 65, 119, 119, 90, 83, 87, 53, 48, 90, 87, + 119, 103, 85, 48, 100, 89, 73, 70, 66, 68, 83, 121, 66, 81, 98, 71, 70, 48, 90, 109, + 57, 121, 98, 83, 66, 68, 81, 84, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 67, 103, 119, + 82, 10, 83, 87, 53, 48, 90, 87, 119, 103, 81, 50, 57, 121, 99, 71, 57, 121, 89, 88, 82, + 112, 98, 50, 52, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 99, 77, 67, 49, 78, 104, + 98, 110, 82, 104, 73, 69, 78, 115, 89, 88, 74, 104, 77, 81, 115, 119, 67, 81, 89, 68, + 86, 81, 81, 73, 10, 68, 65, 74, 68, 81, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, + 66, 104, 77, 67, 86, 86, 77, 119, 72, 104, 99, 78, 77, 106, 81, 120, 77, 106, 65, 49, + 77, 68, 65, 120, 79, 68, 85, 122, 87, 104, 99, 78, 77, 122, 69, 120, 77, 106, 65, 49, + 77, 68, 65, 120, 79, 68, 85, 122, 10, 87, 106, 66, 119, 77, 83, 73, 119, 73, 65, 89, + 68, 86, 81, 81, 68, 68, 66, 108, 74, 98, 110, 82, 108, 98, 67, 66, 84, 82, 49, 103, + 103, 85, 69, 78, 76, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, + 108, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 10, 68, 66, 70, 74, 98, 110, 82, + 108, 98, 67, 66, 68, 98, 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, + 85, 77, 66, 73, 71, 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, + 103, 81, 50, 120, 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 10, 66, 65, + 103, 77, 65, 107, 78, 66, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, + 74, 86, 85, 122, 66, 90, 77, 66, 77, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, + 71, 67, 67, 113, 71, 83, 77, 52, 57, 65, 119, 69, 72, 65, 48, 73, 65, 66, 79, 122, 117, + 10, 122, 56, 66, 78, 78, 88, 71, 102, 48, 48, 85, 66, 100, 53, 52, 90, 97, 120, 85, + 113, 79, 110, 79, 81, 103, 53, 81, 109, 51, 54, 115, 105, 49, 74, 111, 112, 97, 110, + 88, 114, 80, 112, 117, 78, 86, 102, 73, 98, 50, 77, 114, 54, 104, 75, 68, 106, 107, 75, + 107, 100, 114, 82, 81, 103, 10, 55, 101, 117, 57, 84, 73, 76, 86, 57, 53, 82, 43, 55, + 80, 118, 90, 102, 120, 101, 106, 103, 103, 77, 77, 77, 73, 73, 68, 67, 68, 65, 102, 66, + 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 83, 86, 98, 49, 51, 78, 118, 82, + 118, 104, 54, 85, 66, 74, 121, 100, 84, 48, 10, 77, 56, 52, 66, 86, 119, 118, 101, 86, + 68, 66, 114, 66, 103, 78, 86, 72, 82, 56, 69, 90, 68, 66, 105, 77, 71, 67, 103, 88, + 113, 66, 99, 104, 108, 112, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 70, 119, + 97, 83, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 10, 100, 109, 108, + 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, 87, 119, 117, 89, 50, 57, 116, 76, 51, 78, + 110, 101, 67, 57, 106, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, + 117, 76, 51, 89, 48, 76, 51, 66, 106, 97, 50, 78, 121, 98, 68, 57, 106, 89, 84, 49, + 119, 10, 98, 71, 70, 48, 90, 109, 57, 121, 98, 83, 90, 108, 98, 109, 78, 118, 90, 71, + 108, 117, 90, 122, 49, 107, 90, 88, 73, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, + 89, 69, 70, 74, 97, 84, 121, 67, 67, 48, 49, 71, 76, 117, 52, 105, 65, 104, 100, 119, + 98, 111, 115, 84, 105, 112, 10, 75, 119, 90, 87, 77, 65, 52, 71, 65, 49, 85, 100, 68, + 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 71, 119, 68, 65, 77, 66, 103, 78, 86, 72, + 82, 77, 66, 65, 102, 56, 69, 65, 106, 65, 65, 77, 73, 73, 67, 79, 81, 89, 74, 75, 111, + 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 10, 66, 73, 73, 67, 75, 106, 67, 67, 65, + 105, 89, 119, 72, 103, 89, 75, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 65, + 81, 81, 81, 78, 107, 122, 43, 57, 54, 111, 121, 99, 107, 71, 79, 47, 106, 70, 47, 56, + 72, 90, 56, 101, 84, 67, 67, 65, 87, 77, 71, 67, 105, 113, 71, 10, 83, 73, 98, 52, 84, + 81, 69, 78, 65, 81, 73, 119, 103, 103, 70, 84, 77, 66, 65, 71, 67, 121, 113, 71, 83, + 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 66, 65, 103, 69, 72, 77, 66, 65, 71, 67, 121, + 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 67, 65, 103, 69, 72, 10, 77, 66, + 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 68, 65, 103, 69, + 67, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 69, + 65, 103, 69, 67, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 10, + 65, 81, 73, 70, 65, 103, 69, 68, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, + 81, 69, 78, 65, 81, 73, 71, 65, 103, 69, 66, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, + 98, 52, 84, 81, 69, 78, 65, 81, 73, 72, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, + 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 73, 65, 103, 69, 68, 77, 66, 65, + 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 74, 65, 103, 69, 65, + 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 75, 65, + 103, 69, 65, 10, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, + 81, 73, 76, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, + 69, 78, 65, 81, 73, 77, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, + 52, 84, 81, 69, 78, 10, 65, 81, 73, 78, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, + 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 79, 65, 103, 69, 65, 77, 66, 65, 71, + 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 80, 65, 103, 69, 65, 77, + 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 81, 65, + 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, + 73, 82, 65, 103, 69, 76, 77, 66, 56, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, + 78, 65, 81, 73, 83, 66, 66, 65, 72, 10, 66, 119, 73, 67, 65, 119, 69, 65, 65, 119, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 77, 66, 65, 71, 67, 105, 113, 71, 83, 73, 98, 52, + 84, 81, 69, 78, 65, 81, 77, 69, 65, 103, 65, 65, 77, 66, 81, 71, 67, 105, 113, 71, 83, + 73, 98, 52, 84, 81, 69, 78, 65, 81, 81, 69, 10, 66, 103, 67, 65, 98, 119, 85, 65, 65, + 68, 65, 80, 66, 103, 111, 113, 104, 107, 105, 71, 43, 69, 48, 66, 68, 81, 69, 70, 67, + 103, 69, 66, 77, 66, 52, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, + 89, 69, 69, 73, 89, 81, 78, 89, 69, 43, 108, 116, 89, 109, 10, 76, 85, 69, 101, 65, 74, + 83, 109, 67, 116, 65, 119, 82, 65, 89, 75, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, + 48, 66, 66, 122, 65, 50, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, + 78, 65, 81, 99, 66, 65, 81, 72, 47, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, + 52, 84, 81, 69, 78, 65, 81, 99, 67, 65, 81, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, + 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 68, 65, 81, 72, 47, 77, 65, 111, 71, 67, + 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 65, 48, 103, 65, 77, 69, 85, 67, 10, 73, + 65, 74, 88, 103, 116, 73, 109, 88, 71, 51, 97, 104, 113, 81, 82, 122, 48, 90, 66, 43, + 66, 83, 107, 97, 70, 43, 88, 87, 110, 110, 119, 90, 49, 88, 102, 110, 106, 67, 79, 102, + 54, 115, 87, 65, 105, 69, 65, 115, 76, 57, 52, 110, 57, 53, 55, 86, 89, 65, 47, 118, + 109, 77, 119, 10, 103, 65, 56, 104, 78, 115, 112, 97, 66, 71, 80, 106, 99, 105, 50, 43, + 107, 104, 98, 120, 80, 112, 100, 43, 86, 100, 89, 61, 10, 45, 45, 45, 45, 45, 69, 78, + 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, + 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, + 45, 45, 10, 77, 73, 73, 67, 108, 106, 67, 67, 65, 106, 50, 103, 65, 119, 73, 66, 65, + 103, 73, 86, 65, 74, 86, 118, 88, 99, 50, 57, 71, 43, 72, 112, 81, 69, 110, 74, 49, 80, + 81, 122, 122, 103, 70, 88, 67, 57, 53, 85, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, + 52, 57, 66, 65, 77, 67, 10, 77, 71, 103, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, + 77, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, 67, 66, 83, 98, 50, 57, + 48, 73, 69, 78, 66, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 68, 66, 70, 74, + 98, 110, 82, 108, 98, 67, 66, 68, 10, 98, 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, + 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, + 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, + 78, 86, 66, 65, 103, 77, 65, 107, 78, 66, 77, 81, 115, 119, 10, 67, 81, 89, 68, 86, 81, + 81, 71, 69, 119, 74, 86, 85, 122, 65, 101, 70, 119, 48, 120, 79, 68, 65, 49, 77, 106, + 69, 120, 77, 68, 85, 119, 77, 84, 66, 97, 70, 119, 48, 122, 77, 122, 65, 49, 77, 106, + 69, 120, 77, 68, 85, 119, 77, 84, 66, 97, 77, 72, 65, 120, 73, 106, 65, 103, 10, 66, + 103, 78, 86, 66, 65, 77, 77, 71, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, + 67, 66, 81, 81, 48, 115, 103, 85, 71, 120, 104, 100, 71, 90, 118, 99, 109, 48, 103, 81, + 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, + 71, 86, 115, 10, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, + 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, + 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, + 119, 67, 81, 48, 69, 120, 10, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, + 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, + 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 78, 83, + 66, 47, 55, 116, 50, 49, 108, 88, 83, 79, 10, 50, 67, 117, 122, 112, 120, 119, 55, 52, + 101, 74, 66, 55, 50, 69, 121, 68, 71, 103, 87, 53, 114, 88, 67, 116, 120, 50, 116, 86, + 84, 76, 113, 54, 104, 75, 107, 54, 122, 43, 85, 105, 82, 90, 67, 110, 113, 82, 55, 112, + 115, 79, 118, 103, 113, 70, 101, 83, 120, 108, 109, 84, 108, 74, 108, 10, 101, 84, 109, + 105, 50, 87, 89, 122, 51, 113, 79, 66, 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, + 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, + 105, 102, 79, 68, 116, 74, 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, + 10, 66, 103, 78, 86, 72, 82, 56, 69, 83, 122, 66, 74, 77, 69, 101, 103, 82, 97, 66, 68, + 104, 107, 70, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, + 112, 90, 109, 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, + 86, 107, 99, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, + 87, 119, 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, + 109, 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, + 81, 52, 69, 70, 103, 81, 85, 108, 87, 57, 100, 10, 122, 98, 48, 98, 52, 101, 108, 65, + 83, 99, 110, 85, 57, 68, 80, 79, 65, 86, 99, 76, 51, 108, 81, 119, 68, 103, 89, 68, 86, + 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, + 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 10, 65, 102, 56, 67, 65, 81, + 65, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 82, 119, + 65, 119, 82, 65, 73, 103, 88, 115, 86, 107, 105, 48, 119, 43, 105, 54, 86, 89, 71, 87, + 51, 85, 70, 47, 50, 50, 117, 97, 88, 101, 48, 89, 74, 68, 106, 49, 85, 101, 10, 110, + 65, 43, 84, 106, 68, 49, 97, 105, 53, 99, 67, 73, 67, 89, 98, 49, 83, 65, 109, 68, 53, + 120, 107, 102, 84, 86, 112, 118, 111, 52, 85, 111, 121, 105, 83, 89, 120, 114, 68, 87, + 76, 109, 85, 82, 52, 67, 73, 57, 78, 75, 121, 102, 80, 78, 43, 10, 45, 45, 45, 45, 45, + 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, + 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, + 45, 45, 45, 45, 10, 77, 73, 73, 67, 106, 122, 67, 67, 65, 106, 83, 103, 65, 119, 73, + 66, 65, 103, 73, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, + 86, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 67, 103, 89, 73, 75, 111, + 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 97, 68, 69, 97, 77, 66, 103, 71, 65, + 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, + 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, + 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 10, 99, 110, 66, 118, + 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, + 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, + 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 10, 66, + 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 66, 52, 88, 68, 84, 69, 52, 77, 68, + 85, 121, 77, 84, 69, 119, 78, 68, 85, 120, 77, 70, 111, 88, 68, 84, 81, 53, 77, 84, 73, + 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, 119, 97, 68, 69, 97, 77, 66, 103, + 71, 10, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, + 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, + 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 99, 110, + 66, 118, 99, 109, 70, 48, 10, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, + 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, + 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, + 74, 66, 103, 78, 86, 66, 65, 89, 84, 10, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, + 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, + 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 67, 54, 110, 69, 119, 77, 68, 73, 89, 90, 79, + 106, 47, 105, 80, 87, 115, 67, 122, 97, 69, 75, 105, 55, 10, 49, 79, 105, 79, 83, 76, + 82, 70, 104, 87, 71, 106, 98, 110, 66, 86, 74, 102, 86, 110, 107, 89, 52, 117, 51, 73, + 106, 107, 68, 89, 89, 76, 48, 77, 120, 79, 52, 109, 113, 115, 121, 89, 106, 108, 66, + 97, 108, 84, 86, 89, 120, 70, 80, 50, 115, 74, 66, 75, 53, 122, 108, 75, 79, 66, 10, + 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, + 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, 83, + 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 66, 103, 78, 86, 72, 82, 56, 69, 83, + 122, 66, 74, 10, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, 72, 82, 119, + 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, + 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 100, 109, + 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 10, 90, 87, 119, 117, 89, 50, 57, 116, 76, + 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, 118, 100, 69, 78, 66, 76, + 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 73, + 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 10, 85, 114, 57, 81, + 71, 122, 107, 110, 66, 113, 119, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, + 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, + 119, 81, 73, 77, 65, 89, 66, 65, 102, 56, 67, 65, 81, 69, 119, 67, 103, 89, 73, 10, 75, + 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 83, 81, 65, 119, 82, 103, 73, 104, 65, + 79, 87, 47, 53, 81, 107, 82, 43, 83, 57, 67, 105, 83, 68, 99, 78, 111, 111, 119, 76, + 117, 80, 82, 76, 115, 87, 71, 102, 47, 89, 105, 55, 71, 83, 88, 57, 52, 66, 103, 119, + 84, 119, 103, 10, 65, 105, 69, 65, 52, 74, 48, 108, 114, 72, 111, 77, 115, 43, 88, 111, + 53, 111, 47, 115, 88, 54, 79, 57, 81, 87, 120, 72, 82, 65, 118, 90, 85, 71, 79, 100, + 82, 81, 55, 99, 118, 113, 82, 88, 97, 113, 73, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, + 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + + let current_time = 1733406935; + + let collateral = Collateral { + major_version: 3, + minor_version: 0, + tee_type: 129, + pck_crl_issuer_chain: [ + 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, + 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 108, 106, 67, 67, 65, 106, 50, 103, 65, + 119, 73, 66, 65, 103, 73, 86, 65, 74, 86, 118, 88, 99, 50, 57, 71, 43, 72, 112, 81, + 69, 110, 74, 49, 80, 81, 122, 122, 103, 70, 88, 67, 57, 53, 85, 77, 65, 111, 71, + 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 10, 77, 71, 103, 120, 71, 106, 65, + 89, 66, 103, 78, 86, 66, 65, 77, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 70, + 78, 72, 87, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 82, 111, 119, 71, 65, + 89, 68, 86, 81, 81, 75, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 10, 98, + 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, + 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, + 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 103, 77, 65, 107, + 78, 66, 77, 81, 115, 119, 10, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, + 122, 65, 101, 70, 119, 48, 120, 79, 68, 65, 49, 77, 106, 69, 120, 77, 68, 85, 119, + 77, 84, 66, 97, 70, 119, 48, 122, 77, 122, 65, 49, 77, 106, 69, 120, 77, 68, 85, + 119, 77, 84, 66, 97, 77, 72, 65, 120, 73, 106, 65, 103, 10, 66, 103, 78, 86, 66, + 65, 77, 77, 71, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, 67, 66, 81, 81, + 48, 115, 103, 85, 71, 120, 104, 100, 71, 90, 118, 99, 109, 48, 103, 81, 48, 69, + 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, + 86, 115, 10, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, + 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, + 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, + 67, 65, 119, 67, 81, 48, 69, 120, 10, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, + 84, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, + 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, + 65, 69, 78, 83, 66, 47, 55, 116, 50, 49, 108, 88, 83, 79, 10, 50, 67, 117, 122, + 112, 120, 119, 55, 52, 101, 74, 66, 55, 50, 69, 121, 68, 71, 103, 87, 53, 114, 88, + 67, 116, 120, 50, 116, 86, 84, 76, 113, 54, 104, 75, 107, 54, 122, 43, 85, 105, 82, + 90, 67, 110, 113, 82, 55, 112, 115, 79, 118, 103, 113, 70, 101, 83, 120, 108, 109, + 84, 108, 74, 108, 10, 101, 84, 109, 105, 50, 87, 89, 122, 51, 113, 79, 66, 117, + 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, + 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, + 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 10, 66, 103, 78, 86, 72, 82, + 56, 69, 83, 122, 66, 74, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, + 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, + 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, + 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, 87, 119, 117, + 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, + 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, + 52, 69, 70, 103, 81, 85, 108, 87, 57, 100, 10, 122, 98, 48, 98, 52, 101, 108, 65, + 83, 99, 110, 85, 57, 68, 80, 79, 65, 86, 99, 76, 51, 108, 81, 119, 68, 103, 89, 68, + 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, + 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 10, 65, 102, 56, + 67, 65, 81, 65, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, + 73, 68, 82, 119, 65, 119, 82, 65, 73, 103, 88, 115, 86, 107, 105, 48, 119, 43, 105, + 54, 86, 89, 71, 87, 51, 85, 70, 47, 50, 50, 117, 97, 88, 101, 48, 89, 74, 68, 106, + 49, 85, 101, 10, 110, 65, 43, 84, 106, 68, 49, 97, 105, 53, 99, 67, 73, 67, 89, 98, + 49, 83, 65, 109, 68, 53, 120, 107, 102, 84, 86, 112, 118, 111, 52, 85, 111, 121, + 105, 83, 89, 120, 114, 68, 87, 76, 109, 85, 82, 52, 67, 73, 57, 78, 75, 121, 102, + 80, 78, 43, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, + 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, + 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, + 106, 122, 67, 67, 65, 106, 83, 103, 65, 119, 73, 66, 65, 103, 73, 85, 73, 109, 85, + 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 85, 114, 57, 81, 71, 122, + 107, 110, 66, 113, 119, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, + 65, 119, 73, 119, 10, 97, 68, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 65, 119, + 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, + 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, + 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 10, 99, 110, 66, 118, 99, 109, + 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, + 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, + 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 10, 66, + 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 66, 52, 88, 68, 84, 69, 52, 77, + 68, 85, 121, 77, 84, 69, 119, 78, 68, 85, 120, 77, 70, 111, 88, 68, 84, 81, 53, 77, + 84, 73, 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, 119, 97, 68, 69, 97, + 77, 66, 103, 71, 10, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, + 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, + 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, + 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 10, 97, 87, 57, 117, 77, 82, 81, + 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, + 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, + 67, 81, 48, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 10, 65, 108, + 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, + 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 67, + 54, 110, 69, 119, 77, 68, 73, 89, 90, 79, 106, 47, 105, 80, 87, 115, 67, 122, 97, + 69, 75, 105, 55, 10, 49, 79, 105, 79, 83, 76, 82, 70, 104, 87, 71, 106, 98, 110, + 66, 86, 74, 102, 86, 110, 107, 89, 52, 117, 51, 73, 106, 107, 68, 89, 89, 76, 48, + 77, 120, 79, 52, 109, 113, 115, 121, 89, 106, 108, 66, 97, 108, 84, 86, 89, 120, + 70, 80, 50, 115, 74, 66, 75, 53, 122, 108, 75, 79, 66, 10, 117, 122, 67, 66, 117, + 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 81, 105, 90, + 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, 83, 118, 49, 65, 98, + 79, 83, 99, 71, 114, 68, 66, 83, 66, 103, 78, 86, 72, 82, 56, 69, 83, 122, 66, 74, + 10, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, 72, 82, 119, 99, 122, + 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, + 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 100, 109, + 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 10, 90, 87, 119, 117, 89, 50, 57, 116, + 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, 118, 100, 69, 78, + 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, + 81, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 10, + 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 68, 103, 89, 68, 86, 82, 48, + 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, 85, + 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 65, 102, 56, 67, 65, 81, 69, + 119, 67, 103, 89, 73, 10, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 83, + 81, 65, 119, 82, 103, 73, 104, 65, 79, 87, 47, 53, 81, 107, 82, 43, 83, 57, 67, + 105, 83, 68, 99, 78, 111, 111, 119, 76, 117, 80, 82, 76, 115, 87, 71, 102, 47, 89, + 105, 55, 71, 83, 88, 57, 52, 66, 103, 119, 84, 119, 103, 10, 65, 105, 69, 65, 52, + 74, 48, 108, 114, 72, 111, 77, 115, 43, 88, 111, 53, 111, 47, 115, 88, 54, 79, 57, + 81, 87, 120, 72, 82, 65, 118, 90, 85, 71, 79, 100, 82, 81, 55, 99, 118, 113, 82, + 88, 97, 113, 73, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, + 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 0, + ] + .into(), + root_ca_crl: [ + 48, 130, 1, 34, 48, 129, 200, 2, 1, 1, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, + 48, 104, 49, 26, 48, 24, 6, 3, 85, 4, 3, 12, 17, 73, 110, 116, 101, 108, 32, 83, + 71, 88, 32, 82, 111, 111, 116, 32, 67, 65, 49, 26, 48, 24, 6, 3, 85, 4, 10, 12, 17, + 73, 110, 116, 101, 108, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, + 49, 20, 48, 18, 6, 3, 85, 4, 7, 12, 11, 83, 97, 110, 116, 97, 32, 67, 108, 97, 114, + 97, 49, 11, 48, 9, 6, 3, 85, 4, 8, 12, 2, 67, 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, + 19, 2, 85, 83, 23, 13, 50, 52, 48, 51, 50, 48, 49, 57, 49, 57, 51, 48, 90, 23, 13, + 50, 53, 48, 52, 48, 51, 49, 57, 49, 57, 51, 48, 90, 160, 47, 48, 45, 48, 10, 6, 3, + 85, 29, 20, 4, 3, 2, 1, 1, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 34, + 101, 12, 214, 90, 157, 52, 137, 243, 131, 180, 149, 82, 191, 80, 27, 57, 39, 6, + 172, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 73, 0, 48, 70, 2, 33, 0, 231, + 96, 111, 239, 45, 166, 135, 133, 160, 195, 155, 195, 74, 195, 68, 201, 226, 214, + 237, 75, 2, 35, 231, 154, 108, 98, 151, 212, 33, 183, 55, 132, 2, 33, 0, 252, 21, + 135, 174, 206, 66, 150, 213, 233, 55, 15, 214, 164, 68, 167, 45, 3, 197, 152, 203, + 33, 220, 129, 4, 197, 91, 18, 123, 118, 110, 168, 43, 0, + ] + .into(), + pck_crl: [ + 48, 130, 10, 98, 48, 130, 10, 8, 2, 1, 1, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, + 2, 48, 112, 49, 34, 48, 32, 6, 3, 85, 4, 3, 12, 25, 73, 110, 116, 101, 108, 32, 83, + 71, 88, 32, 80, 67, 75, 32, 80, 108, 97, 116, 102, 111, 114, 109, 32, 67, 65, 49, + 26, 48, 24, 6, 3, 85, 4, 10, 12, 17, 73, 110, 116, 101, 108, 32, 67, 111, 114, 112, + 111, 114, 97, 116, 105, 111, 110, 49, 20, 48, 18, 6, 3, 85, 4, 7, 12, 11, 83, 97, + 110, 116, 97, 32, 67, 108, 97, 114, 97, 49, 11, 48, 9, 6, 3, 85, 4, 8, 12, 2, 67, + 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 23, 13, 50, 52, 49, 49, 50, 56, + 49, 51, 50, 51, 48, 57, 90, 23, 13, 50, 52, 49, 50, 50, 56, 49, 51, 50, 51, 48, 57, + 90, 48, 130, 9, 52, 48, 51, 2, 20, 111, 195, 78, 80, 35, 231, 40, 146, 52, 53, 214, + 26, 164, 184, 60, 97, 129, 102, 173, 53, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, + 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, + 21, 0, 239, 174, 110, 151, 21, 252, 161, 59, 135, 227, 51, 232, 38, 30, 214, 217, + 144, 169, 38, 173, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, + 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 253, 96, 134, 72, + 98, 156, 186, 115, 7, 139, 77, 73, 47, 75, 62, 167, 65, 173, 8, 205, 23, 13, 50, + 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, + 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 138, 249, 36, 24, 78, 29, 90, 253, 221, 115, 195, + 214, 58, 18, 245, 232, 181, 115, 126, 86, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, + 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, + 21, 0, 177, 37, 121, 120, 207, 169, 204, 221, 7, 89, 171, 248, 197, 202, 114, 250, + 227, 167, 138, 155, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, + 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 116, 254, 166, 20, + 169, 114, 190, 14, 40, 67, 242, 5, 152, 53, 129, 30, 216, 114, 249, 179, 23, 13, + 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, + 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 249, 196, 239, 86, 179, 171, 72, 213, 119, + 225, 8, 186, 237, 244, 191, 136, 1, 66, 20, 185, 23, 13, 50, 52, 49, 49, 50, 56, + 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, + 51, 2, 20, 7, 29, 224, 119, 143, 158, 95, 196, 242, 135, 143, 48, 214, 176, 124, + 154, 48, 230, 179, 11, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, + 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 205, 226, 66, + 79, 151, 44, 234, 148, 255, 35, 153, 55, 244, 216, 12, 37, 2, 157, 214, 11, 23, 13, + 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, + 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 108, 51, 25, 229, 16, 155, 100, 80, 125, 60, + 241, 19, 44, 224, 3, 73, 239, 82, 115, 25, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, + 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, + 21, 0, 223, 8, 215, 86, 182, 106, 116, 151, 244, 59, 91, 181, 138, 218, 4, 211, + 244, 247, 169, 55, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, + 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 40, 175, 72, 91, 108, + 246, 126, 64, 154, 57, 213, 203, 90, 238, 69, 152, 247, 168, 250, 123, 23, 13, 50, + 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, + 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 251, 139, 45, 174, 192, 146, 202, 218, 138, 169, + 188, 79, 242, 241, 194, 13, 3, 70, 102, 140, 23, 13, 50, 52, 49, 49, 50, 56, 49, + 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, + 2, 21, 0, 205, 72, 80, 172, 82, 189, 204, 105, 166, 166, 240, 88, 200, 188, 87, + 187, 208, 181, 248, 100, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, + 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 153, 77, + 211, 102, 111, 82, 117, 251, 128, 95, 149, 221, 2, 189, 80, 203, 38, 121, 216, 173, + 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, + 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 7, 2, 19, 105, 0, 37, 34, 116, 217, 3, + 94, 237, 245, 69, 116, 98, 250, 208, 239, 76, 23, 13, 50, 52, 49, 49, 50, 56, 49, + 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, + 2, 20, 97, 242, 191, 115, 227, 155, 78, 4, 170, 39, 216, 1, 189, 115, 210, 67, 25, + 181, 191, 128, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, + 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 57, 146, 190, 133, 27, + 150, 144, 46, 255, 56, 149, 158, 108, 46, 255, 27, 6, 81, 164, 181, 23, 13, 50, 52, + 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, + 10, 1, 1, 48, 51, 2, 20, 99, 159, 19, 154, 80, 64, 253, 207, 241, 145, 232, 164, + 251, 27, 240, 134, 237, 96, 57, 113, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, + 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, + 149, 157, 83, 63, 146, 73, 220, 30, 81, 53, 68, 205, 200, 48, 191, 25, 183, 241, + 243, 1, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, + 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 15, 218, 67, 160, 11, 104, 234, + 121, 183, 194, 222, 174, 172, 11, 73, 139, 223, 178, 175, 144, 23, 13, 50, 52, 49, + 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, + 1, 1, 48, 52, 2, 21, 0, 157, 103, 117, 59, 129, 228, 112, 144, 174, 167, 99, 251, + 236, 76, 69, 73, 188, 219, 153, 51, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, + 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 52, + 191, 187, 122, 29, 156, 86, 129, 71, 225, 24, 182, 20, 247, 183, 110, 211, 239, + 104, 223, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, + 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 133, 211, 201, 56, 27, 119, + 167, 224, 77, 17, 156, 158, 90, 214, 116, 159, 243, 255, 171, 135, 23, 13, 50, 52, + 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, + 10, 1, 1, 48, 52, 2, 21, 0, 147, 136, 124, 164, 65, 30, 122, 146, 59, 209, 254, + 210, 129, 155, 41, 73, 242, 1, 181, 180, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, + 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, + 20, 36, 152, 220, 98, 131, 147, 9, 150, 253, 139, 242, 58, 55, 172, 190, 38, 163, + 190, 212, 87, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, + 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 138, 102, 241, 167, 73, + 72, 134, 103, 104, 156, 195, 144, 58, 197, 76, 102, 43, 113, 46, 115, 23, 13, 50, + 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, + 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 175, 193, 54, 16, 189, 211, 108, 183, 152, 93, + 16, 100, 129, 168, 128, 211, 160, 31, 218, 7, 23, 13, 50, 52, 49, 49, 50, 56, 49, + 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, + 2, 21, 0, 239, 224, 75, 44, 51, 208, 54, 170, 201, 108, 166, 115, 191, 30, 154, 71, + 182, 77, 92, 187, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, + 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 131, 217, 172, 141, + 139, 181, 9, 209, 198, 200, 9, 173, 113, 46, 132, 48, 85, 158, 215, 243, 23, 13, + 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, + 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 121, 49, 253, 80, 181, 7, 28, 27, 191, 197, 183, + 182, 222, 216, 180, 91, 157, 139, 133, 41, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, + 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, + 20, 31, 162, 14, 41, 112, 189, 229, 213, 127, 123, 141, 223, 131, 57, 72, 78, 31, + 29, 8, 35, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, + 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 30, 135, 178, 195, 179, 45, + 141, 35, 228, 17, 206, 243, 65, 151, 185, 90, 240, 200, 173, 245, 23, 13, 50, 52, + 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, + 10, 1, 1, 48, 52, 2, 21, 0, 154, 253, 46, 233, 10, 71, 53, 80, 161, 103, 217, 150, + 145, 20, 55, 199, 80, 45, 31, 9, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, + 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 68, + 129, 176, 241, 23, 40, 161, 59, 105, 109, 62, 169, 199, 112, 160, 177, 94, 197, + 141, 218, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, + 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 167, 133, 159, 87, 152, 46, + 240, 230, 125, 55, 188, 142, 242, 239, 90, 200, 53, 255, 26, 169, 23, 13, 50, 52, + 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, + 10, 1, 1, 48, 51, 2, 20, 122, 227, 119, 72, 169, 249, 18, 244, 198, 59, 167, 171, + 7, 197, 147, 206, 29, 29, 17, 129, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, + 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 19, + 136, 75, 51, 38, 153, 56, 193, 149, 170, 23, 15, 202, 117, 218, 23, 117, 56, 223, + 11, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, + 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 44, 60, 198, 254, 146, 121, 219, 21, + 22, 213, 206, 57, 242, 168, 152, 205, 165, 161, 117, 225, 23, 13, 50, 52, 49, 49, + 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, + 1, 48, 51, 2, 20, 113, 121, 72, 104, 117, 9, 35, 75, 233, 121, 228, 183, 220, 230, + 243, 27, 239, 100, 182, 140, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, + 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 157, + 118, 239, 44, 57, 193, 54, 232, 101, 139, 110, 115, 150, 177, 215, 68, 90, 39, 99, + 31, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, + 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 195, 224, 37, 252, 169, 149, 243, + 111, 89, 180, 132, 103, 147, 158, 62, 52, 230, 54, 26, 111, 23, 13, 50, 52, 49, 49, + 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, + 1, 48, 52, 2, 21, 0, 140, 95, 107, 50, 87, 218, 5, 177, 116, 41, 226, 230, 27, 169, + 101, 214, 115, 48, 96, 106, 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, + 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 161, 124, + 81, 114, 46, 193, 224, 195, 39, 143, 232, 189, 240, 82, 5, 156, 190, 196, 230, 72, + 23, 13, 50, 52, 49, 49, 50, 56, 49, 51, 50, 51, 48, 57, 90, 48, 12, 48, 10, 6, 3, + 85, 29, 21, 4, 3, 10, 1, 1, 160, 47, 48, 45, 48, 10, 6, 3, 85, 29, 20, 4, 3, 2, 1, + 1, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 149, 111, 93, 205, 189, 27, + 225, 233, 64, 73, 201, 212, 244, 51, 206, 1, 87, 11, 222, 84, 48, 10, 6, 8, 42, + 134, 72, 206, 61, 4, 3, 2, 3, 72, 0, 48, 69, 2, 32, 113, 129, 124, 253, 92, 251, + 24, 95, 180, 138, 106, 178, 57, 160, 79, 139, 90, 150, 233, 44, 243, 233, 219, 83, + 166, 120, 8, 167, 21, 168, 54, 112, 2, 33, 0, 241, 73, 163, 143, 77, 129, 88, 187, + 205, 46, 218, 183, 36, 140, 195, 164, 84, 101, 227, 217, 121, 192, 245, 25, 116, + 182, 208, 150, 186, 234, 175, 136, 0, + ] + .into(), + tcb_info_issuer_chain: [ + 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, + 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 105, 122, 67, 67, 65, 106, 75, 103, 65, + 119, 73, 66, 65, 103, 73, 85, 102, 106, 105, 67, 49, 102, 116, 86, 75, 85, 112, 65, + 83, 89, 53, 70, 104, 65, 80, 112, 70, 74, 71, 57, 57, 70, 85, 119, 67, 103, 89, 73, + 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 97, 68, 69, 97, 77, 66, + 103, 71, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, + 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, + 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, + 118, 10, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, + 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, + 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, + 48, 69, 120, 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, + 77, 66, 52, 88, 68, 84, 69, 52, 77, 68, 85, 121, 77, 84, 69, 119, 78, 84, 65, 120, + 77, 70, 111, 88, 68, 84, 73, 49, 77, 68, 85, 121, 77, 84, 69, 119, 78, 84, 65, 120, + 77, 70, 111, 119, 98, 68, 69, 101, 77, 66, 119, 71, 10, 65, 49, 85, 69, 65, 119, + 119, 86, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 82, 68, 81, + 105, 66, 84, 97, 87, 100, 117, 97, 87, 53, 110, 77, 82, 111, 119, 71, 65, 89, 68, + 86, 81, 81, 75, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 98, 51, 74, 119, + 10, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, + 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, + 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 103, 77, 65, 107, 78, 66, + 77, 81, 115, 119, 67, 81, 89, 68, 10, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 66, + 90, 77, 66, 77, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, 71, 67, 67, 113, + 71, 83, 77, 52, 57, 65, 119, 69, 72, 65, 48, 73, 65, 66, 69, 78, 70, 71, 56, 120, + 122, 121, 100, 87, 82, 102, 75, 57, 50, 98, 109, 71, 118, 10, 80, 43, 109, 65, 104, + 57, 49, 80, 69, 121, 86, 55, 74, 104, 54, 70, 71, 74, 100, 53, 110, 100, 69, 57, + 97, 66, 72, 55, 82, 51, 69, 52, 65, 55, 117, 98, 114, 108, 104, 47, 122, 78, 51, + 67, 52, 120, 118, 112, 111, 111, 117, 71, 108, 105, 114, 77, 98, 97, 43, 87, 50, + 108, 106, 117, 10, 121, 112, 97, 106, 103, 98, 85, 119, 103, 98, 73, 119, 72, 119, + 89, 68, 86, 82, 48, 106, 66, 66, 103, 119, 70, 111, 65, 85, 73, 109, 85, 77, 49, + 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 85, 114, 57, 81, 71, 122, 107, + 110, 66, 113, 119, 119, 85, 103, 89, 68, 86, 82, 48, 102, 10, 66, 69, 115, 119, 83, + 84, 66, 72, 111, 69, 87, 103, 81, 52, 90, 66, 97, 72, 82, 48, 99, 72, 77, 54, 76, + 121, 57, 106, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 88, 77, 117, + 100, 72, 74, 49, 99, 51, 82, 108, 90, 72, 78, 108, 99, 110, 90, 112, 89, 50, 86, + 122, 10, 76, 109, 108, 117, 100, 71, 86, 115, 76, 109, 78, 118, 98, 83, 57, 74, 98, + 110, 82, 108, 98, 70, 78, 72, 87, 70, 74, 118, 98, 51, 82, 68, 81, 83, 53, 107, 90, + 88, 73, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 72, 52, 52, 103, + 116, 88, 55, 86, 83, 108, 75, 10, 81, 69, 109, 79, 82, 89, 81, 68, 54, 82, 83, 82, + 118, 102, 82, 86, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, + 69, 65, 119, 73, 71, 119, 68, 65, 77, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, + 69, 65, 106, 65, 65, 77, 65, 111, 71, 67, 67, 113, 71, 10, 83, 77, 52, 57, 66, 65, + 77, 67, 65, 48, 99, 65, 77, 69, 81, 67, 73, 66, 57, 67, 56, 119, 79, 65, 78, 47, + 73, 109, 120, 68, 116, 71, 65, 67, 86, 50, 52, 54, 75, 99, 113, 106, 97, 103, 90, + 79, 82, 48, 107, 121, 99, 116, 121, 66, 114, 115, 71, 71, 74, 86, 65, 105, 65, 106, + 10, 102, 116, 98, 114, 78, 71, 115, 71, 85, 56, 89, 72, 50, 49, 49, 100, 82, 105, + 89, 78, 111, 80, 80, 117, 49, 57, 90, 112, 47, 122, 101, 56, 74, 109, 104, 117, + 106, 66, 48, 111, 66, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, + 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, + 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, + 10, 77, 73, 73, 67, 106, 122, 67, 67, 65, 106, 83, 103, 65, 119, 73, 66, 65, 103, + 73, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 85, + 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 67, 103, 89, 73, 75, 111, 90, + 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 97, 68, 69, 97, 77, 66, 103, 71, 65, + 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, + 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, + 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 10, 99, + 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, + 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, + 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, + 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 66, 52, + 88, 68, 84, 69, 52, 77, 68, 85, 121, 77, 84, 69, 119, 78, 68, 85, 120, 77, 70, 111, + 88, 68, 84, 81, 53, 77, 84, 73, 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, + 119, 97, 68, 69, 97, 77, 66, 103, 71, 10, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, + 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, + 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, + 100, 71, 86, 115, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 10, 97, 87, + 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, + 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, + 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, + 89, 84, 10, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, + 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, + 68, 81, 103, 65, 69, 67, 54, 110, 69, 119, 77, 68, 73, 89, 90, 79, 106, 47, 105, + 80, 87, 115, 67, 122, 97, 69, 75, 105, 55, 10, 49, 79, 105, 79, 83, 76, 82, 70, + 104, 87, 71, 106, 98, 110, 66, 86, 74, 102, 86, 110, 107, 89, 52, 117, 51, 73, 106, + 107, 68, 89, 89, 76, 48, 77, 120, 79, 52, 109, 113, 115, 121, 89, 106, 108, 66, 97, + 108, 84, 86, 89, 120, 70, 80, 50, 115, 74, 66, 75, 53, 122, 108, 75, 79, 66, 10, + 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, + 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, + 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 66, 103, 78, 86, 72, 82, + 56, 69, 83, 122, 66, 74, 10, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, + 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, + 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, + 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 10, 90, 87, 119, + 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, + 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, + 81, 52, 69, 70, 103, 81, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, + 103, 55, 83, 86, 10, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 68, + 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, + 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 65, + 102, 56, 67, 65, 81, 69, 119, 67, 103, 89, 73, 10, 75, 111, 90, 73, 122, 106, 48, + 69, 65, 119, 73, 68, 83, 81, 65, 119, 82, 103, 73, 104, 65, 79, 87, 47, 53, 81, + 107, 82, 43, 83, 57, 67, 105, 83, 68, 99, 78, 111, 111, 119, 76, 117, 80, 82, 76, + 115, 87, 71, 102, 47, 89, 105, 55, 71, 83, 88, 57, 52, 66, 103, 119, 84, 119, 103, + 10, 65, 105, 69, 65, 52, 74, 48, 108, 114, 72, 111, 77, 115, 43, 88, 111, 53, 111, + 47, 115, 88, 54, 79, 57, 81, 87, 120, 72, 82, 65, 118, 90, 85, 71, 79, 100, 82, 81, + 55, 99, 118, 113, 82, 88, 97, 113, 73, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, + 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 0, + ] + .into(), + tcb_info: [ + 123, 34, 116, 99, 98, 73, 110, 102, 111, 34, 58, 123, 34, 105, 100, 34, 58, 34, 84, + 68, 88, 34, 44, 34, 118, 101, 114, 115, 105, 111, 110, 34, 58, 51, 44, 34, 105, + 115, 115, 117, 101, 68, 97, 116, 101, 34, 58, 34, 50, 48, 50, 52, 45, 49, 50, 45, + 48, 53, 84, 49, 50, 58, 49, 54, 58, 53, 50, 90, 34, 44, 34, 110, 101, 120, 116, 85, + 112, 100, 97, 116, 101, 34, 58, 34, 50, 48, 50, 53, 45, 48, 49, 45, 48, 52, 84, 49, + 50, 58, 49, 54, 58, 53, 50, 90, 34, 44, 34, 102, 109, 115, 112, 99, 34, 58, 34, 48, + 48, 56, 48, 54, 70, 48, 53, 48, 48, 48, 48, 34, 44, 34, 112, 99, 101, 73, 100, 34, + 58, 34, 48, 48, 48, 48, 34, 44, 34, 116, 99, 98, 84, 121, 112, 101, 34, 58, 48, 44, + 34, 116, 99, 98, 69, 118, 97, 108, 117, 97, 116, 105, 111, 110, 68, 97, 116, 97, + 78, 117, 109, 98, 101, 114, 34, 58, 49, 55, 44, 34, 116, 100, 120, 77, 111, 100, + 117, 108, 101, 34, 58, 123, 34, 109, 114, 115, 105, 103, 110, 101, 114, 34, 58, 34, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 34, 44, 34, 97, 116, 116, 114, 105, + 98, 117, 116, 101, 115, 34, 58, 34, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 34, 44, 34, 97, 116, 116, 114, 105, 98, 117, 116, 101, 115, 77, 97, + 115, 107, 34, 58, 34, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 34, 125, 44, 34, 116, 100, 120, 77, 111, 100, 117, 108, 101, 73, 100, 101, 110, + 116, 105, 116, 105, 101, 115, 34, 58, 91, 123, 34, 105, 100, 34, 58, 34, 84, 68, + 88, 95, 48, 51, 34, 44, 34, 109, 114, 115, 105, 103, 110, 101, 114, 34, 58, 34, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 34, 44, 34, 97, 116, 116, 114, 105, 98, + 117, 116, 101, 115, 34, 58, 34, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 34, 44, 34, 97, 116, 116, 114, 105, 98, 117, 116, 101, 115, 77, 97, + 115, 107, 34, 58, 34, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 70, 34, 44, 34, 116, 99, 98, 76, 101, 118, 101, 108, 115, 34, 58, 91, 123, 34, 116, + 99, 98, 34, 58, 123, 34, 105, 115, 118, 115, 118, 110, 34, 58, 51, 125, 44, 34, + 116, 99, 98, 68, 97, 116, 101, 34, 58, 34, 50, 48, 50, 52, 45, 48, 51, 45, 49, 51, + 84, 48, 48, 58, 48, 48, 58, 48, 48, 90, 34, 44, 34, 116, 99, 98, 83, 116, 97, 116, + 117, 115, 34, 58, 34, 85, 112, 84, 111, 68, 97, 116, 101, 34, 125, 93, 125, 44, + 123, 34, 105, 100, 34, 58, 34, 84, 68, 88, 95, 48, 49, 34, 44, 34, 109, 114, 115, + 105, 103, 110, 101, 114, 34, 58, 34, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 34, 44, 34, 97, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 58, 34, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 34, 44, 34, 97, 116, 116, + 114, 105, 98, 117, 116, 101, 115, 77, 97, 115, 107, 34, 58, 34, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 34, 44, 34, 116, 99, 98, 76, 101, 118, + 101, 108, 115, 34, 58, 91, 123, 34, 116, 99, 98, 34, 58, 123, 34, 105, 115, 118, + 115, 118, 110, 34, 58, 52, 125, 44, 34, 116, 99, 98, 68, 97, 116, 101, 34, 58, 34, + 50, 48, 50, 52, 45, 48, 51, 45, 49, 51, 84, 48, 48, 58, 48, 48, 58, 48, 48, 90, 34, + 44, 34, 116, 99, 98, 83, 116, 97, 116, 117, 115, 34, 58, 34, 85, 112, 84, 111, 68, + 97, 116, 101, 34, 125, 44, 123, 34, 116, 99, 98, 34, 58, 123, 34, 105, 115, 118, + 115, 118, 110, 34, 58, 50, 125, 44, 34, 116, 99, 98, 68, 97, 116, 101, 34, 58, 34, + 50, 48, 50, 51, 45, 48, 56, 45, 48, 57, 84, 48, 48, 58, 48, 48, 58, 48, 48, 90, 34, + 44, 34, 116, 99, 98, 83, 116, 97, 116, 117, 115, 34, 58, 34, 79, 117, 116, 79, 102, + 68, 97, 116, 101, 34, 125, 93, 125, 93, 44, 34, 116, 99, 98, 76, 101, 118, 101, + 108, 115, 34, 58, 91, 123, 34, 116, 99, 98, 34, 58, 123, 34, 115, 103, 120, 116, + 99, 98, 99, 111, 109, 112, 111, 110, 101, 110, 116, 115, 34, 58, 91, 123, 34, 115, + 118, 110, 34, 58, 55, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 66, + 73, 79, 83, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 69, 97, 114, 108, 121, 32, + 77, 105, 99, 114, 111, 99, 111, 100, 101, 32, 85, 112, 100, 97, 116, 101, 34, 125, + 44, 123, 34, 115, 118, 110, 34, 58, 55, 44, 34, 99, 97, 116, 101, 103, 111, 114, + 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, 34, 116, 121, 112, 101, 34, 58, + 34, 83, 71, 88, 32, 76, 97, 116, 101, 32, 77, 105, 99, 114, 111, 99, 111, 100, 101, + 32, 85, 112, 100, 97, 116, 101, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, 50, + 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, + 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 84, 88, 84, 32, 83, 73, 78, 73, 84, 34, + 125, 44, 123, 34, 115, 118, 110, 34, 58, 50, 44, 34, 99, 97, 116, 101, 103, 111, + 114, 121, 34, 58, 34, 66, 73, 79, 83, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, + 51, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 66, 73, 79, 83, 34, + 125, 44, 123, 34, 115, 118, 110, 34, 58, 49, 44, 34, 99, 97, 116, 101, 103, 111, + 114, 121, 34, 58, 34, 66, 73, 79, 83, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, + 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 51, 44, 34, 99, 97, 116, 101, 103, + 111, 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, 34, 116, 121, 112, 101, + 34, 58, 34, 83, 69, 65, 77, 76, 68, 82, 32, 65, 67, 77, 34, 125, 44, 123, 34, 115, + 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, + 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, + 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, + 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, + 34, 58, 48, 125, 93, 44, 34, 112, 99, 101, 115, 118, 110, 34, 58, 49, 49, 44, 34, + 116, 100, 120, 116, 99, 98, 99, 111, 109, 112, 111, 110, 101, 110, 116, 115, 34, + 58, 91, 123, 34, 115, 118, 110, 34, 58, 53, 44, 34, 99, 97, 116, 101, 103, 111, + 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, 34, 116, 121, 112, 101, 34, + 58, 34, 84, 68, 88, 32, 77, 111, 100, 117, 108, 101, 34, 125, 44, 123, 34, 115, + 118, 110, 34, 58, 48, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 79, + 83, 47, 86, 77, 77, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 84, 68, 88, 32, 77, + 111, 100, 117, 108, 101, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, 55, 44, 34, + 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, + 34, 116, 121, 112, 101, 34, 58, 34, 84, 68, 88, 32, 76, 97, 116, 101, 32, 77, 105, + 99, 114, 111, 99, 111, 100, 101, 32, 85, 112, 100, 97, 116, 101, 34, 125, 44, 123, + 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, + 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, + 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, + 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, + 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, + 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, + 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, + 48, 125, 93, 125, 44, 34, 116, 99, 98, 68, 97, 116, 101, 34, 58, 34, 50, 48, 50, + 52, 45, 48, 51, 45, 49, 51, 84, 48, 48, 58, 48, 48, 58, 48, 48, 90, 34, 44, 34, + 116, 99, 98, 83, 116, 97, 116, 117, 115, 34, 58, 34, 85, 112, 84, 111, 68, 97, 116, + 101, 34, 125, 44, 123, 34, 116, 99, 98, 34, 58, 123, 34, 115, 103, 120, 116, 99, + 98, 99, 111, 109, 112, 111, 110, 101, 110, 116, 115, 34, 58, 91, 123, 34, 115, 118, + 110, 34, 58, 54, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 66, 73, + 79, 83, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 69, 97, 114, 108, 121, 32, 77, + 105, 99, 114, 111, 99, 111, 100, 101, 32, 85, 112, 100, 97, 116, 101, 34, 125, 44, + 123, 34, 115, 118, 110, 34, 58, 54, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, + 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 83, + 71, 88, 32, 76, 97, 116, 101, 32, 77, 105, 99, 114, 111, 99, 111, 100, 101, 32, 85, + 112, 100, 97, 116, 101, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, 50, 44, 34, + 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, + 34, 116, 121, 112, 101, 34, 58, 34, 84, 88, 84, 32, 83, 73, 78, 73, 84, 34, 125, + 44, 123, 34, 115, 118, 110, 34, 58, 50, 44, 34, 99, 97, 116, 101, 103, 111, 114, + 121, 34, 58, 34, 66, 73, 79, 83, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, 51, + 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 66, 73, 79, 83, 34, 125, + 44, 123, 34, 115, 118, 110, 34, 58, 49, 44, 34, 99, 97, 116, 101, 103, 111, 114, + 121, 34, 58, 34, 66, 73, 79, 83, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, + 125, 44, 123, 34, 115, 118, 110, 34, 58, 51, 44, 34, 99, 97, 116, 101, 103, 111, + 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, 34, 116, 121, 112, 101, 34, + 58, 34, 83, 69, 65, 77, 76, 68, 82, 32, 65, 67, 77, 34, 125, 44, 123, 34, 115, 118, + 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, + 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, + 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, + 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, + 58, 48, 125, 93, 44, 34, 112, 99, 101, 115, 118, 110, 34, 58, 49, 49, 44, 34, 116, + 100, 120, 116, 99, 98, 99, 111, 109, 112, 111, 110, 101, 110, 116, 115, 34, 58, 91, + 123, 34, 115, 118, 110, 34, 58, 51, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, + 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 84, + 68, 88, 32, 77, 111, 100, 117, 108, 101, 34, 125, 44, 123, 34, 115, 118, 110, 34, + 58, 48, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 79, 83, 47, 86, + 77, 77, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 84, 68, 88, 32, 77, 111, 100, + 117, 108, 101, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, 54, 44, 34, 99, 97, + 116, 101, 103, 111, 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, 34, 116, + 121, 112, 101, 34, 58, 34, 84, 68, 88, 32, 76, 97, 116, 101, 32, 77, 105, 99, 114, + 111, 99, 111, 100, 101, 32, 85, 112, 100, 97, 116, 101, 34, 125, 44, 123, 34, 115, + 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, + 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, + 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, + 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, + 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, + 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, + 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, + 93, 125, 44, 34, 116, 99, 98, 68, 97, 116, 101, 34, 58, 34, 50, 48, 50, 51, 45, 48, + 56, 45, 48, 57, 84, 48, 48, 58, 48, 48, 58, 48, 48, 90, 34, 44, 34, 116, 99, 98, + 83, 116, 97, 116, 117, 115, 34, 58, 34, 79, 117, 116, 79, 102, 68, 97, 116, 101, + 34, 44, 34, 97, 100, 118, 105, 115, 111, 114, 121, 73, 68, 115, 34, 58, 91, 34, 73, + 78, 84, 69, 76, 45, 83, 65, 45, 48, 48, 57, 54, 48, 34, 44, 34, 73, 78, 84, 69, 76, + 45, 83, 65, 45, 48, 48, 57, 56, 50, 34, 44, 34, 73, 78, 84, 69, 76, 45, 83, 65, 45, + 48, 48, 57, 56, 54, 34, 93, 125, 44, 123, 34, 116, 99, 98, 34, 58, 123, 34, 115, + 103, 120, 116, 99, 98, 99, 111, 109, 112, 111, 110, 101, 110, 116, 115, 34, 58, 91, + 123, 34, 115, 118, 110, 34, 58, 53, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, + 34, 58, 34, 66, 73, 79, 83, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 69, 97, + 114, 108, 121, 32, 77, 105, 99, 114, 111, 99, 111, 100, 101, 32, 85, 112, 100, 97, + 116, 101, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, 53, 44, 34, 99, 97, 116, + 101, 103, 111, 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, 34, 116, 121, + 112, 101, 34, 58, 34, 83, 71, 88, 32, 76, 97, 116, 101, 32, 77, 105, 99, 114, 111, + 99, 111, 100, 101, 32, 85, 112, 100, 97, 116, 101, 34, 125, 44, 123, 34, 115, 118, + 110, 34, 58, 50, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 79, 83, + 47, 86, 77, 77, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 84, 88, 84, 32, 83, 73, + 78, 73, 84, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, 50, 44, 34, 99, 97, 116, + 101, 103, 111, 114, 121, 34, 58, 34, 66, 73, 79, 83, 34, 125, 44, 123, 34, 115, + 118, 110, 34, 58, 51, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 66, + 73, 79, 83, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, 49, 44, 34, 99, 97, 116, + 101, 103, 111, 114, 121, 34, 58, 34, 66, 73, 79, 83, 34, 125, 44, 123, 34, 115, + 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 51, 44, 34, 99, 97, + 116, 101, 103, 111, 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, 34, 116, + 121, 112, 101, 34, 58, 34, 83, 69, 65, 77, 76, 68, 82, 32, 65, 67, 77, 34, 125, 44, + 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, + 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, + 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, + 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, + 115, 118, 110, 34, 58, 48, 125, 93, 44, 34, 112, 99, 101, 115, 118, 110, 34, 58, + 49, 49, 44, 34, 116, 100, 120, 116, 99, 98, 99, 111, 109, 112, 111, 110, 101, 110, + 116, 115, 34, 58, 91, 123, 34, 115, 118, 110, 34, 58, 51, 44, 34, 99, 97, 116, 101, + 103, 111, 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, 34, 116, 121, 112, + 101, 34, 58, 34, 84, 68, 88, 32, 77, 111, 100, 117, 108, 101, 34, 125, 44, 123, 34, + 115, 118, 110, 34, 58, 48, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, + 34, 79, 83, 47, 86, 77, 77, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 84, 68, 88, + 32, 77, 111, 100, 117, 108, 101, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, 53, + 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, + 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 84, 68, 88, 32, 76, 97, 116, 101, 32, + 77, 105, 99, 114, 111, 99, 111, 100, 101, 32, 85, 112, 100, 97, 116, 101, 34, 125, + 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, + 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, + 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, + 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, + 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, + 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, + 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, + 34, 58, 48, 125, 93, 125, 44, 34, 116, 99, 98, 68, 97, 116, 101, 34, 58, 34, 50, + 48, 50, 51, 45, 48, 50, 45, 49, 53, 84, 48, 48, 58, 48, 48, 58, 48, 48, 90, 34, 44, + 34, 116, 99, 98, 83, 116, 97, 116, 117, 115, 34, 58, 34, 79, 117, 116, 79, 102, 68, + 97, 116, 101, 34, 44, 34, 97, 100, 118, 105, 115, 111, 114, 121, 73, 68, 115, 34, + 58, 91, 34, 73, 78, 84, 69, 76, 45, 83, 65, 45, 48, 48, 56, 51, 55, 34, 44, 34, 73, + 78, 84, 69, 76, 45, 83, 65, 45, 48, 48, 57, 54, 48, 34, 44, 34, 73, 78, 84, 69, 76, + 45, 83, 65, 45, 48, 48, 57, 56, 50, 34, 44, 34, 73, 78, 84, 69, 76, 45, 83, 65, 45, + 48, 48, 57, 56, 54, 34, 93, 125, 44, 123, 34, 116, 99, 98, 34, 58, 123, 34, 115, + 103, 120, 116, 99, 98, 99, 111, 109, 112, 111, 110, 101, 110, 116, 115, 34, 58, 91, + 123, 34, 115, 118, 110, 34, 58, 53, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, + 34, 58, 34, 66, 73, 79, 83, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 69, 97, + 114, 108, 121, 32, 77, 105, 99, 114, 111, 99, 111, 100, 101, 32, 85, 112, 100, 97, + 116, 101, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, 53, 44, 34, 99, 97, 116, + 101, 103, 111, 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, 34, 116, 121, + 112, 101, 34, 58, 34, 83, 71, 88, 32, 76, 97, 116, 101, 32, 77, 105, 99, 114, 111, + 99, 111, 100, 101, 32, 85, 112, 100, 97, 116, 101, 34, 125, 44, 123, 34, 115, 118, + 110, 34, 58, 50, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 79, 83, + 47, 86, 77, 77, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 84, 88, 84, 32, 83, 73, + 78, 73, 84, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, 50, 44, 34, 99, 97, 116, + 101, 103, 111, 114, 121, 34, 58, 34, 66, 73, 79, 83, 34, 125, 44, 123, 34, 115, + 118, 110, 34, 58, 51, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 66, + 73, 79, 83, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, 49, 44, 34, 99, 97, 116, + 101, 103, 111, 114, 121, 34, 58, 34, 66, 73, 79, 83, 34, 125, 44, 123, 34, 115, + 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 51, 44, 34, 99, 97, + 116, 101, 103, 111, 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, 34, 116, + 121, 112, 101, 34, 58, 34, 83, 69, 65, 77, 76, 68, 82, 32, 65, 67, 77, 34, 125, 44, + 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, + 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, + 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, + 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, + 115, 118, 110, 34, 58, 48, 125, 93, 44, 34, 112, 99, 101, 115, 118, 110, 34, 58, + 53, 44, 34, 116, 100, 120, 116, 99, 98, 99, 111, 109, 112, 111, 110, 101, 110, 116, + 115, 34, 58, 91, 123, 34, 115, 118, 110, 34, 58, 51, 44, 34, 99, 97, 116, 101, 103, + 111, 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, 34, 116, 121, 112, 101, + 34, 58, 34, 84, 68, 88, 32, 77, 111, 100, 117, 108, 101, 34, 125, 44, 123, 34, 115, + 118, 110, 34, 58, 48, 44, 34, 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 79, + 83, 47, 86, 77, 77, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 84, 68, 88, 32, 77, + 111, 100, 117, 108, 101, 34, 125, 44, 123, 34, 115, 118, 110, 34, 58, 53, 44, 34, + 99, 97, 116, 101, 103, 111, 114, 121, 34, 58, 34, 79, 83, 47, 86, 77, 77, 34, 44, + 34, 116, 121, 112, 101, 34, 58, 34, 84, 68, 88, 32, 76, 97, 116, 101, 32, 77, 105, + 99, 114, 111, 99, 111, 100, 101, 32, 85, 112, 100, 97, 116, 101, 34, 125, 44, 123, + 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, + 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, + 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, + 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, + 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, + 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, + 44, 123, 34, 115, 118, 110, 34, 58, 48, 125, 44, 123, 34, 115, 118, 110, 34, 58, + 48, 125, 93, 125, 44, 34, 116, 99, 98, 68, 97, 116, 101, 34, 58, 34, 50, 48, 49, + 56, 45, 48, 49, 45, 48, 52, 84, 48, 48, 58, 48, 48, 58, 48, 48, 90, 34, 44, 34, + 116, 99, 98, 83, 116, 97, 116, 117, 115, 34, 58, 34, 79, 117, 116, 79, 102, 68, 97, + 116, 101, 34, 44, 34, 97, 100, 118, 105, 115, 111, 114, 121, 73, 68, 115, 34, 58, + 91, 34, 73, 78, 84, 69, 76, 45, 83, 65, 45, 48, 48, 49, 48, 54, 34, 44, 34, 73, 78, + 84, 69, 76, 45, 83, 65, 45, 48, 48, 49, 49, 53, 34, 44, 34, 73, 78, 84, 69, 76, 45, + 83, 65, 45, 48, 48, 49, 51, 53, 34, 44, 34, 73, 78, 84, 69, 76, 45, 83, 65, 45, 48, + 48, 50, 48, 51, 34, 44, 34, 73, 78, 84, 69, 76, 45, 83, 65, 45, 48, 48, 50, 50, 48, + 34, 44, 34, 73, 78, 84, 69, 76, 45, 83, 65, 45, 48, 48, 50, 51, 51, 34, 44, 34, 73, + 78, 84, 69, 76, 45, 83, 65, 45, 48, 48, 50, 55, 48, 34, 44, 34, 73, 78, 84, 69, 76, + 45, 83, 65, 45, 48, 48, 50, 57, 51, 34, 44, 34, 73, 78, 84, 69, 76, 45, 83, 65, 45, + 48, 48, 51, 50, 48, 34, 44, 34, 73, 78, 84, 69, 76, 45, 83, 65, 45, 48, 48, 51, 50, + 57, 34, 44, 34, 73, 78, 84, 69, 76, 45, 83, 65, 45, 48, 48, 51, 56, 49, 34, 44, 34, + 73, 78, 84, 69, 76, 45, 83, 65, 45, 48, 48, 51, 56, 57, 34, 44, 34, 73, 78, 84, 69, + 76, 45, 83, 65, 45, 48, 48, 52, 55, 55, 34, 44, 34, 73, 78, 84, 69, 76, 45, 83, 65, + 45, 48, 48, 56, 51, 55, 34, 44, 34, 73, 78, 84, 69, 76, 45, 83, 65, 45, 48, 48, 57, + 54, 48, 34, 44, 34, 73, 78, 84, 69, 76, 45, 83, 65, 45, 48, 48, 57, 56, 50, 34, 44, + 34, 73, 78, 84, 69, 76, 45, 83, 65, 45, 48, 48, 57, 56, 54, 34, 93, 125, 93, 125, + 44, 34, 115, 105, 103, 110, 97, 116, 117, 114, 101, 34, 58, 34, 48, 54, 99, 52, 54, + 48, 56, 54, 55, 56, 56, 50, 100, 99, 99, 100, 100, 97, 49, 55, 48, 48, 52, 98, 97, + 54, 48, 102, 53, 52, 99, 50, 50, 101, 102, 56, 53, 52, 100, 53, 57, 98, 53, 50, 52, + 100, 50, 54, 49, 98, 55, 97, 98, 97, 50, 50, 57, 101, 101, 97, 101, 50, 99, 56, 48, + 48, 51, 56, 53, 101, 55, 51, 48, 56, 51, 50, 53, 98, 56, 97, 48, 49, 48, 53, 48, + 54, 49, 54, 48, 48, 98, 50, 50, 55, 98, 56, 55, 50, 56, 100, 55, 102, 49, 101, 53, + 52, 53, 57, 52, 100, 99, 101, 98, 50, 100, 102, 48, 102, 53, 54, 102, 51, 97, 54, + 100, 102, 102, 99, 34, 125, 0, + ] + .into(), + qe_identity_issuer_chain: [ + 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, + 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 105, 122, 67, 67, 65, 106, 75, 103, 65, + 119, 73, 66, 65, 103, 73, 85, 102, 106, 105, 67, 49, 102, 116, 86, 75, 85, 112, 65, + 83, 89, 53, 70, 104, 65, 80, 112, 70, 74, 71, 57, 57, 70, 85, 119, 67, 103, 89, 73, + 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 97, 68, 69, 97, 77, 66, + 103, 71, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, + 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, + 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, + 118, 10, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, + 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, + 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, + 48, 69, 120, 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, + 77, 66, 52, 88, 68, 84, 69, 52, 77, 68, 85, 121, 77, 84, 69, 119, 78, 84, 65, 120, + 77, 70, 111, 88, 68, 84, 73, 49, 77, 68, 85, 121, 77, 84, 69, 119, 78, 84, 65, 120, + 77, 70, 111, 119, 98, 68, 69, 101, 77, 66, 119, 71, 10, 65, 49, 85, 69, 65, 119, + 119, 86, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 82, 68, 81, + 105, 66, 84, 97, 87, 100, 117, 97, 87, 53, 110, 77, 82, 111, 119, 71, 65, 89, 68, + 86, 81, 81, 75, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 98, 51, 74, 119, + 10, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, + 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, + 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 103, 77, 65, 107, 78, 66, + 77, 81, 115, 119, 67, 81, 89, 68, 10, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 66, + 90, 77, 66, 77, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, 71, 67, 67, 113, + 71, 83, 77, 52, 57, 65, 119, 69, 72, 65, 48, 73, 65, 66, 69, 78, 70, 71, 56, 120, + 122, 121, 100, 87, 82, 102, 75, 57, 50, 98, 109, 71, 118, 10, 80, 43, 109, 65, 104, + 57, 49, 80, 69, 121, 86, 55, 74, 104, 54, 70, 71, 74, 100, 53, 110, 100, 69, 57, + 97, 66, 72, 55, 82, 51, 69, 52, 65, 55, 117, 98, 114, 108, 104, 47, 122, 78, 51, + 67, 52, 120, 118, 112, 111, 111, 117, 71, 108, 105, 114, 77, 98, 97, 43, 87, 50, + 108, 106, 117, 10, 121, 112, 97, 106, 103, 98, 85, 119, 103, 98, 73, 119, 72, 119, + 89, 68, 86, 82, 48, 106, 66, 66, 103, 119, 70, 111, 65, 85, 73, 109, 85, 77, 49, + 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 85, 114, 57, 81, 71, 122, 107, + 110, 66, 113, 119, 119, 85, 103, 89, 68, 86, 82, 48, 102, 10, 66, 69, 115, 119, 83, + 84, 66, 72, 111, 69, 87, 103, 81, 52, 90, 66, 97, 72, 82, 48, 99, 72, 77, 54, 76, + 121, 57, 106, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 90, 88, 77, 117, + 100, 72, 74, 49, 99, 51, 82, 108, 90, 72, 78, 108, 99, 110, 90, 112, 89, 50, 86, + 122, 10, 76, 109, 108, 117, 100, 71, 86, 115, 76, 109, 78, 118, 98, 83, 57, 74, 98, + 110, 82, 108, 98, 70, 78, 72, 87, 70, 74, 118, 98, 51, 82, 68, 81, 83, 53, 107, 90, + 88, 73, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 72, 52, 52, 103, + 116, 88, 55, 86, 83, 108, 75, 10, 81, 69, 109, 79, 82, 89, 81, 68, 54, 82, 83, 82, + 118, 102, 82, 86, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, + 69, 65, 119, 73, 71, 119, 68, 65, 77, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, + 69, 65, 106, 65, 65, 77, 65, 111, 71, 67, 67, 113, 71, 10, 83, 77, 52, 57, 66, 65, + 77, 67, 65, 48, 99, 65, 77, 69, 81, 67, 73, 66, 57, 67, 56, 119, 79, 65, 78, 47, + 73, 109, 120, 68, 116, 71, 65, 67, 86, 50, 52, 54, 75, 99, 113, 106, 97, 103, 90, + 79, 82, 48, 107, 121, 99, 116, 121, 66, 114, 115, 71, 71, 74, 86, 65, 105, 65, 106, + 10, 102, 116, 98, 114, 78, 71, 115, 71, 85, 56, 89, 72, 50, 49, 49, 100, 82, 105, + 89, 78, 111, 80, 80, 117, 49, 57, 90, 112, 47, 122, 101, 56, 74, 109, 104, 117, + 106, 66, 48, 111, 66, 119, 61, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, + 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, + 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, + 10, 77, 73, 73, 67, 106, 122, 67, 67, 65, 106, 83, 103, 65, 119, 73, 66, 65, 103, + 73, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 85, + 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 67, 103, 89, 73, 75, 111, 90, + 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 97, 68, 69, 97, 77, 66, 103, 71, 65, + 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, + 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, + 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 10, 99, + 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, + 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, + 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, + 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 66, 52, + 88, 68, 84, 69, 52, 77, 68, 85, 121, 77, 84, 69, 119, 78, 68, 85, 120, 77, 70, 111, + 88, 68, 84, 81, 53, 77, 84, 73, 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, + 119, 97, 68, 69, 97, 77, 66, 103, 71, 10, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, + 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, + 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, + 100, 71, 86, 115, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 10, 97, 87, + 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, + 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, + 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, + 89, 84, 10, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, + 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, + 68, 81, 103, 65, 69, 67, 54, 110, 69, 119, 77, 68, 73, 89, 90, 79, 106, 47, 105, + 80, 87, 115, 67, 122, 97, 69, 75, 105, 55, 10, 49, 79, 105, 79, 83, 76, 82, 70, + 104, 87, 71, 106, 98, 110, 66, 86, 74, 102, 86, 110, 107, 89, 52, 117, 51, 73, 106, + 107, 68, 89, 89, 76, 48, 77, 120, 79, 52, 109, 113, 115, 121, 89, 106, 108, 66, 97, + 108, 84, 86, 89, 120, 70, 80, 50, 115, 74, 66, 75, 53, 122, 108, 75, 79, 66, 10, + 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, + 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, + 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 66, 103, 78, 86, 72, 82, + 56, 69, 83, 122, 66, 74, 10, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, + 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, + 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, + 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 10, 90, 87, 119, + 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, + 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, + 81, 52, 69, 70, 103, 81, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, + 103, 55, 83, 86, 10, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 68, + 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, + 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 65, + 102, 56, 67, 65, 81, 69, 119, 67, 103, 89, 73, 10, 75, 111, 90, 73, 122, 106, 48, + 69, 65, 119, 73, 68, 83, 81, 65, 119, 82, 103, 73, 104, 65, 79, 87, 47, 53, 81, + 107, 82, 43, 83, 57, 67, 105, 83, 68, 99, 78, 111, 111, 119, 76, 117, 80, 82, 76, + 115, 87, 71, 102, 47, 89, 105, 55, 71, 83, 88, 57, 52, 66, 103, 119, 84, 119, 103, + 10, 65, 105, 69, 65, 52, 74, 48, 108, 114, 72, 111, 77, 115, 43, 88, 111, 53, 111, + 47, 115, 88, 54, 79, 57, 81, 87, 120, 72, 82, 65, 118, 90, 85, 71, 79, 100, 82, 81, + 55, 99, 118, 113, 82, 88, 97, 113, 73, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, + 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 0, + ] + .into(), + qe_identity: [ + 123, 34, 101, 110, 99, 108, 97, 118, 101, 73, 100, 101, 110, 116, 105, 116, 121, + 34, 58, 123, 34, 105, 100, 34, 58, 34, 84, 68, 95, 81, 69, 34, 44, 34, 118, 101, + 114, 115, 105, 111, 110, 34, 58, 50, 44, 34, 105, 115, 115, 117, 101, 68, 97, 116, + 101, 34, 58, 34, 50, 48, 50, 52, 45, 49, 50, 45, 48, 53, 84, 49, 49, 58, 52, 54, + 58, 49, 50, 90, 34, 44, 34, 110, 101, 120, 116, 85, 112, 100, 97, 116, 101, 34, 58, + 34, 50, 48, 50, 53, 45, 48, 49, 45, 48, 52, 84, 49, 49, 58, 52, 54, 58, 49, 50, 90, + 34, 44, 34, 116, 99, 98, 69, 118, 97, 108, 117, 97, 116, 105, 111, 110, 68, 97, + 116, 97, 78, 117, 109, 98, 101, 114, 34, 58, 49, 55, 44, 34, 109, 105, 115, 99, + 115, 101, 108, 101, 99, 116, 34, 58, 34, 48, 48, 48, 48, 48, 48, 48, 48, 34, 44, + 34, 109, 105, 115, 99, 115, 101, 108, 101, 99, 116, 77, 97, 115, 107, 34, 58, 34, + 70, 70, 70, 70, 70, 70, 70, 70, 34, 44, 34, 97, 116, 116, 114, 105, 98, 117, 116, + 101, 115, 34, 58, 34, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 34, 44, 34, 97, + 116, 116, 114, 105, 98, 117, 116, 101, 115, 77, 97, 115, 107, 34, 58, 34, 70, 66, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 34, 44, 34, 109, 114, 115, 105, 103, 110, 101, + 114, 34, 58, 34, 68, 67, 57, 69, 50, 65, 55, 67, 54, 70, 57, 52, 56, 70, 49, 55, + 52, 55, 52, 69, 51, 52, 65, 55, 70, 67, 52, 51, 69, 68, 48, 51, 48, 70, 55, 67, 49, + 53, 54, 51, 70, 49, 66, 65, 66, 68, 68, 70, 54, 51, 52, 48, 67, 56, 50, 69, 48, 69, + 53, 52, 65, 56, 67, 53, 34, 44, 34, 105, 115, 118, 112, 114, 111, 100, 105, 100, + 34, 58, 50, 44, 34, 116, 99, 98, 76, 101, 118, 101, 108, 115, 34, 58, 91, 123, 34, + 116, 99, 98, 34, 58, 123, 34, 105, 115, 118, 115, 118, 110, 34, 58, 52, 125, 44, + 34, 116, 99, 98, 68, 97, 116, 101, 34, 58, 34, 50, 48, 50, 52, 45, 48, 51, 45, 49, + 51, 84, 48, 48, 58, 48, 48, 58, 48, 48, 90, 34, 44, 34, 116, 99, 98, 83, 116, 97, + 116, 117, 115, 34, 58, 34, 85, 112, 84, 111, 68, 97, 116, 101, 34, 125, 93, 125, + 44, 34, 115, 105, 103, 110, 97, 116, 117, 114, 101, 34, 58, 34, 55, 55, 53, 57, 54, + 101, 102, 102, 51, 101, 101, 101, 56, 99, 100, 51, 101, 52, 101, 54, 50, 48, 48, + 56, 102, 57, 97, 102, 97, 100, 100, 51, 51, 51, 101, 57, 102, 56, 100, 99, 56, 51, + 55, 102, 101, 54, 51, 50, 50, 53, 54, 56, 49, 52, 55, 100, 97, 57, 56, 99, 56, 99, + 57, 55, 99, 53, 99, 102, 54, 50, 54, 52, 102, 51, 98, 48, 100, 52, 55, 99, 99, 97, + 97, 54, 49, 98, 49, 98, 53, 97, 49, 101, 56, 99, 53, 53, 51, 97, 49, 54, 51, 50, + 50, 50, 51, 55, 99, 99, 57, 48, 48, 49, 102, 50, 100, 97, 100, 49, 56, 51, 52, 52, + 57, 54, 53, 52, 49, 49, 34, 125, 0, + ] + .into(), + }; + + let report_data = hex::decode("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); + + let mrsigner = + hex::decode("3b909bb3658ff42a1e877b8806fdab857f70dfc90244270c12ec2459c98d191a") + .unwrap(); + + check_quote( + "e, + Some(&collateral), + current_time as i64, + &mrsigner, + &report_data, + sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OK, + ) + .context("check_quote")?; + Ok(()) + } } diff --git a/packages/teepot/default.nix b/packages/teepot/default.nix index fbc280f..a8f64a0 100644 --- a/packages/teepot/default.nix +++ b/packages/teepot/default.nix @@ -1,10 +1,12 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2024 Matter Labs -{ teepotCrate }: teepotCrate.craneLib.buildPackage ( +{ lib, pkgs, makeWrapper, teepotCrate }: teepotCrate.craneLib.buildPackage ( teepotCrate.commonArgs // { pname = "teepot"; inherit (teepotCrate) cargoArtifacts; + nativeBuildInputs = teepotCrate.commonArgs.nativeBuildInputs ++ [ makeWrapper ]; + passthru = { inherit (teepotCrate) rustPlatform rustVersion @@ -28,6 +30,7 @@ "verify_attestation" "verify_era_proof_attestation" ]; + postInstall = '' removeReferencesToVendoredSources "$out" "$cargoVendorDir" removeReferencesToVendoredSources "$out" "${teepotCrate.rustVersion}/lib/rustlib/" @@ -38,6 +41,11 @@ echo -n "''${!i} " >> $out/nix-support/propagated-user-env-packages binname=''${i//_/-} mv "$out/bin/$binname" "''${!i}/bin/" + + makeWrapper "''${!i}/bin/$binname" "''${!i}/bin/$binname-dcap" \ + --prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath [ pkgs.nixsgx.sgx-dcap.quote_verify pkgs.nixsgx.sgx-dcap.default_qpl pkgs.curl ]}" \ + --set-default QCNL_CONF_PATH "${pkgs.nixsgx.sgx-dcap.default_qpl}/etc/sgx_default_qcnl.conf" + done rmdir "$out/bin" '';