mirror of
https://github.com/saymrwulf/betrusted-curve25519-dalek-source.git
synced 2026-09-12 21:40:32 +00:00
accelerate the affine transform in hardware
This commit is contained in:
parent
9ffc75dd3c
commit
41cc7c4ab3
4 changed files with 306 additions and 12 deletions
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"rust-analyzer.diagnostics.disabled": [
|
||||||
|
"macro-error"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -61,6 +61,7 @@ pub(crate) const SQRT_M1: FieldElement2625 = FieldElement2625([
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/// `APLUS2_OVER_FOUR` is (A+2)/4. (This is used internally within the Montgomery ladder.)
|
/// `APLUS2_OVER_FOUR` is (A+2)/4. (This is used internally within the Montgomery ladder.)
|
||||||
|
#[cfg(not(feature = "betrusted"))]
|
||||||
pub(crate) const APLUS2_OVER_FOUR: FieldElement2625 =
|
pub(crate) const APLUS2_OVER_FOUR: FieldElement2625 =
|
||||||
FieldElement2625([121666, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
FieldElement2625([121666, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,9 @@
|
||||||
//! Note that docs will only build on nightly Rust until
|
//! Note that docs will only build on nightly Rust until
|
||||||
//! [RFC 1990 stabilizes](https://github.com/rust-lang/rust/issues/44732).
|
//! [RFC 1990 stabilizes](https://github.com/rust-lang/rust/issues/44732).
|
||||||
|
|
||||||
#![recursion_limit="256"]
|
// needed for engine25519-as. Note vscode is still broken:
|
||||||
|
// https://github.com/rust-analyzer/rust-analyzer/issues/8640
|
||||||
|
#![recursion_limit="512"]
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// External dependencies:
|
// External dependencies:
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,11 @@
|
||||||
|
|
||||||
use core::ops::{Mul, MulAssign};
|
use core::ops::{Mul, MulAssign};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "betrusted"))]
|
||||||
use constants::{APLUS2_OVER_FOUR, MONTGOMERY_A, MONTGOMERY_A_NEG};
|
use constants::{APLUS2_OVER_FOUR, MONTGOMERY_A, MONTGOMERY_A_NEG};
|
||||||
|
#[cfg(feature = "betrusted")]
|
||||||
|
use constants::{MONTGOMERY_A, MONTGOMERY_A_NEG}; // eliminate constants absorbed into the microcode engine
|
||||||
|
|
||||||
use edwards::{CompressedEdwardsY, EdwardsPoint};
|
use edwards::{CompressedEdwardsY, EdwardsPoint};
|
||||||
use field::FieldElement;
|
use field::FieldElement;
|
||||||
use scalar::Scalar;
|
use scalar::Scalar;
|
||||||
|
|
@ -64,7 +68,6 @@ use subtle::{ConditionallyNegatable, ConditionallySelectable};
|
||||||
|
|
||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
|
|
||||||
/// Holds the \\(u\\)-coordinate of a point on the Montgomery form of
|
/// Holds the \\(u\\)-coordinate of a point on the Montgomery form of
|
||||||
/// Curve25519 or its twist.
|
/// Curve25519 or its twist.
|
||||||
#[derive(Copy, Clone, Debug, Hash)]
|
#[derive(Copy, Clone, Debug, Hash)]
|
||||||
|
|
@ -191,7 +194,7 @@ pub(crate) fn elligator_encode(r_0: &FieldElement) -> MontgomeryPoint {
|
||||||
/// \\( \mathbb P(\mathbb F\_p) \\), which we identify with the Kummer
|
/// \\( \mathbb P(\mathbb F\_p) \\), which we identify with the Kummer
|
||||||
/// line of the Montgomery curve.
|
/// line of the Montgomery curve.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct ProjectivePoint {
|
pub(crate) struct ProjectivePoint {
|
||||||
pub U: FieldElement,
|
pub U: FieldElement,
|
||||||
pub W: FieldElement,
|
pub W: FieldElement,
|
||||||
}
|
}
|
||||||
|
|
@ -231,10 +234,163 @@ impl ProjectivePoint {
|
||||||
///
|
///
|
||||||
/// * \\( u = U / W \\) if \\( W \neq 0 \\);
|
/// * \\( u = U / W \\) if \\( W \neq 0 \\);
|
||||||
/// * \\( 0 \\) if \\( W \eq 0 \\);
|
/// * \\( 0 \\) if \\( W \eq 0 \\);
|
||||||
|
#[cfg(not(feature = "betrusted"))]
|
||||||
pub fn to_affine(&self) -> MontgomeryPoint {
|
pub fn to_affine(&self) -> MontgomeryPoint {
|
||||||
|
#[cfg(not(test))] // due to issue https://github.com/rust-lang/rust/issues/59168, you will have to manually comment this out when running a test on the full system and not just this crate.
|
||||||
|
log::warn!("sw to_affine being used - check for build config errors!");
|
||||||
|
|
||||||
let u = &self.U * &self.W.invert();
|
let u = &self.U * &self.W.invert();
|
||||||
MontgomeryPoint(u.to_bytes())
|
MontgomeryPoint(u.to_bytes())
|
||||||
}
|
}
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[cfg(feature = "betrusted")]
|
||||||
|
pub fn to_affine(&self) -> MontgomeryPoint {
|
||||||
|
let mcode = assemble_engine25519!(
|
||||||
|
start:
|
||||||
|
// W.invert() in %21
|
||||||
|
// U in %29
|
||||||
|
// W in %30
|
||||||
|
// result in %31
|
||||||
|
// loop counter in %28
|
||||||
|
|
||||||
|
// from FieldElement.invert()
|
||||||
|
// let (t19, t3) = self.pow22501(); // t19: 249..0 ; t3: 3,1,0
|
||||||
|
// let t0 = self.square(); // 1 e_0 = 2^1
|
||||||
|
mul %0, %30, %30 // self is W, e.g. %30
|
||||||
|
// let t1 = t0.square().square(); // 3 e_1 = 2^3
|
||||||
|
mul %1, %0, %0
|
||||||
|
mul %1, %1, %1
|
||||||
|
// let t2 = self * &t1; // 3,0 e_2 = 2^3 + 2^0
|
||||||
|
mul %2, %30, %1
|
||||||
|
// let t3 = &t0 * &t2; // 3,1,0
|
||||||
|
mul %3, %0, %2
|
||||||
|
// let t4 = t3.square(); // 4,2,1
|
||||||
|
mul %4, %3, %3
|
||||||
|
// let t5 = &t2 * &t4; // 4,3,2,1,0
|
||||||
|
mul %5, %2, %4
|
||||||
|
|
||||||
|
// let t6 = t5.pow2k(5); // 9,8,7,6,5
|
||||||
|
psa %28, #5 // coincidentally, constant #5 is the number 5
|
||||||
|
mul %6, %5, %5
|
||||||
|
pow2k_5:
|
||||||
|
sub %28, %28, #1 // %28 = %28 - 1
|
||||||
|
brz pow2k_5_exit, %28
|
||||||
|
mul %6, %6, %6
|
||||||
|
brz pow2k_5, #0
|
||||||
|
pow2k_5_exit:
|
||||||
|
// let t7 = &t6 * &t5; // 9,8,7,6,5,4,3,2,1,0
|
||||||
|
mul %7, %6, %5
|
||||||
|
|
||||||
|
// let t8 = t7.pow2k(10); // 19..10
|
||||||
|
psa %28, #6 // constant #6 is the number 10
|
||||||
|
mul %8, %7, %7
|
||||||
|
pow2k_10:
|
||||||
|
sub %28, %28, #1
|
||||||
|
brz pow2k_10_exit, %28
|
||||||
|
mul %8, %8, %8
|
||||||
|
brz pow2k_10, #0
|
||||||
|
pow2k_10_exit:
|
||||||
|
// let t9 = &t8 * &t7; // 19..0
|
||||||
|
mul %9, %8, %7
|
||||||
|
|
||||||
|
// let t10 = t9.pow2k(20); // 39..20
|
||||||
|
psa %28, #7 // constant #7 is the number 20
|
||||||
|
mul %10, %9, %9
|
||||||
|
pow2k_20:
|
||||||
|
sub %28, %28, #1
|
||||||
|
brz pow2k_20_exit, %28
|
||||||
|
mul %10, %10, %10
|
||||||
|
brz pow2k_20, #0
|
||||||
|
pow2k_20_exit:
|
||||||
|
// let t11 = &t10 * &t9; // 39..0
|
||||||
|
mul %11, %10, %9
|
||||||
|
|
||||||
|
// let t12 = t11.pow2k(10); // 49..10
|
||||||
|
psa %28, #6 // constant #6 is the number 10
|
||||||
|
mul %12, %11, %11
|
||||||
|
pow2k_10b:
|
||||||
|
sub %28, %28, #1
|
||||||
|
brz pow2k_10b_exit, %28
|
||||||
|
mul %12, %12, %12
|
||||||
|
brz pow2k_10b, #0
|
||||||
|
pow2k_10b_exit:
|
||||||
|
// let t13 = &t12 * &t7; // 49..0
|
||||||
|
mul %13, %12, %7
|
||||||
|
|
||||||
|
// let t14 = t13.pow2k(50); // 99..50
|
||||||
|
psa %28, #8 // constant #8 is the number 50
|
||||||
|
mul %14, %13, %13
|
||||||
|
pow2k_50a:
|
||||||
|
sub %28, %28, #1
|
||||||
|
brz pow2k_50a_exit, %28
|
||||||
|
mul %14, %14, %14
|
||||||
|
brz pow2k_50a, #0
|
||||||
|
pow2k_50a_exit:
|
||||||
|
// let t15 = &t14 * &t13; // 99..0
|
||||||
|
mul %15, %14, %13
|
||||||
|
|
||||||
|
// let t16 = t15.pow2k(100); // 199..100
|
||||||
|
psa %28, #9 // constant #9 is the number 100
|
||||||
|
mul %16, %15, %15
|
||||||
|
pow2k_100:
|
||||||
|
sub %28, %28, #1
|
||||||
|
brz pow2k_100_exit, %28
|
||||||
|
mul %16, %16, %16
|
||||||
|
brz pow2k_100, #0
|
||||||
|
pow2k_100_exit:
|
||||||
|
// let t17 = &t16 * &t15; // 199..0
|
||||||
|
mul %17, %16, %15
|
||||||
|
|
||||||
|
// let t18 = t17.pow2k(50); // 249..50
|
||||||
|
psa %28, #8 // constant #8 is the number 50
|
||||||
|
mul %18, %17, %17
|
||||||
|
pow2k_50b:
|
||||||
|
sub %28, %28, #1
|
||||||
|
brz pow2k_50b_exit, %28
|
||||||
|
mul %18, %18, %18
|
||||||
|
brz pow2k_50b, #0
|
||||||
|
pow2k_50b_exit:
|
||||||
|
// let t19 = &t18 * &t13; // 249..0
|
||||||
|
mul %19, %18, %13
|
||||||
|
//(t19, t3) // just a return value, values are already there, do nothing
|
||||||
|
|
||||||
|
//let t20 = t19.pow2k(5); // 254..5
|
||||||
|
psa %28, #5
|
||||||
|
mul %20, %19, %19
|
||||||
|
pow2k_5_last:
|
||||||
|
sub %28, %28, #1
|
||||||
|
brz pow2k_5_last_exit, %28
|
||||||
|
mul %20, %20, %20
|
||||||
|
brz pow2k_5_last, #0
|
||||||
|
pow2k_5_last_exit:
|
||||||
|
|
||||||
|
//let t21 = &t20 * &t3; // 254..5,3,1,0
|
||||||
|
mul %21, %20, %3
|
||||||
|
|
||||||
|
// u = &self.U * &self.W.invert()
|
||||||
|
mul %31, %29, %21
|
||||||
|
fin // finish execution
|
||||||
|
);
|
||||||
|
let mut engine = engine_25519::Engine25519::new();
|
||||||
|
let mut job = engine_25519::Job {
|
||||||
|
id: None,
|
||||||
|
ucode: [0; 1024],
|
||||||
|
uc_len: mcode.len() as u32,
|
||||||
|
uc_start: 0,
|
||||||
|
window: Some(0),
|
||||||
|
rf: [0; engine_25519::RF_SIZE_IN_U32],
|
||||||
|
};
|
||||||
|
for (&src, dst) in mcode.iter().zip(job.ucode.iter_mut()) {
|
||||||
|
*dst = src as u32;
|
||||||
|
}
|
||||||
|
copy_to_rf(self.U.to_bytes(), 29, &mut job.rf);
|
||||||
|
copy_to_rf(self.W.to_bytes(), 30, &mut job.rf);
|
||||||
|
|
||||||
|
// start the run
|
||||||
|
let result_rf = engine.spawn_job(job).expect("couldn't run engine job");
|
||||||
|
|
||||||
|
MontgomeryPoint(copy_from_rf(31, &result_rf))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform the double-and-add step of the Montgomery ladder.
|
/// Perform the double-and-add step of the Montgomery ladder.
|
||||||
|
|
@ -251,7 +407,8 @@ impl ProjectivePoint {
|
||||||
/// $$
|
/// $$
|
||||||
/// (U\_Q : W\_Q) \gets u(P + Q).
|
/// (U\_Q : W\_Q) \gets u(P + Q).
|
||||||
/// $$
|
/// $$
|
||||||
pub fn differential_add_and_double(
|
#[cfg(not(feature = "betrusted"))]
|
||||||
|
pub(crate) fn differential_add_and_double(
|
||||||
P: &mut ProjectivePoint,
|
P: &mut ProjectivePoint,
|
||||||
Q: &mut ProjectivePoint,
|
Q: &mut ProjectivePoint,
|
||||||
affine_PmQ: &FieldElement,
|
affine_PmQ: &FieldElement,
|
||||||
|
|
@ -312,8 +469,9 @@ fn copy_from_rf(register: usize, rf: &[u32; engine_25519::RF_SIZE_IN_U32]) -> [u
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)] // absorbed into mul, but might be useful later on as a subroutine for something else
|
||||||
#[cfg(feature = "betrusted")]
|
#[cfg(feature = "betrusted")]
|
||||||
pub fn differential_add_and_double_hw(
|
pub(crate) fn differential_add_and_double_hw(
|
||||||
P: &mut ProjectivePoint,
|
P: &mut ProjectivePoint,
|
||||||
Q: &mut ProjectivePoint,
|
Q: &mut ProjectivePoint,
|
||||||
affine_PmQ: &FieldElement,
|
affine_PmQ: &FieldElement,
|
||||||
|
|
@ -591,6 +749,131 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a MontgomeryPoint {
|
||||||
xor %26, %30, %26
|
xor %26, %30, %26
|
||||||
xor %28, %30, %28
|
xor %28, %30, %28
|
||||||
|
|
||||||
|
// AFFINE SPLICE -- pass arguments to the affine block
|
||||||
|
psa %29, %25
|
||||||
|
psa %30, %26
|
||||||
|
// W.invert() in %21
|
||||||
|
// U in %29
|
||||||
|
// W in %30
|
||||||
|
// result in %31
|
||||||
|
// loop counter in %28
|
||||||
|
|
||||||
|
// from FieldElement.invert()
|
||||||
|
// let (t19, t3) = self.pow22501(); // t19: 249..0 ; t3: 3,1,0
|
||||||
|
// let t0 = self.square(); // 1 e_0 = 2^1
|
||||||
|
mul %0, %30, %30 // self is W, e.g. %30
|
||||||
|
// let t1 = t0.square().square(); // 3 e_1 = 2^3
|
||||||
|
mul %1, %0, %0
|
||||||
|
mul %1, %1, %1
|
||||||
|
// let t2 = self * &t1; // 3,0 e_2 = 2^3 + 2^0
|
||||||
|
mul %2, %30, %1
|
||||||
|
// let t3 = &t0 * &t2; // 3,1,0
|
||||||
|
mul %3, %0, %2
|
||||||
|
// let t4 = t3.square(); // 4,2,1
|
||||||
|
mul %4, %3, %3
|
||||||
|
// let t5 = &t2 * &t4; // 4,3,2,1,0
|
||||||
|
mul %5, %2, %4
|
||||||
|
|
||||||
|
// let t6 = t5.pow2k(5); // 9,8,7,6,5
|
||||||
|
psa %28, #5 // coincidentally, constant #5 is the number 5
|
||||||
|
mul %6, %5, %5
|
||||||
|
pow2k_5:
|
||||||
|
sub %28, %28, #1 // %28 = %28 - 1
|
||||||
|
brz pow2k_5_exit, %28
|
||||||
|
mul %6, %6, %6
|
||||||
|
brz pow2k_5, #0
|
||||||
|
pow2k_5_exit:
|
||||||
|
// let t7 = &t6 * &t5; // 9,8,7,6,5,4,3,2,1,0
|
||||||
|
mul %7, %6, %5
|
||||||
|
|
||||||
|
// let t8 = t7.pow2k(10); // 19..10
|
||||||
|
psa %28, #6 // constant #6 is the number 10
|
||||||
|
mul %8, %7, %7
|
||||||
|
pow2k_10:
|
||||||
|
sub %28, %28, #1
|
||||||
|
brz pow2k_10_exit, %28
|
||||||
|
mul %8, %8, %8
|
||||||
|
brz pow2k_10, #0
|
||||||
|
pow2k_10_exit:
|
||||||
|
// let t9 = &t8 * &t7; // 19..0
|
||||||
|
mul %9, %8, %7
|
||||||
|
|
||||||
|
// let t10 = t9.pow2k(20); // 39..20
|
||||||
|
psa %28, #7 // constant #7 is the number 20
|
||||||
|
mul %10, %9, %9
|
||||||
|
pow2k_20:
|
||||||
|
sub %28, %28, #1
|
||||||
|
brz pow2k_20_exit, %28
|
||||||
|
mul %10, %10, %10
|
||||||
|
brz pow2k_20, #0
|
||||||
|
pow2k_20_exit:
|
||||||
|
// let t11 = &t10 * &t9; // 39..0
|
||||||
|
mul %11, %10, %9
|
||||||
|
|
||||||
|
// let t12 = t11.pow2k(10); // 49..10
|
||||||
|
psa %28, #6 // constant #6 is the number 10
|
||||||
|
mul %12, %11, %11
|
||||||
|
pow2k_10b:
|
||||||
|
sub %28, %28, #1
|
||||||
|
brz pow2k_10b_exit, %28
|
||||||
|
mul %12, %12, %12
|
||||||
|
brz pow2k_10b, #0
|
||||||
|
pow2k_10b_exit:
|
||||||
|
// let t13 = &t12 * &t7; // 49..0
|
||||||
|
mul %13, %12, %7
|
||||||
|
|
||||||
|
// let t14 = t13.pow2k(50); // 99..50
|
||||||
|
psa %28, #8 // constant #8 is the number 50
|
||||||
|
mul %14, %13, %13
|
||||||
|
pow2k_50a:
|
||||||
|
sub %28, %28, #1
|
||||||
|
brz pow2k_50a_exit, %28
|
||||||
|
mul %14, %14, %14
|
||||||
|
brz pow2k_50a, #0
|
||||||
|
pow2k_50a_exit:
|
||||||
|
// let t15 = &t14 * &t13; // 99..0
|
||||||
|
mul %15, %14, %13
|
||||||
|
|
||||||
|
// let t16 = t15.pow2k(100); // 199..100
|
||||||
|
psa %28, #9 // constant #9 is the number 100
|
||||||
|
mul %16, %15, %15
|
||||||
|
pow2k_100:
|
||||||
|
sub %28, %28, #1
|
||||||
|
brz pow2k_100_exit, %28
|
||||||
|
mul %16, %16, %16
|
||||||
|
brz pow2k_100, #0
|
||||||
|
pow2k_100_exit:
|
||||||
|
// let t17 = &t16 * &t15; // 199..0
|
||||||
|
mul %17, %16, %15
|
||||||
|
|
||||||
|
// let t18 = t17.pow2k(50); // 249..50
|
||||||
|
psa %28, #8 // constant #8 is the number 50
|
||||||
|
mul %18, %17, %17
|
||||||
|
pow2k_50b:
|
||||||
|
sub %28, %28, #1
|
||||||
|
brz pow2k_50b_exit, %28
|
||||||
|
mul %18, %18, %18
|
||||||
|
brz pow2k_50b, #0
|
||||||
|
pow2k_50b_exit:
|
||||||
|
// let t19 = &t18 * &t13; // 249..0
|
||||||
|
mul %19, %18, %13
|
||||||
|
//(t19, t3) // just a return value, values are already there, do nothing
|
||||||
|
|
||||||
|
//let t20 = t19.pow2k(5); // 254..5
|
||||||
|
psa %28, #5
|
||||||
|
mul %20, %19, %19
|
||||||
|
pow2k_5_last:
|
||||||
|
sub %28, %28, #1
|
||||||
|
brz pow2k_5_last_exit, %28
|
||||||
|
mul %20, %20, %20
|
||||||
|
brz pow2k_5_last, #0
|
||||||
|
pow2k_5_last_exit:
|
||||||
|
|
||||||
|
//let t21 = &t20 * &t3; // 254..5,3,1,0
|
||||||
|
mul %21, %20, %3
|
||||||
|
|
||||||
|
// u = &self.U * &self.W.invert()
|
||||||
|
mul %31, %29, %21
|
||||||
fin // finish execution
|
fin // finish execution
|
||||||
);
|
);
|
||||||
let mut engine = engine_25519::Engine25519::new();
|
let mut engine = engine_25519::Engine25519::new();
|
||||||
|
|
@ -624,7 +907,7 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a MontgomeryPoint {
|
||||||
// start the run
|
// start the run
|
||||||
let result_rf = engine.spawn_job(job).expect("couldn't run engine job");
|
let result_rf = engine.spawn_job(job).expect("couldn't run engine job");
|
||||||
|
|
||||||
|
if false { // unmerged affine path
|
||||||
x0.U = FieldElement::from_bytes(©_from_rf(25, &result_rf));
|
x0.U = FieldElement::from_bytes(©_from_rf(25, &result_rf));
|
||||||
x0.W = FieldElement::from_bytes(©_from_rf(26, &result_rf));
|
x0.W = FieldElement::from_bytes(©_from_rf(26, &result_rf));
|
||||||
|
|
||||||
|
|
@ -632,6 +915,9 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a MontgomeryPoint {
|
||||||
// this consumes about 100ms runtime -- need to implement this using
|
// this consumes about 100ms runtime -- need to implement this using
|
||||||
// curve25519 acceleration!
|
// curve25519 acceleration!
|
||||||
x0.to_affine()
|
x0.to_affine()
|
||||||
|
} else {
|
||||||
|
MontgomeryPoint(copy_from_rf(31, &result_rf))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "betrusted"))]
|
#[cfg(not(feature = "betrusted"))]
|
||||||
fn mul(self, scalar: &'b Scalar) -> MontgomeryPoint {
|
fn mul(self, scalar: &'b Scalar) -> MontgomeryPoint {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue