diff --git a/Cargo.toml b/Cargo.toml index 9c9f1dc..0d137a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,7 +81,7 @@ std = ["alloc", "subtle/std", "rand_core/std"] alloc = ["zeroize/alloc"] # The u32 backend uses u32s with u64 products. -u32_backend = [] +u32_backend = ["utralib"] # The u32e backend uses u32s with u64 products + field25519 accelerator. u32e_backend = ["engine25519-as", "utralib"] # The u64 backend uses u64s with u128 products. diff --git a/src/backend/serial/u32/field.rs b/src/backend/serial/u32/field.rs index c8f3e5e..31711d1 100644 --- a/src/backend/serial/u32/field.rs +++ b/src/backend/serial/u32/field.rs @@ -27,6 +27,9 @@ use subtle::ConditionallySelectable; use zeroize::Zeroize; +#[macro_use] +use debug; + /// A `FieldElement2625` represents an element of the field /// \\( \mathbb Z / (2\^{255} - 19)\\). /// @@ -215,7 +218,9 @@ impl<'a, 'b> Mul<&'b FieldElement2625> for &'a FieldElement2625 { // // So z[0] fits into a u64 if 51 + 2*b + lg(249) < 64 // if b < 2.5. - FieldElement2625::reduce([z0, z1, z2, z3, z4, z5, z6, z7, z8, z9]) + let ret = FieldElement2625::reduce([z0, z1, z2, z3, z4, z5, z6, z7, z8, z9]); + //println!("a:{:?}\n\rb:{:?}\n\rout:{:?}", self.to_bytes(), _rhs.to_bytes(), ret.to_bytes()); + ret } } diff --git a/src/backend/serial/u32e/field.rs b/src/backend/serial/u32e/field.rs index fd0c95c..d5a8586 100644 --- a/src/backend/serial/u32e/field.rs +++ b/src/backend/serial/u32e/field.rs @@ -50,14 +50,17 @@ use zeroize::Zeroize; /// The backend-specific type `Engine25519` should not be used /// outside of the `curve25519_dalek::field` module. +//#[macro_use] +//mod debug; + #[macro_use] -mod debug; +use debug; #[derive(Copy, Clone, Debug)] pub struct Engine25519( pub (crate) [u8; 32] ); - +#[derive(Debug)] pub(crate) enum EngineOp { Mul, Add, @@ -65,17 +68,16 @@ pub(crate) enum EngineOp { } pub(crate) fn engine(a: &[u8; 32], b: &[u8; 32], op: EngineOp) -> Engine25519 { - println!("engine"); - + use core::convert::TryInto; use utralib::generated::*; let mut engine = utralib::CSR::new(utra::engine::HW_ENGINE_BASE as *mut u32); let mcode: &'static mut [u32] = unsafe{ core::slice::from_raw_parts_mut(utralib::HW_ENGINE_MEM as *mut u32, 1024) }; // allocate the first three registers - let rf: [&'static mut [u8]; 3] = + let rf: [&'static mut [u32]; 3] = unsafe { [ - core::slice::from_raw_parts_mut((utralib::HW_ENGINE_MEM + 0x1_0000 + 0 * 32) as *mut u8, 32), - core::slice::from_raw_parts_mut((utralib::HW_ENGINE_MEM + 0x1_0000 + 1 * 32) as *mut u8, 32), - core::slice::from_raw_parts_mut((utralib::HW_ENGINE_MEM + 0x1_0000 + 2 * 32) as *mut u8, 32), + core::slice::from_raw_parts_mut((utralib::HW_ENGINE_MEM + 0x1_0000 + 0 * 32) as *mut u32, 8), + core::slice::from_raw_parts_mut((utralib::HW_ENGINE_MEM + 0x1_0000 + 1 * 32) as *mut u32, 8), + core::slice::from_raw_parts_mut((utralib::HW_ENGINE_MEM + 0x1_0000 + 2 * 32) as *mut u32, 8), ] }; match op { EngineOp::Mul => { @@ -105,7 +107,8 @@ pub(crate) fn engine(a: &[u8; 32], b: &[u8; 32], op: EngineOp) -> Engine25519 { EngineOp::Sub => { let prog = assemble_engine25519!( start: - sub %2, %0, %1 + sub %1, #3, %1 + add %2, %0, %1 trd %30, %2 sub %2, %2, %30 fin @@ -117,12 +120,13 @@ pub(crate) fn engine(a: &[u8; 32], b: &[u8; 32], op: EngineOp) -> Engine25519 { }, } // copy a arg - for (&src, dest) in a.iter().zip(rf[0].iter_mut()) { - *dest = src; + for (src, dst) in a.chunks_exact(4).zip(rf[0].iter_mut()) { + unsafe{ (dst as *mut u32).write_volatile(u32::from_le_bytes(src[0..4].try_into().unwrap()));} } + // copy b arg - for (&src, dest) in b.iter().zip(rf[1].iter_mut()) { - *dest = src; + for (src, dst) in b.chunks_exact(4).zip(rf[1].iter_mut()) { + unsafe{ (dst as *mut u32).write_volatile(u32::from_le_bytes(src[0..4].try_into().unwrap()));} } engine.wfo(utra::engine::CONTROL_GO, 1); @@ -130,9 +134,12 @@ pub(crate) fn engine(a: &[u8; 32], b: &[u8; 32], op: EngineOp) -> Engine25519 { // return result, always in reg 2 let mut result: [u8; 32] = [0; 32]; - for (&src, dest) in rf[2].iter().zip(result.iter_mut()) { - *dest = src; + for (&src, dst) in rf[2].iter().zip(result.chunks_exact_mut(4)) { + for (&sb, db) in src.to_le_bytes().iter().zip(dst.iter_mut()) { + *db = sb; + } } + Engine25519 { 0: result } @@ -184,7 +191,9 @@ impl<'b> MulAssign<&'b Engine25519> for Engine25519 { impl<'a, 'b> Mul<&'b Engine25519> for &'a Engine25519 { type Output = Engine25519; fn mul(self, _rhs: &'b Engine25519) -> Engine25519 { - engine(&self.0, &_rhs.0, EngineOp::Mul) + let ret = engine(&self.0, &_rhs.0, EngineOp::Mul); + //println!("a:{:?}\n\rb:{:?}\n\rout:{:?}", self.0, _rhs.0, ret.0); + ret } } @@ -314,7 +323,7 @@ impl Engine25519 { /// Invert the sign of this field element pub fn negate(&mut self) { let zero: [u8; 32] = [0; 32]; - engine(&zero, &self.0, EngineOp::Sub); + *self = engine(&zero, &self.0, EngineOp::Sub); } /// Construct zero. @@ -346,7 +355,7 @@ impl Engine25519 { z } - /// Load a `FieldElement51` from the low 255 bits of a 256-bit + /// Load a `Engine25519` from the low 255 bits of a 256-bit /// input. /// /// # Warning @@ -358,8 +367,10 @@ impl Engine25519 { /// the canonical encoding, and check that the input was /// canonical. pub fn from_bytes(data: &[u8; 32]) -> Engine25519 { //FeFromBytes + let mut mask_data = data.clone(); + mask_data[31] &= 0x7F; // mask off the high bit per comment above Engine25519 { - 0: (*data).clone(), + 0: mask_data, } } diff --git a/src/debug.rs b/src/debug.rs new file mode 100644 index 0000000..bde1e14 --- /dev/null +++ b/src/debug.rs @@ -0,0 +1,104 @@ +use utralib::generated::*; +pub struct Uart { + // pub base: *mut u32, +} + +impl Uart { + fn put_digit(&mut self, d: u8) { + let nyb = d & 0xF; + if nyb < 10 { + self.putc(nyb + 0x30); + } else { + self.putc(nyb + 0x61 - 10); + } + } + pub fn put_hex(&mut self, c: u8) { + self.put_digit(c >> 4); + self.put_digit(c & 0xF); + } + pub fn newline(&mut self) { + self.putc(0xa); + self.putc(0xd); + } + pub fn print_hex_word(&mut self, word: u32) { + for &byte in word.to_be_bytes().iter() { + self.put_hex(byte); + } + } + + pub fn putc(&self, c: u8) { + let base = utra::uart::HW_UART_BASE as *mut u32; + let mut uart = CSR::new(base); + // Wait until TXFULL is `0` + while uart.r(utra::uart::TXFULL) != 0 {} + uart.wo(utra::uart::RXTX, c as u32) + } + + pub fn getc(&self) -> Option { + let base = utra::uart::HW_UART_BASE as *mut u32; + let mut uart = CSR::new(base); + match uart.rf(utra::uart::EV_PENDING_RX) { + 0 => None, + ack => { + let c = Some(uart.rf(utra::uart::RXTX_RXTX) as u8); + uart.wfo(utra::uart::EV_PENDING_RX, ack); + c + } + } + } + + pub fn tiny_write_str(&mut self, s: &str) { + for c in s.bytes() { + self.putc(c); + } + } + +} + +use core::fmt::{Error, Write}; +impl Write for Uart { + fn write_str(&mut self, s: &str) -> Result<(), Error> { + for c in s.bytes() { + self.putc(c); + } + Ok(()) + } +} + +#[macro_use] +pub mod debug_print_hardware { + #[macro_export] + macro_rules! print + { + ($($args:tt)+) => ({ + use core::fmt::Write; + let _ = write!(debug::Uart {}, $($args)+); + }); + } +} + +#[macro_use] +#[cfg(test)] +mod debug_print_hardware { + #[macro_export] + #[allow(unused_variables)] + macro_rules! print { + ($($args:tt)+) => ({ + std::print!($($args)+) + }); + } +} + +#[macro_export] +macro_rules! println +{ + () => ({ + $crate::print!("\r\n") + }); + ($fmt:expr) => ({ + $crate::print!(concat!($fmt, "\r\n")) + }); + ($fmt:expr, $($args:tt)+) => ({ + $crate::print!(concat!($fmt, "\r\n"), $($args)+) + }); +} diff --git a/src/edwards.rs b/src/edwards.rs index 7c97ca4..8b5c641 100644 --- a/src/edwards.rs +++ b/src/edwards.rs @@ -172,6 +172,9 @@ impl Debug for CompressedEdwardsY { } } +#[macro_use] +use debug; + impl CompressedEdwardsY { /// View this `CompressedEdwardsY` as an array of bytes. pub fn as_bytes(&self) -> &[u8; 32] { @@ -188,21 +191,36 @@ impl CompressedEdwardsY { /// Returns `None` if the input is not the \\(y\\)-coordinate of a /// curve point. pub fn decompress(&self) -> Option { + println!("self.bytes: {:?}", self.as_bytes()); let Y = FieldElement::from_bytes(self.as_bytes()); + println!("Y: {:?}", Y.to_bytes()); let Z = FieldElement::one(); + println!("Z: {:?}", Z.to_bytes()); let YY = Y.square(); + println!("YY: {:?}", YY.to_bytes()); let u = &YY - &Z; // u = y²-1 + println!("u: {:?}", u.to_bytes()); let v = &(&YY * &constants::EDWARDS_D) + &Z; // v = dy²+1 + println!("v: {:?}", v.to_bytes()); let (is_valid_y_coord, mut X) = FieldElement::sqrt_ratio_i(&u, &v); + println!("isvalid: {:?}", is_valid_y_coord); + println!("X: {:?}", X.to_bytes()); if is_valid_y_coord.unwrap_u8() != 1u8 { return None; } + println!("valid"); // FieldElement::sqrt_ratio_i always returns the nonnegative square root, // so we negate according to the supplied sign bit. let compressed_sign_bit = Choice::from(self.as_bytes()[31] >> 7); X.conditional_negate(compressed_sign_bit); + println!("negate"); - Some(EdwardsPoint{ X, Y, Z, T: &X * &Y }) + println!("X: {:?}", X.to_bytes()); + println!("Y: {:?}", Y.to_bytes()); + println!("Z: {:?}", Z.to_bytes()); + let t = &X * &Y; + println!("T: {:?}", t.to_bytes()); + Some(EdwardsPoint{ X, Y, Z, T: t }) } } diff --git a/src/field.rs b/src/field.rs index 16d5d03..53fb29d 100644 --- a/src/field.rs +++ b/src/field.rs @@ -94,6 +94,8 @@ impl ConstantTimeEq for FieldElement { self.to_bytes().ct_eq(&other.to_bytes()) } } +#[macro_use] +use debug; impl FieldElement { /// Determine if this `FieldElement` is negative, in the sense @@ -262,25 +264,41 @@ impl FieldElement { // If v is zero, r is also zero. let v3 = &v.square() * v; + println!("v3: {:?}", v3.to_bytes()); let v7 = &v3.square() * v; + println!("v7: {:?}", v7.to_bytes()); let mut r = &(u * &v3) * &(u * &v7).pow_p58(); + println!("r: {:?}", r.to_bytes()); let check = v * &r.square(); + println!("check: {:?}", check.to_bytes()); let i = &constants::SQRT_M1; + println!("i: {:?}", i.to_bytes()); let correct_sign_sqrt = check.ct_eq( u); let flipped_sign_sqrt = check.ct_eq( &(-u)); let flipped_sign_sqrt_i = check.ct_eq(&(&(-u)*i)); + println!("correct_sign_sqrt: {:?}", correct_sign_sqrt); + println!("u: {:?}", u.to_bytes()); + println!("flipped_sign_sqrt: {:?}", flipped_sign_sqrt); + println!("-u: {:?}", &(-u).to_bytes()); + println!("flipped_sign_sqrt_i: {:?}", flipped_sign_sqrt_i); + println!("-u * i: {:?}", &(&(-u)*i)); let r_prime = &constants::SQRT_M1 * &r; + println!("r_prime: {:?}", r_prime.to_bytes()); r.conditional_assign(&r_prime, flipped_sign_sqrt | flipped_sign_sqrt_i); + println!("r_assign1: {:?}", r.to_bytes()); + // Choose the nonnegative square root. let r_is_negative = r.is_negative(); r.conditional_negate(r_is_negative); + println!("r_assign2: {:?}", r.to_bytes()); let was_nonzero_square = correct_sign_sqrt | flipped_sign_sqrt; + println!("final r: {:?}", r.to_bytes()); (was_nonzero_square, r) } diff --git a/src/lib.rs b/src/lib.rs index 2d56e78..d7aa3e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,9 +73,13 @@ extern crate engine25519_as; #[cfg(feature = "betrusted")] extern crate engine_25519; -#[cfg(feature = "u32e_backend")] +//#[cfg(feature = "u32e_backend")] extern crate utralib; +//#[cfg(feature = "u32e_backend")] +#[macro_use] +mod debug; + //------------------------------------------------------------------------ // curve25519-dalek public modules //------------------------------------------------------------------------ diff --git a/src/montgomery.rs b/src/montgomery.rs index 9630497..e4e69cf 100644 --- a/src/montgomery.rs +++ b/src/montgomery.rs @@ -236,7 +236,7 @@ impl ProjectivePoint { /// * \\( 0 \\) if \\( W \eq 0 \\); #[cfg(not(feature = "betrusted"))] pub fn to_affine(&self) -> MontgomeryPoint { - #[cfg(all(not(test),not(feature="u32e_backend")))] // 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. + #[cfg(all(not(test),feature="betrusted"))] // 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(); @@ -941,7 +941,7 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a MontgomeryPoint { #[cfg(not(feature = "betrusted"))] fn mul(self, scalar: &'b Scalar) -> MontgomeryPoint { // Algorithm 8 of Costello-Smith 2017 - #[cfg(all(not(test),not(feature="u32e_backend")))] // 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. + #[cfg(all(not(test),feature="betrusted"))] // 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 montgomery multiply being used - check for build config errors!"); let affine_u = FieldElement::from_bytes(&self.0); let mut x0 = ProjectivePoint::identity();