-
Couldn't load subscription status.
- Fork 147
[WIP] ctutils: constant-time selection and equality testing #1243
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
base: master
Are you sure you want to change the base?
Conversation
| /// This is used as a "belt-and-suspenders" defense in addition to rhs mechanisms like | ||
| /// constant-time predication intrinsics, and is never expected to be the only line of defense. | ||
| #[derive(Copy, Clone, Debug)] | ||
| pub struct Choice(u8); |
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.
Note: u8 internal representation versus Word in crypto-bigint. This is motivated by the cmov API.
| /// The falsy value. | ||
| pub const FALSE: Self = Self(0); | ||
|
|
||
| /// The truthy value. | ||
| pub const TRUE: Self = Self(1); |
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.
These follow subtle conventions, versus crypto-bigint which uses 0 vs Word::MAX. I'm not completely sure about the motivation for the latter?
Note that cmov doesn't care, as the predication instructions are zero-vs-nonzero.
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 the choice was based on how they were used (generally you'd want a mask, not 1).
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 guess that becomes less relevant given the cmov API
| /// Create a new [`Choice`] from the given `u8` value, which should be either `0` or `1`. | ||
| #[inline] | ||
| pub const fn new(value: u8) -> Self { | ||
| debug_assert!(value == 0 || value == 1, "Choice::new accepts only 0 or 1"); |
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.
Branching here means we aren't constant-time in debug mode, which is something that should probably be called out in the comments/documentation
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.
value >> 1 == 0 ? :)
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 would still leave an effective if value >> 1 == 0
| @@ -0,0 +1,92 @@ | |||
| # [RustCrypto]: CMOV (Conditional Move) | |||
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.
Needs a new README.md 😅
|
So why not just bump the MSRV to 1.86? |
|
@fjarri we're trying to ship everything as 1.85 so it can be packaged on Debian stable, then bumping MSRV after that (now that there's an MSRV-aware resolver) That said, there are several places post-1.85 features would be nice in |
(for lack of a better name)
This is woefully incomplete but I'm pushing it up anyway since several people have asked about
const fnsupport forsubtle.This is effectively a rewrite of
subtleusing thecmovcrate for both constant-time selection/predication as well as equality comparisons. Thecmovcrate uses architecture-specific predication instructions on x86(_64) and ARM, with a portable "best effort" fallback.It uses
core::hint::black_boxon-access as an optimization barrier, however this is a belt-and-suspenders defense paired with the use of intrinsics where available. This is a bit different thansubtlewhich uses a similar black box optimization barrier at initialization time. There are a couple problems with this approach:Choice, which means it could potentially insert a branch to e.g. shortcut-on-zeroblack_boxis (rather annoyingly) onlyconst fnin Rust 1.86. This is targeting an initial MSRV of 1.85, as well as supportingconst fnconstructors forChoicewhich are a big missing piece insubtleright nowI'm not intending to replace our usages of
subtlewith this yet (I'd much rather ship everything), but would like to have a testbed for usingcmovfor constant-time operations which can perhaps inform a potentialsubtlev3.0 (if I can make that happen).To be useful, this still needs an equivalent of
CtOption(ideally with much moreconst fnsupport), which I was hoping to implement before pushing this up.One thing we could consider is trying to get this complete enough to use in
crypto-bigintto replaceConstChoice/ConstCtOption, though it would likely need all of the methods onChoiceto beconst fn, which would probably involve shippingChoicewithoutblack_box(i.e. whatcrypto-bigintis already doing), and then adding asubtleintegration for convertingctutil::Choice->subtle::Choiceand a prospectivectutil::CtOption->subtle::CtOption.cc @andrewwhitehead @fjarri @ycscaly