pub struct Key<'d> { /* private fields */ }Expand description
A loaded TPM key. Its handle is unloaded from the TPM when dropped.
Borrows the Device it lives on, so it cannot outlive the connection.
Implementations§
Source§impl<'d> Key<'d>
impl<'d> Key<'d>
Sourcepub fn ecdh_gen(&self) -> Result<EcdhResult>
pub fn ecdh_gen(&self) -> Result<EcdhResult>
One-shot ephemeral ECDH: the TPM generates an ephemeral key pair, derives
Z against this key’s private part, and returns the ephemeral public point
plus Z. A peer holding this key’s private part can recover the same Z from
the point via ecdh_z.
Source§impl<'d> Key<'d>
impl<'d> Key<'d>
Sourcepub fn hmac(&self, data: &[u8], hash: HashAlg) -> Result<Vec<u8>>
pub fn hmac(&self, data: &[u8], hash: HashAlg) -> Result<Vec<u8>>
Compute HMAC over data using this loaded keyed-hash key, whose secret
stays inside the TPM. hash must match the algorithm the key was
created with (see Template::hmac).
This is the one-shot TPM2_HMAC, so data must fit the TPM’s max
command buffer; larger inputs are rejected rather than truncated.
Source§impl<'d> Key<'d>
impl<'d> Key<'d>
Sourcepub fn handle(&self) -> u32
pub fn handle(&self) -> u32
The TPM handle value for this key.
Examples found in repository?
16fn main() -> Result<(), Box<dyn std::error::Error>> {
17 let dev = Device::open()?;
18 println!("wolfTPM initialized");
19
20 let mut r = [0u8; 16];
21 dev.get_random(&mut r)?;
22 println!("GetRandom: {}", hex(&r));
23
24 let ecc = dev.create_primary(Hierarchy::Owner, KeyAlg::EccP256, None)?;
25 println!("ECC SRK handle: 0x{:08x}", ecc.handle());
26
27 let rsa = dev.create_primary(Hierarchy::Owner, KeyAlg::Rsa, None)?;
28 println!("RSA SRK handle: 0x{:08x}", rsa.handle());
29
30 Ok(())
31}More examples
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}Source§impl<'d> Key<'d>
impl<'d> Key<'d>
Sourcepub fn rsa_encrypt(&self, msg: &[u8]) -> Result<Vec<u8>>
pub fn rsa_encrypt(&self, msg: &[u8]) -> Result<Vec<u8>>
Encrypt msg to this key’s public part with RSA-OAEP.
Sourcepub fn rsa_decrypt(&self, ciphertext: &[u8]) -> Result<Secret>
pub fn rsa_decrypt(&self, ciphertext: &[u8]) -> Result<Secret>
Decrypt an RSA-OAEP ciphertext with this key’s private part.
Sourcepub fn rsa_encrypt_with_hash(
&self,
msg: &[u8],
hash: HashAlg,
) -> Result<Vec<u8>>
pub fn rsa_encrypt_with_hash( &self, msg: &[u8], hash: HashAlg, ) -> Result<Vec<u8>>
Encrypt msg with RSA-OAEP using an explicit label-hash algorithm.
The plain rsa_encrypt uses the TPM’s default OAEP
hash (SHA-256). This variant issues the low-level command directly so any
hash the TPM supports can be selected, including HashAlg::Sha1, which
Microsoft device enrollment (MS-OAPXBC) requires for its session-key
wrap. SHA-1 is legacy and cryptographically weak; select it only for that
interop, not for new designs.
Sourcepub fn rsa_decrypt_with_hash(
&self,
ciphertext: &[u8],
hash: HashAlg,
) -> Result<Secret>
pub fn rsa_decrypt_with_hash( &self, ciphertext: &[u8], hash: HashAlg, ) -> Result<Secret>
Decrypt an RSA-OAEP ciphertext using an explicit label-hash algorithm
(see rsa_encrypt_with_hash). Supports
HashAlg::Sha1 for Microsoft enrollment interop.
Source§impl<'d> Key<'d>
impl<'d> Key<'d>
Sourcepub fn sign_hash(&self, digest: &[u8]) -> Result<Vec<u8>>
pub fn sign_hash(&self, digest: &[u8]) -> Result<Vec<u8>>
Sign a pre-computed digest with this key, returning the raw signature.
The scheme/hash come from the key’s template (e.g. ECDSA-SHA256 for a
P-256 signing key), so digest must be the matching hash length.
Examples found in repository?
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}Sourcepub fn verify_hash(&self, digest: &[u8], sig: &[u8]) -> Result<()>
pub fn verify_hash(&self, digest: &[u8], sig: &[u8]) -> Result<()>
Verify sig over digest with this key.
Examples found in repository?
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}Source§impl<'d> Key<'d>
impl<'d> Key<'d>
Sourcepub fn aes_encrypt(&self, data: &[u8], iv: &[u8]) -> Result<Vec<u8>>
pub fn aes_encrypt(&self, data: &[u8], iv: &[u8]) -> Result<Vec<u8>>
Encrypt data with this loaded AES key (see
Template::symmetric). iv is the CFB
initialization vector (16 bytes for AES).
Sourcepub fn aes_decrypt(&self, data: &[u8], iv: &[u8]) -> Result<Secret>
pub fn aes_decrypt(&self, data: &[u8], iv: &[u8]) -> Result<Secret>
Decrypt data produced by aes_encrypt with the
same key and iv. The recovered plaintext is returned in a zeroizing
Secret.