mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-09 04:39:24 +00:00
\#242 Expand usage of black_box/zeroize
This commit greatly expands the usage of black_box/zeroize on bits, as it originally should have. It is likely overkill, leading to less efficient code generation, yet does its best to be comprehensive where comprehensiveness is extremely annoying to achieve. In the future, this usage of black_box may be desirable to move to its own crate. Credit to @AaronFeickert for identifying the original commit was incomplete.
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
use core::ops::Deref;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
#[cfg(feature = "serialize")]
|
||||
use std::io::{Read, Write};
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -27,8 +29,28 @@ pub(crate) mod aos;
|
||||
mod bits;
|
||||
use bits::{BitSignature, Bits};
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
use std::io::{Read, Write};
|
||||
// Feature gated due to MSRV requirements
|
||||
#[cfg(feature = "black_box")]
|
||||
pub(crate) fn black_box<T>(val: T) -> T {
|
||||
core::hint::black_box(val)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "black_box"))]
|
||||
pub(crate) fn black_box<T>(val: T) -> T {
|
||||
val
|
||||
}
|
||||
|
||||
fn u8_from_bool(bit_ref: &mut bool) -> u8 {
|
||||
let bit_ref = black_box(bit_ref);
|
||||
|
||||
let mut bit = black_box(*bit_ref);
|
||||
let res = black_box(bit as u8);
|
||||
bit.zeroize();
|
||||
debug_assert!((res | 1) == 1);
|
||||
|
||||
bit_ref.zeroize();
|
||||
res
|
||||
}
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
pub(crate) fn read_point<R: Read, G: PrimeGroup>(r: &mut R) -> std::io::Result<G> {
|
||||
@@ -224,15 +246,13 @@ where
|
||||
let mut these_bits: u8 = 0;
|
||||
// Needed to zero out the bits
|
||||
#[allow(unused_assignments)]
|
||||
for (i, mut raw_bit) in raw_bits.iter_mut().enumerate() {
|
||||
for (i, mut bit) in raw_bits.iter_mut().enumerate() {
|
||||
if i == capacity {
|
||||
break;
|
||||
}
|
||||
|
||||
let mut bit = u8::from(*raw_bit);
|
||||
*raw_bit = false;
|
||||
|
||||
// Accumulate this bit
|
||||
let mut bit = u8_from_bool(bit.deref_mut());
|
||||
these_bits |= bit << (i % bits_per_group);
|
||||
bit.zeroize();
|
||||
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
use core::ops::DerefMut;
|
||||
|
||||
use ff::PrimeFieldBits;
|
||||
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use crate::cross_group::u8_from_bool;
|
||||
|
||||
/// Convert a uniform scalar into one usable on both fields, clearing the top bits as needed.
|
||||
pub fn scalar_normalize<F0: PrimeFieldBits + Zeroize, F1: PrimeFieldBits>(
|
||||
mut scalar: F0,
|
||||
) -> (F0, F1) {
|
||||
let mutual_capacity = F0::CAPACITY.min(F1::CAPACITY);
|
||||
|
||||
// The security of a mutual key is the security of the lower field. Accordingly, this bans a
|
||||
// difference of more than 4 bits
|
||||
// A mutual key is only as secure as its weakest group
|
||||
// Accordingly, this bans a capacity difference of more than 4 bits to prevent a curve generally
|
||||
// offering n-bits of security from being forced into a situation with much fewer bits
|
||||
#[cfg(feature = "secure_capacity_difference")]
|
||||
assert!((F0::CAPACITY.max(F1::CAPACITY) - mutual_capacity) < 4);
|
||||
assert!((F0::CAPACITY.max(F1::CAPACITY) - mutual_capacity) <= 4);
|
||||
|
||||
let mut res1 = F0::zero();
|
||||
let mut res2 = F1::zero();
|
||||
// Uses the bit view API to ensure a consistent endianess
|
||||
// Uses the bits API to ensure a consistent endianess
|
||||
let mut bits = scalar.to_le_bits();
|
||||
scalar.zeroize();
|
||||
// Convert it to big endian
|
||||
@@ -24,9 +29,9 @@ pub fn scalar_normalize<F0: PrimeFieldBits + Zeroize, F1: PrimeFieldBits>(
|
||||
let mut skip = bits.len() - usize::try_from(mutual_capacity).unwrap();
|
||||
// Needed to zero out the bits
|
||||
#[allow(unused_assignments)]
|
||||
for mut raw_bit in bits.iter_mut() {
|
||||
for mut bit in bits.iter_mut() {
|
||||
if skip > 0 {
|
||||
*raw_bit = false;
|
||||
bit.deref_mut().zeroize();
|
||||
skip -= 1;
|
||||
continue;
|
||||
}
|
||||
@@ -34,9 +39,7 @@ pub fn scalar_normalize<F0: PrimeFieldBits + Zeroize, F1: PrimeFieldBits>(
|
||||
res1 = res1.double();
|
||||
res2 = res2.double();
|
||||
|
||||
let mut bit = u8::from(*raw_bit);
|
||||
*raw_bit = false;
|
||||
|
||||
let mut bit = u8_from_bool(bit.deref_mut());
|
||||
res1 += F0::from(bit.into());
|
||||
res2 += F1::from(bit.into());
|
||||
bit.zeroize();
|
||||
|
||||
Reference in New Issue
Block a user