Skip to content

Remove core_io dependency and add alternative interface for no_std environments #211

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 13 commits into from
Mar 7, 2023

Conversation

DrTobe
Copy link
Contributor

@DrTobe DrTobe commented Oct 12, 2022

As already stated in #210, core_io "has not been updated for a long time, the latest rust version it supports is 2021-03-25." Since no_std usage of rust-mbedtls currently depends on core_io, this is a major barrier when adopting rust-mbedtls in no_std environments.

As opposed to #210, I propose to remove any std::io replacement altogether because we need a different interface (non io::Write, non io::Read) for DTLS anyways. So this interface can be used for TLS in no_std environments, too, which removes the necessity to have a std::io replacement at all. If you think the benefits are worth the effort, a std::io replacement could be added optionally with a feature. I have not had a detailed look at core2 but I found working with core_io very limiting, so maybe core2 could be a better option.

When working on these changes, I have also fixed some other minor issues with no_std usage. Specifically, this should also fix #208 (making #209 obsolete) while bringing rust-mbedtls to 32 bit targets (specifically the ARM thumb... targets commonly found on MCUs).

With the changes presented in this PR, I was finally able to successfully use rust-mbedtls on an STM32L452CCUx MCU.

@DrTobe
Copy link
Contributor Author

DrTobe commented Nov 7, 2022

@zugzwang Would you mind having a look at this or find another maintainer who could find the time?

@zugzwang
Copy link
Collaborator

Hello @DrTobe, thanks for the PR!
We will shortly be in touch, please allow some days.

@@ -341,20 +341,20 @@ unsafe impl BytesSerde for gcm_context {}

// If the C API changes, the serde implementation needs to be reviewed for correctness.

