Skip to content
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

Using Pin with SecretKey and other types that hold secret data #59

Open
brycx opened this issue Feb 7, 2019 · 5 comments
Open

Using Pin with SecretKey and other types that hold secret data #59

brycx opened this issue Feb 7, 2019 · 5 comments
Labels
help wanted Extra attention is needed improvement General improvements to code security Security-related issues or improvements

Comments

@brycx
Copy link
Member

brycx commented Feb 7, 2019

Ways to use Pin for types that hold secret data need to be explored, to avoid copies being left around. The ideal scenario is implementing Pin with all types that hold secret data, without any changes to the public API's.

@brycx brycx added help wanted Extra attention is needed security Security-related issues or improvements improvement General improvements to code labels Feb 7, 2019
@cyberia-ng
Copy link

cyberia-ng commented Oct 26, 2021

Pin won't help you here -- as I discovered when asking about it on the Rust user forum

The problem here is that SecretKey is a simple pointer-free struct, and as such if it is stack-allocated and moved, then copies of it will be left around the stack. The only solution is to allocate it on the heap before filling it with sensitive data, but the API of this library (and every other Rust crypto library I have come across, unfortunately), returns it as an owned object, and therefore moves it out of the stack of the library function and into the stack of the calling function, before you can think about moving it onto the heap.

One solution would be to add a Box inside the SecretKey struct (or a Zeroizing<Box<[u8]>>). But this would mean the crate no longer worked in #[no_std] environments.

@brycx
Copy link
Member Author

brycx commented Oct 27, 2021

Thanks for chiming in here! This issue was created back when Pin was released IIRC, and I haven't really looked into it since then unfortunately.

The problem here is that SecretKey is a simple pointer-free struct, and as such if it is stack-allocated and moved, then copies of it will be left around the stack.

This is also how I've understood it. There is really nothing much we can do about the stack-allocated data, as you said yourself. Perhaps we should also re-consider/look into the current places where stack-allocated data is zeroed, to see if it even makes sense.

One solution would be to add a Box inside the SecretKey struct (or a Zeroizing<Box<[u8]>>). But this would mean the crate no longer worked in #[no_std] environments.

Strictly speaking, it could work with #[no_std] since Box<T> is exposed in alloc. But since #[no_std] in the context of this crate also means no heap allocations, this would render the crate unusable on devices without an allocator.

We could consider trying out the Box<[u8]> approach for high-level API types only, since they already require std. But then again, the question is if the extra complexity can be justified when it can't be guaranteed that heap memory isn't moved through compiler optimizations, as also mentioned in the discussion thread you linked.

In any case, thanks again. Your input is very much appreciated here.

@cyberia-ng
Copy link

The solution that I have ended up using in my own half-complete file encryption project, which uses libsodium, is to build my own heap pointer type based around libsodium's sodium_malloc function: sodium docs, my code.

I wonder if it would be possible to replicate sodium_malloc in pure Rust (or as pure as possible, given it depends on mlock(3) and friends), and somehow use that with the new Rust allocator API

@brycx
Copy link
Member Author

brycx commented Oct 28, 2021

Thanks for linking your implementation, this could serve as a good reference point!

Using the new allocator API for specific sensitive-data types sounds like an interesting idea. I didn't even know about this new API until now.

In the context of this crate, that would mean implementing such functionality in a different crate though, since Orion forbids unsafe.

@cyberia-ng
Copy link

I suppose, zooming out for a minute, that one class of attack that this kind of memory protection is supposed to prevent is simply not possible in Rust -- in languages without memory safety it makes sense as a defence-in-depth measure against bounds checking bugs, but in (safe) Rust we have guarantees that that doesn't happen.

Not to say that there aren't other classes of vulnerabilities that still exist for Rust programs though (e.g. core dumps, sensitive data being swapped to disk).

Anyway, implementing that memory protection functionality in its own crate sounds like an interesting project. Maybe I or somebody else could take it up one day.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed improvement General improvements to code security Security-related issues or improvements
Projects
None yet
Development

No branches or pull requests

2 participants