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
92 changes: 48 additions & 44 deletions src/arithmetic/bigint/exp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ fn elem_exp_consttime_inner<'out, N, M, const STORAGE_LIMBS: usize>(
};
use crate::{
bssl, c, error,
polyfill::{StartMutPtr, dynarray},
polyfill::{StartMutPtr, slice::Buf},
};

let base_rinverse = base_mod_n.reduced_mont(out, m, tmp);
Expand Down Expand Up @@ -148,50 +148,54 @@ fn elem_exp_consttime_inner<'out, N, M, const STORAGE_LIMBS: usize>(
Ok(acc)
}

let mut storage: [MaybeUninit<Limb>; STORAGE_LIMBS] =
let mut table: [MaybeUninit<Limb>; STORAGE_LIMBS] =
[const { MaybeUninit::uninit() }; STORAGE_LIMBS];
let table = dynarray::Uninit::new(&mut storage, STORAGE_ENTRIES, num_limbs)?.init_fold(
|init, uninit| {
let r: Result<&'_ mut [Limb], LimbSliceError> = match init.len() {
// table[0] = base**0 (i.e. 1).
0 => Ok(
One::write_mont_identity_assuming_full_upper_limb(uninit, m)?
.leak_limbs_into_mut_less_safe(),
),

// table[1] = base*R == (base/R * RRR)/R
1 => limbs_mul_mont(
(
uninit,
base_rinverse.leak_limbs_less_safe(),
oneRRR.leak_limbs_less_safe(),
),
m.limbs(),
m.n0(),
m.cpu_features(),
),

// table[2*i] = (n**i)**2/R
i if i % 2 == 0 => {
let sqrt = init.mid().unwrap_or_else(|| unreachable!());
limbs_square_mont((uninit, sqrt), m.limbs(), m.n0(), m.cpu_features())
}

// table[i + 1] = n**1*n**i/R
_ => {
let one = init.get(1).unwrap_or_else(|| unreachable!());
let previous = init.last().unwrap_or_else(|| unreachable!());
limbs_mul_mont((uninit, one, previous), m.limbs(), m.n0(), m.cpu_features())
}
};
r.map_err(|e| match e {
LimbSliceError::LenMismatch(e) => e, // Also unreachable.
LimbSliceError::TooLong(_) => unreachable!(),
LimbSliceError::TooShort(_) => unreachable!(),
})
},
)?;
let table: &[Limb] = table.as_flattened();
let mut table = Buf::from(Uninit::from(table.as_mut()));

// table[0] = base**0 (i.e. 1).
table.try_write_with::<LenMismatchError>(num_limbs.get(), |_init, uninit| {
Ok(
One::write_mont_identity_assuming_full_upper_limb(uninit, m)?
.leak_limbs_into_mut_less_safe(),
)
})?;

// table[1] = base*R == (base/R * RRR)/R
table.try_write_with(num_limbs.get(), |_init, uninit| {
limbs_mul_mont(
(
uninit,
base_rinverse.leak_limbs_less_safe(),
oneRRR.leak_limbs_less_safe(),
),
m.limbs(),
m.n0(),
m.cpu_features(),
)
})?;

for _i in 1..16 {
let n = num_limbs.get();

// table[2*i] = (n**i)**2/R
table.try_write_with(n, |init, uninit| {
let sqrt_start = init.len() / 2;
let sqrt = init
.get(sqrt_start..(sqrt_start + n))
.unwrap_or_else(|| unreachable!());
limbs_square_mont((uninit, sqrt), m.limbs(), m.n0(), m.cpu_features())
})?;

// table[2*i + 1] = (n**1)*(n**(2*i))/R
table.try_write_with(n, |init, uninit| {
let one = init.get(n..(n + n)).unwrap_or_else(|| unreachable!());
let previous = init
.get((init.len() - n)..)
.unwrap_or_else(|| unreachable!());
limbs_mul_mont((uninit, one, previous), m.limbs(), m.n0(), m.cpu_features())
})?;
}
let table: &[Limb] = table.into_filled();

