Skip to main content

full_flow/
full_flow.rs

1//! Full walkthrough of the wolftpm safe API against a software TPM.
2//!
3//! Start a server first, for example from the repo root:
4//!   ./src/fwtpm/fwtpm_server --clear --port 2321 --platform-port 2322 &
5//! then:
6//!   cargo run --example full_flow
7
8use std::fmt::Write;
9
10use wolftpm::{Device, HashAlg, Hierarchy, KeyAlg, KeyBlob, Template};
11
12fn hex(b: &[u8]) -> String {
13    let mut encoded = String::with_capacity(b.len() * 2);
14    for byte in b {
15        write!(encoded, "{byte:02x}").expect("writing to a String cannot fail");
16    }
17    encoded
18}
19
20fn main() -> Result<(), wolftpm::TpmError> {
21    let dev = Device::open()?;
22    println!("device            connected to TPM");
23
24    let mut nonce = [0u8; 16];
25    dev.get_random(&mut nonce)?;
26    println!("get_random        {}", hex(&nonce));
27
28    let srk = dev.create_primary(Hierarchy::Owner, KeyAlg::EccP256, None)?;
29    println!("create_primary    ECC SRK handle 0x{:08x}", srk.handle());
30
31    let signer = dev.create_and_load(&srk, &Template::signing(KeyAlg::EccP256)?, None)?;
32    println!(
33        "create_and_load   signing key handle 0x{:08x}",
34        signer.handle()
35    );
36
37    let digest = [0x11u8; 32];
38    let sig = signer.sign_hash(&digest)?;
39    signer.verify_hash(&digest, &sig)?;
40    println!("sign/verify       {} byte signature, verified", sig.len());
41
42    let sealed = dev.seal(&srk, b"my secret", None)?;
43    let secret = dev.unseal(sealed, &srk, None)?;
44    println!(
45        "seal/unseal       recovered \"{}\"",
46        core::str::from_utf8(&secret).unwrap_or("<bytes>")
47    );
48
49    // Scope the reloaded key so its handle is freed before the attestation
50    // step below. A TPM only holds a few transient objects at once (often 3),
51    // so keep the number of simultaneously-loaded keys small.
52    {
53        let blob = dev.create_key(&srk, &Template::signing(KeyAlg::EccP256)?, None)?;
54        let bytes = blob.to_bytes()?;
55        let restored = KeyBlob::from_bytes(&dev, &bytes)?;
56        let loaded = restored.load(&srk, None)?;
57        println!(
58            "key blob          {} bytes, reloaded as handle 0x{:08x}",
59            bytes.len(),
60            loaded.handle()
61        );
62    }
63
64    let before = dev.pcr_read(16, HashAlg::Sha256)?;
65    dev.pcr_extend(16, HashAlg::Sha256, &[0xAB; 32])?;
66    let after = dev.pcr_read(16, HashAlg::Sha256)?;
67    println!(
68        "pcr read/extend   PCR16 {}.. -> {}..",
69        hex(&before[..6]),
70        hex(&after[..6])
71    );
72
73    let index = 0x0150_0100;
74    let _ = dev.nv_delete(index);
75    let mut slot = dev.nv_create(index, 32, None)?;
76    dev.nv_write(&mut slot, b"metadata", 0)?;
77    let mut buf = [0u8; 32];
78    let n = dev.nv_read(&mut slot, &mut buf, 0)?;
79    dev.nv_delete(index)?;
80    println!("nv define/rw      {} bytes at index 0x{:08x}", n, index);
81
82    let aik = dev.create_and_load(&srk, &Template::attestation(KeyAlg::EccP256)?, None)?;
83    let att = dev.certify(&signer, &aik, &nonce)?;
84    println!("certify           {} byte attestation", att.attest.len());
85
86    println!("done              all operations succeeded");
87    Ok(())
88}