-
Notifications
You must be signed in to change notification settings - Fork 281
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
Make comparison functions stable #518
Make comparison functions stable #518
Conversation
054a484
to
d9447a3
Compare
Will fix Rust 1.41.1 problems tomorrow. |
Needs rebase. |
d9447a3
to
4ae3cbe
Compare
Inline with UNIX convention add a trailing newline to file.
The two crates `secp256k1` and `secp256k1-sys` serve very different purposes, having a macro defined in one that is used in both makes it hard to get nuanced things correct in the macro, for example the comparison implementations (`Ord`, `PartialEq` etc.) are semantically different in each crate. In an effort to decouple `secp256k1` and `secp256k1-sys` duplicate the `impl_array_newtype` macro.
For interfacing with the FFI layer we implement `ffi::CPtr`, there is not need to provide methods `as_ptr` and `as_mut_ptr` as well.
The leading colons are an artifact of Rust 1.29, remove them.
An array in Rust has no concept of length, it is a fixed size data type. Equally an array cannot be "empty", again since it is a fixed size data type. These are methods/concepts seen in slices and vectors. Remove the `len` and `is_empty` methods.
4ae3cbe
to
32c81fc
Compare
Rebased and fixed Rust 1.41.1 stuff which meant removing derives and implementing them, when fuzzing, in |
Currently we rely on the inner bytes with types that are passed across the FFI boundry when implementing comparison functions (e.g. `Ord`, `PartialEq`), this is incorrect because the bytes are opaque, meaning the byte layout is not guaranteed across versions of `libsecp26k1`. Implement stable comparison functionality by doing: - Implement `core::cmp` traits by first coercing the data into a stable form e.g., by serializing it. - Add fast comparison methods to `secp256k1-sys` types that wrap types from libsecp, add similar methods to types in `secp256k1` that wrap `secp256k1-sys` types (just call through to inner type). - In `secp256k1-sys` feature gate the new `core::cmp` impls on `not(fuzzing)`, when fuzzing just derive the impls instead. Any additional methods added to `secp256k1-sys` types are private, justified by the fact the -sys is meant to be just a thin wrapper around libsecp256k1, we don't want to commit to supporting additional API functions. Please note, the solution presented in this patch is already present for `secp256k1::PublicKey`, this PR removes that code in favour of deriving traits that then call down to the same logic in `secp256k1-sys`.
There is no obvious reason why not to derive `Copy` and `Clone` for types that use the `impl_newtype_macro`. Derives are less surprising so deriving makes the code marginally easier to read.
These two traits are related, in as much as they both give access to the inner byte array. Put them next to each other to assist clarity.
32c81fc
to
9850550
Compare
As an semi-related thing, all this
crap is because I didn't know about the |
I don't think we should implement The reason we haven't done any of this yet is that it's impossible to get right; see this blog post by benma where he eventually starts boxing secret data, which we can't do without requiring |
Done reviewing 9850550. This looks great! The only thing blocking an ACK is the secret key |
Thanks for review man, will respin without |
Quick Rust question please, while implementing the suggestion to remove #[derive(Clone, Debug)]
struct Secret([u8; 32]);
impl Secret {
pub fn foo(self) -> u8 {
0 // Some meaningful use of secret.
}
pub fn baz(&self) {
// Some function that borrows self.
}
}
pub fn bar(x: u8) {
println!("got {}", x);
}
fn main() {
let s = Secret([0_u8; 32]);
bar(s.clone().foo());
s.baz()
} I guess the main takeaway here is that if I implement changes designed around secrets then its going to be guess work at best without me putting in a decent amount of time and thought. |
@tcharding are we taking |
Oh, I see, we already have In that case I don't think the |
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.
ACK 9850550
For real. I'm keen to work on the secret stuff at some stage but I get the feeling that it will require a bunch of time spent reading assembler to make sure we know exactly what is going on where. |
Don't get your hopes high. Neither Rust nor C compiler makes any guarantees about the resulting instructions that would help hide the data. You may see good assembly code on your machine but on a different one the optimizer arranges the code differently and you're screwed. However, the only way to exfiltrate secrets (apart from logic bugs zeroing won't protect you from) is to exploit UB. Rust prevents almost all UB and I think we would better spend our time at minimizing UB in
The closest you could get would be to |
Don't worry, I've tried pinning and I couldn't even deal with the ergonomic hit within this crate ;) |
Supersedes #515
The primary aim of this PR is to fix the fact that we currently implement various comparison traits (
Ord
,PartialEq
) by comparing the inner byte arrays. These bytes are meant to be opaque and are not guaranteed across versions oflibsecp256k1
.This PR is a bit involved because I had to detangle all the various types (across both
secp256k1
andsecp256k1-sys
) that use theimpl_array_newtype
macro.impl_array_newtype
macrosI had a lot of fun with this PR, I hope you enjoy it too.
Fix: #463