Skip to content

Make remote_attestation crate no_std compatible #2556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 24, 2022

Conversation

conradgrobler
Copy link
Collaborator

@conradgrobler conradgrobler commented Feb 22, 2022

This PR reduces dependencies of the remote_attestation crate and makes it usable in no_std environments.

Reducing the dependencies should simplify future code audits. An important part of the change is to move away from the bincode crate to manual serialization of the handshake messages. The bincode crate requires std, and manual serialization will also provide more control over the structure of these handshake messages.

Fixes #2294

@conradgrobler conradgrobler added WIP Work in progress dependencies Pull requests that update a dependency file labels Feb 22, 2022
@conradgrobler conradgrobler force-pushed the no_std_attestation branch 7 times, most recently from df1e7c8 to 297ab62 Compare February 23, 2022 16:36
@conradgrobler conradgrobler removed the WIP Work in progress label Feb 23, 2022
@conradgrobler conradgrobler marked this pull request as ready for review February 23, 2022 17:27
@ipetr0v
Copy link
Contributor

ipetr0v commented Feb 23, 2022

Do we have a CI command that compiles it with no_std?

@conradgrobler
Copy link
Collaborator Author

By default it is built as no_std, so the CI tests it in no_std mode. It only uses std if the feature std is specified. Nothing specifies the feature at the moment, but I manually used it with cargo test while debugging.

log = "*"
prost = "*"
prost = { version = "*", default-features = false, features = ["prost-derive"] }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are not restricting versions, is it possible that the future versions of our dependencies will become std instead of no_std?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is possible. I am not sure whether there is a good way to detect that automatically.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this crate fail to compile in that case (at least with the defaul features, i.e. alloc instead of std)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If prost removes no_std compatibility and removes the std feature so that it always pulls in std I think it will still compile. std reexports the core and alloc types, so the types will still be compatible.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drive-by: the best way I've found to check no_std compatibility is to have a CI step that cross-compiles for a target with no std available.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. At the moment the build requires a target OS because that is required by ring. We should be able to build it for a UEFI target once briansmith/ring#1406 has been merged.

hkdf::{Salt, HKDF_SHA256},
rand::{SecureRandom, SystemRandom},
signature::{EcdsaKeyPair, EcdsaSigningAlgorithm, EcdsaVerificationAlgorithm, KeyPair},
};
use sha2::{digest::Digest, Sha256};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did sha2 require std?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but ring already provides the ability to generate sha256 hashes, so I removed sha2 to reduce the dependencies.

[features]
default = ["alloc"]
std = ["anyhow/std", "prost/std"]
alloc = []
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this actually needed for anything, or is it more for documentation purposes?

Copy link
Collaborator Author

@conradgrobler conradgrobler Feb 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was something I experimented with and forgot to delete. Deleted now.

log = "*"
prost = "*"
prost = { version = "*", default-features = false, features = ["prost-derive"] }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this crate fail to compile in that case (at least with the defaul features, i.e. alloc instead of std)?

@@ -234,7 +235,7 @@ impl KeyNegotiator {
&agreement::UnparsedPublicKey::new(KEY_AGREEMENT_ALGORITHM, peer_public_key),
anyhow!("Couldn't derive session keys"),
|key_material| {
let key_material = key_material.try_into().context(format!(
let key_material = key_material.try_into().context(alloc::format!(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest just re-use all these things from alloc, instead of qualifying them everywhere. In fact I'm surprised they are not already in some prelude. Maybe we should build our own prelude? (see https://doc.rust-lang.org/core/prelude/v1/index.html)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that there used to be an experimental alloc prelude, but it no longer exists. Importing custom preludes does not seem to be encouraged (https://doc.rust-lang.org/beta/unstable-book/language-features/prelude-import.html), so I added use statements as needed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see anything that discourages custom preludes, a lot of libraries do that. The feature to bake a prelude in the compiler is another story, I don't recommend we use that, just use oak_uefi::prelude::* basically.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean that we have to add the use statement to all modules that use it? Or is there another way (apart from prelude-import) to use it for the entire crate?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we would need to import it. e.g. https://docs.rs/futures/latest/futures/prelude/index.html

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created #2564

Copy link
Collaborator Author

@conradgrobler conradgrobler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

[features]
default = ["alloc"]
std = ["anyhow/std", "prost/std"]
alloc = []
Copy link
Collaborator Author

@conradgrobler conradgrobler Feb 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was something I experimented with and forgot to delete. Deleted now.

log = "*"
prost = "*"
prost = { version = "*", default-features = false, features = ["prost-derive"] }
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If prost removes no_std compatibility and removes the std feature so that it always pulls in std I think it will still compile. std reexports the core and alloc types, so the types will still be compatible.

@@ -234,7 +235,7 @@ impl KeyNegotiator {
&agreement::UnparsedPublicKey::new(KEY_AGREEMENT_ALGORITHM, peer_public_key),
anyhow!("Couldn't derive session keys"),
|key_material| {
let key_material = key_material.try_into().context(format!(
let key_material = key_material.try_into().context(alloc::format!(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that there used to be an experimental alloc prelude, but it no longer exists. Importing custom preludes does not seem to be encouraged (https://doc.rust-lang.org/beta/unstable-book/language-features/prelude-import.html), so I added use statements as needed.

@github-actions
Copy link

Reproducibility Index:

d16e9c355afdf34390d3991d52504b574665f6b829136b83c1de9b57aa230a24  ./target/x86_64-unknown-linux-musl/release/oak_functions_loader_base
537dda6bc3e1eb4854d9ff76abb5b019b743b0e0ae8e83f02331629079a51e38  ./target/x86_64-unknown-linux-musl/release/oak_functions_loader_unsafe

Reproducibility Index diff:

diff --git a/reproducibility_index b/reproducibility_index
index c47b5ab..5cb7e3b 100644
--- a/reproducibility_index
+++ b/reproducibility_index
@@ -1,2 +1,2 @@
-e81b77bd5e6aa364b806b14ab64215ef811892a6492f7d4b2cfdf3066b60d029  ./target/x86_64-unknown-linux-musl/release/oak_functions_loader_base
-ed45262f841ab276d9411219c7f5eee7a3aaeefbc7dbe32740089f07e1939407  ./target/x86_64-unknown-linux-musl/release/oak_functions_loader_unsafe
+d16e9c355afdf34390d3991d52504b574665f6b829136b83c1de9b57aa230a24  ./target/x86_64-unknown-linux-musl/release/oak_functions_loader_base
+537dda6bc3e1eb4854d9ff76abb5b019b743b0e0ae8e83f02331629079a51e38  ./target/x86_64-unknown-linux-musl/release/oak_functions_loader_unsafe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies Pull requests that update a dependency file
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove bincode and use manual message serialization
5 participants