unsafe fn _check_cipher_context_t_size(ctx: cipher_context_t) -> [u8; 96] {
unsafe fn _check_cipher_context_t_size(ctx: cipher_context_t) -> [u8; size_of::<cipher_context_t>()] {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we need to use constants here, as compilation of these functions alerts us of changes in these objects.

E.g. if for some reason cipher_context_t changes size, then this will result in a compilation failure. However using cipher_context_t against its own size will always work.

Does this make sense?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yes, I see, this definitely makes sense. But the value of that constant must be platform-dependent. So, it should roughly be x + y * size_of::<usize>() I guess?

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 think so, all these structs fields are only dependent on crypto (see e.g. https://github.com/Mbed-TLS/mbedtls/blob/development/include/mbedtls/cipher.h#L319 for cipher_context_t). E.g. any platform should serialize a cipher_context_t in exactly 96 bytes.

(Orthogonally, I do think that these constants should be declared separately e.g. const CIPHER_CONTEXT_T_SIZE: usize = 96;)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, I haven't checked this specific check in detail but I have changed it because some of the checks failed when building for thumbv7em-none-eabihf so I just assumed now this would be due to different usize sizes. I will take a look at this again soon.

Copy link
Collaborator

@zugzwang zugzwang Nov 22, 2022

Choose a reason for hiding this comment

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

Oh, different usize sizes? I thought usize was always 8 bytes. If this is not the case, you are right, we should adjust by target (and perhaps add some sanity check test that checks that serialized objects are really exactly 96, 288, 128, etc bytes, if possible).

If this is not the case, we should check which of the functions compilation is failing and why exactly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

usize is the type that comes to my mind when talking about different sizes in memory because it is

The pointer-sized unsigned integer type.

The size of this primitive is how many bytes it takes to reference any location in memory. For example, on a 32 bit target, this is 4 bytes and on a 64 bit target, this is 8 bytes.

See https://doc.rust-lang.org/std/primitive.usize.html

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks, so let us adjust those constants according to the target.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had a look at the underlying C structs and calculated the expected sizes. On a 64 bit machine, this works. I still have to test this when building for a 32 bit target.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With the latest commit, this also works for 32 bit targets 👍

@jyao1
Copy link

jyao1 commented Jan 5, 2023

Hello, this seems good solution to replace #210.
We do need make it work in no_std environment with latest rust toolchain.

@zugzwang, Any chance to merge ?

@jyao1
Copy link

jyao1 commented Jan 16, 2023

@MihirLuthra, any chance to merge this one?

Copy link
Collaborator

@zugzwang zugzwang left a comment

Choose a reason for hiding this comment

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

Thanks for the PR. Looks good to me.

@zugzwang
Copy link
Collaborator

@DrTobe do you think that we can add tests for these changes? (apart from the adapted the client_server test?)

@jyao1
Copy link

jyao1 commented Feb 13, 2023

Ping!

What is the status of this PR?

@DrTobe
Copy link
Contributor Author

DrTobe commented Feb 15, 2023

Ping!

What is the status of this PR?

Sorry, I have not found the time yet to look into @zugzwang's request to add tests.

@DrTobe
Copy link
Contributor Author

DrTobe commented Feb 17, 2023

@DrTobe do you think that we can add tests for these changes? (apart from the adapted the client_server test?)

I have had a look at this again and to me, the adaption in the client_server test looks just right because it exactly tests the changes made in this PR. What other test are you imagining?

@zugzwang
Copy link
Collaborator

@DrTobe it was more of a question in case you thought more tests could be added.
Thanks for the PR!

@zugzwang
Copy link
Collaborator

bors r+

bors bot added a commit that referenced this pull request Feb 21, 2023
211: Remove core_io dependency and add alternative interface for no_std environments r=zugzwang a=DrTobe

As already stated in #210, `core_io` "has not been updated for a long time, the latest rust version it supports is 2021-03-25." Since `no_std` usage of `rust-mbedtls` currently depends on `core_io`, this is a major barrier when adopting `rust-mbedtls` in `no_std` environments.

As opposed to #210, I propose to remove any `std::io` replacement altogether because we need a different interface (non `io::Write`, non `io::Read`) for DTLS anyways. So this interface can be used for TLS in `no_std` environments, too, which removes the necessity to have a `std::io` replacement at all. If you think the benefits are worth the effort, a `std::io` replacement could be added optionally with a feature. I have not had a detailed look at `core2` but I found working with `core_io` very limiting, so maybe `core2` could be a better option.

When working on these changes, I have also fixed some other minor issues with `no_std` usage. Specifically, this should also fix #208 (making #209 obsolete) while bringing `rust-mbedtls` to 32 bit targets (specifically the ARM `thumb...` targets commonly found on MCUs).

With the changes presented in this PR, I was finally able to successfully use `rust-mbedtls` on an STM32L452CCUx MCU.

Co-authored-by: Tobias Naumann <[email protected]>
@bors
Copy link
Contributor

bors bot commented Feb 21, 2023

Build failed:

  • continuous-integration/travis-ci/push

@DrTobe
Copy link
Contributor Author

DrTobe commented Mar 7, 2023

The tests failed because the verify_chain test uses certificates which expired last december. I have included the callback which removes the CERT_EXPIRED flag to every verification attempt. This seems to be the right thing to do because the test results should not depend on the current time.

Additionally, the test did the same checks twice. I have removed that duplication.

@zugzwang Assuming that the checks succeed now, can you try to merge again?

@zugzwang
Copy link
Collaborator

zugzwang commented Mar 7, 2023

bors r+

@bors
Copy link
Contributor

bors bot commented Mar 7, 2023

Build succeeded:

  • continuous-integration/travis-ci/push

@jethrogb
Copy link
Member

We should add a safe abstraction for IoCallback

bors bot added a commit that referenced this pull request Mar 22, 2023
237: Add a new IO abstraction r=Taowyoo a=jethrogb

Implement an IO abstraction as [previously suggested](#211 (comment)) to replace Read+Write if you don't have that available. This allows you to layer any `Io` types like you would Read+Write.

cc `@DrTobe` hope you can live with the API change.

Co-authored-by: Jethro Beekman <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Build failed without standard library
4 participants