|
2 | 2 |
|
3 | 3 | [](https://github.com/datachainlab/zkdcap/actions/workflows/test.yml) |
4 | 4 |
|
5 | | -zkDCAP is a Rust library for verifying the ECDSA Quote generated by Intel SGX Data Center Attestation Primitives (DCAP). It also integrates with the RISC Zero zkVM, enabling cost-effective verification on Ethereum and other EVM-based blockchains. |
| 5 | +## Overview |
| 6 | + |
| 7 | +zkDCAP is a guest program that runs inside the [RISC Zero zkVM](https://github.com/risc0/risc0), designed to verify Intel SGX/TDX DCAP quotes and generate a zero-knowledge proof (ZKP) of the result. |
| 8 | + |
| 9 | +Since verifying a quote directly on-chain (e.g., on Ethereum or other EVM-compatible blockchains) is extremely gas-intensive, zkDCAP significantly reduces gas costs by offloading the verification process to the zkVM and proving its validity through ZKP. |
| 10 | + |
| 11 | +The verification logic is based on Intel's reference implementation: [SGX-TDX-DCAP-QuoteVerificationLibrary](https://github.com/intel/SGX-TDX-DCAP-QuoteVerificationLibrary/blob/812e0fa140a284b772b2d8b08583c761e23ec3b3/). |
| 12 | + |
| 13 | +zkDCAP is designed to minimize trust assumptions, requiring trust only in Intel's Root CA certificate. However, performing quote verification inside a zkVM and validating the result via ZKP introduces several challenges. This README outlines these challenges and our design solutions. |
| 14 | + |
| 15 | +## Design Considerations |
| 16 | + |
| 17 | +### Validity Period |
| 18 | + |
| 19 | +#### Background |
| 20 | + |
| 21 | +DCAP quote verification requires multiple components of collateral—including certificates, CRLs, and TCB info—to determine the platform's TCB status. |
| 22 | + |
| 23 | +Each collateral component comes with its own validity period. Verifiers must ensure that the **current time falls within all of these periods**. |
| 24 | + |
| 25 | +If expired collateral (e.g., an outdated TCB info) is used, quotes from already compromised SGX environments may be mistakenly accepted. |
| 26 | + |
| 27 | +#### Our Approach |
| 28 | + |
| 29 | +In a typical quote verification process, the verifier checks whether the current time is within the validity range of the collateral. |
| 30 | + |
| 31 | +However, it is not practical to securely obtain a trusted current timestamp within the zkVM, as the timestamp provided by the prover may have been tampered with. |
| 32 | + |
| 33 | +To solve this, zkDCAP adopts the following two-step approach: |
| 34 | + |
| 35 | +1. Inside the zkVM, it computes the **intersection of the validity periods** across all collateral components and includes this range in the output. |
| 36 | +2. The on-chain verifier (e.g., a smart contract) verifies that the **current block timestamp** falls within this range when verifying the ZKP. |
| 37 | + |
| 38 | +This ensures that the validity check can be enforced **without requiring the verifier to trust any timestamp provided by the prover**. |
| 39 | + |
| 40 | +**Note:** Regarding collateral availability, [Intel documentation](https://cc-enabling.trustedservices.intel.com/intel-tdx-enabling-guide/02/infrastructure_setup/#collateral-caching-service) and our observation of PCS API behavior show that each collateral component typically has a validity period of ~30 days after download, which provides sufficient availability for verification. |
| 41 | + |
| 42 | +### TCB Evaluation Data Number (TCB-R Counter) |
| 43 | + |
| 44 | +#### Background |
| 45 | + |
| 46 | +Intel periodically updates TCB info for SGX/TDX platforms through **TCB Recovery** events. |
| 47 | + |
| 48 | +Each update is assigned a unique **TCB Evaluation Data Number**, also known as the **TCB-R Counter**. |
| 49 | + |
| 50 | +Intel's Provisioning Certification Service (PCS) API allows clients to retrieve TCB information corresponding to different TCB-R Counters using the `update` query parameter. |
| 51 | +For example, the `?update=standard` parameter may return an older TCB info version (commonly up to 12 months prior to the latest). This mechanism is intended to support transitional compatibility, but it introduces a potential security risk. |
| 52 | + |
| 53 | +Because the TCB status of a platform is evaluated based on the TCB info version used during verification, using an outdated TCB-R Counter may lead to a false "UpToDate" result for platforms that have been deprecated or have since become vulnerable. |
| 54 | + |
| 55 | +Therefore, to ensure the correctness and freshness of the attestation, verifiers **must validate quotes against the latest available TCB-R Counter**. |
| 56 | + |
| 57 | +#### Our Approach |
| 58 | + |
| 59 | +zkDCAP includes in its output the **minimum TCB Evaluation Data Number (TCB-R Counter)** among those found in the collateral used during verification. This allows the on-chain verifier to determine which version of TCB info the TCB status is based on. |
| 60 | + |
| 61 | +By comparing this value with the latest TCB-R Counter tracked on-chain, the verifier can ensure that the verification result reflects a sufficiently recent TCB update. This mechanism prevents acceptance of attestations based on outdated TCB data. |
| 62 | + |
| 63 | +For example, in the LCP Client, zkDCAP is integrated with a mechanism that maintains and updates the latest TCB-R Counter. |
| 64 | + |
| 65 | +As long as **at least one operator continuously fetches the latest TCB data from Intel PCS**, the LCP Client ensures that all operators perform verification using up-to-date TCB info. |
| 66 | + |
| 67 | +See more at: [https://docs.lcp.network/protocol/lcp-client-zkdcap](https://docs.lcp.network/protocol/lcp-client-zkdcap) |
| 68 | + |
| 69 | +## Verifier Program |
| 70 | + |
| 71 | +The guest program that performs DCAP quote verification inside the zkVM is implemented in [main.rs](./zkvm/risc0/guest/src/bin/main.rs). |
| 72 | +It reads a serialized quote, collateral, and the current timestamp as input, verifies the quote using the `verify_quote` function, and commits the verification result as a serialized output. |
| 73 | + |
| 74 | +This program is compiled into a zkVM guest binary and used to generate the zero-knowledge proof (ZKP) that is verified on-chain. |
| 75 | + |
| 76 | +### Inputs |
| 77 | + |
| 78 | +zkDCAP's verifier program takes the following three inputs: |
| 79 | + |
| 80 | +1. **Quote** |
| 81 | + |
| 82 | + - A DCAP Quote (SGX/TDX, version 3 or 4) |
| 83 | + - Provided as `Quote::V3(QuoteV3)` or `Quote::V4(QuoteV4)` |
| 84 | + |
| 85 | +2. **QvCollateral** |
| 86 | + |
| 87 | + The collateral required for DCAP quote verification, typically fetched via PCS/PCCS APIs. The following Rust struct defines the format of the `QvCollateral` input, which contains the collateral data used for verification: |
| 88 | + |
| 89 | + ```rust |
| 90 | + #[derive(Clone, Debug, Default)] |
| 91 | + pub struct QvCollateral { |
| 92 | + pub tcb_info_json: String, |
| 93 | + pub qe_identity_json: String, |
| 94 | + pub sgx_intel_root_ca_der: Vec<u8>, |
| 95 | + pub sgx_tcb_signing_der: Vec<u8>, |
| 96 | + pub sgx_intel_root_ca_crl_der: Vec<u8>, |
| 97 | + pub sgx_pck_crl_der: Vec<u8>, |
| 98 | + } |
| 99 | + ``` |
| 100 | + |
| 101 | + - `tcb_info_json`: Platform TCB info (e.g., TCB levels, SVN) |
| 102 | + - `qe_identity_json`: QE identity including MRSIGNER |
| 103 | + - `sgx_intel_root_ca_der`: Intel SGX Root CA certificate (DER) |
| 104 | + - `sgx_tcb_signing_der`: TCBInfo signing cert (DER) |
| 105 | + - `sgx_intel_root_ca_crl_der` / `sgx_pck_crl_der`: CRLs for revocation checks |
| 106 | + |
| 107 | +3. **current_time** |
| 108 | + |
| 109 | + - UNIX timestamp (in seconds), provided by the prover |
| 110 | + - zkDCAP uses it only to **compute the intersection of collateral validity periods** |
| 111 | + - The actual time check is performed by the verifier using **on-chain block timestamp**, without relying on the prover to supply a trusted timestamp |
| 112 | + |
| 113 | +### Output |
| 114 | + |
| 115 | +#### `QuoteVerificationOutput` |
| 116 | + |
| 117 | +The result of the verification process, which includes all necessary data to validate the quote and the integrity of the collateral. |
| 118 | + |
| 119 | +```rust |
| 120 | +#[derive(Debug, Clone, PartialEq, Eq)] |
| 121 | +pub struct QuoteVerificationOutput { |
| 122 | + pub version: u16, |
| 123 | + pub quote_version: u16, |
| 124 | + pub tee_type: u32, |
| 125 | + pub status: Status, |
| 126 | + pub min_tcb_evaluation_data_number: u32, |
| 127 | + pub fmspc: [u8; 6], |
| 128 | + pub sgx_intel_root_ca_hash: [u8; 32], |
| 129 | + pub validity: Validity, |
| 130 | + pub quote_body: QuoteBody, |
| 131 | + pub advisory_ids: Vec<String>, |
| 132 | +} |
| 133 | +``` |
| 134 | + |
| 135 | +Key fields: |
| 136 | + |
| 137 | +1. **min_tcb_evaluation_data_number** |
| 138 | + Minimum TCB evaluation data number(TCB-R Counter) from the collateral used during verification. |
| 139 | + The verifier ensures that this value is greater than or equal to the on-chain configured minimum TCB-R Counter. |
| 140 | + |
| 141 | +2. **validity** |
| 142 | + Validity intersection (NotBefore / NotAfter) of all collateral. |
| 143 | + The verifier checks if the current block timestamp falls within this range. |
| 144 | + |
| 145 | +3. **status** and **advisory_ids** |
| 146 | + The resulting TCB status and any associated Intel security advisory IDs (e.g., `INTEL-SA-xxxx`). |
| 147 | + |
| 148 | +4. **sgx_intel_root_ca_hash** |
| 149 | + Keccak-256 hash of the Intel SGX Root CA certificate. The verifier **MUST** ensure this matches the hash of the expected trusted root CA certificate. |
| 150 | + |
| 151 | +5. **quote_body** |
| 152 | + Includes enclave measurement (`MRENCLAVE`) and attributes from the verified quote. |
| 153 | + |
| 154 | +This output, when verified together with the ZKP on-chain, enables gas-efficient and secure DCAP quote attestation with significantly reduced gas costs. |
| 155 | + |
| 156 | +## Security Audit |
| 157 | + |
| 158 | +zkDCAP was audited as part of its integration into the LCP Client. |
| 159 | + |
| 160 | +The audit was conducted by [Quantstamp](https://quantstamp.com/). You can find the report here: |
| 161 | +[https://certificate.quantstamp.com/full/datachain-lcp-zk-dcap/15bac7cd-3b90-47c7-a25e-b0c3214c6630/index.html](https://certificate.quantstamp.com/full/datachain-lcp-zk-dcap/15bac7cd-3b90-47c7-a25e-b0c3214c6630/index.html) |
| 162 | + |
| 163 | +## Build Instructions |
| 164 | + |
| 165 | +To build the zkDCAP guest program for RISC Zero, run the following command: |
| 166 | + |
| 167 | +```bash |
| 168 | +ZKDCAP_RISC0_BUILD=1 cargo build -r --manifest-path=./zkvm/risc0/Cargo.toml |
| 169 | +``` |
| 170 | + |
| 171 | +This will generate the zkVM guest program file here: `./zkvm/risc0/artifacts/dcap-quote-verifier` |
| 172 | + |
| 173 | +**Note:** Ensure that you have the RISC Zero toolchain properly installed before building. |
| 174 | + |
| 175 | +Also, the generated method ID is automatically written to `zkvm/risc0/src/methods.rs`, where it is embedded and used by the prover and verifier to ensure correct proof generation and verification. |
| 176 | + |
| 177 | +## License |
| 178 | + |
| 179 | +This project is licensed under the **Apache 2.0 License**. |
| 180 | + |
| 181 | +## Contributing |
| 182 | + |
| 183 | +Contributions are welcome! Please open issues or pull requests. |
| 184 | + |
| 185 | +## Acknowledgements |
| 186 | + |
| 187 | +- [RISC Zero](https://github.com/risc0/risc0): We thank the RISC Zero team for providing an excellent zkVM. |
| 188 | +- [dcap-rs](https://github.com/automata-network/dcap-rs): Our implementation was initially based on the dcap-rs codebase by Automata. We have since extended it significantly through architectural modifications, enhancements, and adaptations to support zkDCAP's design goals. |
0 commit comments