8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use std:: num:: { One , Zero , CheckedAdd } ;
11
+ use std:: num:: { Zero , CheckedAdd } ;
12
12
use std:: vec:: bytes:: { MutableByteVector , copy_memory} ;
13
13
14
14
15
- /// Write a u64 into a vector, which must be 8 bytes long. The value is written in big-endian
16
- /// format.
17
- pub fn write_u64_be ( dst : & mut [ u8 ] , input : u64 ) {
18
- use std:: cast:: transmute;
19
- use std:: unstable:: intrinsics:: to_be64;
20
- assert ! ( dst. len( ) == 8 ) ;
21
- unsafe {
22
- let x: * mut i64 = transmute ( dst. unsafe_mut_ref ( 0 ) ) ;
23
- * x = to_be64 ( input as i64 ) ;
24
- }
25
- }
26
-
27
15
/// Write a u32 into a vector, which must be 4 bytes long. The value is written in big-endian
28
16
/// format.
29
17
pub fn write_u32_be ( dst : & mut [ u8 ] , input : u32 ) {
@@ -36,34 +24,6 @@ pub fn write_u32_be(dst: &mut[u8], input: u32) {
36
24
}
37
25
}
38
26
39
- /// Write a u32 into a vector, which must be 4 bytes long. The value is written in little-endian
40
- /// format.
41
- pub fn write_u32_le ( dst : & mut [ u8 ] , input : u32 ) {
42
- use std:: cast:: transmute;
43
- use std:: unstable:: intrinsics:: to_le32;
44
- assert ! ( dst. len( ) == 4 ) ;
45
- unsafe {
46
- let x: * mut i32 = transmute ( dst. unsafe_mut_ref ( 0 ) ) ;
47
- * x = to_le32 ( input as i32 ) ;
48
- }
49
- }
50
-
51
- /// Read a vector of bytes into a vector of u64s. The values are read in big-endian format.
52
- pub fn read_u64v_be ( dst : & mut [ u64 ] , input : & [ u8 ] ) {
53
- use std:: cast:: transmute;
54
- use std:: unstable:: intrinsics:: to_be64;
55
- assert ! ( dst. len( ) * 8 == input. len( ) ) ;
56
- unsafe {
57
- let mut x: * mut i64 = transmute ( dst. unsafe_mut_ref ( 0 ) ) ;
58
- let mut y: * i64 = transmute ( input. unsafe_ref ( 0 ) ) ;
59
- do dst. len ( ) . times ( ) {
60
- * x = to_be64 ( * y) ;
61
- x = x. offset ( 1 ) ;
62
- y = y. offset ( 1 ) ;
63
- }
64
- }
65
- }
66
-
67
27
/// Read a vector of bytes into a vector of u32s. The values are read in big-endian format.
68
28
pub fn read_u32v_be ( dst : & mut [ u32 ] , input : & [ u8 ] ) {
69
29
use std:: cast:: transmute;
@@ -80,22 +40,6 @@ pub fn read_u32v_be(dst: &mut[u32], input: &[u8]) {
80
40
}
81
41
}
82
42
83
- /// Read a vector of bytes into a vector of u32s. The values are read in little-endian format.
84
- pub fn read_u32v_le ( dst : & mut [ u32 ] , input : & [ u8 ] ) {
85
- use std:: cast:: transmute;
86
- use std:: unstable:: intrinsics:: to_le32;
87
- assert ! ( dst. len( ) * 4 == input. len( ) ) ;
88
- unsafe {
89
- let mut x: * mut i32 = transmute ( dst. unsafe_mut_ref ( 0 ) ) ;
90
- let mut y: * i32 = transmute ( input. unsafe_ref ( 0 ) ) ;
91
- do dst. len ( ) . times ( ) {
92
- * x = to_le32 ( * y) ;
93
- x = x. offset ( 1 ) ;
94
- y = y. offset ( 1 ) ;
95
- }
96
- }
97
- }
98
-
99
43
100
44
trait ToBits {
101
45
/// Convert the value in bytes to the number of bits, a tuple where the 1st item is the
@@ -124,51 +68,6 @@ pub fn add_bytes_to_bits<T: Int + CheckedAdd + ToBits>(bits: T, bytes: T) -> T {
124
68
}
125
69
}
126
70
127
- /// Adds the specified number of bytes to the bit count, which is a tuple where the first element is
128
- /// the high order value. fail!() if this would cause numeric overflow.
129
- pub fn add_bytes_to_bits_tuple
130
- < T : Int + Unsigned + CheckedAdd + ToBits >
131
- ( bits : ( T , T ) , bytes : T ) -> ( T , T ) {
132
- let ( new_high_bits, new_low_bits) = bytes. to_bits ( ) ;
133
- let ( hi, low) = bits;
134
-
135
- // Add the low order value - if there is no overflow, then add the high order values
136
- // If the addition of the low order values causes overflow, add one to the high order values
137
- // before adding them.
138
- match low. checked_add ( & new_low_bits) {
139
- Some ( x) => {
140
- if new_high_bits == Zero :: zero ( ) {
141
- // This is the fast path - every other alternative will rarely occur in practice
142
- // considering how large an input would need to be for those paths to be used.
143
- return ( hi, x) ;
144
- } else {
145
- match hi. checked_add ( & new_high_bits) {
146
- Some ( y) => return ( y, x) ,
147
- None => fail ! ( "Numeric overflow occured." )
148
- }
149
- }
150
- } ,
151
- None => {
152
- let one: T = One :: one ( ) ;
153
- let z = match new_high_bits. checked_add ( & one) {
154
- Some ( w) => w,
155
- None => fail ! ( "Numeric overflow occured." )
156
- } ;
157
- match hi. checked_add ( & z) {
158
- // This re-executes the addition that was already performed earlier when overflow
159
- // occured, this time allowing the overflow to happen. Technically, this could be
160
- // avoided by using the checked add intrinsic directly, but that involves using
161
- // unsafe code and is not really worthwhile considering how infrequently code will
162
- // run in practice. This is the reason that this function requires that the type T
163
- // be Unsigned - overflow is not defined for Signed types. This function could be
164
- // implemented for signed types as well if that were needed.
165
- Some ( y) => return ( y, low + new_low_bits) ,
166
- None => fail ! ( "Numeric overflow occured." )
167
- }
168
- }
169
- }
170
- }
171
-
172
71
173
72
/// A FixedBuffer, likes its name implies, is a fixed size buffer. When the buffer becomes full, it
174
73
/// must be processed. The input() method takes care of processing and then clearing the buffer
@@ -204,83 +103,6 @@ pub trait FixedBuffer {
204
103
fn size ( & self ) -> uint ;
205
104
}
206
105
207
- macro_rules! impl_fixed_buffer( ( $name: ident, $size: expr) => (
208
- impl FixedBuffer for $name {
209
- fn input( & mut self , input: & [ u8 ] , func: & fn ( & [ u8 ] ) ) {
210
- let mut i = 0 ;
211
-
212
- // FIXME: #6304 - This local variable shouldn't be necessary.
213
- let size = $size;
214
-
215
- // If there is already data in the buffer, copy as much as we can into it and process
216
- // the data if the buffer becomes full.
217
- if self . buffer_idx != 0 {
218
- let buffer_remaining = size - self . buffer_idx;
219
- if input. len( ) >= buffer_remaining {
220
- copy_memory(
221
- self . buffer. mut_slice( self . buffer_idx, size) ,
222
- input. slice_to( buffer_remaining) ,
223
- buffer_remaining) ;
224
- self . buffer_idx = 0 ;
225
- func( self . buffer) ;
226
- i += buffer_remaining;
227
- } else {
228
- copy_memory(
229
- self . buffer. mut_slice( self . buffer_idx, self . buffer_idx + input. len( ) ) ,
230
- input,
231
- input. len( ) ) ;
232
- self . buffer_idx += input. len( ) ;
233
- return ;
234
- }
235
- }
236
-
237
- // While we have at least a full buffer size chunks's worth of data, process that data
238
- // without copying it into the buffer
239
- while input. len( ) - i >= size {
240
- func( input. slice( i, i + size) ) ;
241
- i += size;
242
- }
243
-
244
- // Copy any input data into the buffer. At this point in the method, the ammount of
245
- // data left in the input vector will be less than the buffer size and the buffer will
246
- // be empty.
247
- let input_remaining = input. len( ) - i;
248
- copy_memory(
249
- self . buffer. mut_slice( 0 , input_remaining) ,
250
- input. slice_from( i) ,
251
- input. len( ) - i) ;
252
- self . buffer_idx += input_remaining;
253
- }
254
-
255
- fn reset( & mut self ) {
256
- self . buffer_idx = 0 ;
257
- }
258
-
259
- fn zero_until( & mut self , idx: uint) {
260
- assert!( idx >= self . buffer_idx) ;
261
- self . buffer. mut_slice( self . buffer_idx, idx) . set_memory( 0 ) ;
262
- self . buffer_idx = idx;
263
- }
264
-
265
- fn next<' s>( & ' s mut self , len: uint) -> & ' s mut [ u8 ] {
266
- self . buffer_idx += len;
267
- return self . buffer. mut_slice( self . buffer_idx - len, self . buffer_idx) ;
268
- }
269
-
270
- fn full_buffer<' s>( & ' s mut self ) -> & ' s [ u8 ] {
271
- assert!( self . buffer_idx == $size) ;
272
- self . buffer_idx = 0 ;
273
- return self . buffer. slice_to( $size) ;
274
- }
275
-
276
- fn position( & self ) -> uint { self . buffer_idx }
277
-
278
- fn remaining( & self ) -> uint { $size - self . buffer_idx }
279
-
280
- fn size( & self ) -> uint { $size }
281
- }
282
- ) )
283
-
284
106
285
107
/// A fixed size buffer of 64 bytes useful for cryptographic operations.
286
108
pub struct FixedBuffer64 {
@@ -298,25 +120,80 @@ impl FixedBuffer64 {
298
120
}
299
121
}
300
122
301
- impl_fixed_buffer ! ( FixedBuffer64 , 64 )
123
+ impl FixedBuffer for FixedBuffer64 {
124
+ fn input ( & mut self , input : & [ u8 ] , func : & fn ( & [ u8 ] ) ) {
125
+ let mut i = 0 ;
302
126
303
- /// A fixed size buffer of 128 bytes useful for cryptographic operations.
304
- pub struct FixedBuffer128 {
305
- priv buffer : [ u8 , ..128 ] ,
306
- priv buffer_idx : uint ,
307
- }
127
+ // FIXME: #6304 - This local variable shouldn't be necessary.
128
+ let size = 64 ;
308
129
309
- impl FixedBuffer128 {
310
- /// Create a new buffer
311
- pub fn new ( ) -> FixedBuffer128 {
312
- return FixedBuffer128 {
313
- buffer : [ 0u8 , ..128 ] ,
314
- buffer_idx : 0
315
- } ;
130
+ // If there is already data in the buffer, copy as much as we can into it and process
131
+ // the data if the buffer becomes full.
132
+ if self . buffer_idx != 0 {
133
+ let buffer_remaining = size - self . buffer_idx ;
134
+ if input. len ( ) >= buffer_remaining {
135
+ copy_memory (
136
+ self . buffer . mut_slice ( self . buffer_idx , size) ,
137
+ input. slice_to ( buffer_remaining) ,
138
+ buffer_remaining) ;
139
+ self . buffer_idx = 0 ;
140
+ func ( self . buffer ) ;
141
+ i += buffer_remaining;
142
+ } else {
143
+ copy_memory (
144
+ self . buffer . mut_slice ( self . buffer_idx , self . buffer_idx + input. len ( ) ) ,
145
+ input,
146
+ input. len ( ) ) ;
147
+ self . buffer_idx += input. len ( ) ;
148
+ return ;
149
+ }
150
+ }
151
+
152
+ // While we have at least a full buffer size chunks's worth of data, process that data
153
+ // without copying it into the buffer
154
+ while input. len ( ) - i >= size {
155
+ func ( input. slice ( i, i + size) ) ;
156
+ i += size;
157
+ }
158
+
159
+ // Copy any input data into the buffer. At this point in the method, the ammount of
160
+ // data left in the input vector will be less than the buffer size and the buffer will
161
+ // be empty.
162
+ let input_remaining = input. len ( ) - i;
163
+ copy_memory (
164
+ self . buffer . mut_slice ( 0 , input_remaining) ,
165
+ input. slice_from ( i) ,
166
+ input. len ( ) - i) ;
167
+ self . buffer_idx += input_remaining;
168
+ }
169
+
170
+ fn reset ( & mut self ) {
171
+ self . buffer_idx = 0 ;
172
+ }
173
+
174
+ fn zero_until ( & mut self , idx : uint ) {
175
+ assert ! ( idx >= self . buffer_idx) ;
176
+ self . buffer . mut_slice ( self . buffer_idx , idx) . set_memory ( 0 ) ;
177
+ self . buffer_idx = idx;
178
+ }
179
+
180
+ fn next < ' s > ( & ' s mut self , len : uint ) -> & ' s mut [ u8 ] {
181
+ self . buffer_idx += len;
182
+ return self . buffer . mut_slice ( self . buffer_idx - len, self . buffer_idx ) ;
316
183
}
317
- }
318
184
319
- impl_fixed_buffer ! ( FixedBuffer128 , 128 )
185
+ fn full_buffer < ' s > ( & ' s mut self ) -> & ' s [ u8 ] {
186
+ assert ! ( self . buffer_idx == 64 ) ;
187
+ self . buffer_idx = 0 ;
188
+ return self . buffer . slice_to ( 64 ) ;
189
+ }
190
+
191
+ fn position ( & self ) -> uint { self . buffer_idx }
192
+
193
+ fn remaining ( & self ) -> uint { 64 - self . buffer_idx }
194
+
195
+ fn size ( & self ) -> uint { 64 }
196
+ }
320
197
321
198
322
199
/// The StandardPadding trait adds a method useful for various hash algorithms to a FixedBuffer
@@ -351,7 +228,7 @@ pub mod test {
351
228
use std:: vec;
352
229
use extra:: hex:: FromHex ;
353
230
354
- use cryptoutil:: { add_bytes_to_bits, add_bytes_to_bits_tuple } ;
231
+ use cryptoutil:: add_bytes_to_bits;
355
232
use digest:: Digest ;
356
233
357
234
/// Feed 1,000,000 'a's into the digest with varying input sizes and check that the result is
@@ -391,38 +268,4 @@ pub mod test {
391
268
fn test_add_bytes_to_bits_overflow ( ) {
392
269
add_bytes_to_bits :: < u64 > ( Bounded :: max_value ( ) , 1 ) ;
393
270
}
394
-
395
- // A normal addition - no overflow occurs (fast path)
396
- #[ test]
397
- fn test_add_bytes_to_bits_tuple_ok ( ) {
398
- assert ! ( add_bytes_to_bits_tuple:: <u64 >( ( 5 , 100 ) , 10 ) == ( 5 , 180 ) ) ;
399
- }
400
-
401
- // The low order value overflows into the high order value
402
- #[ test]
403
- fn test_add_bytes_to_bits_tuple_ok2 ( ) {
404
- assert ! ( add_bytes_to_bits_tuple:: <u64 >( ( 5 , Bounded :: max_value( ) ) , 1 ) == ( 6 , 7 ) ) ;
405
- }
406
-
407
- // The value to add is too large to be converted into bits without overflowing its type
408
- #[ test]
409
- fn test_add_bytes_to_bits_tuple_ok3 ( ) {
410
- assert ! ( add_bytes_to_bits_tuple:: <u64 >( ( 5 , 0 ) , 0x4000000000000001 ) == ( 7 , 8 ) ) ;
411
- }
412
-
413
- // A simple failure case - adding 1 to the max value
414
- #[ test]
415
- #[ should_fail]
416
- fn test_add_bytes_to_bits_tuple_overflow ( ) {
417
- add_bytes_to_bits_tuple :: < u64 > ( ( Bounded :: max_value ( ) , Bounded :: max_value ( ) ) , 1 ) ;
418
- }
419
-
420
- // The value to add is too large to convert to bytes without overflowing its type, but the high
421
- // order value from this conversion overflows when added to the existing high order value
422
- #[ test]
423
- #[ should_fail]
424
- fn test_add_bytes_to_bits_tuple_overflow2 ( ) {
425
- let value: u64 = Bounded :: max_value ( ) ;
426
- add_bytes_to_bits_tuple :: < u64 > ( ( value - 1 , 0 ) , 0x8000000000000000 ) ;
427
- }
428
271
}
0 commit comments