16
16
#![ doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png" ) ]
17
17
#![ warn( missing_docs, rust_2018_idioms) ]
18
18
19
- pub use subtle ;
19
+ pub use universal_hash ;
20
20
21
21
use core:: { cmp:: min, convert:: TryInto } ;
22
- use subtle:: { Choice , ConstantTimeEq } ;
22
+ use universal_hash:: generic_array:: {
23
+ typenum:: { U16 , U32 } ,
24
+ GenericArray ,
25
+ } ;
26
+ use universal_hash:: { Output , UniversalHash } ;
23
27
#[ cfg( feature = "zeroize" ) ]
24
28
use zeroize:: Zeroize ;
25
29
@@ -50,9 +54,12 @@ pub struct Poly1305 {
50
54
buffer : Block ,
51
55
}
52
56
53
- impl Poly1305 {
57
+ impl UniversalHash for Poly1305 {
58
+ type KeySize = U32 ;
59
+ type OutputSize = U16 ;
60
+
54
61
/// Initialize Poly1305 with the given key
55
- pub fn new ( key : & Key ) -> Poly1305 {
62
+ fn new ( key : & GenericArray < u8 , U32 > ) -> Poly1305 {
56
63
let mut poly = Poly1305 {
57
64
r : [ 0u32 ; 5 ] ,
58
65
h : [ 0u32 ; 5 ] ,
@@ -77,75 +84,28 @@ impl Poly1305 {
77
84
}
78
85
79
86
/// Input data into the Poly1305 universal hash function
80
- pub fn input ( & mut self , data : & [ u8 ] ) {
81
- let mut m = data;
82
-
83
- if self . leftover > 0 {
84
- let want = min ( 16 - self . leftover , m. len ( ) ) ;
85
-
86
- for ( i, byte) in m. iter ( ) . cloned ( ) . enumerate ( ) . take ( want) {
87
- self . buffer [ self . leftover + i] = byte;
88
- }
89
-
90
- m = & m[ want..] ;
91
- self . leftover += want;
92
-
93
- if self . leftover < BLOCK_SIZE {
94
- return ;
95
- }
96
-
97
- self . block ( false ) ;
98
- self . leftover = 0 ;
99
- }
100
-
101
- while m. len ( ) >= BLOCK_SIZE {
102
- // TODO(tarcieri): avoid a copy here when `TryInto` is available (1.34+)
103
- // We can avoid copying this data into the buffer, but do for now
104
- // because it simplifies constant-time assessment.
105
- self . buffer . copy_from_slice ( & m[ ..BLOCK_SIZE ] ) ;
106
- self . block ( false ) ;
107
- m = & m[ BLOCK_SIZE ..] ;
108
- }
109
-
110
- self . buffer [ ..m. len ( ) ] . copy_from_slice ( m) ;
111
- self . leftover = m. len ( ) ;
87
+ fn update_block ( & mut self , block : & GenericArray < u8 , U16 > ) {
88
+ // TODO(tarcieri): pass block directly to `Poly1305::compute_block`
89
+ self . update ( block. as_slice ( ) ) ;
112
90
}
113
91
114
- /// Input data into Poly1305, first padding it to Poly1305's block size
115
- /// ala the `pad16()` function described in RFC 8439 section 2.8.1:
116
- /// <https://tools.ietf.org/html/rfc8439#section-2.8.1>
117
- ///
118
- /// This is primarily useful for implementing Salsa20 family authenticated
119
- /// encryption constructions.
120
- pub fn input_padded ( & mut self , data : & [ u8 ] ) {
121
- self . input ( data) ;
122
-
123
- // Pad associated data with `\0` if it's unaligned with the block size
124
- let unaligned_len = data. len ( ) % BLOCK_SIZE ;
125
-
126
- if unaligned_len != 0 {
127
- let pad = Block :: default ( ) ;
128
- let pad_len = BLOCK_SIZE - unaligned_len;
129
- self . input ( & pad[ ..pad_len] ) ;
130
- }
131
- }
132
-
133
- /// Process input messages in a chained manner
134
- pub fn chain ( mut self , data : & [ u8 ] ) -> Self {
135
- self . input ( data) ;
136
- self
92
+ /// Reset internal state
93
+ fn reset ( & mut self ) {
94
+ self . h = Default :: default ( ) ;
95
+ self . buffer = Default :: default ( ) ;
96
+ self . leftover = 0 ;
137
97
}
138
98
139
99
/// Get the hashed output
140
- pub fn result ( mut self ) -> Tag {
100
+ fn result ( mut self ) -> Output < U16 > {
141
101
if self . leftover > 0 {
142
102
self . buffer [ self . leftover ] = 1 ;
143
103
144
104
for i in ( self . leftover + 1 ) ..BLOCK_SIZE {
145
105
self . buffer [ i] = 0 ;
146
106
}
147
107
148
- self . block ( true ) ;
108
+ self . compute_block ( true ) ;
149
109
}
150
110
151
111
// fully carry h
@@ -229,17 +189,58 @@ impl Poly1305 {
229
189
f = u64:: from ( h3) + u64:: from ( self . pad [ 3 ] ) + ( f >> 32 ) ;
230
190
h3 = f as u32 ;
231
191
232
- let mut tag = Block :: default ( ) ;
233
- tag [ 0 ..4 ] . copy_from_slice ( & h0. to_le_bytes ( ) ) ;
234
- tag [ 4 ..8 ] . copy_from_slice ( & h1. to_le_bytes ( ) ) ;
235
- tag [ 8 ..12 ] . copy_from_slice ( & h2. to_le_bytes ( ) ) ;
236
- tag [ 12 ..16 ] . copy_from_slice ( & h3. to_le_bytes ( ) ) ;
192
+ let mut output = GenericArray :: default ( ) ;
193
+ output [ 0 ..4 ] . copy_from_slice ( & h0. to_le_bytes ( ) ) ;
194
+ output [ 4 ..8 ] . copy_from_slice ( & h1. to_le_bytes ( ) ) ;
195
+ output [ 8 ..12 ] . copy_from_slice ( & h2. to_le_bytes ( ) ) ;
196
+ output [ 12 ..16 ] . copy_from_slice ( & h3. to_le_bytes ( ) ) ;
237
197
238
- Tag :: new ( tag)
198
+ Output :: new ( output)
199
+ }
200
+ }
201
+
202
+ impl Poly1305 {
203
+ /// Input data into the Poly1305 universal hash function
204
+ pub fn update ( & mut self , data : & [ u8 ] ) {
205
+ let mut m = data;
206
+
207
+ if self . leftover > 0 {
208
+ let want = min ( 16 - self . leftover , m. len ( ) ) ;
209
+
210
+ for ( i, byte) in m. iter ( ) . cloned ( ) . enumerate ( ) . take ( want) {
211
+ self . buffer [ self . leftover + i] = byte;
212
+ }
213
+
214
+ m = & m[ want..] ;
215
+ self . leftover += want;
216
+
217
+ if self . leftover < BLOCK_SIZE {
218
+ return ;
219
+ }
220
+
221
+ self . compute_block ( false ) ;
222
+ self . leftover = 0 ;
223
+ }
224
+
225
+ while m. len ( ) >= BLOCK_SIZE {
226
+ // TODO(tarcieri): avoid copying data into the buffer here
227
+ self . buffer . copy_from_slice ( & m[ ..BLOCK_SIZE ] ) ;
228
+ self . compute_block ( false ) ;
229
+ m = & m[ BLOCK_SIZE ..] ;
230
+ }
231
+
232
+ self . buffer [ ..m. len ( ) ] . copy_from_slice ( m) ;
233
+ self . leftover = m. len ( ) ;
234
+ }
235
+
236
+ /// Process input messages in a chained manner
237
+ pub fn chain ( mut self , data : & [ u8 ] ) -> Self {
238
+ self . update ( data) ;
239
+ self
239
240
}
240
241
241
242
/// Compute a single block of Poly1305 using the internal buffer
242
- fn block ( & mut self , finished : bool ) {
243
+ fn compute_block ( & mut self , finished : bool ) {
243
244
let hibit = if finished { 0 } else { 1 << 24 } ;
244
245
245
246
let r0 = self . r [ 0 ] ;
@@ -340,31 +341,3 @@ impl Drop for Poly1305 {
340
341
self . buffer . zeroize ( ) ;
341
342
}
342
343
}
343
-
344
- /// Poly1305 authentication tags
345
- pub struct Tag ( Block ) ;
346
-
347
- impl Tag {
348
- /// Create a new Poly1305 authentication tag
349
- fn new ( tag : Block ) -> Self {
350
- Tag ( tag)
351
- }
352
- }
353
-
354
- impl AsRef < Block > for Tag {
355
- fn as_ref ( & self ) -> & Block {
356
- & self . 0
357
- }
358
- }
359
-
360
- impl ConstantTimeEq for Tag {
361
- fn ct_eq ( & self , other : & Self ) -> Choice {
362
- self . 0 . ct_eq ( other. 0 . as_ref ( ) )
363
- }
364
- }
365
-
366
- impl From < Tag > for Block {
367
- fn from ( tag : Tag ) -> Block {
368
- tag. 0
369
- }
370
- }
0 commit comments