Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions ctutils/src/choice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ impl Choice {
/// HACK: workaround to allow `const fn` boolean support on Rust 1.85.
///
/// This does not apply `black_box` to the output.
///
/// <div class = "warning">
/// <b>Security Warning</b>
///
/// See the security warnings for [`Choice::to_bool`].
/// </div>
// TODO(tarcieri): deprecate/remove this in favor of `to_bool` when MSRV is Rust 1.86
pub const fn to_bool_vartime(self) -> bool {
self.0 != 0
Expand Down Expand Up @@ -355,6 +361,16 @@ impl From<Choice> for u8 {
}
}

/// Convert `Choice` into a `bool`.
///
/// <div class = "warning">
/// <b>Security Warning</b>
///
/// Using this function will introduce timing variability, since computing this at all currently
/// requires a branch.
///
/// See the security warnings for [`Choice::to_bool`].
/// </div>
impl From<Choice> for bool {
fn from(choice: Choice) -> bool {
choice.to_bool()
Expand Down
22 changes: 19 additions & 3 deletions ctutils/src/ct_option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ impl<T> CtOption<T> {
self.value
}

/// Return a copy of the contained value without consuming `self`.
/// Return the contained value, consuming the `self` value, with `const fn` support.
///
/// Relies on a `Copy` bound which implies `!Drop` which is needed to be able to move out of
/// `self` in a `const fn` without `feature(const_precise_live_drops)`.
///
/// # Panics
/// In the event `self.is_some()` is [`Choice::FALSE`], panics with a custom panic message
Expand Down Expand Up @@ -157,6 +160,8 @@ impl<T> CtOption<T> {
/// type inference.
///
/// <div class="warning">
/// <b>Warning: variable-time!</b>
///
/// This implementation doesn't intend to be constant-time nor try to protect the leakage of the
/// `T` value since the [`Option`] will do it anyway.
/// </div>
Expand All @@ -176,6 +181,8 @@ impl<T> CtOption<T> {
/// `const fn` and destructors.
///
/// <div class="warning">
/// <b>Warning: variable-time!</b>
///
/// This implementation doesn't intend to be constant-time nor try to protect the leakage of the
/// `T` value since the [`Option`] will do it anyway.
/// </div>
Expand Down Expand Up @@ -310,8 +317,10 @@ impl<T> CtOption<T> {
/// [`Choice::FALSE`].
///
/// <div class="warning">
/// <b>Warning: variable-time!</b>
///
/// This implementation doesn't intend to be constant-time nor try to protect the leakage of the
/// `T` value since the [`Option`] will do it anyway.
/// `T` value since the [`Result`] will do it anyway.
/// </div>
#[inline]
pub fn ok_or<E>(self, err: E) -> Result<T, E> {
Expand All @@ -320,6 +329,13 @@ impl<T> CtOption<T> {

/// Transforms a `CtOption<T>` into a `Result<T, E>` by unconditionally calling the provided
/// callback value and using its result in the event `self.is_some()` is [`Choice::FALSE`].
///
/// <div class="warning">
/// <b>Warning: variable-time!</b>
///
/// This implementation doesn't intend to be constant-time nor try to protect the leakage of the
/// `T` value since the [`Result`] will do it anyway.
/// </div>
#[inline]
pub fn ok_or_else<E, F>(self, err: F) -> Result<T, E>
where
Expand Down Expand Up @@ -524,10 +540,10 @@ impl<T: Default> Default for CtOption<T> {
/// [`CtOption::is_some`] is a truthy or falsy [`Choice`].
///
/// <div class="warning">
/// <b>Warning: variable-time!</b>
///
/// This implementation doesn't intend to be constant-time nor try to protect the leakage of the
/// `T` value since the `Option` will do it anyway.
///
/// </div>
impl<T> From<CtOption<T>> for Option<T> {
fn from(src: CtOption<T>) -> Option<T> {
Expand Down