Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 3bdf094

Browse files
committedSep 1, 2019
[WIP] polyval: Constant-time software implementation
Adapts BearSSL's `ghash_ctmul64.c` into a constant-time software backend for POLYVAL.
1 parent d0b54b0 commit 3bdf094

File tree

11 files changed

+203
-195
lines changed

11 files changed

+203
-195
lines changed
 

‎.travis.yml

+6-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ rust:
66
- nightly
77

88
script:
9-
- cargo test --all --exclude polyval --release
9+
- cargo test --all --release
1010
- cargo test --all --all-features --release
1111

1212
env:
@@ -23,13 +23,15 @@ matrix:
2323
rust: 1.34.0
2424
env: {} # clear `-D warnings` above; allow warnings
2525

26-
# polyval presently needs either RUSTFLAGS or non-default features
26+
# Test `polyval` with the PCLMULQDQ-accelerated backend
2727
- name: "Rust: 1.32.0 (polyval)"
2828
rust: 1.34.0
29-
script: ./test_polyval.sh
29+
env: RUSTFLAGS="-Ctarget-cpu=sandybridge -Ctarget-feature=+sse2,+sse4.1"
30+
script: cd polyval && cargo --no-default-features --release
3031
- name: "Rust: stable (polyval)"
3132
rust: stable
32-
script: ./test_polyval.sh
33+
env: RUSTFLAGS="-Ctarget-cpu=sandybridge -Ctarget-feature=+sse2,+sse4.1"
34+
script: cd polyval && cargo --no-default-features --release
3335

3436
# no_std build
3537
- name: "Rust: stable (thumbv7em-none-eabihf)"

‎poly1305/benches/poly1305.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
extern crate test;
44

5-
use poly1305::{Poly1305, universal_hash::UniversalHash};
5+
use poly1305::{universal_hash::UniversalHash, Poly1305};
66
use test::Bencher;
77

88
// TODO(tarcieri): move this into the `universal-hash` crate

‎polyval/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ zeroize = { version = "0.10", optional = true, default-features = false }
2222
hex-literal = "0.1"
2323

2424
[features]
25-
default = []
25+
default = ["soft"]
2626
std = ["universal-hash/std"]
27-
insecure-soft = []
27+
soft = []
2828

2929
[badges]
3030
maintenance = { status = "experimental" }

‎polyval/benches/polyval.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
extern crate test;
44

5-
use polyval::{Polyval, universal_hash::UniversalHash};
5+
use polyval::{universal_hash::UniversalHash, Polyval};
66
use test::Bencher;
77

88
// TODO(tarcieri): move this into the `universal-hash` crate

‎polyval/src/field.rs

+3-26
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
//!
1515
//! [RFC 8452 Section 3]: https://tools.ietf.org/html/rfc8452#section-3
1616
17-
pub(crate) mod backend;
18-
mod clmul;
17+
pub mod backend;
1918

2019
use self::backend::Backend;
2120
use core::ops::{Add, Mul};
@@ -26,12 +25,6 @@ pub const FIELD_SIZE: usize = 16;
2625
/// POLYVAL field element bytestrings (16-bytes)
2726
pub type Block = [u8; FIELD_SIZE];
2827

29-
/// Mask value used when performing Montgomery fast reduction.
30-
/// This corresponds to POLYVAL's polynomial with the highest bit unset.
31-
///
32-
/// See: <https://crypto.stanford.edu/RealWorldCrypto/slides/gueron.pdf>
33-
const MASK: u128 = 1 << 127 | 1 << 126 | 1 << 121 | 1;
34-
3528
/// POLYVAL field element.
3629
#[derive(Copy, Clone)]
3730
pub struct Element<B: Backend>(B);
@@ -46,17 +39,6 @@ impl<B: Backend> Element<B> {
4639
pub fn to_bytes(self) -> Block {
4740
self.0.into()
4841
}
49-
50-
/// Fast reduction modulo x^128 + x^127 + x^126 +x^121 + 1 (Gueron 2012)
51-
/// Algorithm 4: "Montgomery reduction"
52-
fn reduce(self) -> Self {
53-
let mask = B::from(MASK);
54-
let a = mask.clmul(self.0, 0x01);
55-
let b = self.0.shuffle() ^ a;
56-
let c = mask.clmul(b, 0x01);
57-
let d = b.shuffle() ^ c;
58-
Element(d)
59-
}
6042
}
6143

6244
impl<B: Backend> Default for Element<B> {
@@ -77,7 +59,7 @@ impl<B: Backend> Add for Element<B> {
7759
///
7860
/// [RFC 8452 Section 3]: https://tools.ietf.org/html/rfc8452#section-3
7961
fn add(self, rhs: Self) -> Self {
80-
Element(self.0 ^ rhs.0)
62+
Element(self.0 + rhs.0)
8163
}
8264
}
8365

@@ -95,12 +77,7 @@ impl<B: Backend> Mul for Element<B> {
9577
///
9678
/// [RFC 8452 Section 3]: https://tools.ietf.org/html/rfc8452#section-3
9779
fn mul(self, rhs: Self) -> Self {
98-
let t1 = self.0.clmul(rhs.0, 0x00);
99-
let t2 = self.0.clmul(rhs.0, 0x01);
100-
let t3 = self.0.clmul(rhs.0, 0x10);
101-
let t4 = self.0.clmul(rhs.0, 0x11);
102-
let t5 = t2 ^ t3;
103-
Element(t4 ^ t5.shr64()) + Element(t1 ^ t5.shl64()).reduce()
80+
Element(self.0 * rhs.0)
10481
}
10582
}
10683

‎polyval/src/field/backend.rs

+8-17
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@
88
))]
99
mod pclmulqdq;
1010

11-
#[cfg(feature = "insecure-soft")]
12-
mod soft;
11+
#[cfg(feature = "soft")]
12+
pub mod soft;
1313

14-
use super::clmul::Clmul;
1514
use super::Block;
16-
use core::ops::BitXor;
15+
use core::ops::{Add, Mul};
1716

1817
#[cfg(not(any(
1918
all(
@@ -22,12 +21,12 @@ use core::ops::BitXor;
2221
target_feature = "sse4.1",
2322
any(target_arch = "x86", target_arch = "x86_64")
2423
),
25-
feature = "insecure-soft"
24+
feature = "soft"
2625
)))]
2726
compile_error!(
2827
"no backends available! On x86/x86-64 platforms, enable intrinsics with \
2928
RUSTFLAGS=\"-Ctarget-cpu=sandybridge -Ctarget-feature=+sse2,+sse4.1\" or \
30-
enable **INSECURE** portable emulation with the `insecure-soft` feature"
29+
enable portable emulation with the `soft` Cargo feature"
3130
);
3231

3332
#[cfg(all(
@@ -45,20 +44,12 @@ pub(crate) use self::pclmulqdq::M128i;
4544
target_feature = "sse4.1",
4645
any(target_arch = "x86", target_arch = "x86_64")
4746
)),
48-
feature = "insecure-soft"
47+
feature = "soft"
4948
))]
5049
pub(crate) use self::soft::U64x2 as M128i;
5150

52-
/// Trait representing the arithmetic operations we expect on the XMM registers
51+
/// Field arithmetic backend
5352
pub trait Backend:
54-
BitXor<Output = Self> + Clmul + Copy + From<Block> + Into<Block> + From<u128>
53+
Add<Output = Self> + Mul<Output = Self> + Copy + From<Block> + Into<Block> + From<u128>
5554
{
56-
/// Swap the hi and low 64-bit halves of the register
57-
fn shuffle(self) -> Self;
58-
59-
/// Shift the contents of the register left by 64-bits
60-
fn shl64(self) -> Self;
61-
62-
/// Shift the contents of the register right by 64-bits
63-
fn shr64(self) -> Self;
6455
}

‎polyval/src/field/backend/pclmulqdq.rs

+54-20
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,16 @@ use core::arch::x86::*;
1010
use core::arch::x86_64::*;
1111

1212
use super::Backend;
13-
use crate::field::{
14-
clmul::{self, Clmul},
15-
Block,
16-
};
17-
use core::ops::BitXor;
13+
use crate::field::Block;
14+
use core::ops::{Add, Mul};
1815

