Posts
4534
Following
316
Followers
479
Linux kernel hacker and maintainer etc.

OpenPGP: 3AB05486C7752FE1

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 7 hours ago

It also optimizes performance as that zeros out marshalling and unmarshalling. Internal representation can be buffer to which data structures are mapped.

For capacity it’s not exact science i.e.:

/// Buffer properties for an object.
pub trait TpmBuffer {
    /// Capacity at most required to strore an object implementing the type.
    const BUFFER_CAPACITY: usize;
   
    pub fn len() -> usize; 
}

E.g., for digest this would the maximum digest. For TPMT_PUBLIC capacity would 640 bytes to fit 4096-bit RSA key.

At runtime, however, the exact size is calculated by summing up “recursively”. Lengths also when summed up point the exact location in the byte stream where an attribute is located. I.e., it’s a zerocopy. I

0
0
0
and if tpm_transmit() was implemented with rust, and this protocol crate was used, it could both verify:

1. command size in byte granularity
2. response size in byte granularity, which much more interesting use case and would be hard to nail with C (instead you have just some max value). i.e. it could detect even slight variation to the expected response length from a device (and devices are hostile because we don't control them).

i.e. a measurable objective benefit not a usual borrow checker catch-22. i would definitely support doing something like this.
1
0
0

Jarkko Sakkinen

Edited 13 hours 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 22 hours 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 yesterday
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
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 yesterday
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 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 2 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
@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
Show older