let mut tmp_slice = tmp
.as_uninit(..num_limbs.get())
Expand Down
19 changes: 6 additions & 13 deletions src/arithmetic/bigint/modulus/mont.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,19 +149,12 @@ impl ValidatedInput<'_> {
let (_num_limbs, value) = rest.split_first().unwrap_or_else(|| unreachable!()); // Since we just wrote it.
N0::write_into(n0, value);

let one_pos = out.filled().len();

// Placeholder for the value of 1*RR.
out.unfilled().write_repeat(limb::ZERO, num_limbs)?;
let (mont, one) = out
.filled_mut()
.split_at_mut_checked(one_pos)
.unwrap_or_else(|| unreachable!()); // Since we just wrote it.
let m = &Mont::<'_, M>::from_storage_unchecked_less_safe(mont, cpu);

let _: elem::Mut<'_, _, RR> =
One::write_mont_identity(Uninit::from(one), m, self.len_bits())?.mul_r(m)?; // in place.
Ok(())
out.try_write_with(num_limbs, |init, uninit| {
let m = &Mont::<'_, M>::from_storage_unchecked_less_safe(init, cpu);
let r: elem::Mut<'_, _, RR> =
One::write_mont_identity(uninit, m, self.len_bits())?.mul_r(m)?; // in place.
Ok(r.leak_limbs_into_mut_less_safe())
})
})
}
}
Expand Down
157 changes: 0 additions & 157 deletions src/polyfill/dynarray.rs

This file was deleted.

1 change: 0 additions & 1 deletion src/polyfill/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ mod cold_error;
mod aliasing_slices;
mod array_flat_map;
mod array_split_map;
pub mod dynarray;
pub mod partial_buffer;
pub mod sliceutil;

Expand Down
42 changes: 42 additions & 0 deletions src/polyfill/uninit_slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,11 @@ impl<'target, E: Copy> Buf<'target, E> {
unsafe { filled.assume_init() }
}

#[cfg_attr(target_arch = "x86_64", expect(dead_code))]
pub fn into_filled(self) -> &'target [E] {
self.into_filled_mut()
}

pub fn into_filled_mut(self) -> &'target mut [E] {
let (filled, _unfilled) = self.split_filled_mut();
filled
Expand Down Expand Up @@ -293,6 +298,43 @@ impl<'target, E: Copy> Buf<'target, E> {
let filled = unsafe { filled.assume_init() };
(filled, unfilled)
}

fn split_at_spare_mut(&mut self) -> (&mut [E], Uninit<'_, E>) {
let (filled, unfilled) = self
.storage
.reborrow_mut()
.split_at_mut_checked(self.filled)
.unwrap_or_else(|| unreachable!()); // by invariant.
// SAFETY: by invariant.
let filled = unsafe { filled.assume_init() };
(filled, unfilled)
}

/// Reserves the first `len` bytes of the unfilled space as `to_fill`, then
/// calls `f(filled, to_fill)` where `filled` is the filled space. If `f`
/// returns `Ok(filled)`, then `filled` must be `to_fill`, filled in.
pub fn try_write_with<Err>(
&mut self,
len: usize,
f: impl for<'a> FnOnce(&mut [E], Uninit<'a, E>) -> Result<&'a mut [E], Err>,
) -> Result<(), Err>
where
Err: From<LenMismatchError>,
{
let (filled, mut unfilled) = self.split_at_spare_mut();
let Some(to_fill) = unfilled.get_mut(..len) else {
return Err(LenMismatchError::new(unfilled.len()))?;
};
let len_and_ptr: *const [MaybeUninit<E>] = ptr::from_ref(to_fill.target);
let len_and_ptr: *const [E] = len_and_ptr as *const [E]; // cast_init
let res = f(filled, to_fill)?;
if !ptr::eq(res, len_and_ptr) {
// XXX: It could have been the address that was different.
Err(LenMismatchError::new(res.len()))?;
}
self.filled += res.len();
Ok(())
}
}

/// A writable cursor analogous to `core::io::BorrowedCursor`.
Expand Down
Loading