Posts
4641
Following
318
Followers
484
Linux kernel hacker and maintainer etc.

OpenPGP: 3AB05486C7752FE1

Jarkko Sakkinen

the next thing i do for tpm2_protocol is render out "rstest" and "hex" from cargo test and make my macro auto-generate roundtrip tests.

i'll also add a Makefile to the root with "make test" target. It will build the test binary with rustc and run the tests. Finally this will be added to the CI.
1
0
0

Jarkko Sakkinen

typoed rust-for-linux to my annoucement by accident as ust-for-linux ****
1
0
0

Jarkko Sakkinen

This was nasty one to fix and took many days (and nights tbh) but now finally command parsing is fixed and all my tests pass:

https://github.com/puavo-org/tpm2_library/commit/7b0fc824bd341fb21c90a06b945f01feb1c20f5e

There's MS TPM 2.0 emulator and swtpm, and that's like all of command parsing and response synthesis I'm aware of. I.e. by practical means there was no useful existing work to take example of :-) I'm pretty happy and a bit proud too that I've reach unipolarity by writing Rust macros reflecting TCG specifications.

I don't have now known bugs in the protocol crate. I'm sure there's a bunch but still feels nice after 1.5 weeks of sleepless nights and 7K SLOC of code (protocol + cli).

#linux #kernel #rust #tpm
1
0
1

Jarkko Sakkinen

This makes me happy:

tpm_struct!(
    #[derive(Debug, PartialEq, Eq, Clone)]
    TpmPcrEventCommand,
    TpmCc::PcrEvent,
    TpmSt::Sessions,
    1,
    {
        pub event_data: Tpm2b,
    }
);

tpm_response!(
    #[derive(Debug, Default, PartialEq, Eq, Clone)]
    TpmPcrEventResponse,
    TpmCc::PcrEvent,
    TpmSt::Sessions,
    {
        pub digests: TpmlDigestValues,
    }
);

Also the types inside use the same system (in fact tpm_struct is shared macro with data types and commands). This will generate full parsing and building for both commands and responses - all without heap involved.

1
0
0

Jarkko Sakkinen

Edited 11 days ago
I'm ready to push this online, but not for a while tag a release because cli should be made to work optimally.

E.g., policy-secret is placeholder. it would much nicer to have "policy [--train] <expression>" with some combinatorial language.

It could take advantage of object references provided my baked-in stack machine:

1. Subcommands a take list of JSON objects from stdin and consume as many as they need from top of te stack.
2. Each subcommand then produce results to the top.

Of course some things come through arguments (e.g. for key creation I have "--persistent").

Also perhaps load and import should be combined to a single smart command. The point is that this is where I don't know what to do exactly and changes for cli interface are welcome :-) I'm now happy that I got allocs and panics away from protocol crate making it "linux-rust ready".

In the protocol crate itself there is one single puzzle where constant improvement makes sense both in kernel and user space: narrowing the delta between "SIZE" and "len()" of TpmSize trait. Ideally the delta would be zero t some point. To be usable in kernel I've now reach that goal (easily) but optimizing this equation makes it substantially better.
2
1
2

Jarkko Sakkinen

cannot even imagine what amazing things i end up doing with my zmodem2 crate implementation now that i've learned how to really put protocol shenanigans in place with rust ;-)
0
1
1

Jarkko Sakkinen

Edited 13 days ago
going to make tpm2_protocol also allocless as it is low-hanging fruit given that it know exactly how much data to expect given full structural understanding of commands and responses. so e.g. in kernel one would mostly (always) use just stack because you know what you're going to get and usually it is not whole a lot.

it started as a framework of structs, and it turned into framework generating a framework of structs from a protocol description :-)
1
0
0

Jarkko Sakkinen

first time for a long update to zmodem2: https://crates.io/crates/zmodem2/0.1.3

preparation release to upgrade rzm and szm to something that could be considered nicer than rz and sz.
0
0
1

Jarkko Sakkinen