1916
/// Wrapper for `__m128i` - a 128-bit XMM register (SSE2)
2017
#[repr(align(16))]
2118
#[derive(Copy, Clone)]
2219
pub struct M128i(__m128i);
2320

21+
impl Backend for M128i {}
22+
2423
impl From<Block> for M128i {
2524
fn from(bytes: Block) -> M128i {
2625
M128i(unsafe { _mm_loadu_si128(bytes.as_ptr() as *const __m128i) })
@@ -45,24 +44,50 @@ impl From<u128> for M128i {
4544
}
4645
}
4746

48-
impl BitXor for M128i {
47+
impl Add for M128i {
4948
type Output = Self;
5049

51-
fn bitxor(self, rhs: Self) -> Self::Output {
50+
/// Adds two POLYVAL field elements.
51+
fn add(self, rhs: Self) -> Self {
5252
M128i(unsafe { xor(self.0, rhs.0) })
5353
}
5454
}
5555

56-
impl Clmul for M128i {
57-
fn clmul<I>(self, rhs: Self, imm: I) -> Self
58-
where
59-
I: Into<clmul::PseudoOp>,
60-
{
61-
M128i(unsafe { pclmulqdq(self.0, rhs.0, imm.into()) })
56+
#[allow(clippy::suspicious_arithmetic_impl)]
57+
impl Mul for M128i {
58+
type Output = Self;
59+
60+
/// Computes POLYVAL multiplication over GF(2^128).
61+
fn mul(self, rhs: Self) -> Self {
62+
let t1 = self.clmul(rhs, 0x00);
63+
let t2 = self.clmul(rhs, 0x01);
64+
let t3 = self.clmul(rhs, 0x10);
65+
let t4 = self.clmul(rhs, 0x11);
66+
let t5 = t2 + t3;
67+
(t4 + t5.shr64()) + (t1 + t5.shl64()).reduce()
6268
}
6369
}
6470

65-
impl Backend for M128i {
71+
impl M128i {
72+
/// Wrapper for PCLMULQDQ
73+
fn clmul(self, rhs: Self, imm: u8) -> Self {
74+
M128i(unsafe { pclmulqdq(self.0, rhs.0, imm) })
75+
}
76+
77+
/// Fast reduction modulo x^128 + x^127 + x^126 +x^121 + 1 (Gueron 2012)
78+
/// Algorithm 4: "Montgomery reduction"
79+
///
80+
/// See: <https://crypto.stanford.edu/RealWorldCrypto/slides/gueron.pdf>
81+
fn reduce(self) -> Self {
82+
// Mask value used when performing Montgomery fast reduction.
83+
// This corresponds to POLYVAL's polynomial with the highest bit unset.
84+
let mask = Self::from(1 << 127 | 1 << 126 | 1 << 121 | 1);
85+
let a = mask.clmul(self, 0x01);
86+
let b = self.shuffle() + a;
87+
let c = mask.clmul(b, 0x01);
88+
b.shuffle() + c
89+
}
90+
6691
fn shuffle(self) -> Self {
6792
M128i(unsafe { shufpd1(self.0) })
6893
}
@@ -99,11 +124,20 @@ unsafe fn psrldq8(a: __m128i) -> __m128i {
99124

100125
// TODO(tarcieri): _mm256_clmulepi64_epi128 (vpclmulqdq)
101126
#[target_feature(enable = "pclmulqdq", enable = "sse2", enable = "sse4.1")]
102-
unsafe fn pclmulqdq(a: __m128i, b: __m128i, op: clmul::PseudoOp) -> __m128i {
103-
match op {
104-
clmul::PseudoOp::PCLMULLQLQDQ => _mm_clmulepi64_si128(a, b, 0x00),
105-
clmul::PseudoOp::PCLMULHQLQDQ => _mm_clmulepi64_si128(a, b, 0x01),
106-
clmul::PseudoOp::PCLMULLQHQDQ => _mm_clmulepi64_si128(a, b, 0x10),
107-
clmul::PseudoOp::PCLMULHQHQDQ => _mm_clmulepi64_si128(a, b, 0x11),
127+
unsafe fn pclmulqdq(a: __m128i, b: __m128i, imm: u8) -> __m128i {
128+
match imm {
129+
// Low-Low: `clmul(a[0..8], b[0..8])` (PCLMULLQLQDQ)
130+
0x00 => _mm_clmulepi64_si128(a, b, 0x00),
131+
132+
// High-Low: `clmul(a[8..16], b[0..8])` (PCLMULHQLQDQ)
133+
0x01 => _mm_clmulepi64_si128(a, b, 0x01),
134+
135+
// Low-High: `clmul(a[0..8], b[8..16])` (PCLMULLQHQDQ)
136+
0x10 => _mm_clmulepi64_si128(a, b, 0x10),
137+
138+
// High-High: `clmul(a[8..16], b[8..16])` (PCLMULHQHQDQ)
139+
0x11 => _mm_clmulepi64_si128(a, b, 0x11),
140+
141+
_ => unreachable!(),
108142
}
109143
}

‎polyval/src/field/backend/soft.rs

+125-53
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,51 @@
1-
//! Software emulation support for CLMUL hardware intrinsics.
2-
//!
3-
//! WARNING: Not constant time! Should be made constant-time or disabled by default.
4-
5-
// TODO(tarcieri): performance-oriented constant-time implementation
6-
// See: <https://bearssl.org/gitweb/?p=BearSSL;a=blob;f=src/hash/ghash_ctmul64.c>
1+
//! Constant-time software implementation of POLYVAL
2+
3+
// Adapted from BearSSL's `ghash_ctmul64.c`
4+
// <https://bearssl.org/gitweb/?p=BearSSL;a=blob;f=src/hash/ghash_ctmul64.c;hb=4b6046412bf927d6424f20fc7ee495bb96dbd227>
5+
//
6+
// Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
7+
//
8+
// Permission is hereby granted, free of charge, to any person obtaining
9+
// a copy of this software and associated documentation files (the
10+
// "Software"), to deal in the Software without restriction, including
11+
// without limitation the rights to use, copy, modify, merge, publish,
12+
// distribute, sublicense, and/or sell copies of the Software, and to
13+
// permit persons to whom the Software is furnished to do so, subject to
14+
// the following conditions:
15+
//
16+
// The above copyright notice and this permission notice shall be
17+
// included in all copies or substantial portions of the Software.
18+
//
19+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
23+
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
24+
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25+
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26+
// SOFTWARE.
27+
28+
#![allow(missing_docs)]
729

830
use super::Backend;
9-
use crate::field::{
10-
clmul::{self, Clmul},
11-
Block,
31+
use crate::field::Block;
32+
use core::{
33+
convert::TryInto,
34+
ops::{Add, Mul},
1235
};
13-
use core::{convert::TryInto, ops::BitXor};
1436

1537
/// 2 x `u64` values emulating an XMM register
1638
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
17-
pub struct U64x2([u64; 2]);
39+
pub struct U64x2(u64, u64);
40+
41+
impl Backend for U64x2 {}
1842

1943
impl From<Block> for U64x2 {
2044
fn from(bytes: Block) -> U64x2 {
21-
U64x2([
45+
U64x2(
2246
u64::from_le_bytes(bytes[..8].try_into().unwrap()),
2347
u64::from_le_bytes(bytes[8..].try_into().unwrap()),
24-
])
48+
)
2549
}
2650
}
2751

@@ -36,66 +60,114 @@ impl From<u128> for U64x2 {
3660
fn from(x: u128) -> U64x2 {
3761
let lo = (x & 0xFFFF_FFFFF) as u64;
3862
let hi = (x >> 64) as u64;
39-
U64x2([lo, hi])
63+
U64x2(lo, hi)
4064
}
4165
}
4266

4367
impl From<U64x2> for u128 {
4468
fn from(u64x2: U64x2) -> u128 {
45-
u128::from(u64x2.0[0]) | (u128::from(u64x2.0[1]) << 64)
69+
u128::from(u64x2.0) | (u128::from(u64x2.1) << 64)
4670
}
4771
}
4872

49-
impl BitXor for U64x2 {
73+
#[allow(clippy::suspicious_arithmetic_impl)]
74+
impl Add for U64x2 {
5075
type Output = Self;
5176

52-
fn bitxor(self, rhs: Self) -> Self::Output {
53-
U64x2([self.0[0] ^ rhs.0[0], self.0[1] ^ rhs.0[1]])
77+
/// Adds two POLYVAL field elements.
78+
fn add(self, rhs: Self) -> Self::Output {
79+
U64x2(self.0 ^ rhs.0, self.1 ^ rhs.1)
5480
}
5581
}
5682

57-
impl Clmul for U64x2 {
58-
fn clmul<I>(self, other: Self, imm: I) -> Self
59-
where
60-
I: Into<clmul::PseudoOp>,
61-
{
62-
let (a, b) = match imm.into() {
63-
clmul::PseudoOp::PCLMULLQLQDQ => (self.0[0], other.0[0]),
64-
clmul::PseudoOp::PCLMULHQLQDQ => (self.0[1], other.0[0]),
65-
clmul::PseudoOp::PCLMULLQHQDQ => (self.0[0], other.0[1]),
66-
clmul::PseudoOp::PCLMULHQHQDQ => (self.0[1], other.0[1]),
67-
};
83+
#[allow(clippy::suspicious_arithmetic_impl)]
84+
impl Mul for U64x2 {
85+
type Output = Self;
6886

69-
let mut result = [0u64; 2];
87+
/// Computes POLYVAL multiplication over GF(2^128).
88+
// TODO(tarcieri): actually adapt the arithmetic below from GHASH
89+
fn mul(self, rhs: Self) -> Self {
90+
let h0 = self.0;
91+
let h1 = self.1;
92+
let h0r = rev64(h0);
93+
let h1r = rev64(h1);
94+
let h2 = h0 ^ h1;
95+
let h2r = h0r ^ h1r;
96+
97+
let y0 = rhs.0;
98+
let y1 = rhs.1;
99+
let y0r = rev64(y0);
100+
let y1r = rev64(y1);
101+
let y2 = y0 ^ y1;
102+
let y2r = y0r ^ y1r;
103+
let z0 = bmul64(y0, h0);
104+
let z1 = bmul64(y1, h1);
105+
106+
let mut z2 = bmul64(y2, h2);
107+
let mut z0h = bmul64(y0r, h0r);
108+
let mut z1h = bmul64(y1r, h1r);
109+
let mut z2h = bmul64(y2r, h2r);
110+
111+
z2 ^= z0 ^ z1;
112+
z2h ^= z0h ^ z1h;
113+
z0h = rev64(z0h) >> 1;
114+
z1h = rev64(z1h) >> 1;
115+
z2h = rev64(z2h) >> 1;
116+
117+
let mut v0 = z0;
118+
let mut v1 = z0h ^ z2;
119+
let mut v2 = z1 ^ z2h;
120+
let mut v3 = z1h;
121+
122+
v3 = v3 << 1 | v2 >> 63;
123+
v2 = v2 << 1 | v1 >> 63;
124+
v1 = v1 << 1 | v0 >> 63;
125+
v0 <<= 1;
126+
127+
v2 ^= v0 ^ v0 >> 1 ^ v0 >> 2 ^ v0 >> 7;
128+
v1 ^= v0 << 63 ^ v0 << 62 ^ v0 << 57;
129+
v3 ^= v1 ^ v1 >> 1 ^ v1 >> 2 ^ v1 >> 7;
130+
v2 ^= v1 << 63 ^ v1 << 62 ^ v1 << 57;
131+
132+
U64x2(v2, v3)
133+
}
134+
}
70135

71-
for i in 0..64 {
72-
if b & (1 << i) != 0 {
73-
result[1] ^= a;
74-
}
136+
fn rev64(mut x: u64) -> u64 {
137+
x = ((x & 0x5555_5555_5555_5555) << 1) | ((x >> 1) & 0x5555_5555_5555_5555);
138+
x = ((x & 0x3333_3333_3333_3333) << 2) | ((x >> 2) & 0x3333_3333_3333_3333);
139+
x = ((x & 0x0f0f_0f0f_0f0f_0f0f) << 4) | ((x >> 4) & 0x0f0f_0f0f_0f0f_0f0f);
140+
x = ((x & 0x00ff_00ff_00ff_00ff) << 8) | ((x >> 8) & 0x00ff_00ff_00ff_00ff);
141+
x = ((x & 0xffff_0000_ffff) << 16) | ((x >> 16) & 0xffff_0000_ffff);
142+
(x << 32) | (x >> 32)
143+
}
75144

76-
result[0] >>= 1;
145+
fn bmul64(x: u64, y: u64) -> u64 {
146+
let x0 = x & 0x1111_1111_1111_1111;
147+
let x1 = x & 0x2222_2222_2222_2222;
148+
let x2 = x & 0x4444_4444_4444_4444;
149+
let x3 = x & 0x8888_8888_8888_8888;
150+
let y0 = y & 0x1111_1111_1111_1111;
151+
let y1 = y & 0x2222_2222_2222_2222;
152+
let y2 = y & 0x4444_4444_4444_4444;
153+
let y3 = y & 0x8888_8888_8888_8888;
77154

78-
if result[1] & 1 != 0 {
79-
result[0] ^= 1 << 63;
80-
}
155+
let mut z0 =
156+
x0.wrapping_mul(y0) ^ x1.wrapping_mul(y3) ^ x2.wrapping_mul(y2) ^ x3.wrapping_mul(y1);
81157

82-
result[1] >>= 1;
83-
}
158+
let mut z1 =
159+
x0.wrapping_mul(y1) ^ x1.wrapping_mul(y0) ^ x2.wrapping_mul(y3) ^ x3.wrapping_mul(y2);
84160

85-
U64x2(result)
86-
}
87-
}
161+
let mut z2 =
162+
x0.wrapping_mul(y2) ^ x1.wrapping_mul(y1) ^ x2.wrapping_mul(y0) ^ x3.wrapping_mul(y3);
88163

89-
impl Backend for U64x2 {
90-
fn shuffle(self) -> Self {
91-
U64x2([self.0[1], self.0[0]])
92-
}
164+
let mut z3 =
165+
x0.wrapping_mul(y3) ^ x1.wrapping_mul(y2) ^ x2.wrapping_mul(y1) ^ x3.wrapping_mul(y0);
93166

94-
fn shl64(self) -> Self {
95-
U64x2([0, self.0[0]])
96-
}
167+
z0 &= 0x1111_1111_1111_1111;
168+
z1 &= 0x2222_2222_2222_2222;
169+
z2 &= 0x4444_4444_4444_4444;
170+
z3 &= 0x8888_8888_8888_8888;
97171

98-
fn shr64(self) -> Self {
99-
U64x2([self.0[1], 0])
100-
}
172+
z0 | z1 | z2 | z3
101173
}

‎polyval/src/field/clmul.rs

-55
This file was deleted.

‎polyval/src/lib.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,12 @@
1414
//! ## Requirements
1515
//!
1616
//! - Rust 1.34.0 or newer
17-
//! - `RUSTFLAGS` with `-Ctarget-cpu` and `-Ctarget-feature`:
17+
//! - Recommended: `RUSTFLAGS` with `-Ctarget-cpu` and `-Ctarget-feature`:
1818
//! - x86(-64) CPU: `target-cpu=sandybridge` or newer
1919
//! - SSE2 + SSE4.1: `target-feature=+sse2,+sse4.1`
2020
//!
21-
//! An **INSECURE** (variable timing) portable implementation is gated behind
22-
//! the `insecure-soft` cargo feature. Use of this implementation is
23-
//! **NOT RECOMMENDED** and may potentially leak the POLYVAL key!
21+
//! If `RUSTFLAGS` are not provided, this crate will fall back to a much slower
22+
//! software-only implementation.
2423
//!
2524
//! ## Relationship to GHASH
2625
//!

‎test_polyval.sh

-12
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.