Posts
4875
Following
323
Followers
491
Linux kernel hacker and maintainer etc.

OpenPGP: 3AB05486C7752FE1
SLOC went over 6k before I migrated into extensive macro usage :-)

My goal for full TCG is ~5k SLOC.
0
0
0

Jarkko Sakkinen

Edited 2 months 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
features that protocol crate can do is to break down any byte stream to either direction into a data type 1:1 matching its internal structure, modify it and turn it back into bytes, which delivers quite robust filtering architecture, which is non-existent in /dev/tpmrm0.
0
0
0

Jarkko Sakkinen

Edited 2 months 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 2 months 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
@arj yeah it should not take too long
0
0
0

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
@arj and neither are deps but this also for the stituation if some wants to extend kernel tpm stack to rust side. by the time i have this polished, mature and tested and can give this and say that "this is how i want to protocol parsing work".

i thought that for such extensions there are better people than me to bind io for linux-rust shenanigans but for tpm2 protocol itself i have over decade long expertise and believe that i can solve this particular subproblem better than anyone else ;-)
1
0
0
@arj just saying but having "extern crate alloc;" for no_std crate is not necessarily a problem as long as you have suitable alloc for the application. depends on goals.
2
0
0
@arj i'll release the repository in upcoming days/weeks and rather use the repository for source code for proper licensing platters etc. :-)

as for deps:

bitflags = { workspace = true }
strum = { workspace = true }

I use these for convenience (for now at least) and for the reason that I can eventually remove them :-)

if i want to translate this to kernel there's no cargo.
1
0
1
@jejb @oleksandr it's possible buf since given how tpm_transmit() works i don't think that is like behaviour. it looks more like if tpm_transmit() was not invoked at all.
0
0
0
Imaginary kernel example would be /devtpmrm0 but given ability to break the bytestream apart and put it back together, be it either direction, it could be much more sophisticated than the existing.
0
0
0
As secondary priority, I want to have this ready for any linux-rust interactions because it would be the part of implementation I would be most concerned of. That is one reason I've ended up to a context-free and environment agnostic implementation like this.
1
0
0
Totally applicable also to be used in pre-boot loaders, operating system kernels etc. as it does what it does efficiently but is io-less (it does things right tho with AsRef and similar traits so to that it melts nicely to io-full world).
1
0
0

Jarkko Sakkinen

Edited 2 months 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
@oleksandr @jejb lol that is true :-) good catch (i was intuitively thinking that it is leaking length from some return value).
1
0
0
@oleksandr It's interesting because I don't recognize by eye 0x161 as TPM error code (I have to check this tho formally). I will take a look at it later this week, just my initial guess.

RT @jejb
1
0
0
In its simplicity this extends quite nicely:

├── protocol
│   ├── Cargo.toml
│   └── src
│   ├── envelope
│   │   ├── context_save_command.rs
│   │   ├── context_save_response.rs
│   │   ├── create_command.rs
│   │   ├── create_primary_command.rs
│   │   ├── create_primary_response.rs
│   │   ├── create_response.rs
│   │   ├── dictionary_attack_lock_reset_command.rs
│   │   ├── empty_response.rs
│   │   ├── evict_control_command.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
│   │   ├── tpm2b.rs
│   │   ├── tpm_alg_id.rs
│   │   ├── tpma_object.rs
│   │   ├── tpm_cap.rs
│   │   ├── tpm_cc.rs
│   │   ├── tpm_ecc_curve.rs
│   │   ├── tpml_pcr_selection.rs
│   │   ├── tpm_rc.rs
│   │   ├── tpm_rh.rs
│   │   ├── tpms_context.rs
│   │   ├── tpms_ecc_point.rs
│   │   ├── tpms_sensitive_create.rs
│   │   ├── tpm_st.rs
│   │   └── tpmt_public.rs
│   └── session
│   └── mod.rs

[session is still a bit stub]

It's fully no_std too and that is an invariant that will be maintained :-)
0
0
0
Show older