type Element --> struct FieldElement

This commit is contained in:
2019-05-16 17:27:29 -07:00
parent 4c03ab6648
commit 44618c2e2f
4 changed files with 1109 additions and 1105 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -14,8 +14,38 @@ use testing::run_test;
// This is all an extremely straightforward translation of the usual C // This is all an extremely straightforward translation of the usual C
// implementation, as linked in ring and other libraries. // implementation, as linked in ring and other libraries.
pub const NUM_ELEMENT_LIMBS: usize = 10; const NUM_ELEMENT_LIMBS: usize = 10;
pub type Element = [i32; NUM_ELEMENT_LIMBS];
#[derive(Clone,Debug,PartialEq)]
pub struct FieldElement
{
pub(crate) value: [i32; NUM_ELEMENT_LIMBS]
}
impl FieldElement
{
pub fn new() -> FieldElement
{
FieldElement{ value: [0; NUM_ELEMENT_LIMBS] }
}
pub fn zero() -> FieldElement
{
FieldElement{ value: [0; NUM_ELEMENT_LIMBS] }
}
pub fn one() -> FieldElement
{
let mut res = FieldElement::zero();
res.value[0] = 1;
res
}
pub fn overwrite_with(&mut self, other: &FieldElement)
{
self.value.copy_from_slice(&other.value);
}
}
pub const KBOTTOM_25BITS : i64 = 0x1ffffffi64; pub const KBOTTOM_25BITS : i64 = 0x1ffffffi64;
pub const KBOTTOM_26BITS : i64 = 0x3ffffffi64; pub const KBOTTOM_26BITS : i64 = 0x3ffffffi64;
@@ -50,7 +80,7 @@ fn loads() {
}); });
} }
pub fn fe_frombytes(h: &mut Element, s: &[u8]) pub fn fe_frombytes(h: &mut FieldElement, s: &[u8])
{ {
/* Ignores top bit of h. */ /* Ignores top bit of h. */
let mut h0 = load4(s) as i64; let mut h0 = load4(s) as i64;
@@ -76,23 +106,31 @@ pub fn fe_frombytes(h: &mut Element, s: &[u8])
let carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & KTOP_38BITS; let carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & KTOP_38BITS;
let carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & KTOP_38BITS; let carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & KTOP_38BITS;
h[0] = h0 as i32; h[1] = h1 as i32; h[2] = h2 as i32; h[3] = h3 as i32; h[4] = h4 as i32; h.value[0] = h0 as i32;
h[5] = h5 as i32; h[6] = h6 as i32; h[7] = h7 as i32; h[8] = h8 as i32; h[9] = h9 as i32; h.value[1] = h1 as i32;
h.value[2] = h2 as i32;
h.value[3] = h3 as i32;
h.value[4] = h4 as i32;
h.value[5] = h5 as i32;
h.value[6] = h6 as i32;
h.value[7] = h7 as i32;
h.value[8] = h8 as i32;
h.value[9] = h9 as i32;
} }
pub fn fe_tobytes(s: &mut [u8], h: &Element) pub fn fe_tobytes(s: &mut [u8], h: &FieldElement)
{ {
assert!(s.len() >= 32); assert!(s.len() >= 32);
let mut h0 = h[0]; let mut h0 = h.value[0];
let mut h1 = h[1]; let mut h1 = h.value[1];
let mut h2 = h[2]; let mut h2 = h.value[2];
let mut h3 = h[3]; let mut h3 = h.value[3];
let mut h4 = h[4]; let mut h4 = h.value[4];
let mut h5 = h[5]; let mut h5 = h.value[5];
let mut h6 = h[6]; let mut h6 = h.value[6];
let mut h7 = h[7]; let mut h7 = h.value[7];
let mut h8 = h[8]; let mut h8 = h.value[8];
let mut h9 = h[9]; let mut h9 = h.value[9];
let mut q = (19 * h9 + ((1i32) << 24)) >> 25; let mut q = (19 * h9 + ((1i32) << 24)) >> 25;
q = (h0 + q) >> 26; q = (h0 + q) >> 26;
@@ -168,11 +206,11 @@ fn from_to_bytes() {
let (negb, bbytes) = case.get("b").unwrap(); let (negb, bbytes) = case.get("b").unwrap();
assert!(!nega && !negb); assert!(!nega && !negb);
let mut e = [0; NUM_ELEMENT_LIMBS]; let mut e = FieldElement::new();
let mut target = [0; NUM_ELEMENT_LIMBS]; let mut target = FieldElement::new();
fe_frombytes(&mut e, abytes); fe_frombytes(&mut e, abytes);
let mut cursor = Cursor::new(bbytes); let mut cursor = Cursor::new(bbytes);
cursor.read_i32_into::<NativeEndian>(&mut target).unwrap(); cursor.read_i32_into::<NativeEndian>(&mut target.value).unwrap();
assert_eq!(e, target, "from bytes"); assert_eq!(e, target, "from bytes");
let mut bytes = [0; 32]; let mut bytes = [0; 32];
fe_tobytes(&mut bytes, &e); fe_tobytes(&mut bytes, &e);
@@ -182,29 +220,29 @@ fn from_to_bytes() {
#[cfg(test)] #[cfg(test)]
#[derive(Clone,Debug)] #[derive(Clone,Debug)]
struct ValidElement { struct ValidFieldElement {
values: Element values: FieldElement
} }
#[cfg(test)] #[cfg(test)]
impl Arbitrary for ValidElement { impl Arbitrary for ValidFieldElement {
fn arbitrary<G: Gen>(g: &mut G) -> ValidElement fn arbitrary<G: Gen>(g: &mut G) -> ValidFieldElement
{ {
let mut bytes = [0; 32]; let mut bytes = [0; 32];
g.fill_bytes(&mut bytes); g.fill_bytes(&mut bytes);
curve25519_scalar_mask(&mut bytes); curve25519_scalar_mask(&mut bytes);
let mut res = ValidElement{ values: [0; NUM_ELEMENT_LIMBS] }; let mut res = ValidFieldElement{ values: FieldElement::new() };
fe_frombytes(&mut res.values, &bytes); fe_frombytes(&mut res.values, &bytes);
res res
} }
} }
#[cfg(test)] #[cfg(test)]
pub fn test_from_bytes(x: &[u8]) -> Element pub fn test_from_bytes(x: &[u8]) -> FieldElement
{ {
let mut res = [0; NUM_ELEMENT_LIMBS]; let mut res = FieldElement::new();
let mut helper = Cursor::new(x); let mut helper = Cursor::new(x);
helper.read_i32_into::<LittleEndian>(&mut res).unwrap(); helper.read_i32_into::<LittleEndian>(&mut res.value).unwrap();
res res
} }
@@ -212,64 +250,26 @@ pub fn test_from_bytes(x: &[u8]) -> Element
quickcheck! { quickcheck! {
// this is somewhat self referential, given the definition of arbitrary, // this is somewhat self referential, given the definition of arbitrary,
// but more testing is more good // but more testing is more good
fn from_to_bytes_roundtrip(e: ValidElement) -> bool { fn from_to_bytes_roundtrip(e: ValidFieldElement) -> bool {
let mut bytes = [0; 32]; let mut bytes = [0; 32];
fe_tobytes(&mut bytes, &e.values); fe_tobytes(&mut bytes, &e.values);
let mut trans = [0; NUM_ELEMENT_LIMBS]; let mut trans = FieldElement::new();
fe_frombytes(&mut trans, &bytes); fe_frombytes(&mut trans, &bytes);
trans == e.values trans == e.values
} }
} }
// pub fn fe_zero() -> Element pub fn fe_add(h: &mut FieldElement, f: &FieldElement, g: &FieldElement)
// {
// [0; NUM_ELEMENT_LIMBS]
// }
pub fn fe0(x: &mut Element)
{
x[0] = 0;
x[1] = 0;
x[2] = 0;
x[3] = 0;
x[4] = 0;
x[5] = 0;
x[6] = 0;
x[7] = 0;
x[8] = 0;
x[9] = 0;
}
// pub fn fe_one() -> Element
// {
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
// }
pub fn fe1(x: &mut Element)
{
x[0] = 1;
x[1] = 0;
x[2] = 0;
x[3] = 0;
x[4] = 0;
x[5] = 0;
x[6] = 0;
x[7] = 0;
x[8] = 0;
x[9] = 0;
}
pub fn fe_add(h: &mut Element, f: &Element, g: &Element)
{ {
for i in 0..10 { for i in 0..10 {
h[i] = f[i] + g[i] h.value[i] = f.value[i] + g.value[i]
} }
} }
pub fn fe_sub(h: &mut Element, f: &Element, g: &Element) pub fn fe_sub(h: &mut FieldElement, f: &FieldElement, g: &FieldElement)
{ {
for i in 0..10 { for i in 0..10 {
h[i] = f[i] - g[i] h.value[i] = f.value[i] - g.value[i]
} }
} }
@@ -288,8 +288,8 @@ fn addsub() {
let b = test_from_bytes(&bbytes); let b = test_from_bytes(&bbytes);
let c = test_from_bytes(&cbytes); let c = test_from_bytes(&cbytes);
let d = test_from_bytes(&dbytes); let d = test_from_bytes(&dbytes);
let mut r = [0; NUM_ELEMENT_LIMBS]; let mut r = FieldElement::new();
let mut s = [0; NUM_ELEMENT_LIMBS]; let mut s = FieldElement::new();
fe_add(&mut r, &a, &b); fe_add(&mut r, &a, &b);
fe_sub(&mut s, &a, &b); fe_sub(&mut s, &a, &b);
assert_eq!(r, c, "field addition"); assert_eq!(r, c, "field addition");
@@ -297,28 +297,28 @@ fn addsub() {
}); });
} }
pub fn fe_mul(h: &mut Element, f: &Element, g: &Element) pub fn fe_mul(h: &mut FieldElement, f: &FieldElement, g: &FieldElement)
{ {
let f0 : i32 = f[0]; let f0 : i32 = f.value[0];
let f1 : i32 = f[1]; let f1 : i32 = f.value[1];
let f2 : i32 = f[2]; let f2 : i32 = f.value[2];
let f3 : i32 = f[3]; let f3 : i32 = f.value[3];
let f4 : i32 = f[4]; let f4 : i32 = f.value[4];
let f5 : i32 = f[5]; let f5 : i32 = f.value[5];
let f6 : i32 = f[6]; let f6 : i32 = f.value[6];
let f7 : i32 = f[7]; let f7 : i32 = f.value[7];
let f8 : i32 = f[8]; let f8 : i32 = f.value[8];
let f9 : i32 = f[9]; let f9 : i32 = f.value[9];
let g0 : i32 = g[0]; let g0 : i32 = g.value[0];
let g1 : i32 = g[1]; let g1 : i32 = g.value[1];
let g2 : i32 = g[2]; let g2 : i32 = g.value[2];
let g3 : i32 = g[3]; let g3 : i32 = g.value[3];
let g4 : i32 = g[4]; let g4 : i32 = g.value[4];
let g5 : i32 = g[5]; let g5 : i32 = g.value[5];
let g6 : i32 = g[6]; let g6 : i32 = g.value[6];
let g7 : i32 = g[7]; let g7 : i32 = g.value[7];
let g8 : i32 = g[8]; let g8 : i32 = g.value[8];
let g9 : i32 = g[9]; let g9 : i32 = g.value[9];
let g1_19 : i32 = 19 * g1; /* 1.959375*2^29 */ let g1_19 : i32 = 19 * g1; /* 1.959375*2^29 */
let g2_19 : i32 = 19 * g2; /* 1.959375*2^30; still ok */ let g2_19 : i32 = 19 * g2; /* 1.959375*2^30; still ok */
let g3_19 : i32 = 19 * g3; let g3_19 : i32 = 19 * g3;
@@ -503,16 +503,16 @@ pub fn fe_mul(h: &mut Element, f: &Element, g: &Element)
/* |h0| <= 2^25; from now on fits into int32 unchanged */ /* |h0| <= 2^25; from now on fits into int32 unchanged */
/* |h1| <= 1.01*2^24 */ /* |h1| <= 1.01*2^24 */
h[0] = h0 as i32; h.value[0] = h0 as i32;
h[1] = h1 as i32; h.value[1] = h1 as i32;
h[2] = h2 as i32; h.value[2] = h2 as i32;
h[3] = h3 as i32; h.value[3] = h3 as i32;
h[4] = h4 as i32; h.value[4] = h4 as i32;
h[5] = h5 as i32; h.value[5] = h5 as i32;
h[6] = h6 as i32; h.value[6] = h6 as i32;
h[7] = h7 as i32; h.value[7] = h7 as i32;
h[8] = h8 as i32; h.value[8] = h8 as i32;
h[9] = h9 as i32; h.value[9] = h9 as i32;
} }
#[cfg(test)] #[cfg(test)]
@@ -528,24 +528,24 @@ fn mul() {
let a = test_from_bytes(&abytes); let a = test_from_bytes(&abytes);
let b = test_from_bytes(&bbytes); let b = test_from_bytes(&bbytes);
let c = test_from_bytes(&cbytes); let c = test_from_bytes(&cbytes);
let mut r = [0; NUM_ELEMENT_LIMBS]; let mut r = FieldElement::new();
fe_mul(&mut r, &a, &b); fe_mul(&mut r, &a, &b);
assert_eq!(r, c); assert_eq!(r, c);
}); });
} }
pub fn fe_square(h: &mut Element, f: &Element) pub fn fe_square(h: &mut FieldElement, f: &FieldElement)
{ {
let f0 : i32 = f[0]; let f0 : i32 = f.value[0];
let f1 : i32 = f[1]; let f1 : i32 = f.value[1];
let f2 : i32 = f[2]; let f2 : i32 = f.value[2];
let f3 : i32 = f[3]; let f3 : i32 = f.value[3];
let f4 : i32 = f[4]; let f4 : i32 = f.value[4];
let f5 : i32 = f[5]; let f5 : i32 = f.value[5];
let f6 : i32 = f[6]; let f6 : i32 = f.value[6];
let f7 : i32 = f[7]; let f7 : i32 = f.value[7];
let f8 : i32 = f[8]; let f8 : i32 = f.value[8];
let f9 : i32 = f[9]; let f9 : i32 = f.value[9];
let f0_2 : i32 = 2 * f0; let f0_2 : i32 = 2 * f0;
let f1_2 : i32 = 2 * f1; let f1_2 : i32 = 2 * f1;
let f2_2 : i32 = 2 * f2; let f2_2 : i32 = 2 * f2;
@@ -648,16 +648,16 @@ pub fn fe_square(h: &mut Element, f: &Element)
carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & KTOP_39BITS; carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & KTOP_39BITS;
carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & KTOP_38BITS; carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & KTOP_38BITS;
h[0] = h0 as i32; h.value[0] = h0 as i32;
h[1] = h1 as i32; h.value[1] = h1 as i32;
h[2] = h2 as i32; h.value[2] = h2 as i32;
h[3] = h3 as i32; h.value[3] = h3 as i32;
h[4] = h4 as i32; h.value[4] = h4 as i32;
h[5] = h5 as i32; h.value[5] = h5 as i32;
h[6] = h6 as i32; h.value[6] = h6 as i32;
h[7] = h7 as i32; h.value[7] = h7 as i32;
h[8] = h8 as i32; h.value[8] = h8 as i32;
h[9] = h9 as i32; h.value[9] = h9 as i32;
} }
#[cfg(test)] #[cfg(test)]
@@ -671,89 +671,89 @@ fn square() {
assert!(!nega && !negc); assert!(!nega && !negc);
let a = test_from_bytes(&abytes); let a = test_from_bytes(&abytes);
let c = test_from_bytes(&cbytes); let c = test_from_bytes(&cbytes);
let mut r = [0; NUM_ELEMENT_LIMBS]; let mut r = FieldElement::new();
fe_square(&mut r, &a); fe_square(&mut r, &a);
assert_eq!(r, c); assert_eq!(r, c);
}); });
} }
pub fn fe_invert(z: &Element) -> Element pub fn fe_invert(z: &FieldElement) -> FieldElement
{ {
let mut t0 = [0; NUM_ELEMENT_LIMBS]; let mut t0 = FieldElement::new();
let mut t1 = [0; NUM_ELEMENT_LIMBS]; let mut t1 = FieldElement::new();
let mut t2 = [0; NUM_ELEMENT_LIMBS]; let mut t2 = FieldElement::new();
let mut t3 = [0; NUM_ELEMENT_LIMBS]; let mut t3 = FieldElement::new();
let mut temp = [0; NUM_ELEMENT_LIMBS]; let mut temp = FieldElement::new();
let mut out = [0; NUM_ELEMENT_LIMBS]; let mut out = FieldElement::new();
fe_square(&mut t0, &z); fe_square(&mut t0, &z);
fe_square(&mut t1, &t0); fe_square(&mut t1, &t0);
for _ in 1..2 { for _ in 1..2 {
temp.copy_from_slice(&t1); temp.overwrite_with(&t1);
fe_square(&mut t1, &temp); fe_square(&mut t1, &temp);
} }
temp.copy_from_slice(&t1); temp.overwrite_with(&t1);
fe_mul(&mut t1, &z, &temp); fe_mul(&mut t1, &z, &temp);
temp.copy_from_slice(&t0); temp.overwrite_with(&t0);
fe_mul(&mut t0, &temp, &t1); fe_mul(&mut t0, &temp, &t1);
fe_square(&mut t2, &t0); fe_square(&mut t2, &t0);
temp.copy_from_slice(&t1); temp.overwrite_with(&t1);
fe_mul(&mut t1, &temp, &t2); fe_mul(&mut t1, &temp, &t2);
fe_square(&mut t2, &t1); fe_square(&mut t2, &t1);
for _ in 1..5 { for _ in 1..5 {
temp.copy_from_slice(&t2); temp.overwrite_with(&t2);
fe_square(&mut t2, &temp); fe_square(&mut t2, &temp);
} }
temp.copy_from_slice(&t1); temp.overwrite_with(&t1);
fe_mul(&mut t1, &t2, &temp); fe_mul(&mut t1, &t2, &temp);
fe_square(&mut t2, &t1); fe_square(&mut t2, &t1);
for _ in 1..10 { for _ in 1..10 {
temp.copy_from_slice(&t2); temp.overwrite_with(&t2);
fe_square(&mut t2, &temp); fe_square(&mut t2, &temp);
} }
temp.copy_from_slice(&t2); temp.overwrite_with(&t2);
fe_mul(&mut t2, &temp, &t1); fe_mul(&mut t2, &temp, &t1);
fe_square(&mut t3, &t2); fe_square(&mut t3, &t2);
for _ in 1..20 { for _ in 1..20 {
temp.copy_from_slice(&t3); temp.overwrite_with(&t3);
fe_square(&mut t3, &temp); fe_square(&mut t3, &temp);
} }
temp.copy_from_slice(&t2); temp.overwrite_with(&t2);
fe_mul(&mut t2, &t3, &temp); fe_mul(&mut t2, &t3, &temp);
temp.copy_from_slice(&t2); temp.overwrite_with(&t2);
fe_square(&mut t2, &temp); fe_square(&mut t2, &temp);
for _ in 1..10 { for _ in 1..10 {
temp.copy_from_slice(&t2); temp.overwrite_with(&t2);
fe_square(&mut t2, &temp); fe_square(&mut t2, &temp);
} }
temp.copy_from_slice(&t1); temp.overwrite_with(&t1);
fe_mul(&mut t1, &t2, &temp); fe_mul(&mut t1, &t2, &temp);
fe_square(&mut t2, &t1); fe_square(&mut t2, &t1);
for _ in 1..50 { for _ in 1..50 {
temp.copy_from_slice(&t2); temp.overwrite_with(&t2);
fe_square(&mut t2, &temp); fe_square(&mut t2, &temp);
} }
temp.copy_from_slice(&t2); temp.overwrite_with(&t2);
fe_mul(&mut t2, &temp, &t1); fe_mul(&mut t2, &temp, &t1);
fe_square(&mut t3, &t2); fe_square(&mut t3, &t2);
for _ in 1..100 { for _ in 1..100 {
temp.copy_from_slice(&t3); temp.overwrite_with(&t3);
fe_square(&mut t3, &temp); fe_square(&mut t3, &temp);
} }
temp.copy_from_slice(&t2); temp.overwrite_with(&t2);
fe_mul(&mut t2, &t3, &temp); fe_mul(&mut t2, &t3, &temp);
temp.copy_from_slice(&t2); temp.overwrite_with(&t2);
fe_square(&mut t2, &temp); fe_square(&mut t2, &temp);
for _ in 1..50 { for _ in 1..50 {
temp.copy_from_slice(&t2); temp.overwrite_with(&t2);
fe_square(&mut t2, &temp); fe_square(&mut t2, &temp);
} }
temp.copy_from_slice(&t1); temp.overwrite_with(&t1);
fe_mul(&mut t1, &t2, &temp); fe_mul(&mut t1, &t2, &temp);
temp.copy_from_slice(&t1); temp.overwrite_with(&t1);
fe_square(&mut t1, &temp); fe_square(&mut t1, &temp);
for _ in 1..5 { for _ in 1..5 {
temp.copy_from_slice(&t1); temp.overwrite_with(&t1);
fe_square(&mut t1, &temp); fe_square(&mut t1, &temp);
} }
fe_mul(&mut out, &t1, &t0); fe_mul(&mut out, &t1, &t0);
@@ -776,10 +776,10 @@ fn invert() {
}); });
} }
pub fn fe_neg(h: &mut Element, f: &Element) pub fn fe_neg(h: &mut FieldElement, f: &FieldElement)
{ {
for i in 0..NUM_ELEMENT_LIMBS { for i in 0..NUM_ELEMENT_LIMBS {
h[i] = -f[i]; h.value[i] = -f.value[i];
} }
} }
@@ -794,19 +794,19 @@ fn negate() {
assert!(!nega && !negc); assert!(!nega && !negc);
let a = test_from_bytes(&abytes); let a = test_from_bytes(&abytes);
let c = test_from_bytes(&cbytes); let c = test_from_bytes(&cbytes);
let mut r = [0; NUM_ELEMENT_LIMBS]; let mut r = FieldElement::new();
fe_neg(&mut r, &a); fe_neg(&mut r, &a);
assert_eq!(r, c); assert_eq!(r, c);
}); });
} }
pub fn fe_cmov(f: &mut Element, g: &Element, bl: bool) pub fn fe_cmov(f: &mut FieldElement, g: &FieldElement, bl: bool)
{ {
let b = if bl { -1 } else { 0 }; let b = if bl { -1 } else { 0 };
for i in 0..10 { for i in 0..10 {
let mut x = f[i] ^ g[i]; let mut x = f.value[i] ^ g.value[i];
x &= b; x &= b;
f[i] ^= x; f.value[i] ^= x;
} }
} }
@@ -823,13 +823,13 @@ fn cmov() {
let a = test_from_bytes(&abytes); let a = test_from_bytes(&abytes);
let b = bbytes.len() > 1; let b = bbytes.len() > 1;
let c = test_from_bytes(&cbytes); let c = test_from_bytes(&cbytes);
let mut r = [0; NUM_ELEMENT_LIMBS]; let mut r = FieldElement::new();
fe_cmov(&mut r, &a, b); fe_cmov(&mut r, &a, b);
assert_eq!(r, c); assert_eq!(r, c);
}); });
} }
pub fn fe_isnonzero(f: &Element) -> bool pub fn fe_isnonzero(f: &FieldElement) -> bool
{ {
let mut s = [0; 32]; let mut s = [0; 32];
let mut res = false; let mut res = false;
@@ -840,7 +840,7 @@ pub fn fe_isnonzero(f: &Element) -> bool
res res
} }
pub fn fe_isnegative(f: &Element) -> bool pub fn fe_isnegative(f: &FieldElement) -> bool
{ {
let mut s = [0; 32]; let mut s = [0; 32];
fe_tobytes(&mut s, &f); fe_tobytes(&mut s, &f);
@@ -866,18 +866,18 @@ fn is_tests() {
}); });
} }
pub fn fe_sq2(h: &mut Element, f: &Element) pub fn fe_sq2(h: &mut FieldElement, f: &FieldElement)
{ {
let f0 = f[0]; let f0 = f.value[0];
let f1 = f[1]; let f1 = f.value[1];
let f2 = f[2]; let f2 = f.value[2];
let f3 = f[3]; let f3 = f.value[3];
let f4 = f[4]; let f4 = f.value[4];
let f5 = f[5]; let f5 = f.value[5];
let f6 = f[6]; let f6 = f.value[6];
let f7 = f[7]; let f7 = f.value[7];
let f8 = f[8]; let f8 = f.value[8];
let f9 = f[9]; let f9 = f.value[9];
let f0_2 = 2 * f0; let f0_2 = 2 * f0;
let f1_2 = 2 * f1; let f1_2 = 2 * f1;
let f2_2 = 2 * f2; let f2_2 = 2 * f2;
@@ -997,16 +997,16 @@ pub fn fe_sq2(h: &mut Element, f: &Element)
carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & KTOP_38BITS; carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & KTOP_38BITS;
h[0] = h0 as i32; h.value[0] = h0 as i32;
h[1] = h1 as i32; h.value[1] = h1 as i32;
h[2] = h2 as i32; h.value[2] = h2 as i32;
h[3] = h3 as i32; h.value[3] = h3 as i32;
h[4] = h4 as i32; h.value[4] = h4 as i32;
h[5] = h5 as i32; h.value[5] = h5 as i32;
h[6] = h6 as i32; h.value[6] = h6 as i32;
h[7] = h7 as i32; h.value[7] = h7 as i32;
h[8] = h8 as i32; h.value[8] = h8 as i32;
h[9] = h9 as i32; h.value[9] = h9 as i32;
} }
#[cfg(test)] #[cfg(test)]
@@ -1020,16 +1020,16 @@ fn square2() {
assert!(!nega && !negc); assert!(!nega && !negc);
let a = test_from_bytes(&abytes); let a = test_from_bytes(&abytes);
let c = test_from_bytes(&cbytes); let c = test_from_bytes(&cbytes);
let mut r = [0; NUM_ELEMENT_LIMBS]; let mut r = FieldElement::new();
fe_sq2(&mut r, &a); fe_sq2(&mut r, &a);
assert_eq!(r, c); assert_eq!(r, c);
}); });
} }
pub fn fe_pow22523(out: &mut Element, z: &Element) { pub fn fe_pow22523(out: &mut FieldElement, z: &FieldElement) {
let mut t0 = [0; NUM_ELEMENT_LIMBS]; let mut t0 = FieldElement::new();
let mut t1 = [0; NUM_ELEMENT_LIMBS]; let mut t1 = FieldElement::new();
let mut t2 = [0; NUM_ELEMENT_LIMBS]; let mut t2 = FieldElement::new();
let mut temp; let mut temp;
fe_square(&mut t0, &z); fe_square(&mut t0, &z);
@@ -1117,9 +1117,8 @@ fn pow22523() {
assert!(!nega && !negc); assert!(!nega && !negc);
let a = test_from_bytes(&abytes); let a = test_from_bytes(&abytes);
let c = test_from_bytes(&cbytes); let c = test_from_bytes(&cbytes);
let mut r = [0; NUM_ELEMENT_LIMBS]; let mut r = FieldElement::new();
fe_pow22523(&mut r, &a); fe_pow22523(&mut r, &a);
assert_eq!(r, c); assert_eq!(r, c);
}); });
} }

