Move FROST to Read

Fixes https://github.com/serai-dex/serai/issues/33 and 
https://github.com/serai-dex/serai/issues/35. Also fixes a few potential 
panics/DoS AFAICT.
This commit is contained in:
Luke Parker
2022-07-13 02:38:29 -04:00
parent c0c8915698
commit 6cc8ce840e
13 changed files with 357 additions and 349 deletions

View File

@@ -1,3 +1,5 @@
use std::io::Cursor;
use rand_core::{RngCore, CryptoRng};
use sha2::{digest::Update, Digest, Sha256};
@@ -6,7 +8,7 @@ use group::{ff::Field, GroupEncoding};
use elliptic_curve::{bigint::{Encoding, U384}, hash2curve::{Expander, ExpandMsg, ExpandMsgXmd}};
use crate::{curve::{Curve, F_from_slice}, algorithm::Hram};
use crate::{curve::Curve, algorithm::Hram};
macro_rules! kp_curve {
(
@@ -58,16 +60,18 @@ macro_rules! kp_curve {
let mut modulus = vec![0; 16];
modulus.extend((Self::F::zero() - Self::F::one()).to_bytes());
let modulus = U384::from_be_slice(&modulus).wrapping_add(&U384::ONE);
F_from_slice::<Self::F>(
&U384::from_be_slice(&{
let mut bytes = [0; 48];
ExpandMsgXmd::<Sha256>::expand_message(
&[msg],
dst,
48
).unwrap().fill_bytes(&mut bytes);
bytes
}).reduce(&modulus).unwrap().to_be_bytes()[16 ..]
Self::read_F(
&mut Cursor::new(
&U384::from_be_slice(&{
let mut bytes = [0; 48];
ExpandMsgXmd::<Sha256>::expand_message(
&[msg],
dst,
48
).unwrap().fill_bytes(&mut bytes);
bytes
}).reduce(&modulus).unwrap().to_be_bytes()[16 ..]
)
).unwrap()
}
}

View File

@@ -1,4 +1,5 @@
use core::fmt::Debug;
use std::io::Read;
use thiserror::Error;
@@ -77,41 +78,37 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug {
// hash_msg and hash_binding_factor
#[allow(non_snake_case)]
fn hash_to_F(dst: &[u8], msg: &[u8]) -> Self::F;
}
#[allow(non_snake_case)]
pub(crate) fn F_len<C: Curve>() -> usize {
<C::F as PrimeField>::Repr::default().as_ref().len()
}
#[allow(non_snake_case)]
pub(crate) fn G_len<C: Curve>() -> usize {
<C::G as GroupEncoding>::Repr::default().as_ref().len()
}
/// Field element from slice
#[allow(non_snake_case)]
pub(crate) fn F_from_slice<F: PrimeField>(slice: &[u8]) -> Result<F, CurveError> {
let mut encoding = F::Repr::default();
encoding.as_mut().copy_from_slice(slice);
let point = Option::<F>::from(F::from_repr(encoding)).ok_or(CurveError::InvalidScalar)?;
if point.to_repr().as_ref() != slice {
Err(CurveError::InvalidScalar)?;
#[allow(non_snake_case)]
fn F_len() -> usize {
<Self::F as PrimeField>::Repr::default().as_ref().len()
}
Ok(point)
}
/// Group element from slice
#[allow(non_snake_case)]
pub(crate) fn G_from_slice<G: PrimeGroup>(slice: &[u8]) -> Result<G, CurveError> {
let mut encoding = G::Repr::default();
encoding.as_mut().copy_from_slice(slice);
let point = Option::<G>::from(G::from_bytes(&encoding)).ok_or(CurveError::InvalidPoint)?;
// Ban the identity, per the FROST spec, and non-canonical points
if (point.is_identity().into()) || (point.to_bytes().as_ref() != slice) {
Err(CurveError::InvalidPoint)?;
#[allow(non_snake_case)]
fn G_len() -> usize {
<Self::G as GroupEncoding>::Repr::default().as_ref().len()
}
#[allow(non_snake_case)]
fn read_F<R: Read>(r: &mut R) -> Result<Self::F, CurveError> {
let mut encoding = <Self::F as PrimeField>::Repr::default();
r.read_exact(encoding.as_mut()).map_err(|_| CurveError::InvalidScalar)?;
// ff mandates this is canonical
Option::<Self::F>::from(Self::F::from_repr(encoding)).ok_or(CurveError::InvalidScalar)
}
#[allow(non_snake_case)]
fn read_G<R: Read>(r: &mut R) -> Result<Self::G, CurveError> {
let mut encoding = <Self::G as GroupEncoding>::Repr::default();
r.read_exact(encoding.as_mut()).map_err(|_| CurveError::InvalidPoint)?;
let point = Option::<Self::G>::from(
Self::G::from_bytes(&encoding)
).ok_or(CurveError::InvalidPoint)?;
// Ban the identity, per the FROST spec, and non-canonical points
if (point.is_identity().into()) || (point.to_bytes().as_ref() != encoding.as_ref()) {
Err(CurveError::InvalidPoint)?;
}
Ok(point)
}
Ok(point)
}