diff --git a/Cargo.toml b/Cargo.toml index ab19814..173a4d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ traits = ["ed25519"] self-verify = [] blind-keys = [] std = [] +opt_size = [] [dependencies] ct-codecs = { version = "1.1", optional = true } diff --git a/README.md b/README.md index 22ef68c..fc64e6e 100644 --- a/README.md +++ b/README.md @@ -60,3 +60,4 @@ println!("Signature as bytes: {:?}", signature_as_bytes); * `traits`: add support for the traits from the `ed25519` and `signature` crates. * `pem`: add support for importing/exporting keys as OpenSSL-compatible PEM files. * `blind-keys`: add support for key blinding. +* `opt_size`: Enable size optimizations (based on benchmarks, 8-15% size reduction at the cost of 6.5-7% performance). diff --git a/src/curve25519.rs b/src/curve25519.rs index 7422f0e..1bde3c5 100644 --- a/src/curve25519.rs +++ b/src/curve25519.rs @@ -8,7 +8,8 @@ pub type fiat_25519_u1 = u8; pub type fiat_25519_i1 = i8; pub type fiat_25519_i2 = i8; -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] pub fn fiat_25519_addcarryx_u51( out1: &mut u64, out2: &mut fiat_25519_u1, @@ -23,7 +24,8 @@ pub fn fiat_25519_addcarryx_u51( *out2 = x3; } -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] pub fn fiat_25519_subborrowx_u51( out1: &mut u64, out2: &mut fiat_25519_u1, @@ -39,7 +41,8 @@ pub fn fiat_25519_subborrowx_u51( *out2 = ((0x0_i8.wrapping_sub((x2 as fiat_25519_i2))) as fiat_25519_u1); } -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] pub fn fiat_25519_cmovznz_u64(out1: &mut u64, arg1: fiat_25519_u1, arg2: u64, arg3: u64) { let x1: fiat_25519_u1 = (!(!arg1)); let x2: u64 = (((((0x0_i8.wrapping_sub((x1 as fiat_25519_i2))) as fiat_25519_i1) as i128) @@ -48,7 +51,8 @@ pub fn fiat_25519_cmovznz_u64(out1: &mut u64, arg1: fiat_25519_u1, arg2: u64, ar *out1 = x3; } -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] pub fn fiat_25519_carry_mul(out1: &mut [u64; 5], arg1: &[u64; 5], arg2: &[u64; 5]) { let x1: u128 = (((arg1[4]) as u128).wrapping_mul((((arg2[4]).wrapping_mul(0x13)) as u128))); let x2: u128 = (((arg1[4]) as u128).wrapping_mul((((arg2[3]).wrapping_mul(0x13)) as u128))); @@ -114,7 +118,8 @@ pub fn fiat_25519_carry_mul(out1: &mut [u64; 5], arg1: &[u64; 5], arg2: &[u64; 5 out1[4] = x44; } -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] pub fn fiat_25519_carry_square(out1: &mut [u64; 5], arg1: &[u64; 5]) { let x1: u64 = ((arg1[4]).wrapping_mul(0x13)); let x2: u64 = (x1.wrapping_mul(0x2)); @@ -173,7 +178,8 @@ pub fn fiat_25519_carry_square(out1: &mut [u64; 5], arg1: &[u64; 5]) { out1[4] = x42; } -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] pub fn fiat_25519_carry(out1: &mut [u64; 5], arg1: &[u64; 5]) { let x1: u64 = (arg1[0]); let x2: u64 = ((x1 >> 51).wrapping_add((arg1[1]))); @@ -194,7 +200,8 @@ pub fn fiat_25519_carry(out1: &mut [u64; 5], arg1: &[u64; 5]) { out1[4] = x12; } -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] pub fn fiat_25519_add(out1: &mut [u64; 5], arg1: &[u64; 5], arg2: &[u64; 5]) { let x1: u64 = ((arg1[0]).wrapping_add((arg2[0]))); let x2: u64 = ((arg1[1]).wrapping_add((arg2[1]))); @@ -208,7 +215,8 @@ pub fn fiat_25519_add(out1: &mut [u64; 5], arg1: &[u64; 5], arg2: &[u64; 5]) { out1[4] = x5; } -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] pub fn fiat_25519_sub(out1: &mut [u64; 5], arg1: &[u64; 5], arg2: &[u64; 5]) { let x1: u64 = ((0xfffffffffffdau64.wrapping_add((arg1[0]))).wrapping_sub((arg2[0]))); let x2: u64 = ((0xffffffffffffeu64.wrapping_add((arg1[1]))).wrapping_sub((arg2[1]))); @@ -222,7 +230,8 @@ pub fn fiat_25519_sub(out1: &mut [u64; 5], arg1: &[u64; 5], arg2: &[u64; 5]) { out1[4] = x5; } -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] pub fn fiat_25519_opp(out1: &mut [u64; 5], arg1: &[u64; 5]) { let x1: u64 = (0xfffffffffffdau64.wrapping_sub((arg1[0]))); let x2: u64 = (0xffffffffffffeu64.wrapping_sub((arg1[1]))); @@ -236,7 +245,8 @@ pub fn fiat_25519_opp(out1: &mut [u64; 5], arg1: &[u64; 5]) { out1[4] = x5; } -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] pub fn fiat_25519_selectznz( out1: &mut [u64; 5], arg1: fiat_25519_u1, @@ -433,7 +443,8 @@ static FE_D2: Fe = Fe([ 633789495995903, ]); -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] fn load_8u(s: &[u8]) -> u64 { (s[0] as u64) | ((s[1] as u64) << 8) @@ -445,22 +456,26 @@ fn load_8u(s: &[u8]) -> u64 { | ((s[7] as u64) << 56) } -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] fn load_4u(s: &[u8]) -> u64 { (s[0] as u64) | ((s[1] as u64) << 8) | ((s[2] as u64) << 16) | ((s[3] as u64) << 24) } -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] fn load_4i(s: &[u8]) -> i64 { load_4u(s) as i64 } -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] fn load_3u(s: &[u8]) -> u64 { (s[0] as u64) | ((s[1] as u64) << 8) | ((s[2] as u64) << 16) } -#[inline] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline)] fn load_3i(s: &[u8]) -> i64 { load_3u(s) as i64 } diff --git a/src/sha512.rs b/src/sha512.rs index 333e942..66ab498 100644 --- a/src/sha512.rs +++ b/src/sha512.rs @@ -10,7 +10,8 @@ clippy::unreadable_literal )] -#[inline(always)] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline(always))] fn load_be(base: &[u8], offset: usize) -> u64 { let addr = &base[offset..]; (addr[7] as u64) @@ -23,7 +24,8 @@ fn load_be(base: &[u8], offset: usize) -> u64 { | (addr[0] as u64) << 56 } -#[inline(always)] +#[cfg_attr(feature = "opt_size", inline(never))] +#[cfg_attr(not(feature = "opt_size"), inline(always))] fn store_be(base: &mut [u8], offset: usize, x: u64) { let addr = &mut base[offset..]; addr[7] = x as u8; @@ -50,37 +52,44 @@ impl W { W(w) } - #[inline(always)] + #[cfg_attr(feature = "opt_size", inline(never))] + #[cfg_attr(not(feature = "opt_size"), inline(always))] fn Ch(x: u64, y: u64, z: u64) -> u64 { (x & y) ^ (!x & z) } - #[inline(always)] + #[cfg_attr(feature = "opt_size", inline(never))] + #[cfg_attr(not(feature = "opt_size"), inline(always))] fn Maj(x: u64, y: u64, z: u64) -> u64 { (x & y) ^ (x & z) ^ (y & z) } - #[inline(always)] + #[cfg_attr(feature = "opt_size", inline(never))] + #[cfg_attr(not(feature = "opt_size"), inline(always))] fn Sigma0(x: u64) -> u64 { x.rotate_right(28) ^ x.rotate_right(34) ^ x.rotate_right(39) } - #[inline(always)] + #[cfg_attr(feature = "opt_size", inline(never))] + #[cfg_attr(not(feature = "opt_size"), inline(always))] fn Sigma1(x: u64) -> u64 { x.rotate_right(14) ^ x.rotate_right(18) ^ x.rotate_right(41) } - #[inline(always)] + #[cfg_attr(feature = "opt_size", inline(never))] + #[cfg_attr(not(feature = "opt_size"), inline(always))] fn sigma0(x: u64) -> u64 { x.rotate_right(1) ^ x.rotate_right(8) ^ (x >> 7) } - #[inline(always)] + #[cfg_attr(feature = "opt_size", inline(never))] + #[cfg_attr(not(feature = "opt_size"), inline(always))] fn sigma1(x: u64) -> u64 { x.rotate_right(19) ^ x.rotate_right(61) ^ (x >> 6) } - #[inline(always)] + #[cfg_attr(feature = "opt_size", inline(never))] + #[cfg_attr(not(feature = "opt_size"), inline(always))] fn M(&mut self, a: usize, b: usize, c: usize, d: usize) { let w = &mut self.0; w[a] = w[a] @@ -89,7 +98,8 @@ impl W { .wrapping_add(Self::sigma0(w[d])); } - #[inline] + #[cfg_attr(feature = "opt_size", inline(never))] + #[cfg_attr(not(feature = "opt_size"), inline(always))] fn expand(&mut self) { self.M(0, (0 + 14) & 15, (0 + 9) & 15, (0 + 1) & 15); self.M(1, (1 + 14) & 15, (1 + 9) & 15, (1 + 1) & 15); @@ -109,7 +119,8 @@ impl W { self.M(15, (15 + 14) & 15, (15 + 9) & 15, (15 + 1) & 15); } - #[inline(always)] + #[cfg_attr(feature = "opt_size", inline(never))] + #[cfg_attr(not(feature = "opt_size"), inline(always))] fn F(&mut self, state: &mut State, i: usize, k: u64) { let t = &mut state.0; t[(16 - i + 7) & 7] = t[(16 - i + 7) & 7] @@ -250,7 +261,8 @@ impl State { State(t) } - #[inline(always)] + #[cfg_attr(feature = "opt_size", inline(never))] + #[cfg_attr(not(feature = "opt_size"), inline(always))] fn add(&mut self, x: &State) { let sx = &mut self.0; let ex = &x.0;