Posts
4782
Following
319
Followers
489
Linux kernel hacker and maintainer etc.

OpenPGP: 3AB05486C7752FE1

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 1 month 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 1 month 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 1 month 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 1 month 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 1 month 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 1 month 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 1 month 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 1 month 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

Jarkko Sakkinen

With the idea how to organize TPM2 protocol in my resurrected tpm2_library and trying how they work in tpm2-cli, this starts produce usable results and working code:

❯ sudo RUST_LOG=trace target/debug/tpm2-cli create-primary -H owner ecc --curve nist-p256
2025-08-05T07:51:22.223171Z DEBUG tpm2_cli::tpm: Opening device: /dev/tpmrm0
2025-08-05T07:51:22.223258Z TRACE tpm2_cli::tpm: Command:
2025-08-05T07:51:22.223283Z TRACE tpm2_cli::tpm: 0000: 80 02 00 00 00 43 00 00 01 31 40 00 00 01 00 00
2025-08-05T07:51:22.223298Z TRACE tpm2_cli::tpm: 0010: 00 09 40 00 00 09 00 00 00 00 00 00 04 00 00 00
2025-08-05T07:51:22.223310Z TRACE tpm2_cli::tpm: 0020: 00 00 1a 00 23 00 0b 00 03 00 72 00 00 00 06 00
2025-08-05T07:51:22.223326Z TRACE tpm2_cli::tpm: 0030: 80 00 43 00 10 00 03 00 10 00 00 00 00 00 00 00
2025-08-05T07:51:22.223335Z TRACE tpm2_cli::tpm: 0040: 00 00 00
2025-08-05T07:51:22.467218Z TRACE tpm2_cli::tpm: Response Header:
2025-08-05T07:51:22.467308Z TRACE tpm2_cli::tpm: 0000: 80 02 00 00 01 1a 00 00 00 00
2025-08-05T07:51:22.467332Z TRACE tpm2_cli::tpm: Response Body:
2025-08-05T07:51:22.467363Z TRACE tpm2_cli::tpm: 0000: 80 ff ff ff 00 00 01 03 00 5a 00 23 00 0b 00 03
2025-08-05T07:51:22.467393Z TRACE tpm2_cli::tpm: 0010: 00 72 00 00 00 06 00 80 00 43 00 10 00 03 00 10
2025-08-05T07:51:22.467421Z TRACE tpm2_cli::tpm: 0020: 00 20 a7 a6 81 0c 1c 1e 49 00 6f 24 69 12 22 e5
2025-08-05T07:51:22.467455Z TRACE tpm2_cli::tpm: 0030: af 6f 2a 47 65 ed 8e 68 4a 9f 16 e9 03 db 5a 42
2025-08-05T07:51:22.467485Z TRACE tpm2_cli::tpm: 0040: 5c 0a 00 20 57 7c e3 94 59 4c ab 5b 46 49 32 9a
2025-08-05T07:51:22.467516Z TRACE tpm2_cli::tpm: 0050: be 04 e9 9e 8f 21 6d 3d 86 53 42 c3 48 20 40 dd
2025-08-05T07:51:22.467545Z TRACE tpm2_cli::tpm: 0060: fc 83 95 f2 00 37 00 00 00 00 00 20 e3 b0 c4 42
2025-08-05T07:51:22.467572Z TRACE tpm2_cli::tpm: 0070: 98 fc 1c 14 9a fb f4 c8 99 6f b9 24 27 ae 41 e4
2025-08-05T07:51:22.467600Z TRACE tpm2_cli::tpm: 0080: 64 9b 93 4c a4 95 99 1b 78 52 b8 55 01 00 10 00
2025-08-05T07:51:22.467631Z TRACE tpm2_cli::tpm: 0090: 04 40 00 00 01 00 04 40 00 00 01 00 00 00 20 5d
2025-08-05T07:51:22.467661Z TRACE tpm2_cli::tpm: 00a0: a0 41 ba c0 ee 31 35 ae bb 0c ad fb a4 97 c6 a1
2025-08-05T07:51:22.467690Z TRACE tpm2_cli::tpm: 00b0: 87 7f ae 83 2d d3 d1 f8 f7 a8 71 b8 25 e8 54 80
2025-08-05T07:51:22.467720Z TRACE tpm2_cli::tpm: 00c0: 21 40 00 00 01 00 20 52 97 3a e0 e3 f0 a2 4e a3
2025-08-05T07:51:22.467750Z TRACE tpm2_cli::tpm: 00d0: 49 de 48 4c 75 d3 5d b8 ea b7 d3 d6 e2 f9 63 22
2025-08-05T07:51:22.467780Z TRACE tpm2_cli::tpm: 00e0: 73 f5 bb db 1b ae 84 00 22 00 0b 82 79 ad e2 be
2025-08-05T07:51:22.467809Z TRACE tpm2_cli::tpm: 00f0: 16 9a 3c b5 20 69 67 97 1b ee 93 bc be c8 fe d3
2025-08-05T07:51:22.467840Z TRACE tpm2_cli::tpm: 0100: cc b4 e6 bd 02 0a 69 48 d7 23 dc 00 00 01 00 00
0x80ffffff

