Skip to content

feat(wasm): default-enable builtin-as mode (in-process AS, no external AS)#165

Closed
imlk0 wants to merge 9 commits into
masterfrom
wasm-as-builtin
Closed

feat(wasm): default-enable builtin-as mode (in-process AS, no external AS)#165
imlk0 wants to merge 9 commits into
masterfrom
wasm-as-builtin

Conversation

@imlk0

@imlk0 imlk0 commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

The tng-wasm browser SDK now default-enables builtin-as mode, so it can verify a server's attestation in-process — no external Attestation Service (AS) / ITA process required. The browser SDK becomes fully self-contained for trust-all/sample scenarios.

Background

Native builtin-as (__builtin-as feature) embeds the trustee attestation-service crate in-process. That crate has an unconditional openssl dependency with no wasm32-unknown-unknown target, so it cannot be in the wasm dependency graph at all. A separate, pure-Rust wasm builtin-AS was therefore implemented.

Approach

  • New __builtin-as-wasm feature (pure-Rust only — no attestation-service/rvps/tempfile), default-enabled for the wasm SDK via tng-wasmtng's feature.
  • WasmBuiltinCocoConverter (rats-cert): generates an ECDSA P-256 key with rcgen, signs an EAR-shaped JWT with jsonwebtoken embedding the AS public JWK in the JWT header. Claims shape taken directly from CommonCocoVerifier::verify_evidence_internal's contract.
  • BuiltinCocoVerifier::new_insecure(): reuses the existing wasm-compatible TokenVerifier/CommonCocoVerifier, trusting the JWK embedded in the token header (insecure_key: true — a closed system: the same TNG instance signs and verifies), mirroring native builtin semantics.
  • Dispatch wired in tng/src/tunnel/ra_context.rs with precise per-arm cfg gates (all(not(wasm), __builtin-as) native / all(wasm, __builtin-as-wasm) wasm). Native builtin-as is unchanged.

Verifier limitation (by design)

On wasm there is no real TEE evidence appraisal — the TEE verifier crates (TDX/SGX/SNP/CSV/TPM) have no wasm32-unknown-unknown targets. The wasm builtin-as supports trust_all (and hardware_only, which degrades to trust-all); hardware_with_reference_values/inline/path rego policies are rejected. Sample reference values are accepted for config compatibility but not appraised (the token is always affirming). Real TEE verification must use an external AS (as_type: "restful") or native TNG. This matches the goal: get builtin-as core functionality compiling on wasm, dropping verifiers that lack wasm targets.

Tests

  • Native sign→verify round-trip (cargo test -p rats-cert --features __builtin-as-wasm --lib) — the correctness gate.
  • E2E js_sdk_builtin_as — drives the real wasm SDK through the OHTTP tunnel with as_type: "builtin", requiring only make test-dep-aa (no make test-dep-as). GET+POST, 5 repeats, PASS.
  • make wasm-build-debug — whole wasm SDK builds with builtin-as compiled in.
  • Native builtin-as tests (116/0) — no regression.

Docs (bilingual EN/ZH)

  • tng-wasm/README{,_zh}.mdas_type: "builtin" for the browser SDK, default-enabled build, verifier limits.
  • docs/architecture{,_zh}.md — "Builtin-AS on WASM" subsection.
  • docs/developer{,_zh}.md — wasm build default-enables builtin-as; js_sdk_builtin_as needs only make test-dep-aa; __builtin-as/__builtin-as-wasm per-target build-flag constraint.
  • docs/version_compatibility{,_zh}.md — additive row (no break to existing as_type: "restful" configs).

imlk0 added 9 commits July 10, 2026 18:59
Move PolicyConfig / ReferenceValueConfig out of the native-only
converter/builtin.rs into a shared converter/builtin_config.rs module
gated any(__builtin-as, __builtin-as-wasm). Inline reference-value
payloads are typed serde_json::Value (not trustee types like Provenance)
so the same config surface compiles under both the native builtin-AS
(__builtin-as) and the wasm pure-Rust builtin-AS (__builtin-as-wasm).