Edited 13 days ago
For tpm2-cli I'm planning to do tests with it by using tpm2_protocol as the mocked TPM chip.

It should demonstrate the unipolarity quite well and also possibilities to use the crate as interoperability layer for alt keystores.

It's quite maintainable as I've developed a domain language for declaratively describing TCG specification:

❯ git grep macro_rules
protocol/src/command/util.rs:macro_rules! tpm_message {
protocol/src/command/util.rs:macro_rules! tpm_response_with_params {
protocol/src/command/util.rs:macro_rules! tpm_dispatch {
protocol/src/command/util.rs: macro_rules! tpm_command_parser {
protocol/src/command/util.rs: macro_rules! tpm_response_parser {
protocol/src/lib.rs:macro_rules! tpm_handle {
protocol/src/lib.rs:macro_rules! tpm_bitflags {
protocol/src/lib.rs:macro_rules! tpm_enum {
protocol/src/lib.rs:macro_rules! tpm_integer {
protocol/src/structure/mod.rs:macro_rules! tpm_struct {
protocol/src/structure/tpm2b.rs:macro_rules! tpm2b {
protocol/src/structure/tpml.rs:macro_rules! tpml {

I've produced now 5K SLOC of non-boilerplate code since I got the inspiration last Sunday (with not much sleep), and total size of crate is about 6K SLOC making it my largest Rust project so far written single-handidly :-) It was kind of effort that if you don't just push it through it never will be finished.

#linux #tpm
0
0
0

Jarkko Sakkinen

I've had really good experiences working with Oracle's kernel security engineers in and out (in private threads) of LKML for past year. They seem to get the difference between business goals and schedules, and the goals in the mainline, and not whole a lot of useless debating. They know how to behave it seems ...

Just stands out from the crowd somehow so had to let ths out :-)
0
0
0

Jarkko Sakkinen

Edited 14 days ago
The design that I'm aiming with this cli interface is that it would be usable for TPM2 interaction for application written shell (bash, fish etc.) scripting languages (i.e. password managers and similar).

When it starts to be easy to combine the subcommands in script this should be in fairly good state.

Import and load support keys in ASN.1 format, which is used by kernel for loading trusted keys. Software crypto for now is with libssl bindings as it is sort for safe-play for crypto (CVEs, security hotfixes, auditing) and also it is what I'm most used to in kernel development (and that is what I ultimately care about).
0
0
1

Jarkko Sakkinen

Edited 14 days ago
After playing seriously with Rust's declrative macros for the first time instead of just using them I got pretty neat results. This is because I intend to keep tpm2_protocol depdency free so that it could be used in-kernel if that is ever feasible.

This is how I declare command bodies now in the implementation:

tpm_command!(
TpmStartAuthSessionCommand,
TpmCc::StartAuthSession,
TpmSt::NoSessions,
2,
pub nonce_caller: Tpm2b,
pub encrypted_salt: Tpm2b,
pub session_type: TpmSe,
pub symmetric: TpmtSymDefObject,
pub auth_hash: TpmAlgId,
);

[2 is in fact number handles]

This will generate the command and implement traits for marshalling AND unmarshalling command. Both are implemented in-depth for all TCG specification types across the board.

Another simpler example is TPML_* from the specification:

tpml!(TpmlAlgProperty, TpmsAlgProperty);
tpml!(TpmlDigest, Tpm2b);
tpml!(TpmlDigestValues, TpmtHa);
tpml!(TpmlHandle, u32);
tpml!(TpmlPcrSelection, TpmsPcrSelection);

And TPM2B_*:

tpm2b!(full; Tpm2bAttest, TpmsAttest);
tpm2b!(full; Tpm2bContextData, TpmsContextData);
tpm2b!(full; Tpm2bCreationData, TpmsCreationData);
tpm2b!(full; Tpm2bEccPoint, TpmsEccPoint);
tpm2b!(full; Tpm2bEncryptedSecret, TpmuEncryptedSecret);
tpm2b!(full; Tpm2bIdObject, TpmsIdObject);
tpm2b!(full; Tpm2bNvPublic, TpmsNvPublic);
tpm2b!(full; Tpm2bSensitive, TpmtSensitive);
tpm2b!(full; Tpm2bTemplate, TpmtPublic);

I find this really fascinating :-)

#rust #rustlang #linux #kernel #tpm
1
1
1

Jarkko Sakkinen

Edited 14 days ago
i'd be interested on seeing a new version of /dev/tpmrm0 that would take advantage of my protocol marshaler/unmarshaler.

it's about 5k of rust code but large portion of that is just architectural types.

the first problem is the hardest: what to call the new at this point still imaginary device :-)

it's a post initcall use case just like /dev/tpmrm0 e..g, use by systemd (afaik tbh have not checked) where as hardware interfacing stuff would be tedious given tight bindings to to the boot. thus, it is not extremely hard to implement in linux-rust as long as the device can turn on before PID 1.

benefits could be e.g., to simplify TPM code in daemons such as systemd, if the resource manager would do a better job servicing their requirements.

#linux #tpm #rust #rustlang
1
0
0

Jarkko Sakkinen

Edited 15 days ago
Regex filtered search for algorithms in the TPM chip and the format used for algorithms in tpm2-cli.

Some other idioms are context: and nvram: as sinks for output.
0
0
0

Jarkko Sakkinen

I'm making sure the cli works nicely before pushing to Gitlab for some days. It is at least much saner looking already (IMHO) than tpm2-tools.
0
0
1

Jarkko Sakkinen

It's always a good sign when things converge like this :-) I reached unipolarity (can assemble and disassemble to both directions) with the TPM2 architectural structures I've already included (~40% of the spec) in tpm2_protocol.

pub trait Command<'a>: Marshal + Unmarshal<'a> {
const COMMAND_CODE: TpmCc;
const COMMAND_TAG: TpmSt;
}

pub trait Response<'a>: Marshal + Unmarshal<'a> {
const COMMAND_CODE: TpmCc;
const COMMAND_TAG: TpmSt;
}
0
0
0

Jarkko Sakkinen

Edited 16 days ago
tpm2_protocol is turning into quite cool crate:

1. It's a no_std crate that uses Rust's type system describe TPM commands and responses in the same resolution as the spec.
2. It marshals also responses and unmarshals commands.
3. It's not a stack. it's stackless implementation of types.

These properties allow to nest and glue it to TSS2 and any other pre-existing TPM stack.

Also it could be theoretically used to implement a chip since it is designed to run also bare metal and has been designed to be skimpy on resources ;-)

Hopefully next week get this out...
2
0
1

Jarkko Sakkinen

This is amount of spec types I uncarved from tpm2-scripts and redefined Rust types:

```
creation_ticket.rs
mod.rs
tpm2b_public.rs
tpm2b.rs
tpm2b_sensitive_create.rs
tpm_alg_id.rs
tpma_object.rs
tpma_session.rs
tpm_cap.rs
tpm_cc.rs
tpm_ecc_curve.rs
tpml_digest.rs
tpml_digest_values.rs
tpml_pcr_selection.rs
tpm_rc.rs
tpm_rh.rs
tpms_auth_command.rs
tpms_auth_response.rs
tpms_context.rs
tpms_ecc_point.rs
tpm_se.rs
tpms_keyedhash_parms.rs
tpms_pcr_selection.rs
tpms_pcr_select.rs
tpms_sensitive_create.rs
tpms_symcipher_parms.rs
tpm_st.rs
tpmt_ha.rs
tpmt_kdf_scheme.rs
tpmt_public.rs
tpmt_scheme.rs
tpmt_sym_def_object.rs
tpmu_ha.rs
tpmu_public_id.rs
tpmu_public_parms.rs
```

This is horribly slow process as first because it is not as mechanical process one might think. There's lot of scattered per-type quirks. But as this grows this becomes less and less of pain :-)

I define "completed" status for every type that they must serialize and deserialize, which creates constraints that make them feasible for mock testing for instance.
0
0
0
Show older