❯ sudo target/debug/tpm2-cli create-primary -H owner ecc --curve nist-p256
0x80ffffff

❯ sudo target/debug/tpm2-cli create-primary -H owner --export-file primary.ctx ecc --curve nist-p256

I'll still need to check that this at least can feature wise in par with tpm2-scripts (mainly cphash functionality) and that tpm2_protocol does not have immediate glitches when implementing features to tpm2-cli. Also since tpm2_protocol is Apache/MIT and tpm2_cli I add a bit features to make sure that right parts
of the code are in the "correct basket".

I'm also looking into if I could make TPM protocol assets fit into the constrainsts of bincode and serde, and since it is looking good I finish this feature too.

Sunday I got there feature-wise but only at the end realized I was creating a wrong thing. Now I prepare the code base a bit, test etc. and the I put this to Gitlab :-)

#tpm #linux
1
1
1

Jarkko Sakkinen

this is how i'm reorganizing tpm2_library that i resurrected yesterday:

protocol
├── Cargo.toml
└── src
├── envelope
│   ├── create_primary_command.rs
│   ├── create_primary_response.rs
│   ├── create_response.rs
│   ├── dictionary_attack_lock_reset_command.rs
│   ├── empty_response.rs
│   ├── flush_context_command.rs
│   ├── get_capability_command.rs
│   ├── get_capability_response.rs
│   └── mod.rs
├── lib.rs
├── object
│   ├── creation_ticket.rs
│   ├── mod.rs
│   ├── tpm2b_data.rs
│   ├── tpm_alg_id.rs
│   ├── tpma_object.rs
│   ├── tpml_pcr_selection.rs
│   ├── tpms_sensitive_create.rs
│   └── tpmt_public.rs

and further:

1. object "registry" is a flat and fat given that there is standard body doing "intelligent hashing", i.e. TCG is my UUID algorithm for that directory. agreed that the de-facto names are ugly but it is ugly AND clean :-) it is known to scale with the spec from the get go to foreseeable future making it ugly, clean and super stable.
2. all objects marshal and unmarshhal.
3. envelope is also flat as i have unidirectionality as constraint and both commands and responses translate bytestream and back.

this api is aimed to work for clients and emulators. i have no interest to write a simulator but it's still easy to figure out how to make that useful: the same crate can be used to implement TPM interaction and tests can use it to mock the TPM chip interaction :-)

[and it will appear to gitlab anytime soon]

#tpm #linux #tss
0
0
0

Jarkko Sakkinen

Edited 1 month ago

I’m finally updating tpm2_library crates which provide near spec idiomatic naming balanced with Rust conventions, marshalling/unmarshalling, parsing displaying error codes with parameter numbers etc.

The protocol crate is aiming to be no_std style IO free crate. In fact I aim to polish it to the level that it would be equally useful and complete for both clients and TPM emulators to take advantage of and given the use purpose having super-conservative list of deps:

[dependencies] bitflags = { workspace = true } strum = { workspace = true } strum_macros = { workspace = true }

The idea how naming goes is easiest to demostrate with TPM_CC type form TPM2 Structures specification. Let’s randomly pick TPM_CC_EvictControl, which is use for transient-persistent and persistent-evicted conversions.

EDIT: So, uhm, I’ll setting it up the project to Gitlab. Was doing too many things at once :-) I moved the repo away from Codeberg some weeks ago to get more CI quota basically but Github was not the right move. Gitlab is a better fit because I already do kernel CI there, keyutils is hosted in Gitlab and I’ve had less luck running actions locally with “act” than “gitlab-ci-local” (https://github.com/firecow/gitlab-ci-local).

I have already placeholder for it in Gitlab but it is probably better sleep first and do after (and make sure that everything works).

[*] https://github.com/ColinIanKing/tpm2-scripts Thanks for @colinianking again for preservation! It came for use now …

#tpm #linux #kernel

1
0
0

Jarkko Sakkinen

probably the most time standing tutorial i've ever read is cpumemory.pdf. still from time to take a peak on it because it is such a great refresher :-)
1
0
0

Jarkko Sakkinen

Edited 1 month ago
Fun fact: Finnish signal intelligence agency is called "SIGINT"
0
1
6
Show older