From 872065c8a14078b5c7a881a4606736823fb833b0 Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Thu, 17 Feb 2022 17:06:02 +0100 Subject: [PATCH] Add 'repr-c' feature to facilitate FFI. --- Cargo.toml | 1 + src/curves.rs | 32 +++++++++++++++++++++++++------- src/fields/fp.rs | 1 + src/fields/fq.rs | 1 + 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6b1429f..c9a124e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,3 +58,4 @@ default = ["bits", "sqrt-table"] alloc = ["group/alloc", "blake2b_simd"] bits = ["ff/bits"] sqrt-table = ["alloc", "lazy_static"] +repr-c = [] diff --git a/src/curves.rs b/src/curves.rs index 7c16ead..3518ae3 100644 --- a/src/curves.rs +++ b/src/curves.rs @@ -29,6 +29,7 @@ macro_rules! new_curve_impl { $curve_id:literal, $a_raw:expr, $b_raw:expr, $curve_type:ident) => { /// Represents a point in the projective coordinate space. #[derive(Copy, Clone, Debug)] + #[cfg_attr(feature = "repr-c", repr(C))] $($privacy)* struct $name { x: $base, y: $base, @@ -48,15 +49,17 @@ macro_rules! new_curve_impl { /// Represents a point in the affine coordinate space (or the point at /// infinity). #[derive(Copy, Clone)] + #[cfg_attr(feature = "repr-c", repr(C))] $($privacy)* struct $name_affine { x: $base, y: $base, + #[cfg(not(feature = "repr-c"))] infinity: Choice, } impl fmt::Debug for $name_affine { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - if self.infinity.into() { + if self.is_identity().into() { write!(f, "Infinity") } else { write!(f, "({:?}, {:?})", self.x, self.y) @@ -81,6 +84,7 @@ macro_rules! new_curve_impl { let p = $name_affine { x, y, + #[cfg(not(feature = "repr-c"))] infinity: Choice::from(0u8), }; break p.to_curve(); @@ -200,7 +204,8 @@ macro_rules! new_curve_impl { q.x = p.x * tmp2; q.y = p.y * tmp3; - q.infinity = Choice::from(0u8); + #[cfg(not(feature = "repr-c"))] + { q.infinity = Choice::from(0u8); } *q = $name_affine::conditional_select(&q, &$name_affine::identity(), skip); } @@ -216,6 +221,7 @@ macro_rules! new_curve_impl { let tmp = $name_affine { x, y, + #[cfg(not(feature = "repr-c"))] infinity: Choice::from(0u8), }; @@ -502,6 +508,7 @@ macro_rules! new_curve_impl { $name_affine { x: self.x, y: -self.y, + #[cfg(not(feature = "repr-c"))] infinity: self.infinity, } } @@ -621,19 +628,25 @@ macro_rules! new_curve_impl { Self { x: $base::zero(), y: $base::zero(), + #[cfg(not(feature = "repr-c"))] infinity: Choice::from(1u8), } } + #[cfg(not(feature = "repr-c"))] fn is_identity(&self) -> Choice { self.infinity } + #[cfg(feature = "repr-c")] + fn is_identity(&self) -> Choice { + self.x.is_zero() & self.y.is_zero() + } fn to_curve(&self) -> Self::Curve { $name { x: self.x, y: self.y, - z: $base::conditional_select(&$base::one(), &$base::zero(), self.infinity), + z: $base::conditional_select(&$base::one(), &$base::zero(), self.is_identity()), } } } @@ -679,6 +692,7 @@ macro_rules! new_curve_impl { $name_affine { x, y, + #[cfg(not(feature = "repr-c"))] infinity: Choice::from(0u8), }, Choice::from(1u8), @@ -717,7 +731,7 @@ macro_rules! new_curve_impl { fn is_on_curve(&self) -> Choice { // y^2 - x^3 - ax ?= b (self.y.square() - (self.x.square() + &$name::curve_constant_a()) * self.x).ct_eq(&$name::curve_constant_b()) - | self.infinity + | self.is_identity() } fn coordinates(&self) -> CtOption> { @@ -726,7 +740,9 @@ macro_rules! new_curve_impl { fn from_xy(x: Self::Base, y: Self::Base) -> CtOption { let p = $name_affine { - x, y, infinity: 0u8.into() + x, y, + #[cfg(not(feature = "repr-c"))] + infinity: 0u8.into() }; CtOption::new(p, p.is_on_curve()) } @@ -760,8 +776,8 @@ macro_rules! new_curve_impl { impl ConstantTimeEq for $name_affine { fn ct_eq(&self, other: &Self) -> Choice { - let z1 = self.infinity; - let z2 = other.infinity; + let z1 = self.is_identity(); + let z2 = other.is_identity(); (z1 & z2) | ((!z1) & (!z2) & (self.x.ct_eq(&other.x)) & (self.y.ct_eq(&other.y))) } @@ -780,6 +796,7 @@ macro_rules! new_curve_impl { $name_affine { x: $base::conditional_select(&a.x, &b.x, choice), y: $base::conditional_select(&a.y, &b.y, choice), + #[cfg(not(feature = "repr-c"))] infinity: Choice::conditional_select(&a.infinity, &b.infinity, choice), } } @@ -951,6 +968,7 @@ macro_rules! impl_affine_curve_specific { Self { x: NEGATIVE_ONE, y: TWO, + #[cfg(not(feature = "repr-c"))] infinity: Choice::from(0u8), } } diff --git a/src/fields/fp.rs b/src/fields/fp.rs index 17be5d6..b1d1b20 100644 --- a/src/fields/fp.rs +++ b/src/fields/fp.rs @@ -26,6 +26,7 @@ use crate::arithmetic::SqrtTables; // integers in little-endian order. `Fp` values are always in // Montgomery form; i.e., Fp(a) = aR mod p, with R = 2^256. #[derive(Clone, Copy, Eq)] +#[repr(transparent)] pub struct Fp(pub(crate) [u64; 4]); impl fmt::Debug for Fp { diff --git a/src/fields/fq.rs b/src/fields/fq.rs index 618bf54..cfb0f4e 100644 --- a/src/fields/fq.rs +++ b/src/fields/fq.rs @@ -26,6 +26,7 @@ use crate::arithmetic::SqrtTables; // integers in little-endian order. `Fq` values are always in // Montgomery form; i.e., Fq(a) = aR mod q, with R = 2^256. #[derive(Clone, Copy, Eq)] +#[repr(transparent)] pub struct Fq(pub(crate) [u64; 4]); impl fmt::Debug for Fq {