-
Notifications
You must be signed in to change notification settings - Fork 351
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
Optionally Implement Zeroize on exported types #309
Conversation
Cargo.toml
Outdated
@@ -88,6 +88,7 @@ constant_time_eq = "0.2.4" | |||
rayon = { version = "1.2.1", optional = true } | |||
cfg-if = "1.0.0" | |||
digest = { version = "0.10.1", features = [ "mac" ], optional = true } | |||
zeroize = { version = "1", features = ["zeroize_derive"], optional = true } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need default-features = false
here, so that this doesn't pull in alloc
? And then we should also make our own std
feature above pull in zeroize/std
(just like it's currently doing with digest/std
). Does that sound right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That will enable this also when zeroize
is not enabled (that's actually what happens now with digest
)
if we want to do this (which I'm not sure we want, why should you enable std
on a crate if you don't use anything it adds?) we need the weak dependencies feature which was stabilized in 1.60 (rust-lang/cargo#10269) this will allow us to do std = [zeroize?/std]
which will only enable the feature of the dep if the dep is actually enabled
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah that's a good point. The std
features of those crates are independent of what we're deriving, and the caller can depend on that feature themselves if they need it. Do you think default-features = false
still makes sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I'll add that
src/lib.rs
Outdated
self.cv_stack.capacity(), | ||
) | ||
}; | ||
uninit_cv_stack.zeroize(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if either Zeroize
or ArrayVec
would consider supporting the other directly. They're both pretty popular crates, and this seems like the sort of sharp edge that a lot of folks will run into.
In any case, I think we could do this safely by just appending a bunch of all-zero CVs to the array until .is_full()
, and then zeroizing a mutable slice over the whole ArrayVec
. Annoyingly, that doesn't seem to work directly on the slice type, because Zeroize
over slices depends on DefaultIsZeroes
, and arrays of ints don't implement DefaultIsZeroes
(no idea why). But we can work around that by casting the slice into an array reference, like this:
while !self.cv_stack.is_full() {
self.cv_stack.push([0; 32]);
}
let cv_stack_array: &mut [CVBytes; MAX_DEPTH + 1] =
(&mut self.cv_stack[..]).try_into().unwrap();
cv_stack_array.zeroize();
self.cv_stack.clear();
What do you think?
Whatever we decide to do here, we should definitely add a test to exercise it :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I can make a PR to
ArrayVec
to see if they'll land it. - General arrays don't implement
DefaultIsZeroes
because they don't implementDefault
(They implement up to[T; 32]
). - I like your no unsafe solution, I did not know you can
try_into()
a reference to a slice into a reference to an array (I thought only owned values are possible) :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooo it looks like number 1 might work out, that's awesome.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah! I think I'll leave this PR as is for a few days to wait for arrayvec
as there's no rush here
@oconnor663 Replaced the unsafe with the implementation from bluss/arrayvec#240 and added a test that checks everything is actually zero (the cv_stack is truncated to 0 length, I could add a check that all it's content is also 0 but that will require some unsafe and assumes the underlying memory is not uninitialized(which it shouldn't be)) |
This is looking really good. I'm also working on a big refactoring that'll probably get rid of the
I think the robust way to do this is to use |
I'm concerned this might be UB if But checking the content of |
Hmm that's an interesting point. (I'm definitely going down a rabit hole here but I do love this rabbit hole :-D) The assignment of the return value of |
Yeah I don't see how this can be done soundly, even with |
Ok theory aside, this looks great. Landed. Thank you! |
Implements the
zeroize::Zeroize
on exported types, this is guarded by azeroize
feature.This doesn't zeroize on drop, it just let's the user derive themselves / zeroize when needed