tpm2sh 0.15.0 is much more stabilized than previous iterations, and
enhances key management with a proper support for compiling command
lists from policy expressions embedded to the TPM 2.0 ASN.1 key
files:
~ main ≡
❯ tpm2sh create tpm:81000001 --data deadbeef --policy '(pcr(sha256:16) or
pcr(sha256:7)) and secret(tpm:81000001)' keyedhash:sha256 | tpm2sh load
vtpm:80000000
~ main ≡
❯ tpm2sh cache
HANDLE TYPE DETAILS
80000000 transient keyedhash:sha256
~ main ≡
❯ tpm2sh unseal vtpm:80000000
deadbeef
RustCrypto crates have been erased and all software crypto is based
on openssl crate and libssl in order to have a patchable crypto:
❯ ldd target/release/tpm2sh
linux-vdso.so.1 (0x00007f4eddc64000)
libssl.so.3 => /lib/x86_64-linux-gnu/libssl.so.3 (0x00007f4edd757000)
libcrypto.so.3 => /lib/x86_64-linux-gnu/libcrypto.so.3
(0x00007f4edd2d0000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1
(0x00007f4eddc0a000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4edd1f0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4edd00e000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4eddc66000)
Total size of dependency graph is 129, which is not whole a lot in the
usual Rust metrics and tpm2sh is fine-tuned to compile nicely with rustc
1.7x toolchains. This allows to compile it fluently to e.g., BuildRoot
and Yocto images. E.g., to keep some control and narrow down
dependencies I wrote my own custom PKCS#1, PCKS#8, SEC1 and X.509
parsers using rasn [1].
Converting external keys to TPM keys is super trivial:
~ main ≡
❯ tpm2sh create-primary ecc-nist-p256:sha256
vtpm:80000000
~ main ≡
❯ tpm2sh cache
HANDLE TYPE DETAILS
80000000 transient ecc-nist-p256:sha256
~ main ≡
❯ tpm2sh convert vtpm:80000000 -I private.pem | tpm2sh load
vtpm:80000001
~ main ≡
❯ tpm2sh cache
HANDLE TYPE DETAILS
80000000 transient ecc-nist-p256:sha256
80000001 transient rsa-2048:sha256
`tpm2-tpmkey` crate reads and writes otherwise the format following the
standard, except it adds an optional `parentPubkey` attribute, which
enable parent auto-discovery from persistent handles and vtpm cache
for the tpm2sh load subcommand.
The custom (and stripped off) X.509 parser allows to trivially download
EC certificates:
~ main ≡
❯ tpm2sh memory
HANDLE TYPE DETAILS
01c00002 certificate rsa-2048:sha256
01c0000a certificate ecc-nist-p256:sha256
81000001 persistent rsa-2048:sha256
81000002 persistent ecc-nist-p256:sha256
~ main ≡
❯ tpm2sh memory tpm:01c0000a | openssl x509 -text -noout | head -15
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1298017026 (0x4d5e2b02)
Signature Algorithm: ecdsa-with-SHA256
Issuer: C = DE, O = Infineon Technologies AG, OU = OPTIGA(TM), CN =
Infineon OPTIGA(TM) TPM 2.0 ECC CA 042
Validity
Not Before: Sep 16 22:18:38 2020 GMT
Not After : Sep 16 22:18:38 2035 GMT
Subject:
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:a5:09:12:cd:a6:0d:79:49:2f:b0:fa:39:bf:cf:
The stack overall has grown into a micro-ecosystem of re-usable components:
1. https://crates.io/crates/tpm2sh
3. https://crates.io/crates/tpm2-tpmkey
2. https://crates.io/crates/tpm2-policy-language
4. https://crates.io/crates/tpm2-crypto
5. https://crates.io/crates/tpm2-protocol
[1] https://github.com/librasn/compiler
BR, Jarkko