View File

@@ -136,7 +136,7 @@ impl ED25519Public {
let mut a = Point::new(); let mut a = Point::new();
x25519_ge_frombytes_vartime(&mut a, &self.public); x25519_ge_frombytes_vartime(&mut a, &self.public);
invert_vartime(&mut a); a.invert();
let h_digest = eddsa_digest(signature_r, &self.public, msg); let h_digest = eddsa_digest(signature_r, &self.public, msg);
let h = digest_scalar(&h_digest); let h = digest_scalar(&h_digest);
let mut r = Point2::new(); let mut r = Point2::new();
@@ -164,14 +164,6 @@ fn digest_scalar(digest: &[u8]) -> Vec<u8> {
copy[..32].to_vec() copy[..32].to_vec()
} }
fn invert_vartime(v: &mut Point)
{
for i in 0..NUM_ELEMENT_LIMBS {
v.x[i] = -v.x[i];
v.t[i] = -v.t[i];
}
}
#[cfg(test)] #[cfg(test)]
fn run_signing_testcase(case: HashMap<String,(bool,Vec<u8>)>) fn run_signing_testcase(case: HashMap<String,(bool,Vec<u8>)>)
{ {
@@ -207,4 +199,4 @@ fn rfc8072() {
fn signing() { fn signing() {
let fname = "testdata/ed25519/sign.test"; let fname = "testdata/ed25519/sign.test";
run_test(fname.to_string(), 4, run_signing_testcase); run_test(fname.to_string(), 4, run_signing_testcase);
} }

View File

@@ -5,22 +5,22 @@ use ed25519::fe::*;
use ed25519::constants::*; use ed25519::constants::*;
// This is ge_p3 in the original source code // This is ge_p3 in the original source code
#[derive(Debug,PartialEq)] #[derive(Clone,Debug,PartialEq)]
pub struct Point { pub struct Point {
pub x: Element, pub x: FieldElement,
pub y: Element, pub y: FieldElement,
pub z: Element, pub z: FieldElement,
pub t: Element pub t: FieldElement
} }
impl Point { impl Point {
pub fn new() -> Point pub fn new() -> Point
{ {
Point { Point {
x: [0; NUM_ELEMENT_LIMBS], x: FieldElement::new(),
y: [0; NUM_ELEMENT_LIMBS], y: FieldElement::new(),
z: [0; NUM_ELEMENT_LIMBS], z: FieldElement::new(),
t: [0; NUM_ELEMENT_LIMBS] t: FieldElement::new()
} }
} }
@@ -39,25 +39,36 @@ impl Point {
{ {
into_encoded_point(target, &self.x, &self.y, &self.z); into_encoded_point(target, &self.x, &self.y, &self.z);
} }
pub fn invert(&mut self)
{
let tmp = self.clone();
fe_neg(&mut self.x, &tmp.x);
fe_neg(&mut self.t, &tmp.t);
}
} }
const D: Element = [-10913610, 13857413, -15372611, 6949391, 114729, const D: FieldElement = FieldElement {
-8787816, -6275908, -3247719, -18696448, -12055116]; value: [-10913610, 13857413, -15372611, 6949391, 114729,
-8787816, -6275908, -3247719, -18696448, -12055116]
};
const SQRTM1: Element = [-32595792, -7943725, 9377950, 3500415, 12389472, const SQRTM1: FieldElement = FieldElement {
-272473, -25146209, -2005654, 326686, 11406482]; value: [-32595792, -7943725, 9377950, 3500415, 12389472,
-272473, -25146209, -2005654, 326686, 11406482]
};
pub fn x25519_ge_frombytes_vartime(h: &mut Point, s: &[u8]) -> bool pub fn x25519_ge_frombytes_vartime(h: &mut Point, s: &[u8]) -> bool
{ {
let mut u = [0; NUM_ELEMENT_LIMBS]; let mut u = FieldElement::new();
let mut v = [0; NUM_ELEMENT_LIMBS]; let mut v = FieldElement::new();
let mut v3 = [0; NUM_ELEMENT_LIMBS]; let mut v3 = FieldElement::new();
let mut vxx = [0; NUM_ELEMENT_LIMBS]; let mut vxx = FieldElement::new();
let mut check = [0; NUM_ELEMENT_LIMBS]; let mut check = FieldElement::new();
let mut temp; let mut temp;
fe_frombytes(&mut h.y, s); fe_frombytes(&mut h.y, s);
fe1(&mut h.z); h.z.overwrite_with(&FieldElement::one());
fe_square(&mut u, &h.y); fe_square(&mut u, &h.y);
fe_mul(&mut v, &u, &D); fe_mul(&mut v, &u, &D);
temp = u.clone(); temp = u.clone();
@@ -121,26 +132,26 @@ fn from_bytes_vartime() {
fn ge_p3_0(h: &mut Point) fn ge_p3_0(h: &mut Point)
{ {
fe0(&mut h.x); h.x.overwrite_with(&FieldElement::zero());
fe1(&mut h.y); h.y.overwrite_with(&FieldElement::one());
fe1(&mut h.z); h.z.overwrite_with(&FieldElement::one());
fe0(&mut h.t); h.t.overwrite_with(&FieldElement::zero());
} }
#[derive(Debug,PartialEq)] #[derive(Debug,PartialEq)]
pub struct Point2 { pub struct Point2 {
pub x: Element, pub x: FieldElement,
pub y: Element, pub y: FieldElement,
pub z: Element, pub z: FieldElement,
} }
impl Point2 { impl Point2 {
pub fn new() -> Point2 pub fn new() -> Point2
{ {
Point2 { Point2 {
x: [0; NUM_ELEMENT_LIMBS], x: FieldElement::new(),
y: [0; NUM_ELEMENT_LIMBS], y: FieldElement::new(),
z: [0; NUM_ELEMENT_LIMBS] z: FieldElement::new()
} }
} }
@@ -162,34 +173,34 @@ impl Point2 {
fn ge_p2_0(h: &mut Point2) fn ge_p2_0(h: &mut Point2)
{ {
fe0(&mut h.x); h.x.overwrite_with(&FieldElement::zero());
fe1(&mut h.y); h.y.overwrite_with(&FieldElement::one());
fe1(&mut h.z); h.z.overwrite_with(&FieldElement::one());
} }
fn ge_p3_to_p2(r: &mut Point2, p: &Point) fn ge_p3_to_p2(r: &mut Point2, p: &Point)
{ {
r.x.copy_from_slice(&p.x); r.x.overwrite_with(&p.x);
r.y.copy_from_slice(&p.y); r.y.overwrite_with(&p.y);
r.z.copy_from_slice(&p.z); r.z.overwrite_with(&p.z);
} }
#[derive(Debug,PartialEq)] #[derive(Debug,PartialEq)]
struct PointP1P1 { struct PointP1P1 {
x: Element, x: FieldElement,
y: Element, y: FieldElement,
z: Element, z: FieldElement,
t: Element t: FieldElement
} }
impl PointP1P1 { impl PointP1P1 {
fn new() -> PointP1P1 fn new() -> PointP1P1
{ {
PointP1P1 { PointP1P1 {
x: [0; NUM_ELEMENT_LIMBS], x: FieldElement::new(),
y: [0; NUM_ELEMENT_LIMBS], y: FieldElement::new(),
z: [0; NUM_ELEMENT_LIMBS], z: FieldElement::new(),
t: [0; NUM_ELEMENT_LIMBS], t: FieldElement::new(),
} }
} }
@@ -207,10 +218,10 @@ impl PointP1P1 {
#[derive(Debug,PartialEq)] #[derive(Debug,PartialEq)]
struct Cached { struct Cached {
yplusx: Element, yplusx: FieldElement,
yminusx: Element, yminusx: FieldElement,
z: Element, z: FieldElement,
t2d: Element t2d: FieldElement
} }
impl Cached impl Cached
@@ -218,10 +229,10 @@ impl Cached
fn new() -> Cached fn new() -> Cached
{ {
Cached { Cached {
yplusx: [0; NUM_ELEMENT_LIMBS], yplusx: FieldElement::new(),
yminusx: [0; NUM_ELEMENT_LIMBS], yminusx: FieldElement::new(),
z: [0; NUM_ELEMENT_LIMBS], z: FieldElement::new(),
t2d: [0; NUM_ELEMENT_LIMBS] t2d: FieldElement::new()
} }
} }
@@ -237,14 +248,16 @@ impl Cached
} }
} }
const D2: Element = [-21827239, -5839606, -30745221, 13898782, 229458, const D2: FieldElement = FieldElement {
15978800, -12551817, -6495438, 29715968, 9444199]; value: [-21827239, -5839606, -30745221, 13898782, 229458,
15978800, -12551817, -6495438, 29715968, 9444199]
};
fn x25519_ge_p3_to_cached(r: &mut Cached, p: &Point) fn x25519_ge_p3_to_cached(r: &mut Cached, p: &Point)
{ {
fe_add(&mut r.yplusx, &p.y, &p.x); fe_add(&mut r.yplusx, &p.y, &p.x);
fe_sub(&mut r.yminusx, &p.y, &p.x); fe_sub(&mut r.yminusx, &p.y, &p.x);
r.z.copy_from_slice(&p.z); r.z.overwrite_with(&p.z);
fe_mul(&mut r.t2d, &p.t, &D2); fe_mul(&mut r.t2d, &p.t, &D2);
} }
@@ -311,7 +324,7 @@ fn conversion() {
/* r = 2 * p */ /* r = 2 * p */
fn ge_p2_dbl(r: &mut PointP1P1, p: &Point2) fn ge_p2_dbl(r: &mut PointP1P1, p: &Point2)
{ {
let mut t0 = [0; NUM_ELEMENT_LIMBS]; let mut t0 = FieldElement::new();
fe_square(&mut r.x, &p.x); fe_square(&mut r.x, &p.x);
fe_square(&mut r.z, &p.y); fe_square(&mut r.z, &p.y);
@@ -361,7 +374,7 @@ fn double() {
/* r = p + q */ /* r = p + q */
fn ge_madd(r: &mut PointP1P1, p: &Point, q: &Precomp) fn ge_madd(r: &mut PointP1P1, p: &Point, q: &Precomp)
{ {
let mut t0 = [0; NUM_ELEMENT_LIMBS]; let mut t0 = FieldElement::new();
let mut temp; let mut temp;
fe_add(&mut r.x, &p.y, &p.x); fe_add(&mut r.x, &p.y, &p.x);
@@ -382,7 +395,7 @@ fn ge_madd(r: &mut PointP1P1, p: &Point, q: &Precomp)
/* r = p - q */ /* r = p - q */
fn ge_msub(r: &mut PointP1P1, p: &Point, q: &Precomp) fn ge_msub(r: &mut PointP1P1, p: &Point, q: &Precomp)
{ {
let mut t0 = [0; NUM_ELEMENT_LIMBS]; let mut t0 = FieldElement::new();
let mut temp; let mut temp;
fe_add(&mut r.x, &p.y, &p.x); fe_add(&mut r.x, &p.y, &p.x);
@@ -427,7 +440,7 @@ fn maddsub() {
/* r = p + q */ /* r = p + q */
fn x25519_ge_add(r: &mut PointP1P1, p: &Point, q: &Cached) fn x25519_ge_add(r: &mut PointP1P1, p: &Point, q: &Cached)
{ {
let mut t0 = [0; NUM_ELEMENT_LIMBS]; let mut t0 = FieldElement::new();
let mut temp; let mut temp;
fe_add(&mut r.x, &p.y, &p.x); fe_add(&mut r.x, &p.y, &p.x);
@@ -449,7 +462,7 @@ fn x25519_ge_add(r: &mut PointP1P1, p: &Point, q: &Cached)
/* r = p - q */ /* r = p - q */
fn x25519_ge_sub(r: &mut PointP1P1, p: &Point, q: &Cached) fn x25519_ge_sub(r: &mut PointP1P1, p: &Point, q: &Cached)
{ {
let mut t0 = [0; NUM_ELEMENT_LIMBS]; let mut t0 = FieldElement::new();
let mut temp; let mut temp;
fe_add(&mut r.x, &p.y, &p.x); fe_add(&mut r.x, &p.y, &p.x);
@@ -529,8 +542,8 @@ fn table_select(t: &mut Precomp, pos: i32, b: i8)
cmov(t, &K25519_PRECOMP[pos as usize][5], equal(babs, 6)); cmov(t, &K25519_PRECOMP[pos as usize][5], equal(babs, 6));
cmov(t, &K25519_PRECOMP[pos as usize][6], equal(babs, 7)); cmov(t, &K25519_PRECOMP[pos as usize][6], equal(babs, 7));
cmov(t, &K25519_PRECOMP[pos as usize][7], equal(babs, 8)); cmov(t, &K25519_PRECOMP[pos as usize][7], equal(babs, 8));
minust.yplusx.copy_from_slice(&t.yminusx); minust.yplusx.overwrite_with(&t.yminusx);
minust.yminusx.copy_from_slice(&t.yplusx); minust.yminusx.overwrite_with(&t.yplusx);
fe_neg(&mut minust.xy2d, &t.xy2d); fe_neg(&mut minust.xy2d, &t.xy2d);
cmov(t, &minust, bnegative != 0); cmov(t, &minust, bnegative != 0);
} }
@@ -1640,7 +1653,7 @@ pub fn curve25519_scalar_mask(a: &mut [u8])
* replace (f,g) with (f,g) if b == 0. * replace (f,g) with (f,g) if b == 0.
* *
* Preconditions: b in {0,1}. */ * Preconditions: b in {0,1}. */
//fn fe_cswap(f: &mut Element, g: &mut Element, inb: bool) { //fn fe_cswap(f: &mut FieldElement, g: &mut FieldElement, inb: bool) {
// let b = if inb { 0xFFFFFFFFu32 as i32 } else { 0x00000000 }; // let b = if inb { 0xFFFFFFFFu32 as i32 } else { 0x00000000 };
// for i in 0..NUM_ELEMENT_LIMBS { // for i in 0..NUM_ELEMENT_LIMBS {
// let mut x = f[i] ^ g[i]; // let mut x = f[i] ^ g[i];
@@ -1658,7 +1671,7 @@ pub fn curve25519_scalar_mask(a: &mut [u8])
* *
* Postconditions: * Postconditions:
* |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. */ * |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. */
//fn fe_mul121666(h: &mut Element, f: &Element) //fn fe_mul121666(h: &mut FieldElement, f: &FieldElement)
//{ //{
// let f0 = f[0]; // let f0 = f[0];
// let f1 = f[1]; // let f1 = f[1];
@@ -1711,13 +1724,13 @@ pub fn curve25519_scalar_mask(a: &mut [u8])
// assert_eq!(scalar.len(), 32); // assert_eq!(scalar.len(), 32);
// assert_eq!(point.len(), 32); // assert_eq!(point.len(), 32);
// //
// let mut x1 = [0; NUM_ELEMENT_LIMBS]; // let mut x1 = FieldElement::new();
// let mut x2 = [0; NUM_ELEMENT_LIMBS]; // let mut x2 = FieldElement::new();
// let mut z2 = [0; NUM_ELEMENT_LIMBS]; // let mut z2 = FieldElement::new();
// let mut x3 = [0; NUM_ELEMENT_LIMBS]; // let mut x3 = FieldElement::new();
// let mut z3 = [0; NUM_ELEMENT_LIMBS]; // let mut z3 = FieldElement::new();
// let mut tmp0 = [0; NUM_ELEMENT_LIMBS]; // let mut tmp0 = FieldElement::new();
// let mut tmp1 = [0; NUM_ELEMENT_LIMBS]; // let mut tmp1 = FieldElement::new();
// let mut tmp2; // let mut tmp2;
// let mut e = [0; 32]; // let mut e = [0; 32];
// //
@@ -1792,8 +1805,8 @@ pub fn x25519_public_from_private(public: &mut [u8], private: &[u8])
/* We only need the u-coordinate of the curve25519 point. The map is /* We only need the u-coordinate of the curve25519 point. The map is
* u=(y+1)/(1-y). Since y=Y/Z, this gives u=(Z+Y)/(Z-Y). */ * u=(y+1)/(1-y). Since y=Y/Z, this gives u=(Z+Y)/(Z-Y). */
let mut zplusy = [0; NUM_ELEMENT_LIMBS]; let mut zplusy = FieldElement::new();
let mut zminusy = [0; NUM_ELEMENT_LIMBS]; let mut zminusy = FieldElement::new();
fe_add(&mut zplusy, &A.z, &A.y); fe_add(&mut zplusy, &A.z, &A.y);
fe_sub(&mut zminusy, &A.z, &A.y); fe_sub(&mut zminusy, &A.z, &A.y);
let zminusy_inv = fe_invert(&zminusy); let zminusy_inv = fe_invert(&zminusy);
@@ -1819,10 +1832,10 @@ fn public_from_private() {
}); });
} }
fn into_encoded_point(bytes: &mut [u8], x: &Element, y: &Element, z: &Element) fn into_encoded_point(bytes: &mut [u8], x: &FieldElement, y: &FieldElement, z: &FieldElement)
{ {
let mut x_over_z = [0; NUM_ELEMENT_LIMBS]; let mut x_over_z = FieldElement::new();
let mut y_over_z = [0; NUM_ELEMENT_LIMBS]; let mut y_over_z = FieldElement::new();
assert!(bytes.len() >= 32); assert!(bytes.len() >= 32);
let recip = fe_invert(z); let recip = fe_invert(z);
@@ -1834,4 +1847,4 @@ fn into_encoded_point(bytes: &mut [u8], x: &Element, y: &Element, z: &Element)
// The preceding computations must execute in constant time, but this // The preceding computations must execute in constant time, but this
// doesn't need to. // doesn't need to.
bytes[31] ^= sign_bit << 7; bytes[31] ^= sign_bit << 7;
} }