1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10 
11 /*!
12 An implementation of the SHA-1 cryptographic hash algorithm.
13 
14 To use this module, first create a `Sha1` object using the `Sha1` constructor,
15 then feed it an input message using the `input` or `input_str` methods,
16 which may be called any number of times; they will buffer the input until
17 there is enough to call the block algorithm.
18 
19 After the entire input has been fed to the hash read the result using
20 the `result` or `result_str` methods. The first will return bytes, and
21 the second will return a `String` object of the same bytes represented
22 in hexadecimal form.
23 
24 The `Sha1` object may be reused to create multiple hashes by calling
25 the `reset()` method. These traits are implemented by all hash digest
26 algorithms that implement the `Digest` trait. An example of use is:
27 
28 ```rust
29 use self::crypto::digest::Digest;
30 use self::crypto::sha1::Sha1;
31 
32 // create a Sha1 object
33 let mut hasher = Sha1::new();
34 
35 // write input message
36 hasher.input_str("hello world");
37 
38 // read hash digest
39 let hex = hasher.result_str();
40 
41 assert_eq!(hex, "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed");
42 ```
43 
44 # Mathematics
45 
46 The mathematics of the SHA-1 algorithm are quite interesting. In its
47 definition, The SHA-1 algorithm uses:
48 
49 * 1 binary operation on bit-arrays:
50   * "exclusive or" (XOR)
51 * 2 binary operations on integers:
52   * "addition" (ADD)
53   * "rotate left" (ROL)
54 * 3 ternary operations on bit-arrays:
55   * "choose" (CH)
56   * "parity" (PAR)
57   * "majority" (MAJ)
58 
59 Some of these functions are commonly found in all hash digest
60 algorithms, but some, like "parity" is only found in SHA-1.
61  */
62 
63 use digest::Digest;
64 use cryptoutil::{write_u32_be, read_u32v_be, add_bytes_to_bits, FixedBuffer, FixedBuffer64, StandardPadding};
65 use simd::u32x4;
66 
67 const STATE_LEN: usize = 5;
68 const BLOCK_LEN: usize = 16;
69 
70 const K0: u32 = 0x5A827999u32;
71 const K1: u32 = 0x6ED9EBA1u32;
72 const K2: u32 = 0x8F1BBCDCu32;
73 const K3: u32 = 0xCA62C1D6u32;
74 
75 /// Not an intrinsic, but gets the first element of a vector.
76 #[inline]
sha1_first(w0: u32x4) -> u3277 pub fn sha1_first(w0: u32x4) -> u32 {
78     w0.0
79 }
80 
81 /// Not an intrinsic, but adds a word to the first element of a vector.
82 #[inline]
sha1_first_add(e: u32, w0: u32x4) -> u32x483 pub fn sha1_first_add(e: u32, w0: u32x4) -> u32x4 {
84     let u32x4(a, b, c, d) = w0;
85     u32x4(e.wrapping_add(a), b, c, d)
86 }
87 
88 /// Emulates `llvm.x86.sha1msg1` intrinsic.
sha1msg1(a: u32x4, b: u32x4) -> u32x489 fn sha1msg1(a: u32x4, b: u32x4) -> u32x4 {
90     let u32x4(_, _, w2, w3) = a;
91     let u32x4(w4, w5, _, _) = b;
92     a ^ u32x4(w2, w3, w4, w5)
93 }
94 
95 /// Emulates `llvm.x86.sha1msg2` intrinsic.
sha1msg2(a: u32x4, b: u32x4) -> u32x496 fn sha1msg2(a: u32x4, b: u32x4) -> u32x4 {
97     let u32x4(x0, x1, x2, x3) = a;
98     let u32x4(_, w13, w14, w15) = b;
99 
100     let w16 = (x0 ^ w13).rotate_left(1);
101     let w17 = (x1 ^ w14).rotate_left(1);
102     let w18 = (x2 ^ w15).rotate_left(1);
103     let w19 = (x3 ^ w16).rotate_left(1);
104 
105     u32x4(w16, w17, w18, w19)
106 }
107 
108 /// Performs 4 rounds of the message schedule update.
sha1_schedule_x4(v0: u32x4, v1: u32x4, v2: u32x4, v3: u32x4) -> u32x4109 pub fn sha1_schedule_x4(v0: u32x4, v1: u32x4, v2: u32x4, v3: u32x4) -> u32x4 {
110     sha1msg2(sha1msg1(v0, v1) ^ v2, v3)
111 }
112 
113 /// Emulates `llvm.x86.sha1nexte` intrinsic.
114 #[inline]
sha1_first_half(abcd: u32x4, msg: u32x4) -> u32x4115 pub fn sha1_first_half(abcd: u32x4, msg: u32x4) -> u32x4 {
116     sha1_first_add(sha1_first(abcd).rotate_left(30), msg)
117 }
118 
119 /// Emulates `llvm.x86.sha1rnds4` intrinsic.
120 /// Performs 4 rounds of the message block digest.
sha1_digest_round_x4(abcd: u32x4, work: u32x4, i: i8) -> u32x4121 pub fn sha1_digest_round_x4(abcd: u32x4, work: u32x4, i: i8) -> u32x4 {
122     const K0V: u32x4 = u32x4(K0, K0, K0, K0);
123     const K1V: u32x4 = u32x4(K1, K1, K1, K1);
124     const K2V: u32x4 = u32x4(K2, K2, K2, K2);
125     const K3V: u32x4 = u32x4(K3, K3, K3, K3);
126 
127     match i {
128         0 => sha1rnds4c(abcd, work + K0V),
129         1 => sha1rnds4p(abcd, work + K1V),
130         2 => sha1rnds4m(abcd, work + K2V),
131         3 => sha1rnds4p(abcd, work + K3V),
132         _ => panic!("unknown icosaround index")
133     }
134 }
135 
136 /// Not an intrinsic, but helps emulate `llvm.x86.sha1rnds4` intrinsic.
sha1rnds4c(abcd: u32x4, msg: u32x4) -> u32x4137 fn sha1rnds4c(abcd: u32x4, msg: u32x4) -> u32x4 {
138     let u32x4(mut a, mut b, mut c, mut d) = abcd;
139     let u32x4(t, u, v, w) = msg;
140     let mut e = 0u32;
141 
142     macro_rules! bool3ary_202 {
143         ($a:expr, $b:expr, $c:expr) => (($c ^ ($a & ($b ^ $c))))
144     } // Choose, MD5F, SHA1C
145 
146     e = e.wrapping_add(a.rotate_left(5)).wrapping_add(bool3ary_202!(b, c, d)).wrapping_add(t);
147     b = b.rotate_left(30);
148 
149     d = d.wrapping_add(e.rotate_left(5)).wrapping_add(bool3ary_202!(a, b, c)).wrapping_add(u);
150     a = a.rotate_left(30);
151 
152     c = c.wrapping_add(d.rotate_left(5)).wrapping_add(bool3ary_202!(e, a, b)).wrapping_add(v);
153     e = e.rotate_left(30);
154 
155     b = b.wrapping_add(c.rotate_left(5)).wrapping_add(bool3ary_202!(d, e, a)).wrapping_add(w);
156     d = d.rotate_left(30);
157 
158     u32x4(b, c, d, e)
159 }
160 
161 /// Not an intrinsic, but helps emulate `llvm.x86.sha1rnds4` intrinsic.
sha1rnds4p(abcd: u32x4, msg: u32x4) -> u32x4162 fn sha1rnds4p(abcd: u32x4, msg: u32x4) -> u32x4 {
163     let u32x4(mut a, mut b, mut c, mut d) = abcd;
164     let u32x4(t, u, v, w) = msg;
165     let mut e = 0u32;
166 
167     macro_rules! bool3ary_150 {
168         ($a:expr, $b:expr, $c:expr) => (($a ^ $b ^ $c))
169     } // Parity, XOR, MD5H, SHA1P
170 
171     e = e.wrapping_add(a.rotate_left(5)).wrapping_add(bool3ary_150!(b, c, d)).wrapping_add(t);
172     b = b.rotate_left(30);
173 
174     d = d.wrapping_add(e.rotate_left(5)).wrapping_add(bool3ary_150!(a, b, c)).wrapping_add(u);
175     a = a.rotate_left(30);
176 
177     c = c.wrapping_add(d.rotate_left(5)).wrapping_add(bool3ary_150!(e, a, b)).wrapping_add(v);
178     e = e.rotate_left(30);
179 
180     b = b.wrapping_add(c.rotate_left(5)).wrapping_add(bool3ary_150!(d, e, a)).wrapping_add(w);
181     d = d.rotate_left(30);
182 
183     u32x4(b, c, d, e)
184 }
185 
186 /// Not an intrinsic, but helps emulate `llvm.x86.sha1rnds4` intrinsic.
sha1rnds4m(abcd: u32x4, msg: u32x4) -> u32x4187 fn sha1rnds4m(abcd: u32x4, msg: u32x4) -> u32x4 {
188     let u32x4(mut a, mut b, mut c, mut d) = abcd;
189     let u32x4(t, u, v, w) = msg;
190     let mut e = 0u32;
191 
192     macro_rules! bool3ary_232 {
193         ($a:expr, $b:expr, $c:expr) => (($a & $b) ^ ($a & $c) ^ ($b & $c))
194     } // Majority, SHA1M
195 
196     e = e.wrapping_add(a.rotate_left(5)).wrapping_add(bool3ary_232!(b, c, d)).wrapping_add(t);
197     b = b.rotate_left(30);
198 
199     d = d.wrapping_add(e.rotate_left(5)).wrapping_add(bool3ary_232!(a, b, c)).wrapping_add(u);
200     a = a.rotate_left(30);
201 
202     c = c.wrapping_add(d.rotate_left(5)).wrapping_add(bool3ary_232!(e, a, b)).wrapping_add(v);
203     e = e.rotate_left(30);
204 
205     b = b.wrapping_add(c.rotate_left(5)).wrapping_add(bool3ary_232!(d, e, a)).wrapping_add(w);
206     d = d.rotate_left(30);
207 
208     u32x4(b, c, d, e)
209 }
210 
211 /// Process a block with the SHA-1 algorithm.
sha1_digest_block_u32(state: &mut [u32; 5], block: &[u32; 16])212 pub fn sha1_digest_block_u32(state: &mut [u32; 5], block: &[u32; 16]) {
213 
214     macro_rules! schedule {
215         ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => (
216             sha1msg2(sha1msg1($v0, $v1) ^ $v2, $v3)
217         )
218     }
219 
220     macro_rules! rounds4 {
221         ($h0:ident, $h1:ident, $wk:expr, $i:expr) => (
222             sha1_digest_round_x4($h0, sha1_first_half($h1, $wk), $i)
223         )
224     }
225 
226     // Rounds 0..20
227     let mut h0 = u32x4(state[0],
228                        state[1],
229                        state[2],
230                        state[3]);
231     let mut w0 = u32x4(block[0],
232                        block[1],
233                        block[2],
234                        block[3]);
235     let mut h1 = sha1_digest_round_x4(h0, sha1_first_add(state[4], w0), 0);
236     let mut w1 = u32x4(block[4],
237                        block[5],
238                        block[6],
239                        block[7]);
240     h0 = rounds4!(h1, h0, w1, 0);
241     let mut w2 = u32x4(block[8],
242                        block[9],
243                        block[10],
244                        block[11]);
245     h1 = rounds4!(h0, h1, w2, 0);
246     let mut w3 = u32x4(block[12],
247                        block[13],
248                        block[14],
249                        block[15]);
250     h0 = rounds4!(h1, h0, w3, 0);
251     let mut w4 = schedule!(w0, w1, w2, w3);
252     h1 = rounds4!(h0, h1, w4, 0);
253 
254     // Rounds 20..40
255     w0 = schedule!(w1, w2, w3, w4);
256     h0 = rounds4!(h1, h0, w0, 1);
257     w1 = schedule!(w2, w3, w4, w0);
258     h1 = rounds4!(h0, h1, w1, 1);
259     w2 = schedule!(w3, w4, w0, w1);
260     h0 = rounds4!(h1, h0, w2, 1);
261     w3 = schedule!(w4, w0, w1, w2);
262     h1 = rounds4!(h0, h1, w3, 1);
263     w4 = schedule!(w0, w1, w2, w3);
264     h0 = rounds4!(h1, h0, w4, 1);
265 
266     // Rounds 40..60
267     w0 = schedule!(w1, w2, w3, w4);
268     h1 = rounds4!(h0, h1, w0, 2);
269     w1 = schedule!(w2, w3, w4, w0);
270     h0 = rounds4!(h1, h0, w1, 2);
271     w2 = schedule!(w3, w4, w0, w1);
272     h1 = rounds4!(h0, h1, w2, 2);
273     w3 = schedule!(w4, w0, w1, w2);
274     h0 = rounds4!(h1, h0, w3, 2);
275     w4 = schedule!(w0, w1, w2, w3);
276     h1 = rounds4!(h0, h1, w4, 2);
277 
278     // Rounds 60..80
279     w0 = schedule!(w1, w2, w3, w4);
280     h0 = rounds4!(h1, h0, w0, 3);
281     w1 = schedule!(w2, w3, w4, w0);
282     h1 = rounds4!(h0, h1, w1, 3);
283     w2 = schedule!(w3, w4, w0, w1);
284     h0 = rounds4!(h1, h0, w2, 3);
285     w3 = schedule!(w4, w0, w1, w2);
286     h1 = rounds4!(h0, h1, w3, 3);
287     w4 = schedule!(w0, w1, w2, w3);
288     h0 = rounds4!(h1, h0, w4, 3);
289 
290     let e = sha1_first(h1).rotate_left(30);
291     let u32x4(a, b, c, d) = h0;
292 
293     state[0] = state[0].wrapping_add(a);
294     state[1] = state[1].wrapping_add(b);
295     state[2] = state[2].wrapping_add(c);
296     state[3] = state[3].wrapping_add(d);
297     state[4] = state[4].wrapping_add(e);
298 }
299 
300 /// Process a block with the SHA-1 algorithm. (See more...)
301 ///
302 /// SHA-1 is a cryptographic hash function, and as such, it operates
303 /// on an arbitrary number of bytes. This function operates on a fixed
304 /// number of bytes. If you call this function with anything other than
305 /// 64 bytes, then it will panic! This function takes two arguments:
306 ///
307 /// * `state` is reference to an **array** of 5 words.
308 /// * `block` is reference to a **slice** of 64 bytes.
309 ///
310 /// If you want the function that performs a message digest on an arbitrary
311 /// number of bytes, then see also the `Sha1` struct above.
312 ///
313 /// # Implementation
314 ///
315 /// First, some background. Both ARM and Intel are releasing documentation
316 /// that they plan to include instruction set extensions for SHA1 and SHA256
317 /// sometime in the near future. Second, LLVM won't lower these intrinsics yet,
318 /// so these functions were written emulate these instructions. Finally,
319 /// the block function implemented with these emulated intrinsics turned out
320 /// to be quite fast! What follows is a discussion of this CPU-level view
321 /// of the SHA-1 algorithm and how it relates to the mathematical definition.
322 ///
323 /// The SHA instruction set extensions can be divided up into two categories:
324 ///
325 /// * message work schedule update calculation ("schedule" v., "work" n.)
326 /// * message block 80-round digest calculation ("digest" v., "block" n.)
327 ///
328 /// The schedule-related functions can be used to easily perform 4 rounds
329 /// of the message work schedule update calculation, as shown below:
330 ///
331 /// ```ignore
332 /// macro_rules! schedule_x4 {
333 ///     ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => (
334 ///         sha1msg2(sha1msg1($v0, $v1) ^ $v2, $v3)
335 ///     )
336 /// }
337 ///
338 /// macro_rules! round_x4 {
339 ///     ($h0:ident, $h1:ident, $wk:expr, $i:expr) => (
340 ///         sha1rnds4($h0, sha1_first_half($h1, $wk), $i)
341 ///     )
342 /// }
343 /// ```
344 ///
345 /// and also shown above is how the digest-related functions can be used to
346 /// perform 4 rounds of the message block digest calculation.
347 ///
sha1_digest_block(state: &mut [u32; 5], block: &[u8 ])348 pub fn sha1_digest_block(state: &mut [u32; 5], block: &[u8/*; 64*/]) {
349     assert_eq!(block.len(), BLOCK_LEN*4);
350     let mut block2 = [0u32; BLOCK_LEN];
351     read_u32v_be(&mut block2[..], block);
352     sha1_digest_block_u32(state, &block2);
353 }
354 
add_input(st: &mut Sha1, msg: &[u8])355 fn add_input(st: &mut Sha1, msg: &[u8]) {
356     assert!((!st.computed));
357     // Assumes that msg.len() can be converted to u64 without overflow
358     st.length_bits = add_bytes_to_bits(st.length_bits, msg.len() as u64);
359     let st_h = &mut st.h;
360     st.buffer.input(msg, |d: &[u8]| { sha1_digest_block(st_h, d); });
361 }
362 
mk_result(st: &mut Sha1, rs: &mut [u8])363 fn mk_result(st: &mut Sha1, rs: &mut [u8]) {
364     if !st.computed {
365         let st_h = &mut st.h;
366         st.buffer.standard_padding(8, |d: &[u8]| { sha1_digest_block(&mut *st_h, d) });
367         write_u32_be(st.buffer.next(4), (st.length_bits >> 32) as u32 );
368         write_u32_be(st.buffer.next(4), st.length_bits as u32);
369         sha1_digest_block(st_h, st.buffer.full_buffer());
370 
371         st.computed = true;
372     }
373 
374     write_u32_be(&mut rs[0..4], st.h[0]);
375     write_u32_be(&mut rs[4..8], st.h[1]);
376     write_u32_be(&mut rs[8..12], st.h[2]);
377     write_u32_be(&mut rs[12..16], st.h[3]);
378     write_u32_be(&mut rs[16..20], st.h[4]);
379 }
380 
381 /// Structure representing the state of a Sha1 computation
382 #[derive(Clone, Copy)]
383 pub struct Sha1 {
384     h: [u32; STATE_LEN],
385     length_bits: u64,
386     buffer: FixedBuffer64,
387     computed: bool,
388 }
389 
390 impl Sha1 {
391     /// Construct a `sha` object
new() -> Sha1392     pub fn new() -> Sha1 {
393         let mut st = Sha1 {
394             h: [0u32; STATE_LEN],
395             length_bits: 0u64,
396             buffer: FixedBuffer64::new(),
397             computed: false,
398         };
399         st.reset();
400         st
401     }
402 }
403 
404 impl Digest for Sha1 {
reset(&mut self)405     fn reset(&mut self) {
406         self.length_bits = 0;
407         self.h[0] = 0x67452301u32;
408         self.h[1] = 0xEFCDAB89u32;
409         self.h[2] = 0x98BADCFEu32;
410         self.h[3] = 0x10325476u32;
411         self.h[4] = 0xC3D2E1F0u32;
412         self.buffer.reset();
413         self.computed = false;
414     }
input(&mut self, msg: &[u8])415     fn input(&mut self, msg: &[u8]) { add_input(self, msg); }
result(&mut self, out: &mut [u8])416     fn result(&mut self, out: &mut [u8]) { mk_result(self, out) }
output_bits(&self) -> usize417     fn output_bits(&self) -> usize { 160 }
block_size(&self) -> usize418     fn block_size(&self) -> usize { 64 }
419 }
420 
421 #[cfg(test)]
422 mod tests {
423     use cryptoutil::test::test_digest_1million_random;
424     use digest::Digest;
425     use sha1::Sha1;
426 
427     #[derive(Clone)]
428     struct Test {
429         input: &'static str,
430         output: Vec<u8>,
431         output_str: &'static str,
432     }
433 
434     #[test]
test()435     fn test() {
436         let tests = vec![
437             // Test messages from FIPS 180-1
438             Test {
439                 input: "abc",
440                 output: vec![
441                     0xA9u8, 0x99u8, 0x3Eu8, 0x36u8,
442                     0x47u8, 0x06u8, 0x81u8, 0x6Au8,
443                     0xBAu8, 0x3Eu8, 0x25u8, 0x71u8,
444                     0x78u8, 0x50u8, 0xC2u8, 0x6Cu8,
445                     0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8,
446                 ],
447                 output_str: "a9993e364706816aba3e25717850c26c9cd0d89d"
448             },
449             Test {
450                 input:
451                      "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
452                 output: vec![
453                     0x84u8, 0x98u8, 0x3Eu8, 0x44u8,
454                     0x1Cu8, 0x3Bu8, 0xD2u8, 0x6Eu8,
455                     0xBAu8, 0xAEu8, 0x4Au8, 0xA1u8,
456                     0xF9u8, 0x51u8, 0x29u8, 0xE5u8,
457                     0xE5u8, 0x46u8, 0x70u8, 0xF1u8,
458                 ],
459                 output_str: "84983e441c3bd26ebaae4aa1f95129e5e54670f1"
460             },
461             // Examples from wikipedia
462             Test {
463                 input: "The quick brown fox jumps over the lazy dog",
464                 output: vec![
465                     0x2fu8, 0xd4u8, 0xe1u8, 0xc6u8,
466                     0x7au8, 0x2du8, 0x28u8, 0xfcu8,
467                     0xedu8, 0x84u8, 0x9eu8, 0xe1u8,
468                     0xbbu8, 0x76u8, 0xe7u8, 0x39u8,
469                     0x1bu8, 0x93u8, 0xebu8, 0x12u8,
470                 ],
471                 output_str: "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12",
472             },
473             Test {
474                 input: "The quick brown fox jumps over the lazy cog",
475                 output: vec![
476                     0xdeu8, 0x9fu8, 0x2cu8, 0x7fu8,
477                     0xd2u8, 0x5eu8, 0x1bu8, 0x3au8,
478                     0xfau8, 0xd3u8, 0xe8u8, 0x5au8,
479                     0x0bu8, 0xd1u8, 0x7du8, 0x9bu8,
480                     0x10u8, 0x0du8, 0xb4u8, 0xb3u8,
481                 ],
482                 output_str: "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3",
483             },
484         ];
485 
486         // Test that it works when accepting the message all at once
487 
488         let mut out = [0u8; 20];
489 
490         let mut sh = Box::new(Sha1::new());
491         for t in tests.iter() {
492             (*sh).input_str(t.input);
493             sh.result(&mut out);
494             assert!(t.output[..] == out[..]);
495 
496             let out_str = (*sh).result_str();
497             assert_eq!(out_str.len(), 40);
498             assert!(&out_str[..] == t.output_str);
499 
500             sh.reset();
501         }
502 
503 
504         // Test that it works when accepting the message in pieces
505         for t in tests.iter() {
506             let len = t.input.len();
507             let mut left = len;
508             while left > 0 {
509                 let take = (left + 1) / 2;
510                 (*sh).input_str(&t.input[len - left..take + len - left]);
511                 left = left - take;
512             }
513             sh.result(&mut out);
514             assert!(t.output[..] == out[..]);
515 
516             let out_str = (*sh).result_str();
517             assert_eq!(out_str.len(), 40);
518             assert!(&out_str[..] == t.output_str);
519 
520             sh.reset();
521         }
522     }
523 
524     #[test]
test_1million_random_sha1()525     fn test_1million_random_sha1() {
526         let mut sh = Sha1::new();
527         test_digest_1million_random(
528             &mut sh,
529             64,
530             "34aa973cd4c4daa4f61eeb2bdbad27316534016f");
531     }
532 }
533 
534 #[cfg(all(test, feature = "with-bench"))]
535 mod bench {
536     use test::Bencher;
537     use digest::Digest;
538     use sha1::{STATE_LEN, BLOCK_LEN};
539     use sha1::{Sha1, sha1_digest_block_u32};
540 
541     #[bench]
sha1_block(bh: & mut Bencher)542     pub fn sha1_block(bh: & mut Bencher) {
543         let mut state = [0u32; STATE_LEN];
544         let words = [1u32; BLOCK_LEN];
545         bh.iter( || {
546             sha1_digest_block_u32(&mut state, &words);
547         });
548         bh.bytes = 64u64;
549     }
550 
551     #[bench]
sha1_10(bh: & mut Bencher)552     pub fn sha1_10(bh: & mut Bencher) {
553         let mut sh = Sha1::new();
554         let bytes = [1u8; 10];
555         bh.iter( || {
556             sh.input(&bytes);
557         });
558         bh.bytes = bytes.len() as u64;
559     }
560 
561     #[bench]
sha1_1k(bh: & mut Bencher)562     pub fn sha1_1k(bh: & mut Bencher) {
563         let mut sh = Sha1::new();
564         let bytes = [1u8; 1024];
565         bh.iter( || {
566             sh.input(&bytes);
567         });
568         bh.bytes = bytes.len() as u64;
569     }
570 
571     #[bench]
sha1_64k(bh: & mut Bencher)572     pub fn sha1_64k(bh: & mut Bencher) {
573         let mut sh = Sha1::new();
574         let bytes = [1u8; 65536];
575         bh.iter( || {
576             sh.input(&bytes);
577         });
578         bh.bytes = bytes.len() as u64;
579     }
580 
581 }
582