1147 lines
37 KiB
Rust
1147 lines
37 KiB
Rust
#![recursion_limit="768"]
|
|
|
|
extern crate engine25519_as;
|
|
use engine25519_as::*;
|
|
|
|
fn main() -> std::io::Result<()> {
|
|
let mcode = assemble_engine25519!(
|
|
start:
|
|
// P.U in %20
|
|
// P.W in %21
|
|
// Q.U in %22
|
|
// Q.W in %23
|
|
// affine_PmQ in %24 // I
|
|
// %30 is the TRD scratch register and cswap dummy
|
|
// %29 is the subtraction temporary value register and k_t
|
|
// x0.U in %25 // I
|
|
// x0.W in %26 // I
|
|
// x1.U in %27 // I
|
|
// x1.W in %28 /// I
|
|
// %19 is the loop counter, starts with 254 (if 0, loop runs exactly once) // I
|
|
// %31 is the scalar // I
|
|
// %18 is the swap variable
|
|
psa %18, #0
|
|
|
|
// for i in (0..255).rev()
|
|
mainloop:
|
|
// let choice: u8 = (bits[i + 1] ^ bits[i]) as u8;
|
|
// ProjectivePoint::conditional_swap(&mut x0, &mut x1, choice.into());
|
|
xbt %29, %31 // orignally[k_t = (k>>t) & 1] now[k_t = k[254]]
|
|
shl %31, %31 // k = k<<1
|
|
xor %18, %18, %29 // swap ^= k_t
|
|
|
|
// cswap x0.U (%25), x1.U (%27)
|
|
xor %30, %25, %27
|
|
msk %30, %18, %30
|
|
xor %25, %30, %25
|
|
xor %27, %30, %27
|
|
// cswap x0.W (%26), x1.W (%28)
|
|
xor %30, %26, %28
|
|
msk %30, %18, %30
|
|
xor %26, %30, %26
|
|
xor %28, %30, %28
|
|
|
|
psa %18, %29 // swap = k_t
|
|
|
|
// differential_add_and_double(&mut x0, &mut x1, &affine_u);
|
|
psa %20, %25
|
|
psa %21, %26
|
|
psa %22, %27
|
|
psa %23, %28
|
|
// affine_u is already in %24
|
|
|
|
// let t0 = &P.U + &P.W;
|
|
add %0, %20, %21
|
|
trd %30, %0
|
|
sub %0, %0, %30
|
|
// let t1 = &P.U - &P.W;
|
|
sub %21, #3, %21 // negate &P.W using #FIELDPRIME (#3)
|
|
add %1, %20, %21
|
|
trd %30, %1
|
|
sub %1, %1, %30
|
|
// let t2 = &Q.U + &Q.W;
|
|
add %2, %22, %23
|
|
trd %30, %2
|
|
sub %2, %2, %30
|
|
// let t3 = &Q.U - &Q.W;
|
|
sub %23, #3, %23
|
|
add %3, %22, %23
|
|
trd %30, %3
|
|
sub %3, %3, %30
|
|
// let t4 = t0.square(); // (U_P + W_P)^2 = U_P^2 + 2 U_P W_P + W_P^2
|
|
mul %4, %0, %0
|
|
// let t5 = t1.square(); // (U_P - W_P)^2 = U_P^2 - 2 U_P W_P + W_P^2
|
|
mul %5, %1, %1
|
|
// let t6 = &t4 - &t5; // 4 U_P W_P
|
|
sub %29, #3, %5
|
|
add %6, %4, %29
|
|
trd %30, %6
|
|
sub %6, %6, %30
|
|
// let t7 = &t0 * &t3; // (U_P + W_P) (U_Q - W_Q) = U_P U_Q + W_P U_Q - U_P W_Q - W_P W_Q
|
|
mul %7, %0, %3
|
|
// let t8 = &t1 * &t2; // (U_P - W_P) (U_Q + W_Q) = U_P U_Q - W_P U_Q + U_P W_Q - W_P W_Q
|
|
mul %8, %1, %2
|
|
// let t9 = &t7 + &t8; // 2 (U_P U_Q - W_P W_Q)
|
|
add %9, %7, %8
|
|
trd %30, %9
|
|
sub %9, %9, %30
|
|
// let t10 = &t7 - &t8; // 2 (W_P U_Q - U_P W_Q)
|
|
sub %29, #3, %8
|
|
add %10, %7, %29
|
|
trd %30, %10
|
|
sub %10, %10, %30
|
|
// let t11 = t9.square(); // 4 (U_P U_Q - W_P W_Q)^2
|
|
mul %11, %9, %9
|
|
// let t12 = t10.square(); // 4 (W_P U_Q - U_P W_Q)^2
|
|
mul %12, %10, %10
|
|
// let t13 = &APLUS2_OVER_FOUR * &t6; // (A + 2) U_P U_Q
|
|
mul %13, #4, %6 // #4 is A+2/4
|
|
// let t14 = &t4 * &t5; // ((U_P + W_P)(U_P - W_P))^2 = (U_P^2 - W_P^2)^2
|
|
mul %14, %4, %5
|
|
// let t15 = &t13 + &t5; // (U_P - W_P)^2 + (A + 2) U_P W_P
|
|
add %15, %13, %5
|
|
trd %30, %15
|
|
sub %15, %15, %30
|
|
// let t16 = &t6 * &t15; // 4 (U_P W_P) ((U_P - W_P)^2 + (A + 2) U_P W_P)
|
|
mul %16, %6, %15
|
|
// let t17 = affine_PmQ * &t12; // U_D * 4 (W_P U_Q - U_P W_Q)^2
|
|
mul %17, %24, %12 // affine_PmQ loaded into %24
|
|
|
|
///// these can be eliminated down the road, but included for 1:1 algorithm correspodence to reference in early testing
|
|
// P.U = t14; // U_{P'} = (U_P + W_P)^2 (U_P - W_P)^2
|
|
psa %20, %14
|
|
// P.W = t16; // W_{P'} = (4 U_P W_P) ((U_P - W_P)^2 + ((A + 2)/4) 4 U_P W_P)
|
|
psa %21, %16
|
|
// let t18 = t11; // W_D * 4 (U_P U_Q - W_P W_Q)^2
|
|
// Q.U = t18; // U_{Q'} = W_D * 4 (U_P U_Q - W_P W_Q)^2
|
|
psa %22, %11 // collapsed two to save a register
|
|
// Q.W = t17; // W_{Q'} = U_D * 4 (W_P U_Q - U_P W_Q)^2
|
|
psa %23, %17
|
|
|
|
///// 'return' arguments for next iteration, can be optimized out later
|
|
psa %25, %20
|
|
psa %26, %21
|
|
psa %27, %22
|
|
psa %28, %23
|
|
|
|
brz end, %19 // if loop counter is 0, quit
|
|
sub %19, %19, #1 // subtract one from the loop counter and run again
|
|
brz mainloop, #0 // go back to the top
|
|
end:
|
|
// ProjectivePoint::conditional_swap(&mut x0, &mut x1, Choice::from(bits[0] as u8));
|
|
// cswap x0.U (%25), x1.U (%27)
|
|
xor %30, %25, %27
|
|
msk %30, %18, %30
|
|
xor %25, %30, %25
|
|
xor %27, %30, %27
|
|
// cswap x0.W (%26), x1.W (%28)
|
|
xor %30, %26, %28
|
|
msk %30, %18, %30
|
|
xor %26, %30, %26
|
|
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
|
|
);
|
|
let mcode_upd = assemble_engine25519!(
|
|
start:
|
|
// P.U in %20
|
|
// P.W in %21
|
|
// Q.U in %22
|
|
// Q.W in %23
|
|
// affine_PmQ in %24 // I
|
|
// %30 is the TRD scratch register and cswap dummy
|
|
// %29 is the subtraction temporary value register and k_t
|
|
// x0.U in %25 // !I
|
|
// x0.W in %26 // !I
|
|
// x1.U in %27 // !I
|
|
// x1.W in %28 // !I
|
|
// %19 is the loop counter, starts with 254 (if 0, loop runs exactly once) // I
|
|
// %31 is the scalar // I
|
|
// %18 is the swap variable
|
|
psa %25, #1
|
|
psa %26, #0
|
|
psa %27, %24
|
|
psa %28, #1
|
|
// #10 is 254 in my Engine
|
|
psa %19, #10
|
|
psa %18, #0
|
|
|
|
// for i in (0..255).rev()
|
|
mainloop:
|
|
// let choice: u8 = (bits[i + 1] ^ bits[i]) as u8;
|
|
// ProjectivePoint::conditional_swap(&mut x0, &mut x1, choice.into());
|
|
xbt %29, %31 // orignally[k_t = (k>>t) & 1] now[k_t = k[254]]
|
|
shl %31, %31 // k = k<<1
|
|
xor %18, %18, %29 // swap ^= k_t
|
|
|
|
// cswap x0.U (%25), x1.U (%27)
|
|
xor %30, %25, %27
|
|
msk %30, %18, %30
|
|
xor %25, %30, %25
|
|
xor %27, %30, %27
|
|
// cswap x0.W (%26), x1.W (%28)
|
|
xor %30, %26, %28
|
|
msk %30, %18, %30
|
|
xor %26, %30, %26
|
|
xor %28, %30, %28
|
|
|
|
psa %18, %29 // swap = k_t
|
|
|
|
// differential_add_and_double(&mut x0, &mut x1, &affine_u);
|
|
// affine_u is already in %24
|
|
|
|
// let t0 = &P.U + &P.W;
|
|
add %0, %25, %26
|
|
trd %30, %0
|
|
sub %0, %0, %30
|
|
// let t1 = &P.U - &P.W;
|
|
sub %26, #3, %26 // negate &P.W using #FIELDPRIME (#3)
|
|
add %1, %25, %26
|
|
trd %30, %1
|
|
sub %1, %1, %30
|
|
// let t2 = &Q.U + &Q.W;
|
|
add %2, %27, %28
|
|
trd %30, %2
|
|
sub %2, %2, %30
|
|
// let t3 = &Q.U - &Q.W;
|
|
sub %28, #3, %28
|
|
add %3, %27, %28
|
|
trd %30, %3
|
|
sub %3, %3, %30
|
|
// let t4 = t0.square(); // (U_P + W_P)^2 = U_P^2 + 2 U_P W_P + W_P^2
|
|
mul %4, %0, %0
|
|
// let t5 = t1.square(); // (U_P - W_P)^2 = U_P^2 - 2 U_P W_P + W_P^2
|
|
mul %5, %1, %1
|
|
// let t6 = &t4 - &t5; // 4 U_P W_P
|
|
sub %29, #3, %5
|
|
add %6, %4, %29
|
|
trd %30, %6
|
|
sub %6, %6, %30
|
|
// let t7 = &t0 * &t3; // (U_P + W_P) (U_Q - W_Q) = U_P U_Q + W_P U_Q - U_P W_Q - W_P W_Q
|
|
mul %7, %0, %3
|
|
// let t8 = &t1 * &t2; // (U_P - W_P) (U_Q + W_Q) = U_P U_Q - W_P U_Q + U_P W_Q - W_P W_Q
|
|
mul %8, %1, %2
|
|
// let t9 = &t7 + &t8; // 2 (U_P U_Q - W_P W_Q)
|
|
add %9, %7, %8
|
|
trd %30, %9
|
|
sub %9, %9, %30
|
|
// let t10 = &t7 - &t8; // 2 (W_P U_Q - U_P W_Q)
|
|
sub %29, #3, %8
|
|
add %10, %7, %29
|
|
trd %30, %10
|
|
sub %10, %10, %30
|
|
// let t11 = t9.square(); // 4 (U_P U_Q - W_P W_Q)^2
|
|
mul %27, %9, %9
|
|
// let t12 = t10.square(); // 4 (W_P U_Q - U_P W_Q)^2
|
|
mul %12, %10, %10
|
|
// let t13 = &APLUS2_OVER_FOUR * &t6; // (A + 2) U_P U_Q
|
|
mul %13, #4, %6 // #4 is A+2/4
|
|
// let t14 = &t4 * &t5; // ((U_P + W_P)(U_P - W_P))^2 = (U_P^2 - W_P^2)^2
|
|
mul %25, %4, %5
|
|
// let t15 = &t13 + &t5; // (U_P - W_P)^2 + (A + 2) U_P W_P
|
|
add %15, %13, %5
|
|
trd %30, %15
|
|
sub %15, %15, %30
|
|
// let t16 = &t6 * &t15; // 4 (U_P W_P) ((U_P - W_P)^2 + (A + 2) U_P W_P)
|
|
mul %26, %6, %15
|
|
// let t17 = affine_PmQ * &t12; // U_D * 4 (W_P U_Q - U_P W_Q)^2
|
|
mul %28, %24, %12 // affine_PmQ loaded into %24
|
|
|
|
brz end, %19 // if loop counter is 0, quit
|
|
sub %19, %19, #1 // subtract one from the loop counter and run again
|
|
brz mainloop, #0 // go back to the top
|
|
end:
|
|
// ProjectivePoint::conditional_swap(&mut x0, &mut x1, Choice::from(bits[0] as u8));
|
|
// cswap x0.U (%25), x1.U (%27)
|
|
xor %30, %25, %27
|
|
msk %30, %18, %30
|
|
xor %25, %30, %25
|
|
xor %27, %30, %27
|
|
// cswap x0.W (%26), x1.W (%28)
|
|
xor %30, %26, %28
|
|
msk %30, %18, %30
|
|
xor %26, %30, %26
|
|
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
|
|
);
|
|
|
|
let mcode2 = assemble_engine25519!(
|
|
start:
|
|
// P.U in %20
|
|
// P.W in %21
|
|
// Q.U in %22
|
|
// Q.W in %23
|
|
// affine_PmQ in %24 // I
|
|
// %30 is the TRD scratch register and cswap dummy
|
|
// %29 is the subtraction temporary value register and k_t
|
|
// x0.U in %25 // I
|
|
// x0.W in %26 // I
|
|
// x1.U in %27 // I
|
|
// x1.W in %28 /// I
|
|
// %19 is the loop counter, starts with 254 (if 0, loop runs exactly once) // I
|
|
// %31 is the scalar // I
|
|
// %18 is the swap variable
|
|
psa %25, #9
|
|
psa %26, #1
|
|
mul %27, %25, %26
|
|
mul %28, %25, %25
|
|
mul %31, %24, %24
|
|
fin
|
|
);
|
|
|
|
let gcmcode_test = assemble_engine25519!(
|
|
start:
|
|
// A in %0
|
|
// B in %1
|
|
clmul %4, %0, %1, #0
|
|
clmul %5, %0, %1, #1
|
|
clmul %6, %0, %1, #2
|
|
clmul %7, %0, %1, #3
|
|
//gcm_sl1ai %8, %0, %1
|
|
//gcm_sl1ai %9, %0, #0
|
|
//gcm_sl1ai %10, %1, %0
|
|
//gcm_sl1ai %11, %1, #0
|
|
gcm_cmpd %12, %0
|
|
gcm_cmpd %13, %1
|
|
//gcm_sri %14, %0, #0
|
|
//gcm_sri %15, %0, #1
|
|
//gcm_sri %16, %0, #2
|
|
//gcm_sri %17, %0, #3
|
|
//gcm_sri %18, %0, #4
|
|
//gcm_sri %19, %0, #5
|
|
//gcm_sri %20, %0, #6
|
|
//gcm_sri %21, %0, #7
|
|
fin
|
|
);
|
|
let gcmcode = assemble_engine25519!(
|
|
start:
|
|
// A in %0
|
|
// B in %1
|
|
|
|
// // poly mult
|
|
// C
|
|
clmul %4, %0, %1, #0
|
|
// E
|
|
clmul %5, %0, %1, #1
|
|
// F
|
|
clmul %6, %0, %1, #2
|
|
// D
|
|
clmul %7, %0, %1, #3
|
|
// E ^ F
|
|
xor %6, %5, %6
|
|
// put low64 of E^F in high64
|
|
gcm_swap64 %5, %6, #0
|
|
// put high64 of E^F in low64
|
|
gcm_swap64 %6, #0, %6
|
|
// D xor low
|
|
xor %7, %7, %6
|
|
// C xor high
|
|
xor %4, %4, %5
|
|
|
|
// // reduction
|
|
// X1:X0 in %4
|
|
// X3:X2 in %7
|
|
// shift everybody by 1 to the left
|
|
// high shifting in 1 bit from low
|
|
gcm_shlmi %1, %7, %4, #1
|
|
// low
|
|
gcm_shlmi %0, %4, #0, #1
|
|
// post-shift
|
|
// X1:X0 in %0
|
|
// X3:X2 in %1
|
|
// compute D
|
|
gcm_cmpd %2, %0
|
|
// compute E, F, G
|
|
gcm_shrmi %3, %2, #0, #1
|
|
gcm_shrmi %4, %2, #0, #2
|
|
gcm_shrmi %5, %2, #0, #7
|
|
// XOR everybody
|
|
xor %2, %2, %3
|
|
xor %4, %4, %5
|
|
xor %2, %2, %4
|
|
xor %0, %2, %1
|
|
// output in %0
|
|
fin
|
|
);
|
|
let aescode = assemble_engine25519!(
|
|
start:
|
|
// X in %0
|
|
// KEY in %31-%17 (backward)
|
|
// one full round demo
|
|
xor %0, %0, %31
|
|
|
|
aesesmi %1, %0, %30
|
|
|
|
aesesmi %0, %1, %29
|
|
|
|
aesesmi %1, %0, %28
|
|
|
|
aesesmi %0, %1, %27
|
|
|
|
aesesmi %1, %0, %26
|
|
|
|
aesesmi %0, %1, %25
|
|
|
|
aesesmi %1, %0, %24
|
|
|
|
aesesmi %0, %1, %23
|
|
|
|
aesesmi %1, %0, %22
|
|
|
|
aesesmi %0, %1, %21
|
|
|
|
aesesmi %1, %0, %20
|
|
|
|
aesesmi %0, %1, %19
|
|
|
|
aesesmi %1, %0, %18
|
|
|
|
aesesi %0, %1, %17
|
|
|
|
fin
|
|
);
|
|
let gcm_pfx_code = assemble_engine25519!(
|
|
start:
|
|
// Input: rkeys in %31-%17 (backward, LE)
|
|
// pub in %16 (0-11, 12-15 are ctr so 0, LE)
|
|
// RD_PTR in %3
|
|
// ADLEN in %12 (in 16-byte-blocks)
|
|
// Transient:
|
|
// %0, %1, %2 are tmp
|
|
// Output:
|
|
// all inputs preserved
|
|
// H will go in %15 (byte-reverted)
|
|
// T will go in %14
|
|
// accum (0) will go in %13
|
|
gcm_brev32 %16, %16
|
|
// use %2 as a flag
|
|
psa %2, #1
|
|
psa %1, #0
|
|
genht:
|
|
xor %0, %1, %31
|
|
|
|
aesesmi %1, %0, %30
|
|
|
|
aesesmi %0, %1, %29
|
|
|
|
aesesmi %1, %0, %28
|
|
|
|
aesesmi %0, %1, %27
|
|
|
|
aesesmi %1, %0, %26
|
|
|
|
aesesmi %0, %1, %25
|
|
|
|
aesesmi %1, %0, %24
|
|
|
|
aesesmi %0, %1, %23
|
|
|
|
aesesmi %1, %0, %22
|
|
|
|
aesesmi %0, %1, %21
|
|
|
|
aesesmi %1, %0, %20
|
|
|
|
aesesmi %0, %1, %19
|
|
|
|
aesesmi %1, %0, %18
|
|
|
|
aesesi %0, %1, %17
|
|
|
|
// if the %2 flag is cleared, we've just computed T
|
|
brz afterht, %2
|
|
// store H in %15
|
|
psa %15, %0
|
|
// increment counter; should we have a gcm_inc_be ?
|
|
// for now byterev + special constant
|
|
gcm_brev32 %16, %16
|
|
add %16, %16, #11
|
|
gcm_brev32 %16, %16
|
|
// clear flag & go encrypt t
|
|
psa %2, #0
|
|
psa %1, %16
|
|
brz genht, #0
|
|
|
|
afterht:
|
|
// store T in %14
|
|
psa %14, %0
|
|
|
|
// fully byte-revert H (first byte-in-dword, then dword-in-64bit)
|
|
gcm_brev64 %15, %15
|
|
gcm_swap64 %15, %15, %15
|
|
|
|
psa %13, #0
|
|
|
|
// no fin; we fall directly into the AD code
|
|
//fin
|
|
);
|
|
let gcm_ad_code = assemble_engine25519!(
|
|
// Input: rkeys in %31-%17 (backward, LE)
|
|
// pub in %16 (0-11, 12-15 are ctr so 0, LE)
|
|
// RD_PTR in %3
|
|
// ADLEN in %12 (in 16-byte-blocks)
|
|
// H in %15 (byte-reverted)
|
|
// T in %14
|
|
// accum in %13
|
|
// Transient:
|
|
// %0, %1, %4, %5, %6, %7 are tmp
|
|
// Output:
|
|
// all inputs preserved except ADLEN (%12) & RD_PTR (%3)
|
|
// Updated accum is in %13
|
|
|
|
// if no ad, finish
|
|
brz done, %12
|
|
// do one block, repeat
|
|
do_ad: load %0, %3
|
|
gcm_brev64 %0, %0
|
|
gcm_swap64 %0, %0, %0
|
|
|
|
xor %0, %0, %13
|
|
add %3, %3, #16
|
|
sub %12, %12, #1
|
|
|
|
// // poly mult accum = ((accum^ad) * H)
|
|
// C
|
|
clmul %4, %0, %15, #0
|
|
// E
|
|
clmul %5, %0, %15, #1
|
|
// F
|
|
clmul %6, %0, %15, #2
|
|
// D
|
|
clmul %7, %0, %15, #3
|
|
// E ^ F
|
|
xor %6, %5, %6
|
|
// put low64 of E^F in high64
|
|
gcm_swap64 %5, %6, #0
|
|
// put high64 of E^F in low64
|
|
gcm_swap64 %6, #0, %6
|
|
// D xor low
|
|
xor %7, %7, %6
|
|
// C xor high
|
|
xor %4, %4, %5
|
|
|
|
// // reduction
|
|
// X1:X0 in %4
|
|
// X3:X2 in %7
|
|
// shift everybody by 1 to the left
|
|
// high shifting in 1 bit from low
|
|
gcm_shlmi %1, %7, %4, #1
|
|
// low
|
|
gcm_shlmi %0, %4, #0, #1
|
|
// post-shift
|
|
// X1:X0 in %0
|
|
// X3:X2 in %1
|
|
// compute D
|
|
gcm_cmpd %2, %0
|
|
// compute E, F, G
|
|
gcm_shrmi %6, %2, #0, #1
|
|
gcm_shrmi %4, %2, #0, #2
|
|
gcm_shrmi %5, %2, #0, #7
|
|
// XOR everybody
|
|
xor %2, %2, %6
|
|
xor %4, %4, %5
|
|
xor %2, %2, %4
|
|
xor %13, %2, %1
|
|
|
|
brz done, %12
|
|
brz do_ad, #0
|
|
|
|
done:
|
|
fin
|
|
);
|
|
let gcm_aes_code = assemble_engine25519!(
|
|
// pub in %16 (0-11, 12-15 are ctr so 0, LE)
|
|
// RD_PTR in %3
|
|
// WR_PTR in %11
|
|
// MLEN in %12 (in *complete* 16-byte-blocks)
|
|
// H in %15 (byte-reverted)
|
|
// T in %14
|
|
// accum in %13
|
|
// Transient:
|
|
// %0, %1, %4, %5, %6, %7 are tmp
|
|
// Output:
|
|
// all inputs preserved except RD_PTR (%3), WR_PTR (%11), MLEN (%12)
|
|
// accum is in %13
|
|
|
|
// if no msg, finish
|
|
brz done, %12
|
|
// do one block, repeat
|
|
do_msg:
|
|
// increment counter
|
|
gcm_brev32 %16, %16
|
|
add %16, %16, #11
|
|
gcm_brev32 %16, %16
|
|
|
|
xor %0, %16, %31
|
|
|
|
aesesmi %1, %0, %30
|
|
|
|
aesesmi %0, %1, %29
|
|
|
|
aesesmi %1, %0, %28
|
|
|
|
aesesmi %0, %1, %27
|
|
|
|
aesesmi %1, %0, %26
|
|
|
|
aesesmi %0, %1, %25
|
|
|
|
aesesmi %1, %0, %24
|
|
|
|
aesesmi %0, %1, %23
|
|
|
|
aesesmi %1, %0, %22
|
|
|
|
aesesmi %0, %1, %21
|
|
|
|
aesesmi %1, %0, %20
|
|
|
|
aesesmi %0, %1, %19
|
|
|
|
aesesmi %1, %0, %18
|
|
|
|
aesesi %1, %1, %17
|
|
|
|
//gcm_brev64 %1, %0
|
|
//gcm_swap64 %1, %1, %1
|
|
|
|
load %0, %3
|
|
xor %0, %0, %1
|
|
store %11, %11, %0
|
|
|
|
gcm_brev64 %0, %0
|
|
gcm_swap64 %0, %0, %0
|
|
|
|
xor %0, %0, %13
|
|
add %3, %3, #16
|
|
add %11, %11, #16
|
|
|
|
sub %12, %12, #1
|
|
|
|
// // poly mult accum = ((accum^ad) * H)
|
|
// C
|
|
clmul %4, %0, %15, #0
|
|
// E
|
|
clmul %5, %0, %15, #1
|
|
// F
|
|
clmul %6, %0, %15, #2
|
|
// D
|
|
clmul %7, %0, %15, #3
|
|
// E ^ F
|
|
xor %6, %5, %6
|
|
// put low64 of E^F in high64
|
|
gcm_swap64 %5, %6, #0
|
|
// put high64 of E^F in low64
|
|
gcm_swap64 %6, #0, %6
|
|
// D xor low
|
|
xor %7, %7, %6
|
|
// C xor high
|
|
xor %4, %4, %5
|
|
|
|
// // reduction
|
|
// X1:X0 in %4
|
|
// X3:X2 in %7
|
|
// shift everybody by 1 to the left
|
|
// high shifting in 1 bit from low
|
|
gcm_shlmi %1, %7, %4, #1
|
|
// low
|
|
gcm_shlmi %0, %4, #0, #1
|
|
// post-shift
|
|
// X1:X0 in %0
|
|
// X3:X2 in %1
|
|
// compute D
|
|
gcm_cmpd %2, %0
|
|
// compute E, F, G
|
|
gcm_shrmi %6, %2, #0, #1
|
|
gcm_shrmi %4, %2, #0, #2
|
|
gcm_shrmi %5, %2, #0, #7
|
|
// XOR everybody
|
|
xor %2, %2, %6
|
|
xor %4, %4, %5
|
|
xor %2, %2, %4
|
|
xor %13, %2, %1
|
|
|
|
brz done, %12
|
|
brz do_msg, #0
|
|
done:
|
|
fin
|
|
|
|
);
|
|
let gcm_finish_code = assemble_engine25519!(
|
|
// pub in %16 (0-11, 12-15 are ctr so 0, LE)
|
|
// RD_PTR in %3
|
|
// WR_PTR in %11
|
|
// MLEN in %12 (do one *partial* 16-byte-blocks, so 0 or non-zero)
|
|
// MMASK in %10 (could be computed from MLEN%16 but we don't have an instruction for it yet)
|
|
// finalblock in %9 (could be computed but we'd need to know the exact value of adlen)
|
|
// H in %15 (byte-reverted)
|
|
// T in %14
|
|
// accum in %13
|
|
// Transient:
|
|
// %0, %1, %4, %5, %6, %7 are tmp
|
|
// Output:
|
|
// all inputs preserved except RD_PTR (%3), WR_PTR (%11), MLEN (%12)
|
|
// accum is in %13
|
|
// accum ^ T is in %8
|
|
brz last, %12
|
|
|
|
finish_mlen:
|
|
// increment counter
|
|
gcm_brev32 %16, %16
|
|
add %16, %16, #11
|
|
gcm_brev32 %16, %16
|
|
|
|
xor %0, %16, %31
|
|
|
|
aesesmi %1, %0, %30
|
|
|
|
aesesmi %0, %1, %29
|
|
|
|
aesesmi %1, %0, %28
|
|
|
|
aesesmi %0, %1, %27
|
|
|
|
aesesmi %1, %0, %26
|
|
|
|
aesesmi %0, %1, %25
|
|
|
|
aesesmi %1, %0, %24
|
|
|
|
aesesmi %0, %1, %23
|
|
|
|
aesesmi %1, %0, %22
|
|
|
|
aesesmi %0, %1, %21
|
|
|
|
aesesmi %1, %0, %20
|
|
|
|
aesesmi %0, %1, %19
|
|
|
|
aesesmi %1, %0, %18
|
|
|
|
aesesi %1, %1, %17
|
|
|
|
//gcm_brev64 %1, %0
|
|
//gcm_swap64 %1, %1, %1
|
|
|
|
and %1, %1, %10
|
|
load %0, %3
|
|
xor %0, %0, %1
|
|
|
|
store %11, %11, %0
|
|
|
|
gcm_brev64 %0, %0
|
|
gcm_swap64 %0, %0, %0
|
|
|
|
xor %0, %0, %13
|
|
//add %3, %3, #16
|
|
//add %11, %11, #16
|
|
|
|
//sub %12, %12, #1
|
|
|
|
// // poly mult accum = ((accum^ad) * H)
|
|
// C
|
|
clmul %4, %0, %15, #0
|
|
// E
|
|
clmul %5, %0, %15, #1
|
|
// F
|
|
clmul %6, %0, %15, #2
|
|
// D
|
|
clmul %7, %0, %15, #3
|
|
// E ^ F
|
|
xor %6, %5, %6
|
|
// put low64 of E^F in high64
|
|
gcm_swap64 %5, %6, #0
|
|
// put high64 of E^F in low64
|
|
gcm_swap64 %6, #0, %6
|
|
// D xor low
|
|
xor %7, %7, %6
|
|
// C xor high
|
|
xor %4, %4, %5
|
|
|
|
// // reduction
|
|
// X1:X0 in %4
|
|
// X3:X2 in %7
|
|
// shift everybody by 1 to the left
|
|
// high shifting in 1 bit from low
|
|
gcm_shlmi %1, %7, %4, #1
|
|
// low
|
|
gcm_shlmi %0, %4, #0, #1
|
|
// post-shift
|
|
// X1:X0 in %0
|
|
// X3:X2 in %1
|
|
// compute D
|
|
gcm_cmpd %2, %0
|
|
// compute E, F, G
|
|
gcm_shrmi %6, %2, #0, #1
|
|
gcm_shrmi %4, %2, #0, #2
|
|
gcm_shrmi %5, %2, #0, #7
|
|
// XOR everybody
|
|
xor %2, %2, %6
|
|
xor %4, %4, %5
|
|
xor %2, %2, %4
|
|
xor %13, %2, %1
|
|
last:
|
|
// addmul of finalblock
|
|
|
|
gcm_brev64 %9, %9
|
|
gcm_swap64 %9, %9, %9
|
|
xor %0, %9, %13
|
|
//add %3, %3, #16
|
|
//add %11, %11, #16
|
|
//sub %12, %12, #1
|
|
|
|
// // poly mult accum = ((accum^ad) * H)
|
|
// C
|
|
clmul %4, %0, %15, #0
|
|
// E
|
|
clmul %5, %0, %15, #1
|
|
// F
|
|
clmul %6, %0, %15, #2
|
|
// D
|
|
clmul %7, %0, %15, #3
|
|
// E ^ F
|
|
xor %6, %5, %6
|
|
// put low64 of E^F in high64
|
|
gcm_swap64 %5, %6, #0
|
|
// put high64 of E^F in low64
|
|
gcm_swap64 %6, #0, %6
|
|
// D xor low
|
|
xor %7, %7, %6
|
|
// C xor high
|
|
xor %4, %4, %5
|
|
|
|
// // reduction
|
|
// X1:X0 in %4
|
|
// X3:X2 in %7
|
|
// shift everybody by 1 to the left
|
|
// high shifting in 1 bit from low
|
|
gcm_shlmi %1, %7, %4, #1
|
|
// low
|
|
gcm_shlmi %0, %4, #0, #1
|
|
// post-shift
|
|
// X1:X0 in %0
|
|
// X3:X2 in %1
|
|
// compute D
|
|
gcm_cmpd %2, %0
|
|
// compute E, F, G
|
|
gcm_shrmi %6, %2, #0, #1
|
|
gcm_shrmi %4, %2, #0, #2
|
|
gcm_shrmi %5, %2, #0, #7
|
|
// XOR everybody
|
|
xor %2, %2, %6
|
|
xor %4, %4, %5
|
|
xor %2, %2, %4
|
|
xor %13, %2, %1
|
|
|
|
gcm_brev64 %13, %13
|
|
gcm_swap64 %13, %13, %13
|
|
|
|
xor %8, %13, %14
|
|
|
|
fin
|
|
);
|
|
|
|
|
|
let mut pos = 0;
|
|
|
|
pos = 0;
|
|
println!("test AES:");
|
|
while pos < aescode.len() {
|
|
print!("0x{:08x},", aescode[pos]);
|
|
pos = pos + 1;
|
|
}
|
|
println!("");
|
|
println!("-> {}", aescode.len());
|
|
|
|
pos = 0;
|
|
println!("GCM PFX:");
|
|
while pos < gcm_pfx_code.len() {
|
|
print!("0x{:08x},", gcm_pfx_code[pos]);
|
|
pos = pos + 1;
|
|
}
|
|
println!("");
|
|
println!("-> {}", gcm_pfx_code.len());
|
|
|
|
pos = 0;
|
|
println!("GCM AD:");
|
|
while pos < gcm_ad_code.len() {
|
|
print!("0x{:08x},", gcm_ad_code[pos]);
|
|
pos = pos + 1;
|
|
}
|
|
println!("");
|
|
println!("-> {}", gcm_ad_code.len());
|
|
|
|
pos = 0;
|
|
println!("GCM AES:");
|
|
while pos < gcm_aes_code.len() {
|
|
print!("0x{:08x},", gcm_aes_code[pos]);
|
|
pos = pos + 1;
|
|
}
|
|
println!("");
|
|
println!("-> {}", gcm_aes_code.len());
|
|
|
|
pos = 0;
|
|
println!("GCM FINISH:");
|
|
while pos < gcm_finish_code.len() {
|
|
print!("0x{:08x},", gcm_finish_code[pos]);
|
|
pos = pos + 1;
|
|
}
|
|
println!("");
|
|
println!("-> {}", gcm_finish_code.len());
|
|
|
|
|
|
Ok(())
|
|
}
|