1414//!
1515//! [RFC 8452 Section 3]: https://tools.ietf.org/html/rfc8452#section-3
1616
17- pub mod backend;
17+ #[ cfg( all(
18+ target_feature = "pclmulqdq" ,
19+ target_feature = "sse2" ,
20+ target_feature = "sse4.1" ,
21+ any( target_arch = "x86" , target_arch = "x86_64" )
22+ ) ) ]
23+ mod pclmulqdq;
24+ mod soft;
1825
19- use self :: backend:: Backend ;
20- use core:: ops:: { Add , Mul } ;
26+ #[ cfg( all(
27+ target_feature = "pclmulqdq" ,
28+ target_feature = "sse2" ,
29+ target_feature = "sse4.1" ,
30+ any( target_arch = "x86" , target_arch = "x86_64" )
31+ ) ) ]
32+ use self :: pclmulqdq:: M128i ;
33+ use self :: soft:: U64x2 ;
2134
2235/// Size of GF(2^128) in bytes (16-bytes).
2336pub const FIELD_SIZE : usize = 16 ;
@@ -27,29 +40,64 @@ pub type Block = [u8; FIELD_SIZE];
2740
2841/// POLYVAL field element.
2942#[ derive( Copy , Clone ) ]
30- pub struct Element < B : Backend > ( B ) ;
43+ pub enum Element {
44+ #[ cfg( all(
45+ target_feature = "pclmulqdq" ,
46+ target_feature = "sse2" ,
47+ target_feature = "sse4.1" ,
48+ any( target_arch = "x86" , target_arch = "x86_64" )
49+ ) ) ]
50+ /// (P)CLMUL(QDQ)-accelerated backend on supported x86 architectures
51+ Clmul ( M128i ) ,
3152
32- impl < B : Backend > Element < B > {
53+ /// Portable software fallback
54+ Soft ( U64x2 ) ,
55+ }
56+
57+ impl Element {
3358 /// Load a `FieldElement` from its bytestring representation.
59+ #[ cfg( all(
60+ target_feature = "pclmulqdq" ,
61+ target_feature = "sse2" ,
62+ target_feature = "sse4.1" ,
63+ any( target_arch = "x86" , target_arch = "x86_64" )
64+ ) ) ]
3465 pub fn from_bytes ( bytes : Block ) -> Self {
35- Element ( bytes. into ( ) )
66+ if cfg ! ( feature = "std" ) {
67+ if is_x86_feature_detected ! ( "pclmulqdq" ) {
68+ Element :: Clmul ( bytes. into ( ) )
69+ } else {
70+ Element :: Soft ( bytes. into ( ) )
71+ }
72+ } else {
73+ Element :: Clmul ( bytes. into ( ) )
74+ }
3675 }
3776
38- /// Serialize this `FieldElement` as a bytestring.
39- pub fn to_bytes ( self ) -> Block {
40- self . 0 . into ( )
77+ /// Load a `FieldElement` from its bytestring representation.
78+ #[ cfg( not( all(
79+ target_feature = "pclmulqdq" ,
80+ target_feature = "sse2" ,
81+ target_feature = "sse4.1" ,
82+ any( target_arch = "x86" , target_arch = "x86_64" )
83+ ) ) ) ]
84+ pub fn from_bytes ( bytes : Block ) -> Self {
85+ Element :: Soft ( bytes. into ( ) )
4186 }
42- }
4387
44- impl < B : Backend > Default for Element < B > {
45- fn default ( ) -> Self {
46- Self :: from_bytes ( Block :: default ( ) )
88+ /// Serialize this `FieldElement` as a bytestring.
89+ pub fn to_bytes ( self ) -> Block {
90+ match self {
91+ #[ cfg( all(
92+ target_feature = "pclmulqdq" ,
93+ target_feature = "sse2" ,
94+ target_feature = "sse4.1" ,
95+ any( target_arch = "x86" , target_arch = "x86_64" )
96+ ) ) ]
97+ Element :: Clmul ( m128i) => m128i. into ( ) ,
98+ Element :: Soft ( u64x2) => u64x2. into ( ) ,
99+ }
47100 }
48- }
49-
50- #[ allow( clippy:: suspicious_arithmetic_impl) ]
51- impl < B : Backend > Add for Element < B > {
52- type Output = Self ;
53101
54102 /// Adds two POLYVAL field elements.
55103 ///
@@ -58,16 +106,21 @@ impl<B: Backend> Add for Element<B> {
58106 /// > "The sum of any two elements in the field is the result of XORing them."
59107 ///
60108 /// [RFC 8452 Section 3]: https://tools.ietf.org/html/rfc8452#section-3
61- fn add ( self , rhs : Self ) -> Self {
62- Element ( self . 0 + rhs. 0 )
109+ #[ allow( clippy:: should_implement_trait) ]
110+ pub fn add ( self , other : Block ) -> Self {
111+ match self {
112+ #[ cfg( all(
113+ target_feature = "pclmulqdq" ,
114+ target_feature = "sse2" ,
115+ target_feature = "sse4.1" ,
116+ any( target_arch = "x86" , target_arch = "x86_64" )
117+ ) ) ]
118+ Element :: Clmul ( m128i) => Element :: Clmul ( m128i + M128i :: from ( other) ) ,
119+ Element :: Soft ( u64x2) => Element :: Soft ( u64x2 + U64x2 :: from ( other) ) ,
120+ }
63121 }
64- }
65-
66- #[ allow( clippy:: suspicious_arithmetic_impl) ]
67- impl < B : Backend > Mul for Element < B > {
68- type Output = Self ;
69122
70- /// Computes POLYVAL multiplication over GF(2^128).
123+ /// Computes carryless POLYVAL multiplication over GF(2^128).
71124 ///
72125 /// From [RFC 8452 Section 3]:
73126 ///
@@ -76,13 +129,22 @@ impl<B: Backend> Mul for Element<B> {
76129 /// > irreducible polynomial."
77130 ///
78131 /// [RFC 8452 Section 3]: https://tools.ietf.org/html/rfc8452#section-3
79- fn mul ( self , rhs : Self ) -> Self {
80- Element ( self . 0 * rhs. 0 )
132+ pub fn clmul ( self , other : Block ) -> Self {
133+ match self {
134+ #[ cfg( all(
135+ target_feature = "pclmulqdq" ,
136+ target_feature = "sse2" ,
137+ target_feature = "sse4.1" ,
138+ any( target_arch = "x86" , target_arch = "x86_64" )
139+ ) ) ]
140+ Element :: Clmul ( m128i) => Element :: Clmul ( m128i * M128i :: from ( other) ) ,
141+ Element :: Soft ( u64x2) => Element :: Soft ( u64x2 * U64x2 :: from ( other) ) ,
142+ }
81143 }
82144}
83145
84- impl < B : Backend > From < B > for Element < B > {
85- fn from ( element : B ) -> Element < B > {
86- Element ( element )
146+ impl Default for Element {
147+ fn default ( ) -> Self {
148+ Self :: from_bytes ( Block :: default ( ) )
87149 }
88150}
0 commit comments