Skip to content

Commit 6c83532

Browse files
committed
Create a "fake-SIMD" type to work around rust-lang/rust#23037
1 parent 1e56cb7 commit 6c83532

File tree

7 files changed

+166
-22
lines changed

7 files changed

+166
-22
lines changed

src/chacha20.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
// option. This file may not be copied, modified, or distributed
55
// except according to those terms.
66
use std::cmp;
7-
use std::simd::u32x4;
87

98
use buffer::{BufferResult, RefReadBuffer, RefWriteBuffer};
109
use symmetriccipher::{Encryptor, Decryptor, SynchronousStreamCipher, SymmetricCipherError};
1110
use cryptoutil::{read_u32_le, symm_enc_or_dec, write_u32_le, xor_keystream};
11+
use simd::u32x4;
1212

1313
#[derive(Copy)]
1414
struct ChaChaState {
@@ -56,13 +56,13 @@ macro_rules! state_to_buffer {
5656

5757
macro_rules! round{
5858
($state: expr) => {{
59-
$state.a += $state.b;
59+
$state.a = $state.a + $state.b;
6060
rotate!($state.d, $state.a, S16);
61-
$state.c += $state.d;
61+
$state.c = $state.c + $state.d;
6262
rotate!($state.b, $state.c, S12);
63-
$state.a += $state.b;
63+
$state.a = $state.a + $state.b;
6464
rotate!($state.d, $state.a, S8);
65-
$state.c += $state.d;
65+
$state.c = $state.c + $state.d;
6666
rotate!($state.b, $state.c, S7);
6767
}}
6868
}
@@ -217,14 +217,14 @@ impl ChaCha20 {
217217
round!(state);
218218
swizzle!(state.d, state.c, state.b);
219219
}
220-
state.a += self.state.a;
221-
state.b += self.state.b;
222-
state.c += self.state.c;
223-
state.d += self.state.d;
220+
state.a = state.a + self.state.a;
221+
state.b = state.b + self.state.b;
222+
state.c = state.c + self.state.c;
223+
state.d = state.d + self.state.d;
224224

225225
state_to_buffer!(state, self.output);
226226

227-
self.state.d += u32x4(1, 0, 0, 0);
227+
self.state.d = self.state.d + u32x4(1, 0, 0, 0);
228228
let u32x4(c12, _, _, _) = self.state.d;
229229
if c12 == 0 {
230230
// we could increment the other counter word with an 8 byte nonce

src/ghash.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
1818
use std::ops::BitXor;
1919
use std::mem;
20-
use std::simd;
2120
use std::slice::bytes::copy_memory;
2221

2322
use cryptoutil::{read_u32_be, write_u32_be};
2423
use mac::{Mac, MacResult};
24+
use simd;
2525

2626
// A struct representing an element in GF(2^128)
2727
// x^0 is the msb, while x^127 is the lsb
@@ -56,7 +56,7 @@ impl Gf128 {
5656

5757
// Multiply the element by x modulo x^128
5858
// This is equivalent to a rightshift in the bit representation
59-
#[cfg(target_arch = "x86_64")]
59+
#[cfg(all(target_arch = "x86_64",ndebug))]
6060
fn times_x(mut self) -> Gf128 {
6161
unsafe {
6262
asm!("
@@ -70,7 +70,7 @@ impl Gf128 {
7070
self
7171
}
7272

73-
#[cfg(not(target_arch = "x86_64"))]
73+
#[cfg(any(not(target_arch = "x86_64"),not(ndebug)))]
7474
fn times_x(self) -> Gf128 {
7575
let simd::u32x4(a, b, c, d) = self.d;
7676
Gf128::new(a >> 1 | b << 31, b >> 1 | c << 31, c >> 1 | d << 31, d >> 1)
@@ -96,7 +96,7 @@ impl Gf128 {
9696
}
9797

9898
// This XORs the value of y with x if the LSB of self is set, otherwise y is returned
99-
#[cfg(target_arch = "x86_64")]
99+
#[cfg(all(target_arch = "x86_64",ndebug))]
100100
fn cond_xor(self, x: Gf128, mut y: Gf128) -> Gf128 {
101101
let lsb = simd::u32x4(1, 0, 0, 0);
102102
unsafe {
@@ -113,10 +113,11 @@ impl Gf128 {
113113
y
114114
}
115115

116-
#[cfg(not(target_arch = "x86_64"))]
116+
#[cfg(any(not(target_arch = "x86_64"),not(ndebug)))]
117117
fn cond_xor(self, x: Gf128, y: Gf128) -> Gf128 {
118+
use simd::SimdExt;
118119
let lsb = simd::u32x4(1, 0, 0, 0);
119-
let simd::u32x4(m, _, _, _) = (self.d & lsb) == lsb;
120+
let simd::u32x4(m, _, _, _) = (self.d & lsb).simd_eq(lsb);
120121
let mask = simd::u32x4(m, m, m, m);
121122
Gf128 { d: (x.d & mask) ^ y.d }
122123
}

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub mod salsa20;
4747
pub mod scrypt;
4848
pub mod sha1;
4949
pub mod sha2;
50+
mod simd;
5051
pub mod sosemanuk;
5152
pub mod symmetriccipher;
5253
pub mod util;

src/salsa20.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
use buffer::{BufferResult, RefReadBuffer, RefWriteBuffer};
88
use symmetriccipher::{Encryptor, Decryptor, SynchronousStreamCipher, SymmetricCipherError};
99
use cryptoutil::{read_u32_le, symm_enc_or_dec, write_u32_le, xor_keystream};
10+
use simd::u32x4;
1011

1112
use std::cmp;
12-
use std::simd::u32x4;
1313

1414
#[derive(Copy)]
1515
struct SalsaState {
@@ -59,7 +59,7 @@ macro_rules! add_rotate_xor {
5959
let v = $a + $b;
6060
let r = S32 - $shift;
6161
let right = v >> r;
62-
$dst ^= (v << $shift) ^ right
62+
$dst = $dst ^ (v << $shift) ^ right
6363
}}
6464
}
6565

@@ -177,10 +177,10 @@ impl Salsa20 {
177177
write_u32_le(&mut self.output[i*4..(i+1)*4], lens[i]);
178178
}
179179

180-
self.state.b += u32x4(1, 0, 0, 0);
180+
self.state.b = self.state.b + u32x4(1, 0, 0, 0);
181181
let u32x4(_, _, _, ctr_lo) = self.state.b;
182182
if ctr_lo == 0 {
183-
self.state.a += u32x4(0, 1, 0, 0);
183+
self.state.a = self.state.a + u32x4(0, 1, 0, 0);
184184
}
185185

186186
self.offset = 0;

src/sha1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ algorithms, but some, like "parity" is only found in SHA-1.
6161
*/
6262

6363
use std::num::Int;
64-
use std::simd::u32x4;
6564
use digest::Digest;
6665
use cryptoutil::{write_u32_be, read_u32v_be, add_bytes_to_bits, FixedBuffer, FixedBuffer64, StandardPadding};
66+
use simd::u32x4;
6767

6868
const STATE_LEN: usize = 5;
6969
const BLOCK_LEN: usize = 16;

src/sha2.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,15 @@ assert_eq!(hex.as_slice(),
7070
7171
*/
7272

73-
use std::simd::{u32x4, u64x2};
7473
use std::num::Int;
7574
use digest::Digest;
7675
use cryptoutil::{write_u32_be, read_u32v_be,
7776
write_u64_be, read_u64v_be,
7877
add_bytes_to_bits, add_bytes_to_bits_tuple,
7978
FixedBuffer, FixedBuffer128, FixedBuffer64, StandardPadding};
8079

80+
use simd::{u32x4, u64x2};
81+
8182
const STATE_LEN: usize = 8;
8283
const BLOCK_LEN: usize = 16;
8384

src/simd.rs

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4+
// option. This file may not be copied, modified, or distributed
5+
// except according to those terms.
6+
7+
#[cfg(not(ndebug))]
8+
pub use self::fake::*;
9+
10+
#[cfg(ndebug)]
11+
pub use self::real::*;
12+
13+
pub trait SimdExt {
14+
fn simd_eq(self, rhs: Self) -> Self;
15+
}
16+
17+
#[cfg(not(ndebug))]
18+
impl SimdExt for fake::u32x4 {
19+
fn simd_eq(self, rhs: Self) -> Self {
20+
if self == rhs {
21+
fake::u32x4(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff)
22+
} else {
23+
fake::u32x4(0, 0, 0, 0)
24+
}
25+
}
26+
}
27+
28+
#[cfg(ndebug)]
29+
impl SimdExt for real::u32x4 {
30+
fn simd_eq(self, rhs: Self) -> Self {
31+
self == rhs
32+
}
33+
}
34+
35+
#[cfg(not(ndebug))]
36+
mod fake {
37+
use std::ops::{Add, BitAnd, BitOr, BitXor, Shl, Shr, Sub};
38+
39+
#[derive(Copy, PartialEq, Eq)]
40+
#[allow(non_camel_case_types)]
41+
pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
42+
43+
impl Add for u32x4 {
44+
type Output = u32x4;
45+
46+
fn add(self, rhs: u32x4) -> u32x4 {
47+
u32x4(
48+
self.0.wrapping_add(rhs.0),
49+
self.1.wrapping_add(rhs.1),
50+
self.2.wrapping_add(rhs.2),
51+
self.3.wrapping_add(rhs.3))
52+
}
53+
}
54+
55+
impl Sub for u32x4 {
56+
type Output = u32x4;
57+
58+
fn sub(self, rhs: u32x4) -> u32x4 {
59+
u32x4(
60+
self.0.wrapping_sub(rhs.0),
61+
self.1.wrapping_sub(rhs.1),
62+
self.2.wrapping_sub(rhs.2),
63+
self.3.wrapping_sub(rhs.3))
64+
}
65+
}
66+
67+
impl BitAnd for u32x4 {
68+
type Output = u32x4;
69+
70+
fn bitand(self, rhs: u32x4) -> u32x4 {
71+
u32x4(self.0 & rhs.0, self.1 & rhs.1, self.2 & rhs.2, self.3 & rhs.3)
72+
}
73+
}
74+
75+
impl BitOr for u32x4 {
76+
type Output = u32x4;
77+
78+
fn bitor(self, rhs: u32x4) -> u32x4 {
79+
u32x4(self.0 | rhs.0, self.1 | rhs.1, self.2 | rhs.2, self.3 | rhs.3)
80+
}
81+
}
82+
83+
impl BitXor for u32x4 {
84+
type Output = u32x4;
85+
86+
fn bitxor(self, rhs: u32x4) -> u32x4 {
87+
u32x4(self.0 ^ rhs.0, self.1 ^ rhs.1, self.2 ^ rhs.2, self.3 ^ rhs.3)
88+
}
89+
}
90+
91+
impl Shl<usize> for u32x4 {
92+
type Output = u32x4;
93+
94+
fn shl(self, amt: usize) -> u32x4 {
95+
u32x4(self.0 << amt, self.1 << amt, self.2 << amt, self.3 << amt)
96+
}
97+
}
98+
99+
impl Shl<u32x4> for u32x4 {
100+
type Output = u32x4;
101+
102+
fn shl(self, rhs: u32x4) -> u32x4 {
103+
u32x4(self.0 << rhs.0, self.1 << rhs.1, self.2 << rhs.2, self.3 << rhs.3)
104+
}
105+
}
106+
107+
impl Shr<usize> for u32x4 {
108+
type Output = u32x4;
109+
110+
fn shr(self, amt: usize) -> u32x4 {
111+
u32x4(self.0 >> amt, self.1 >> amt, self.2 >> amt, self.3 >> amt)
112+
}
113+
}
114+
115+
impl Shr<u32x4> for u32x4 {
116+
type Output = u32x4;
117+
118+
fn shr(self, rhs: u32x4) -> u32x4 {
119+
u32x4(self.0 >> rhs.0, self.1 >> rhs.1, self.2 >> rhs.2, self.3 >> rhs.3)
120+
}
121+
}
122+
123+
#[derive(Copy)]
124+
#[allow(non_camel_case_types)]
125+
pub struct u64x2(pub u64, pub u64);
126+
127+
impl Add for u64x2 {
128+
type Output = u64x2;
129+
130+
fn add(self, rhs: u64x2) -> u64x2 {
131+
u64x2(self.0.wrapping_add(rhs.0), self.1.wrapping_add(rhs.1))
132+
}
133+
}
134+
}
135+
136+
#[cfg(ndebug)]
137+
mod real {
138+
pub use std::simd::u32x4;
139+
pub use std::simd::u64x2;
140+
}
141+

0 commit comments

Comments
 (0)