Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2df90cd
WIP: Add policy validation support
kvinwang Feb 10, 2026
a74b476
WIP: policy branch checkpoint
kvinwang Feb 10, 2026
17beb8c
feat: lazy SupplementalData for gas-efficient verify()
kvinwang Mar 5, 2026
2268e84
fix: eliminate redundant JSON/CRL parsing in Rego path
kvinwang Mar 6, 2026
f8d63d7
refactor: rename QuotePolicy→SimplePolicy, split policy into submodules
kvinwang Mar 10, 2026
fa9a36d
docs: add policy guide, rename into_report → into_report_unchecked
kvinwang Mar 10, 2026
9bbc97a
merge: integrate origin/master (Go bindings, danger-allow-tcb-override)
kvinwang Mar 10, 2026
5ce8c2f
refactor: unify SupplementalData, impl Policy for Rego, restore flat …
kvinwang Mar 10, 2026
cf71c19
feat: full Intel QAL compat — rand.intn, final_appraisal_result, qe_i…
kvinwang Mar 10, 2026
e0c8f43
docs: fix ignored doc tests to compile (ignore → no_run)
kvinwang Mar 10, 2026
6555659
docs: clean up duplicate SimplePolicy doc comment
kvinwang Mar 10, 2026
14bb557
fix: update cli for two-phase verify API, fix rustfmt
kvinwang Mar 10, 2026
4a78472
fix: update Python test_case.py for two-phase verify API
kvinwang Mar 10, 2026
125d242
fix: match expected error message for Revoked TCB status
kvinwang Mar 10, 2026
4f0a271
fix: restore js_verify and js_verify_with_root_ca WASM bindings
kvinwang Mar 10, 2026
d31f9e1
fix: separate QE grace from platform grace
kvinwang Mar 11, 2026
482995f
fix: preserve verified PCK chain for supplemental data
kvinwang Mar 11, 2026
8fb59a0
docs: note upstream TODO for platform_provider_id
kvinwang Mar 11, 2026
6566261
chore: fix all-features clippy warnings
kvinwang Mar 11, 2026
e1e05e5
fix: accept kwargs in python collateral constructor
kvinwang Mar 11, 2026
2415315
feat: two-phase WASM API with QuoteVerifier, SimplePolicy, QuoteVerif…
kvinwang Mar 11, 2026
1a3d87f
fix: update remaining JS/TS files to QuoteVerifier API, add accepted_…
kvinwang Mar 11, 2026
f3f349c
fix: add js_class annotations for SimplePolicy and QuoteVerificationR…
kvinwang Mar 11, 2026
5bb08f7
fix: check grace period mutual exclusivity before data-dependent checks
kvinwang Mar 11, 2026
a01b284
fix: match OPA semantics for rand.intn with n <= 0
kvinwang Mar 11, 2026
0b3977e
fix: remove grace period mutual exclusivity constraint
kvinwang Mar 11, 2026
e6b8b16
feat: expose Rego policies to python and wasm bindings
kvinwang Mar 11, 2026
a329512
test: add Rego binding examples and coverage
kvinwang Mar 11, 2026
d9f9dde
refactor: switch SimplePolicy advisories to blacklist semantics
kvinwang Mar 12, 2026
7b9baf1
feat: derive QuoteVerificationResult and nested types
kvinwang Mar 12, 2026
ebd1f0d
fix: reject pre-epoch RFC3339 timestamps
kvinwang Mar 12, 2026
73246f7
feat: add strict mode to CLI verify
kvinwang Mar 12, 2026
4c2e3b3
feat: add ppid() accessor to QuoteVerificationResult
kvinwang Mar 12, 2026
e508e1c
refactor: preserve PCK pce_id as raw bytes
kvinwang Mar 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ signature = { version = "2.2", default-features = false, optional = true }

dcap-qvl-webpki = { version = "=0.103.4", features = ["alloc"] }

# Rego policy engine (optional, for Intel QAL compatibility)
regorus = { version = "0.9", optional = true, default-features = false, features = [
"arc", "time", "regex", "semver",
] }


[dev-dependencies]
hex-literal = "1.1.0"
Expand All @@ -89,7 +94,7 @@ name = "dcap_qvl"
crate-type = ["cdylib", "staticlib", "rlib"]

