mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-07 20:50:39 +00:00
Add skeleton of parallel Edwards formulas.
This commit is contained in:
parent
5880fced2b
commit
3f21bb3b58
3 changed files with 187 additions and 0 deletions
136
src/backend/vector/ifma/edwards.rs
Normal file
136
src/backend/vector/ifma/edwards.rs
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
// -*- mode: rust; -*-
|
||||||
|
//
|
||||||
|
// This file is part of curve25519-dalek.
|
||||||
|
// Copyright (c) 2018 Henry de Valence
|
||||||
|
// See LICENSE for licensing information.
|
||||||
|
//
|
||||||
|
// Authors:
|
||||||
|
// - Henry de Valence <hdevalence@hdevalence.ca>
|
||||||
|
|
||||||
|
use traits::Identity;
|
||||||
|
|
||||||
|
use std::ops::Add;
|
||||||
|
|
||||||
|
use edwards;
|
||||||
|
|
||||||
|
use super::field::{F51x4Reduced, F51x4Unreduced, Lanes, Shuffle};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct ExtendedPoint(pub(super) F51x4Unreduced);
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct CachedPoint(pub(super) F51x4Reduced);
|
||||||
|
|
||||||
|
impl From<edwards::EdwardsPoint> for ExtendedPoint {
|
||||||
|
fn from(P: edwards::EdwardsPoint) -> ExtendedPoint {
|
||||||
|
ExtendedPoint(F51x4Unreduced::new(&P.X, &P.Y, &P.Z, &P.T))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ExtendedPoint> for edwards::EdwardsPoint {
|
||||||
|
fn from(P: ExtendedPoint) -> edwards::EdwardsPoint {
|
||||||
|
let tmp = P.0.split();
|
||||||
|
edwards::EdwardsPoint {
|
||||||
|
X: tmp[0],
|
||||||
|
Y: tmp[1],
|
||||||
|
Z: tmp[2],
|
||||||
|
T: tmp[3],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ExtendedPoint> for CachedPoint {
|
||||||
|
fn from(P: ExtendedPoint) -> CachedPoint {
|
||||||
|
let mut x = P.0;
|
||||||
|
|
||||||
|
x = x.blend(&x.diff_sum(), Lanes::AB);
|
||||||
|
x = &F51x4Reduced::from(x) * (121666, 121666, 2 * 121666, 2 * 121665);
|
||||||
|
x = x.blend(&x.negate_lazy(), Lanes::D);
|
||||||
|
|
||||||
|
CachedPoint(F51x4Reduced::from(x))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> Add<&'b CachedPoint> for &'a ExtendedPoint {
|
||||||
|
type Output = ExtendedPoint;
|
||||||
|
|
||||||
|
/// Add an `ExtendedPoint` and a `CachedPoint`.
|
||||||
|
fn add(self, other: &'b CachedPoint) -> ExtendedPoint {
|
||||||
|
let mut tmp = self.0;
|
||||||
|
|
||||||
|
tmp = tmp.blend(&tmp.diff_sum(), Lanes::AB);
|
||||||
|
// tmp = (Y1-X1 Y1+X1 Z1 T1) = (S0 S1 Z1 T1)
|
||||||
|
|
||||||
|
tmp = &F51x4Reduced::from(tmp) * &other.0;
|
||||||
|
// tmp = (S0*S2' S1*S3' Z1*Z2' T1*T2') = (S8 S9 S10 S11)
|
||||||
|
|
||||||
|
tmp = tmp.shuffle(Shuffle::ABDC);
|
||||||
|
// tmp = (S8 S9 S11 S10)
|
||||||
|
|
||||||
|
let tmp = F51x4Reduced::from(tmp.diff_sum());
|
||||||
|
// tmp = (S9-S8 S9+S8 S10-S11 S10+S11) = (S12 S13 S14 S15)
|
||||||
|
|
||||||
|
let t0 = tmp.shuffle(Shuffle::ADDA);
|
||||||
|
// t0 = (S12 S15 S15 S12)
|
||||||
|
let t1 = tmp.shuffle(Shuffle::CBCB);
|
||||||
|
// t1 = (S14 S13 S14 S13)
|
||||||
|
|
||||||
|
// Return (S12*S14 S15*S13 S15*S14 S12*S13) = (X3 Y3 Z3 T3)
|
||||||
|
ExtendedPoint(&t0 * &t1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn addition_test_helper(P: edwards::EdwardsPoint, Q: edwards::EdwardsPoint) {
|
||||||
|
// Test the serial implementation of the parallel addition formulas
|
||||||
|
//let R_serial: edwards::EdwardsPoint = serial_add(P.into(), Q.into()).into();
|
||||||
|
|
||||||
|
// Test the vector implementation of the parallel readdition formulas
|
||||||
|
let cached_Q = CachedPoint::from(ExtendedPoint::from(Q));
|
||||||
|
let R_vector: edwards::EdwardsPoint = (&ExtendedPoint::from(P) + &cached_Q).into();
|
||||||
|
//et S_vector: edwards::EdwardsPoint = (&ExtendedPoint::from(P) - &cached_Q).into();
|
||||||
|
|
||||||
|
println!("Testing point addition:");
|
||||||
|
println!("P = {:?}", P);
|
||||||
|
println!("Q = {:?}", Q);
|
||||||
|
println!("cached Q = {:?}", cached_Q);
|
||||||
|
println!("R = P + Q = {:?}", &P + &Q);
|
||||||
|
//println!("R_serial = {:?}", R_serial);
|
||||||
|
println!("R_vector = {:?}", R_vector);
|
||||||
|
//println!("S = P - Q = {:?}", &P - &Q);
|
||||||
|
//println!("S_vector = {:?}", S_vector);
|
||||||
|
//assert_eq!(R_serial.compress(), (&P + &Q).compress());
|
||||||
|
assert_eq!(R_vector.compress(), (&P + &Q).compress());
|
||||||
|
//assert_eq!(S_vector.compress(), (&P - &Q).compress());
|
||||||
|
println!("OK!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn vector_addition_vs_serial_addition_vs_edwards_extendedpoint() {
|
||||||
|
use constants;
|
||||||
|
use scalar::Scalar;
|
||||||
|
|
||||||
|
println!("Testing id +- id");
|
||||||
|
let P = edwards::EdwardsPoint::identity();
|
||||||
|
let Q = edwards::EdwardsPoint::identity();
|
||||||
|
addition_test_helper(P, Q);
|
||||||
|
|
||||||
|
println!("Testing id +- B");
|
||||||
|
let P = edwards::EdwardsPoint::identity();
|
||||||
|
let Q = constants::ED25519_BASEPOINT_POINT;
|
||||||
|
addition_test_helper(P, Q);
|
||||||
|
|
||||||
|
println!("Testing B +- B");
|
||||||
|
let P = constants::ED25519_BASEPOINT_POINT;
|
||||||
|
let Q = constants::ED25519_BASEPOINT_POINT;
|
||||||
|
addition_test_helper(P, Q);
|
||||||
|
|
||||||
|
println!("Testing B +- kB");
|
||||||
|
let P = constants::ED25519_BASEPOINT_POINT;
|
||||||
|
let Q = &constants::ED25519_BASEPOINT_TABLE * &Scalar::from(8475983829u64);
|
||||||
|
addition_test_helper(P, Q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,12 +30,18 @@ pub struct F51x4Reduced(pub(crate) [u64x4; 5]);
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Lanes {
|
pub enum Lanes {
|
||||||
|
D,
|
||||||
AB,
|
AB,
|
||||||
|
AC,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Shuffle {
|
pub enum Shuffle {
|
||||||
AAAA,
|
AAAA,
|
||||||
|
BADC,
|
||||||
|
ADDA,
|
||||||
|
CBCB,
|
||||||
|
ABDC,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
@ -45,6 +51,10 @@ fn shuffle_lanes(x: u64x4, control: Shuffle) -> u64x4 {
|
||||||
|
|
||||||
match control {
|
match control {
|
||||||
Shuffle::AAAA => perm(x.into_bits(), 0b00_00_00_00).into_bits(),
|
Shuffle::AAAA => perm(x.into_bits(), 0b00_00_00_00).into_bits(),
|
||||||
|
Shuffle::BADC => perm(x.into_bits(), 0b10_11_00_01).into_bits(),
|
||||||
|
Shuffle::ADDA => perm(x.into_bits(), 0b00_11_11_00).into_bits(),
|
||||||
|
Shuffle::CBCB => perm(x.into_bits(), 0b01_10_01_10).into_bits(),
|
||||||
|
Shuffle::ABDC => perm(x.into_bits(), 0b10_11_01_00).into_bits(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -55,7 +65,9 @@ fn blend_lanes(x: u64x4, y: u64x4, control: Lanes) -> u64x4 {
|
||||||
use core::arch::x86_64::_mm256_blend_epi32 as blend;
|
use core::arch::x86_64::_mm256_blend_epi32 as blend;
|
||||||
|
|
||||||
match control {
|
match control {
|
||||||
|
Lanes::D => blend(x.into_bits(), y.into_bits(), 0b11_00_00_00).into_bits(),
|
||||||
Lanes::AB => blend(x.into_bits(), y.into_bits(), 0b00_00_11_11).into_bits(),
|
Lanes::AB => blend(x.into_bits(), y.into_bits(), 0b00_00_11_11).into_bits(),
|
||||||
|
Lanes::AC => blend(x.into_bits(), y.into_bits(), 0b00_11_00_11).into_bits(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -110,6 +122,29 @@ impl F51x4Unreduced {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn diff_sum(&self) -> F51x4Unreduced {
|
||||||
|
// tmp1 = (B, A, D, C)
|
||||||
|
let tmp1 = self.shuffle(Shuffle::BADC);
|
||||||
|
// tmp2 = (-A, B, -C, D)
|
||||||
|
let tmp2 = self.blend(&self.negate_lazy(), Lanes::AC);
|
||||||
|
// (B - A, B + A, D - C, D + C)
|
||||||
|
tmp1 + tmp2
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn negate_lazy(&self) -> F51x4Unreduced {
|
||||||
|
let lo = u64x4::splat(36028797018963664u64);
|
||||||
|
let hi = u64x4::splat(36028797018963952u64);
|
||||||
|
F51x4Unreduced([
|
||||||
|
lo - self.0[0],
|
||||||
|
hi - self.0[1],
|
||||||
|
hi - self.0[2],
|
||||||
|
hi - self.0[3],
|
||||||
|
hi - self.0[4],
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn shuffle(&self, control: Shuffle) -> F51x4Unreduced {
|
pub fn shuffle(&self, control: Shuffle) -> F51x4Unreduced {
|
||||||
F51x4Unreduced([
|
F51x4Unreduced([
|
||||||
|
|
@ -189,6 +224,20 @@ impl From<F51x4Unreduced> for F51x4Reduced {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Add<F51x4Unreduced> for F51x4Unreduced {
|
||||||
|
type Output = F51x4Unreduced;
|
||||||
|
#[inline]
|
||||||
|
fn add(self, rhs: F51x4Unreduced) -> F51x4Unreduced {
|
||||||
|
F51x4Unreduced([
|
||||||
|
self.0[0] + rhs.0[0],
|
||||||
|
self.0[1] + rhs.0[1],
|
||||||
|
self.0[2] + rhs.0[2],
|
||||||
|
self.0[3] + rhs.0[3],
|
||||||
|
self.0[4] + rhs.0[4],
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Mul<(u32, u32, u32, u32)> for &'a F51x4Reduced {
|
impl<'a> Mul<(u32, u32, u32, u32)> for &'a F51x4Reduced {
|
||||||
type Output = F51x4Unreduced;
|
type Output = F51x4Unreduced;
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,5 @@
|
||||||
|
|
||||||
pub mod field;
|
pub mod field;
|
||||||
|
|
||||||
|
pub mod edwards;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue