Skip to content

Commit 5f7632e

Browse files
committed
[WIP] polyval: implement R/F algorithm
1 parent fed0f15 commit 5f7632e

File tree

17 files changed

+874
-825
lines changed

17 files changed

+874
-825
lines changed

ghash/src/lib.rs

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@
88

99
pub use polyval::universal_hash;
1010

11-
use polyval::{DEFAULT_PARALLELISM, PolyvalGeneric};
11+
use polyval::Polyval;
1212
use universal_hash::{
1313
KeyInit, UhfBackend, UhfClosure, UniversalHash,
14-
array::ArraySize,
1514
common::{BlockSizeUser, KeySizeUser, ParBlocksSizeUser},
1615
consts::U16,
17-
typenum::{Const, ToUInt, U},
1816
};
1917

2018
#[cfg(feature = "zeroize")]
@@ -33,26 +31,17 @@ pub type Tag = universal_hash::Block<GHash>;
3331
///
3432
/// GHASH is a universal hash function used for message authentication in the AES-GCM authenticated
3533
/// encryption cipher.
36-
pub type GHash = GHashGeneric<{ DEFAULT_PARALLELISM }>;
37-
38-
/// **GHASH**: universal hash over GF(2^128) used by AES-GCM.
39-
///
40-
/// GHASH is a universal hash function used for message authentication in the AES-GCM authenticated
41-
/// encryption cipher.
42-
///
43-
/// Parameterized on a constant that determines how many blocks to process at once: higher numbers
44-
/// use more memory, and require more time to re-key, but process data significantly faster.
4534
#[derive(Clone)]
46-
pub struct GHashGeneric<const N: usize = { DEFAULT_PARALLELISM }>(PolyvalGeneric<N>);
35+
pub struct GHash(Polyval);
4736

48-
impl<const N: usize> KeySizeUser for GHashGeneric<N> {
37+
impl KeySizeUser for GHash {
4938
type KeySize = U16;
5039
}
5140

52-
impl<const N: usize> GHashGeneric<N> {
53-
/// Initialize GHASH with the given `H` field element and initial block
41+
impl GHash {
42+
/// Initialize GHASH with the given `H` field element as the key.
5443
#[inline]
55-
pub fn new_with_init_block(h: &Key, init_block: u128) -> Self {
44+
pub fn new(h: &Key) -> Self {
5645
let mut h = *h;
5746
h.reverse();
5847

@@ -63,7 +52,7 @@ impl<const N: usize> GHashGeneric<N> {
6352
h.zeroize();
6453

6554
#[allow(clippy::let_and_return)]
66-
let result = GHashGeneric(PolyvalGeneric::new_with_init_block(&h_polyval, init_block));
55+
let result = Self(Polyval::new(&h_polyval));
6756

6857
#[cfg(feature = "zeroize")]
6958
h_polyval.zeroize();
@@ -72,55 +61,51 @@ impl<const N: usize> GHashGeneric<N> {
7261
}
7362
}
7463

75-
impl<const N: usize> KeyInit for GHashGeneric<N> {
64+
impl KeyInit for GHash {
7665
/// Initialize GHASH with the given `H` field element
7766
#[inline]
7867
fn new(h: &Key) -> Self {
79-
Self::new_with_init_block(h, 0)
68+
Self::new(h)
8069
}
8170
}
8271

83-
struct GHashGenericBackend<'b, B: UhfBackend>(&'b mut B);
72+
struct GHashBackend<'b, B: UhfBackend>(&'b mut B);
8473

85-
impl<B: UhfBackend> BlockSizeUser for GHashGenericBackend<'_, B> {
74+
impl<B: UhfBackend> BlockSizeUser for GHashBackend<'_, B> {
8675
type BlockSize = B::BlockSize;
8776
}
8877

89-
impl<B: UhfBackend> ParBlocksSizeUser for GHashGenericBackend<'_, B> {
78+
impl<B: UhfBackend> ParBlocksSizeUser for GHashBackend<'_, B> {
9079
type ParBlocksSize = B::ParBlocksSize;
9180
}
9281

93-
impl<B: UhfBackend> UhfBackend for GHashGenericBackend<'_, B> {
82+
impl<B: UhfBackend> UhfBackend for GHashBackend<'_, B> {
9483
fn proc_block(&mut self, x: &universal_hash::Block<B>) {
9584
let mut x = x.clone();
9685
x.reverse();
9786
self.0.proc_block(&x);
9887
}
9988
}
10089

101-
impl<const N: usize> BlockSizeUser for GHashGeneric<N> {
90+
impl BlockSizeUser for GHash {
10291
type BlockSize = U16;
10392
}
10493

105-
impl<const N: usize> UniversalHash for GHashGeneric<N>
106-
where
107-
U<N>: ArraySize,
108-
Const<N>: ToUInt,
109-
{
94+
impl UniversalHash for GHash {
11095
fn update_with_backend(&mut self, f: impl UhfClosure<BlockSize = Self::BlockSize>) {
111-
struct GHashGenericClosure<C: UhfClosure>(C);
96+
struct GhashClosure<C: UhfClosure>(C);
11297

113-
impl<C: UhfClosure> BlockSizeUser for GHashGenericClosure<C> {
98+
impl<C: UhfClosure> BlockSizeUser for GhashClosure<C> {
11499
type BlockSize = C::BlockSize;
115100
}
116101

117-
impl<C: UhfClosure> UhfClosure for GHashGenericClosure<C> {
102+
impl<C: UhfClosure> UhfClosure for GhashClosure<C> {
118103
fn call<B: UhfBackend<BlockSize = Self::BlockSize>>(self, backend: &mut B) {
119-
self.0.call(&mut GHashGenericBackend(backend));
104+
self.0.call(&mut GHashBackend(backend));
120105
}
121106
}
122107

123-
self.0.update_with_backend(GHashGenericClosure(f));
108+
self.0.update_with_backend(GhashClosure(f));
124109
}
125110

126111
/// Get GHASH output
@@ -132,8 +117,8 @@ where
132117
}
133118
}
134119

135-
impl<const N: usize> core::fmt::Debug for GHashGeneric<N> {
120+
impl core::fmt::Debug for GHash {
136121
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
137-
write!(f, "GHashGeneric<{}> {{ ... }}", N)
122+
f.debug_tuple("GHash").finish_non_exhaustive()
138123
}
139124
}

polyval/src/backend.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
mod soft;
2+
3+
cpubits::cfg_if! {
4+
if #[cfg(all(target_arch = "aarch64", not(polyval_backend = "soft")))] {
5+
// PMULL/NEON backend for aarch64
6+
mod autodetect;
7+
mod neon;
8+
pub(crate) use autodetect::State;
9+
pub(crate) use neon::InitToken;
10+
} else if #[cfg(all(
11+
any(target_arch = "x86_64", target_arch = "x86"),
12+
not(polyval_backend = "soft")
13+
))] {
14+
// CLMUL/AVX2 backend for x86/x86-64
15+
mod autodetect;
16+
mod avx2;
17+
pub(crate) use autodetect::State;
18+
pub(crate) use avx2::InitToken;
19+
} else {
20+
// "soft" pure Rust portable fallback implementation for other targets
21+
pub(crate) use soft::{State, InitToken};
22+
}
23+
}

polyval/src/backend/autodetect.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//! Support for CPU feature autodetection with a portable pure Rust fallback.
2+
3+
use super::{InitToken, soft};
4+
use crate::{Block, FieldElement, ParBlocks, Tag};
5+
6+
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
7+
use super::avx2 as intrinsics;
8+
#[cfg(target_arch = "aarch64")]
9+
use super::neon as intrinsics;
10+
11+
pub(crate) union State {
12+
intrinsics: intrinsics::State,
13+
soft: soft::State,
14+
}
15+
16+
impl State {
17+
pub(crate) fn new(h: FieldElement, has_intrinsics: InitToken) -> Self {
18+
if has_intrinsics.get() {
19+
Self {
20+
intrinsics: unsafe { intrinsics::State::new(&h.into()) },
21+
}
22+
} else {
23+
Self {
24+
soft: soft::State::new(h, soft::InitToken::init()),
25+
}
26+
}
27+
}
28+
29+
pub(crate) fn proc_block(&mut self, block: &Block, has_intrinsics: InitToken) {
30+
if has_intrinsics.get() {
31+
unsafe { self.intrinsics.update_block(&block.0) }
32+
} else {
33+
unsafe { self.soft.proc_block(block, soft::InitToken::init()) }
34+
}
35+
}
36+
37+
pub(crate) fn proc_par_blocks(&mut self, par_blocks: &ParBlocks, has_intrinsics: InitToken) {
38+
if has_intrinsics.get() {
39+
unsafe { self.intrinsics.proc_par_blocks(par_blocks) }
40+
} else {
41+
unsafe {
42+
self.soft
43+
.proc_par_blocks(par_blocks, soft::InitToken::init());
44+
}
45+
}
46+
}
47+
48+
pub(crate) fn finalize(&self, has_intrinsics: InitToken) -> Tag {
49+
if has_intrinsics.get() {
50+
unsafe { self.intrinsics.finalize().into() }
51+
} else {
52+
unsafe { self.soft.finalize(soft::InitToken::init()) }
53+
}
54+
}
55+
56+
pub(crate) fn reset(&mut self, has_intrinsics: InitToken) {
57+
if has_intrinsics.get() {
58+
unsafe { self.intrinsics.reset() }
59+
} else {
60+
unsafe { self.soft.reset(soft::InitToken::init()) }
61+
}
62+
}
63+
64+
pub(crate) fn clone_with_intrinsics(&self, has_intrinsics: InitToken) -> Self {
65+
if has_intrinsics.get() {
66+
Self {
67+
intrinsics: unsafe { self.intrinsics.clone() },
68+
}
69+
} else {
70+
Self {
71+
soft: unsafe { self.soft.clone() },
72+
}
73+
}
74+
}
75+
76+
#[cfg(feature = "zeroize")]
77+
pub(crate) fn zeroize(&mut self, has_intrinsics: InitToken) {
78+
if has_intrinsics.get() {
79+
unsafe {
80+
self.intrinsics.zeroize();
81+
}
82+
} else {
83+
unsafe {
84+
self.soft.zeroize(soft::InitToken::init());
85+
}
86+
}
87+
}
88+
}

0 commit comments

Comments
 (0)