[features]
default = ["std", "report", "ring", "rustcrypto"]
default = ["std", "report", "ring", "rustcrypto", "rego"]
std = [
"serde/std",
"scale/std",
Expand All @@ -106,13 +111,14 @@ std = [
borsh = ["dep:borsh"]
borsh_schema = ["borsh", "borsh/unstable__schema"]
report = ["std", "tracing", "futures", "reqwest"]
js = ["getrandom/js", "serde-wasm-bindgen", "wasm-bindgen"]
python = ["pyo3", "pyo3-async-runtimes", "tokio", "std", "report", "ring"]
js = ["getrandom/js", "serde-wasm-bindgen", "wasm-bindgen", "rustcrypto", "rego"]
python = ["pyo3", "pyo3-async-runtimes", "tokio", "std", "report", "ring", "rego"]
go = ["std", "ring", "serde_json"]
ring = ["dep:ring", "dcap-qvl-webpki/ring", "_anycrypto"]
rustcrypto = ["dep:sha2", "dep:p256", "dep:signature", "dcap-qvl-webpki/rustcrypto", "_anycrypto"]
_anycrypto = []
contract = ["getrandom"]
rego = ["dep:regorus", "std", "serde_json", "getrandom"]

# Enables the dangerous_verify_with_tcb_override() function, allowing TCB checks to be overridden
# with custom collateral. Normal verify() is not affected.
Expand Down
82 changes: 77 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ use dcap_qvl::verify::rustcrypto::verify;

```rust
use dcap_qvl::collateral::get_collateral;
// Use explicit backend for predictable behavior
use dcap_qvl::verify::ring::verify;
use dcap_qvl::verify::{QuoteVerifier, ring};
use dcap_qvl::SimplePolicy;
use dcap_qvl::PHALA_PCCS_URL;

#[tokio::main]
Expand All @@ -86,11 +86,40 @@ async fn main() {
let collateral = get_collateral(&pccs_url, &quote).await.expect("failed to get collateral");

let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs();
let report = verify(&quote, &collateral, now).expect("failed to verify quote");

// Phase 1: Cryptographic verification
let verifier = QuoteVerifier::new_prod(ring::backend());
let result = verifier.verify(&quote, collateral, now).expect("verification failed");

// Phase 2: Policy validation
let report = result.validate(&SimplePolicy::strict(now)).expect("policy failed");
println!("{:?}", report);
}
```

# Policy Validation

After cryptographic verification, apply a **policy** to check TCB status, advisory IDs, collateral freshness, and platform flags.

```rust
use dcap_qvl::{SimplePolicy, TcbStatus};
use core::time::Duration;

// Strict: only UpToDate (default)
let policy = SimplePolicy::strict(now);

// Relaxed: accept OutOfDate + 30-day collateral grace
let policy = SimplePolicy::strict(now)
.allow_status(TcbStatus::OutOfDate)
.collateral_grace_period(Duration::from_secs(30 * 24 * 3600))
.reject_advisory("INTEL-SA-00334")
.reject_advisories(&["INTEL-SA-00615", "INTEL-SA-00809"]);
```

For custom validation logic, implement the `Policy` trait directly.

See [docs/policy.md](docs/policy.md) for the complete policy guide, including grace period semantics, platform flags, `RegoPolicy`, and custom `Policy` trait examples.

<!-- cargo-rdme end -->

# Python Bindings
Expand All @@ -112,18 +141,61 @@ make test_python_versions

```python
import asyncio
import time
import dcap_qvl

async def main():
quote_data = open("quote.bin", "rb").read()

# Get collateral and verify in one step (defaults to Phala PCCS)
# Get collateral and perform crypto verification (defaults to Phala PCCS)
result = await dcap_qvl.get_collateral_and_verify(quote_data)
print(f"Status: {result.status}")

# Validate with SimplePolicy
now = int(time.time())
policy = dcap_qvl.SimplePolicy.strict(now)
report = result.validate(policy)
print(f"Status: {report.status}")

asyncio.run(main())
```

You can also validate with Intel QAL-compatible Rego policies:

```python
policy_json = r'''{
"environment": {
"class_id": "3123ec35-8d38-4ea5-87a5-d6c48b567570"
},
"reference": {
"accepted_tcb_status": ["UpToDate"],
"collateral_grace_period": 0
}
}'''

rego_policy = dcap_qvl.RegoPolicy(policy_json)
report = result.validate(rego_policy)
```

And from JS/WASM:

```js
import init, { QuoteVerifier, SimplePolicy, RegoPolicy } from "@phala/dcap-qvl-web";

await init();

const collateral = await QuoteVerifier.get_collateral(pccsUrl, quoteBytes);
const verifier = new QuoteVerifier();
const now = BigInt(Math.floor(Date.now() / 1000));
const result = verifier.verify(quoteBytes, collateral, now);

const simplePolicy = new SimplePolicy(now);
const report1 = result.validate(simplePolicy);

const regoPolicy = new RegoPolicy(policyJson);
const result2 = verifier.verify(quoteBytes, collateral, now);
const report2 = result2.validate_rego(regoPolicy);
```

See [python-bindings/](python-bindings/) for complete documentation, examples, and testing information.

# License
Expand Down
6 changes: 6 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ git clone https://github.com/Phala-Network/dcap-qvl.git
cd dcap-qvl/cli
cargo run -- decode-quote --hex ../sample/tdx-quote.hex | jq .
```

Strict verification:

```sh
cargo run -- verify --strict --hex ../sample/tdx-quote.hex
```
Loading
Loading