Add official wolfTPM Rust wrapper crate - #602
Conversation
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Pull request overview
Adds an official wolftpm Rust crate that wraps wolfTPM’s C API via bindgen, provides a safe Rust interface for common TPM 2.0 workflows, and ships integration tests + CI to validate against an in-tree software TPM.
Changes:
- Introduces the
wolftpmcrate with a safe API (Device/Key/KeyBlob/Session/Secret) layered over build-time-generated bindgen FFI. - Implements higher-level features (seal/unseal, PCR, NV, RSA-OAEP, AES-CFB, HMAC, ECDH, persistence, attestation, credential activation, encrypted sessions).
- Adds integration tests, examples, packaging include lists, and a GitHub Actions workflow to build wolfSSL/wolfTPM and run the Rust suite.
Reviewed changes
Copilot reviewed 47 out of 47 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| wrapper/rust/wolftpm/Cargo.toml | Defines the new wolftpm crate, features, and build dependencies |
| wrapper/rust/wolftpm/README.md | Documents build/linking expectations, tests, examples, and API coverage |
| wrapper/rust/wolftpm/build.rs | Generates bindgen FFI, links prebuilt libs, and emits cfgs reflecting C build options |
| wrapper/rust/wolftpm/headers.h | Bindgen shim translation unit for wolfTPM public headers |
| wrapper/rust/wolftpm/src/lib.rs | Crate root: exports safe API, error/Result types, and secret zeroization |
| wrapper/rust/wolftpm/src/sys.rs | FFI module including bindgen output from $OUT_DIR |
| wrapper/rust/wolftpm/src/device.rs | Implements Device open/init/cleanup + RNG + primary key creation |
| wrapper/rust/wolftpm/src/key.rs | Implements templates, key/keyblob lifetimes, serialization, and imports |
| wrapper/rust/wolftpm/src/sign.rs | Adds signing and verification methods on loaded keys |
| wrapper/rust/wolftpm/src/seal.rs | Adds seal/unseal and PCR-policy-based sealing |
| wrapper/rust/wolftpm/src/nv.rs | Adds NV define/write/read/delete and optional NV cert read API |
| wrapper/rust/wolftpm/src/pcr.rs | Adds PCR read/extend helpers |
| wrapper/rust/wolftpm/src/certify.rs | Adds certify + quote attestation APIs and signature marshalling |
| wrapper/rust/wolftpm/src/rsa.rs | Adds RSA-OAEP encrypt/decrypt APIs including explicit OAEP hash |
| wrapper/rust/wolftpm/src/persist.rs | Adds NV-backed key persistence, readback, and eviction |
| wrapper/rust/wolftpm/src/hmac.rs | Adds raw-key HMAC and loaded keyed-hash HMAC APIs |
| wrapper/rust/wolftpm/src/session.rs | Adds parameter-encryption session management with RAII |
| wrapper/rust/wolftpm/src/caps.rs | Adds self-test and capability discovery |
| wrapper/rust/wolftpm/src/symmetric.rs | Adds AES-CFB encrypt/decrypt with TPM-resident symmetric keys |
| wrapper/rust/wolftpm/src/ecdh.rs | Adds ECDH generation + shared-secret derivation APIs |
| wrapper/rust/wolftpm/src/credential.rs | Adds MakeCredential/ActivateCredential support |
| wrapper/rust/wolftpm/examples/create_primary.rs | Minimal example exercising open/RNG/create-primary |
| wrapper/rust/wolftpm/examples/full_flow.rs | End-to-end example walking through major APIs |
| wrapper/rust/wolftpm/tests/common/mod.rs | Shared test harness for connecting to the software TPM |
| wrapper/rust/wolftpm/tests/smoke.rs | Basic integration smoke test |
| wrapper/rust/wolftpm/tests/keys.rs | Tests key creation/loading and blob serialization round-trips |
| wrapper/rust/wolftpm/tests/sign.rs | Tests sign/verify and negative tamper case |
| wrapper/rust/wolftpm/tests/seal.rs | Tests seal/unseal and wrong-auth negative case |
| wrapper/rust/wolftpm/tests/seal_pcr.rs | Tests PCR-bound sealing and invalid selections |
| wrapper/rust/wolftpm/tests/nv.rs | Tests NV create/write/read/delete |
| wrapper/rust/wolftpm/tests/pcr.rs | Tests PCR read/extend behavior |
| wrapper/rust/wolftpm/tests/certify.rs | Tests certify using ECC and RSA AIKs |
| wrapper/rust/wolftpm/tests/quote.rs | Tests PCR quote and invalid PCR selection rejection |
| wrapper/rust/wolftpm/tests/credential.rs | Tests MakeCredential/ActivateCredential round-trip |
| wrapper/rust/wolftpm/tests/ek.rs | Tests EK creation + public export |
| wrapper/rust/wolftpm/tests/persist.rs | Tests persist/readback/evict for persistent handles |
| wrapper/rust/wolftpm/tests/rsa.rs | Tests RSA-OAEP round-trips including OAEP-SHA1 path |
| wrapper/rust/wolftpm/tests/hmac.rs | Tests raw-key and TPM-resident HMAC |
| wrapper/rust/wolftpm/tests/caps.rs | Tests self-test and capabilities |
| wrapper/rust/wolftpm/tests/ecdh.rs | Tests ECDHGen/ECDHGenZ shared secret agreement |
| wrapper/rust/wolftpm/tests/symmetric.rs | Tests AES-CFB encrypt/decrypt round-trip |
| wrapper/rust/wolftpm/tests/import.rs | Tests external RSA/ECC private key import |
| wrapper/rust/include.am | Adds Rust wrapper files to distribution packaging |
| wrapper/rust/README.md | Top-level wrapper README pointing to the crate |
| wrapper/include.am | Includes the Rust wrapper in the overall wrapper build/packaging |
| .github/workflows/rust-test.yml | CI workflow building dependencies and running Rust tests/docs |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #602
No scan targets match the changed files in this PR. Review skipped.
3533eac to
ec340f7
Compare
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #602
No scan targets match the changed files in this PR. Review skipped.
wolfTPM Rust Support
Current public types
DeviceDeviceat a time.Key<'d>Device.KeyBlob<'d>TemplateSession<'d>SecretDerefto&[u8].TpmErrorError/Display/Debug.Result<T>core::result::Result<T, TpmError>.HierarchyOwner,Endorsement,Platform.KeyAlgRsa,EccP256.HashAlgdigest_size()).NvSlot<'d>Attestationcertify/quote: attest bytes, signature, signature algorithm.CapsEcdhResultSecret.CredentialMakeCredentialoutput (encrypted secret + blob) for activation.Public API's
Device— connection, RNG, self-test/capsopen()(cfg: any transport) — open the default TPM (autodetect transport)open_swtpm()(cfg: swtpm) — open against a swtpm/fwTPM socketget_random(buf)(cfg: rng) — fill a buffer from the TPM RNGself_test()(cfg: caps) — run the TPM self-testcapabilities()(cfg: caps) — queryCapsDevice— key creation and importcreate_primary(hierarchy, alg, auth)— create a primary/storage-root key under a hierarchycreate_ek(alg)— create the Endorsement Keycreate_key(parent, template, auth)— create a child key blob (not loaded)create_and_load(parent, template, auth)— create and load a child key in one stepimport_rsa_key(...)(cfg: import) — import an external RSA private keyimport_ecc_key(...)(cfg: import) — import an external ECC private keyDevice— seal / unsealseal(parent, data, auth)(cfg: seal) — seal data to the TPMunseal(...)(cfg: seal) — unseal (returnsSecret)seal_pcr(parent, data, pcr_indices)(cfg: seal) — PCR-policy-bound sealunseal_pcr(...)(cfg: seal) — unseal a PCR-bound blob (returnsSecret)Device— NV storagenv_create(index, size, auth)(cfg: nv) — define an NV indexnv_write(slot, data, offset)(cfg: nv)nv_read(slot, buf, offset)(cfg: nv)nv_delete(index)(cfg: nv)read_cert(nv_handle)(cfg: nvcert) — read an EK certificate from NVDevice— PCRspcr_read(index, hash)(cfg: pcr)pcr_extend(index, hash, digest)(cfg: pcr)Device— attestationcertify(...)— an AIK certifies another object (returnsAttestation)quote(...)— signed PCR quote (returnsAttestation)make_credential(...)—TPM2_MakeCredential(returnsCredential)activate_credential(...)(cfg: ek_policy) —TPM2_ActivateCredential(returnsSecret)Device— persistent handlespersist_key(...)(cfg: persist) — persist a key to an NV persistent handleread_persistent(persistent_handle, auth)(cfg: persist)evict_key(key, hierarchy)(cfg: persist)Device— HMAC and sessionshmac(...)(cfg: hmac) — one-shot raw-key HMACstart_encrypted_session(salt)— start a parameter-encryption sessionKey— identity, sign/verifyhandle()— the TPM handlename()— the object Name (hash of its public area)export_public(pem)(cfg: pubexport) — export the public key as DER or PEMsign_hash(digest)— sign a digestverify_hash(digest, sig)— verify a signatureKey— RSA (OAEP), AES, ECDH, HMACrsa_encrypt(msg)(cfg: rsa) — RSA-OAEP encryptrsa_decrypt(ciphertext)(cfg: rsa) — RSA-OAEP decrypt (returnsSecret)rsa_encrypt_with_hash(msg, hash)(cfg: rsa) — OAEP with an explicit label hash (Microsoft enrollment)rsa_decrypt_with_hash(ciphertext, hash)(cfg: rsa)aes_encrypt(data, iv)(cfg: symmetric) — AES-CFB encryptaes_decrypt(data, iv)(cfg: symmetric) — AES-CFB decrypt (returnsSecret)ecdh_gen()(cfg: ecdh) — ephemeral ECDH (returnsEcdhResult)ecdh_z(point)(cfg: ecdh) — Z-agreement with a peer point (returnsSecret)hmac(data, hash)(cfg: keyedhash) — HMAC with a TPM-resident keyed-hash keyKeyBlob— serialize / loadto_bytes()— serialize the wrapped blobfrom_bytes(dev, bytes)— deserialize a blobload(parent, auth)— load into the TPM (yields aKey)Template— key templatessrk(alg)— storage-root/primary (restricted decrypt parent)attestation(alg)— restricted signing AIKek(alg)— endorsement keysigning(alg)— general signing key (ECDSA / RSASSA-SHA256)rsa_decrypt()— RSA decryption key (OAEP)hmac(hash)(cfg: keyedhash) — TPM-resident keyed-hash HMAC keysymmetric(bits)(cfg: symmetric) — AES-CFB key (128/256)ecdh()(cfg: ecdh) — ECDH key-agreement key (P-256)Secret:as_bytes(),len(),is_empty(),Deref<Target=[u8]>, zeroizes on drop.TpmError:code()— the raw return code.HashAlg:digest_size().Tests ran on fwtpm
caps.rsself_test_and_capabilitiescertify.rscertify_with_ecc_aik,certify_with_rsa_aikcredential.rsmake_and_activate_credentialecdh.rsecdh_gen_then_z_agreeek.rscreate_ek_and_export_publichmac.rshmac_deterministic_and_keyed,loaded_hmac_key_computeimport.rsimport_rsa_private_key,import_ecc_private_keykeys.rscreate_and_load_child,key_blob_roundtrip_then_load,key_blob_roundtrip_preserves_short_auth,auth_protected_parent_loads_childnv.rsnv_write_read_deletepcr.rspcr_extend_changes_digestpersist.rspersist_read_evictquote.rsquote_ecc_aik,quote_rsa_aik,quote_rejects_invalid_pcr_selectionrsa.rsrsa_oaep_roundtrip,rsa_oaep_sha1_roundtripseal.rsseal_unseal_roundtrip,unseal_wrong_auth_failsseal_pcr.rspcr_bound_seal_roundtrip,pcr_change_breaks_unseal,seal_pcr_rejects_invalid_selectionsession.rssecret_ops_under_encrypted_session,second_session_rejected,attestation_refused_during_sessionsign.rssign_then_verify,verify_rejects_tampered_signaturesmoke.rsrandom_and_primary_keyssymmetric.rsaes_cfb_roundtriptests/common/mod.rs::open()connects each test to the fwTPM.examples/create_primary.rs,examples/full_flow.rs..github/workflows/rust-test.yml):rustjob builds wolfSSL (matrix:masterand latest-stable) + wolfTPM with the in-tree fwTPM and runs the suite;rust-devtpm-compilejob is a compile-only Linux kernel-device (--enable-devtpm) build.Post merge steps
Cargo.tomlmetadata: namewolftpm, version,license = GPL-3.0-or-later, description, repository, keywords, categories, readmewolftpmname is owned by the wolfSSL org on crates.io (reserve it if not)build.rsonDOCS_RS(generate bindings from vendored headers / skip the link step), since docs.rs has no prebuiltlibwolftpm/libwolfsslpackage.include/excludeso the published tarball ships only intended files (src,build.rs,headers.h, README, examples — nottarget/)cargo publish --dry-runfromwrapper/rust/wolftpmand review the packaged file listcargo publishwith a crates.io token that has wolfSSL-org publish rightswrapper/rust/README.mdand the top-level wolfTPM READMEChangeLog.mdentry and tag the release