-
Notifications
You must be signed in to change notification settings - Fork 82
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
Add ConstantTimeSelect
and ConstantTimeClone
traits
#118
Conversation
@@ -752,17 +862,9 @@ impl<T> CtOption<T> { | |||
#[inline] | |||
pub fn map<U, F>(self, f: F) -> CtOption<U> | |||
where | |||
T: Default + ConditionallySelectable, |
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.
This resolves #63, although I do worry that removing the bounds is potentially breaking, as presently it should be possible to call Default::default
or the ConditionallySelectable
methods on T
within the scope of these callbacks in generic code without explicitly adding these bounds.
While Default
could be preserved (even if it's no longer used), unless ConditionallySelectable
is removed this method can't be used with ConstantTimeSelect
types.
For full backwards compatibility, an alternative would be to add new methods which use the new trait (something like map_ext
or map_ct
). Or perhaps we could try this and see if it actually causes any real-world breakages (we could always yank that release and ship a new one which adds new methods that use the new trait).
f(T::conditional_select( | ||
&T::default(), | ||
&self.value, | ||
self.is_some, | ||
)), |
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.
See my notes here regarding this: #63 (comment)
It's actually quite problematic for the case of heap-allocated values, since they have a dynamically chosen size (e.g. number of limbs) and T::default()
may not match that number of limbs, leading to timing variability.
Unconditionally invoking f(self.value)
would prevent any possible timing variability from this function.
`ConstantTimeSelect` is intended as a replacement to `ConditionallySelectable`, which is preserved but deprecated. It replaces the previous `Copy` bound with a bound on a new `ConstantTimeClone` marker trait, which allows the trait to be impl'd for heap-allocated types. No existing impls of `ConditionallySelectable` have been removed, however a blanket impl of `ConstantTimeSelect` for `T: ConditionallySelectable` has been added, allowing the two traits to interoperate and for `ConstantTimeSelect` to work on all types which currently impl `ConditionallySelectable`. `ConstantTimeClone` likewise has a blanket impl for all types which impl `Copy`. `CtOption`'s combinator methods have been changed to bound on `ConstantTimeSelect` which unlocks using them with heap-allocated types, which otherwise is a major limitation. In theory these changes are all backwards compatible due to the blanket impl, which should allow all types which previously worked to continue to do so. Closes dalek-cryptography#63, dalek-cryptography#94
c67166b
to
3a8e7ca
Compare
Another option here would be to make the breaking changes necessary to solve #63 and #94, retaining the current name for While technically breaking, most users of subtle = ">=2, <4" This would allow compatible crates to work with either Still, a major version bump would be annoying, but full backwards compatibility is a bit hard to preserve here. |
Yet another option would be to use the semver trick to provide backwards compatibility between In this case, I think that would need to involve |
We can't impl `subtle::ConditionallySelectable` for `Boxed*` types due to a bound on `Copy`. I've proposed various ways to try to fix this upstream, e.g. dalek-cryptography/subtle#118, from which the `ConstantTimeSelect` trait has been extracted. It provides the same API as `ConditionallySelectable` but without the `Copy` bound. A blanket impl of `ConstantTimeSelect` for all `ConditionallySelectable` types means that all stack allocated types can continue to use `ConditionallySelectable` and will receive an impl of `ConstantTimeSelect` as well. A bound on `ConstantTimeSelect` has been added to the `Integer` trait as well, allowing it to be used on all `*Uint` types in this crate with `Integer` as the trait abstraction.
I've been thinking more about the "semver trick" approach and how it could be done the proper way according to that blog: releasing a
That would provide a huge degree of interop between the two versions to allow for a gradual transition, and also ensure that |
We can't impl `subtle::ConditionallySelectable` for `Boxed*` types due to a bound on `Copy`. I've proposed various ways to try to fix this upstream, e.g. dalek-cryptography/subtle#118, from which the `ConstantTimeSelect` trait has been extracted. It provides the same API as `ConditionallySelectable` but without the `Copy` bound. A blanket impl of `ConstantTimeSelect` for all `ConditionallySelectable` types means that all stack allocated types can continue to use `ConditionallySelectable` and will receive an impl of `ConstantTimeSelect` as well. A bound on `ConstantTimeSelect` has been added to the `Integer` trait as well, allowing it to be used on all `*Uint` types in this crate with `Integer` as the trait abstraction.
This commit contains a minimal set of proposed breaking changes, as an alternative to trying to make additive changes which may be "subtly" breaking: - Add `ConstantTimeClone` trait and use it as `ConditionallySelectable`'s supertrait bound (alternative to dalek-cryptography#118): this makes it possible to implement `ConditionallySelectable` on heap-allocated types (fixes dalek-cryptography#94) - Remove `Default` bound on `CtOption::map` and `CtOption::and_then`: allows using these methods with types that don't impl `Default` and avoids potential timing sidechannels if there might be timing variability in `Default` types (fixes dalek-cryptography#63)
Note: opened #136 as an alternative which makes a deliberate breaking change to |
Closing in favor of #137 |
ConstantTimeSelect
is intended as a replacement toConditionallySelectable
, which is preserved but deprecated. It replaces the previousCopy
bound with a bound on a newConstantTimeClone
marker trait, which allows the trait to be impl'd for heap-allocated types.No existing impls of
ConditionallySelectable
have been removed, however a blanket impl ofConstantTimeSelect
forT: ConditionallySelectable
has been added, allowing the two traits to interoperate and forConstantTimeSelect
to work on all types which currently implConditionallySelectable
.ConstantTimeClone
likewise has a blanket impl for all types which implCopy
.CtOption
's combinator methods have been changed to bound onConstantTimeSelect
which unlocks using them with heap-allocated types, which otherwise is a major limitation. In theory these changes are all backwards compatible due to the blanket impl, which should allow all types which previously worked to continue to do so.Closes #63, #94