The two old payload-config enums (SampleProvenancePayloadConfig,
SlsaReferenceValuePayloadConfig) are unified into a single
ReferenceValuePayloadConfig since both had the same Inline/Path shape,
differing only in the trustee content type.

In native builtin.rs, load_reference_values converts the serde_json::Value
payloads back into the concrete trustee types (Provenance /
ReferenceValueListPayload) via serde_json::from_value at the
attestation-service call site, preserving existing logic and comments.

Update downstream re-exports (rats-cert verify.rs, tng config/ra.rs and
tunnel/ra_context.rs) and all test constructions to use the unified
serde_json::Value payloads.
Add WasmBuiltinCocoConverter that generates an ECDSA P-256 key with
rcgen and signs an EAR-shaped JWT with jsonwebtoken, embedding the AS
public JWK in the JWT header. The paired BuiltinCocoVerifier (via
new_insecure, insecure_key=true) trusts that JWK in the closed builtin
system.

The converter mirrors native BuiltinCocoConverter but does not depend
on the attestation-service crate (whose openssl dep has no wasm target).
Appraisal is TrustAll only — no TEE verifier or regorus policy engine
compiles for wasm.

Module and enum arm are gated on __builtin-as-wasm (no target_arch
predicate) so a native #[cfg(test)] round-trip validates sign/verify
correctness. The verifier's new_wasm() is renamed to new_insecure()
with the same feature-only gate, and its work_dir field becomes
Option<Arc<...>> to allow the insecure path to set None.

Native round-trip test passes: convert signs a token, verify_evidence
accepts it end-to-end with empty runtime-data subset check.
Widen the Builtin config variant gates in tng/src/config/ra.rs from
`#[cfg(feature = "__builtin-as")]" to `#[cfg(any(feature = "__builtin-as",
feature = "__builtin-as-wasm"))]" so the `as_type: "builtin"" config
surface is available on both native and wasm. Update the match arms in
into_checked (validation) and the re-exported config enums accordingly.

Restructure the VerifyContext::from_verify_args BackgroundCheck dispatch in
tng/src/tunnel/ra_context.rs to target-select between the native
BuiltinCocoConverter (on native with __builtin-as) and the wasm
WasmBuiltinCocoConverter (on wasm with __builtin-as-wasm), routing each
into the matching CocoConverter enum arm (Builtin / WasmBuiltin).

Widen the factory.rs Builtin bail arms to the same any(...) gate so the
match stays exhaustive on wasm, and add Builtin arms to the
tng-wasm fetch/attestation.rs exhaustive matches (which expose a
non-sensitive subset of config to JS).

On native the dispatch is unchanged (native arm only); on wasm the
WasmBuiltinCocoConverter + BuiltinCocoVerifier path is now reachable.
Add a js_sdk_builtin_as integration test mirroring js_sdk_http's
background_check case but with the BrowserClient (wasm SDK) verify config
using as_type: "builtin" instead of as_addr/as_type: restful. The wasm
SDK converts + verifies the server's attestation token in-process, so the
test requires only make test-dep-aa (AA + ASR) and must NOT require
make test-dep-as (the external AS) -- that is the whole point of
builtin-as.

The server-side attest block is unchanged (still uses the AA to produce
evidence); builtin-as only replaces the AS (convert/verify side).

A dedicated builtin_check_response JS helper is used instead of the
harness's common_check_response, because the builtin path intentionally
omits attest_info.as_addr and attest_info.policy_ids (no remote AS),
which the default coco background_check assertions require.
@shankailun-aliyun

Copy link
Copy Markdown
Collaborator

@imlk0 ,您好,您的请求已接收,请耐心等待结果。

@shankailun-aliyun

Copy link
Copy Markdown
Collaborator

@imlk0 ,您好,未检测到有镜像需要构建,如需重新检测请评论 /start

@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 59.45946% with 30 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
rats-cert/src/tee/coco/converter/builtin.rs 65.07% 20 Missing and 2 partials ⚠️
rats-cert/src/tee/coco/evidence.rs 0.00% 8 Missing ⚠️

📢 Thoughts on this report? Let us know!

@imlk0 imlk0 closed this Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants