The current feature set of upcoming tpm2sh 0.11. It’s quite basic but everything is tested with care and e.g., load does all the import dance for PKCS8 RSA and ECC keys without having to mess with openssl command line. I.e. single robust load command instead of:
tpm2_createprimary --hierarchy o -G ecc -c owner.txt
tpm2_evictcontrol -c owner.txt 0x81000001
openssl ecparam -name prime256v1 -genkey -noout -out private.pem
tpm2_import -C 0x81000001 -G ecc -i private.pem -u key.pub -r key.priv
tpm2_encodeobject -C 0x81000001 -u key.pub -r key.priv -o key.priv.pem
openssl asn1parse -inform pem -in key.priv.pem -noout -out key.priv.der
And generally flows are somewhat polished and will be polished further before released to not have any rough corners. Finally most of non-trivial functionality is tested against built-in TPM emulator MockTPM.
Sometime after 0.11 release I’ll add also --dry-run switch that can exercise TPM commands with the emulator before applying them to the chip.
great now i have a single data-drive test where test cases translate between legacy (build/parse) and new (zerocopy fat pointers):
# ...
TPM_CC_Startup Response TPM_RC_FAILURE 80010000000a00000101
TPM_CC_Startup Response TPM_RC_CONTEXT_GAP 80010000000a00000901
TPM_CC_PCR_Read Response Success 800100000038000000000000000100000000000000010020dededededededededededededededededededededededededededededededed
# ...
        awesome “cast” version of tpm_enum!:
tpm_enum_cast! {
    name: TpmRcBaseCast,
    repr: TpmUint32,
    value_enum: TpmRcBaseEnumCast,
    value_repr: u32,
    variants: {
        (Success, 0x0000, "TPM_RC_SUCCESS"),
        (BadTag, 0x001E, "TPM_RC_BAD_TAG"),
        (Initialize, TPM_RC_VER1, "TPM_RC_INITIALIZE"),
        (Failure, TPM_RC_VER1 | 0x001, "TPM_RC_FAILURE"),
 // ...
        Cast version TPM structures starts to shape:
use crate::{tpm_struct_cast, TpmUint32, TpmUint64, TpmUint8};
tpm_struct_cast! {
    name: TpmsClockInfoCast,
    field_enum: TpmsClockInfoField,
    field_ref_enum: TpmsClockInfoFieldRef,
    fields: {
        (pub clock: TpmUint64<'a>),
        (pub reset_count: TpmUint32<'a>),
        (pub restart_count: TpmUint32<'a>),
        (pub safe: TpmUint8<'a>),
    }
}
And after migration is completed:
use crate::{tpm_struct_cast, TpmUint32, TpmUint64, TpmUint8};
tpm_struct! {
    name: TpmsClockInfo,
    field_enum: TpmsClockInfoField,
    field_ref_enum: TpmsClockInfoFieldRef,
    fields: {
        (pub clock: TpmUint64<'a>),
        (pub reset_count: TpmUint32<'a>),
        (pub restart_count: TpmUint32<'a>),
        (pub safe: TpmUint8<'a>),
    }
}
        no SIZE constant anymore in the new TpmSized as no stack allocation is required:
/// Provides a `dyn`-safe way to get the exact size of a zero-copy cast object.
pub trait TpmSizedCast {
    /// Returns the exact serialized size of the object.
    fn len(&self) -> usize;
    /// Returns `true` if the object has a serialized length of zero.
    fn is_empty(&self) -> bool {
        self.len() == 0
    }
}
This ought to be renamed as TpmSized as full migration is over :-) Applies also to all other *Cast.
In the end of the day this is superior despite adding up a new trick to my sack of random macro hacks:
tpm_integer!(u8, TpmUint8, Unsigned);
tpm_integer!(i8, TpmInt8, Signed);
tpm_integer!(u16, TpmUint16, Unsigned);
tpm_integer!(i32, TpmInt32, Signed);
tpm_integer!(u32, TpmUint32, Unsigned);
tpm_integer!(u64, TpmUint64, Unsigned);
Now the names match TCG specification names, and they are also first fully zerocopy migrated types. This way previously redundant looking field now is actually self-documenting field.
Other zerocopy types will get the nasty “Cast” postfix up until migration is complete (e.g., TpmBufferCast).
For the record, the last field is used to address exactly one quirk related to TCG specs: TPM_CLOCK_TIME, meaning that “invalid discriminant error” needs too versions :-/
I’m sure we would get numbers going from zero to six, and “get this complex science” as e.g., most of have ability to read, and understand nuances such as the difference between slower and faster… This is DailyWTF proximity enough level bad definition that I tend to like that TPM_CLOCK_TIME exist…