]> git.lizzy.rs Git - rust.git/blob - src/librustc_back/sha2.rs
Auto merge of #23678 - richo:check-flightcheck, r=alexcrichton
[rust.git] / src / librustc_back / sha2.rs
1 // Copyright 2012-2014 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 //! This module implements only the Sha256 function since that is all that is needed for internal
12 //! use. This implementation is not intended for external use or for any use where security is
13 //! important.
14
15 #![allow(deprecated)] // to_be32
16
17 use std::iter::{range_step, repeat};
18 use std::num::Int;
19 use std::slice::bytes::{MutableByteVector, copy_memory};
20 use serialize::hex::ToHex;
21
22 /// Write a u32 into a vector, which must be 4 bytes long. The value is written in big-endian
23 /// format.
24 fn write_u32_be(dst: &mut[u8], input: u32) {
25     dst[0] = (input >> 24) as u8;
26     dst[1] = (input >> 16) as u8;
27     dst[2] = (input >> 8) as u8;
28     dst[3] = input as u8;
29 }
30
31 /// Read the value of a vector of bytes as a u32 value in big-endian format.
32 fn read_u32_be(input: &[u8]) -> u32 {
33     return
34         (input[0] as u32) << 24 |
35         (input[1] as u32) << 16 |
36         (input[2] as u32) << 8 |
37         (input[3] as u32);
38 }
39
40 /// Read a vector of bytes into a vector of u32s. The values are read in big-endian format.
41 fn read_u32v_be(dst: &mut[u32], input: &[u8]) {
42     assert!(dst.len() * 4 == input.len());
43     let mut pos = 0;
44     for chunk in input.chunks(4) {
45         dst[pos] = read_u32_be(chunk);
46         pos += 1;
47     }
48 }
49
50 trait ToBits {
51     /// Convert the value in bytes to the number of bits, a tuple where the 1st item is the
52     /// high-order value and the 2nd item is the low order value.
53     fn to_bits(self) -> (Self, Self);
54 }
55
56 impl ToBits for u64 {
57     fn to_bits(self) -> (u64, u64) {
58         return (self >> 61, self << 3);
59     }
60 }
61
62 /// Adds the specified number of bytes to the bit count. panic!() if this would cause numeric
63 /// overflow.
64 fn add_bytes_to_bits<T: Int + ToBits>(bits: T, bytes: T) -> T {
65     let (new_high_bits, new_low_bits) = bytes.to_bits();
66
67     if new_high_bits > T::zero() {
68         panic!("numeric overflow occurred.")
69     }
70
71     match bits.checked_add(new_low_bits) {
72         Some(x) => return x,
73         None => panic!("numeric overflow occurred.")
74     }
75 }
76
77 /// A FixedBuffer, likes its name implies, is a fixed size buffer. When the buffer becomes full, it
78 /// must be processed. The input() method takes care of processing and then clearing the buffer
79 /// automatically. However, other methods do not and require the caller to process the buffer. Any
80 /// method that modifies the buffer directory or provides the caller with bytes that can be modified
81 /// results in those bytes being marked as used by the buffer.
82 trait FixedBuffer {
83     /// Input a vector of bytes. If the buffer becomes full, process it with the provided
84     /// function and then clear the buffer.
85     fn input<F>(&mut self, input: &[u8], func: F) where
86         F: FnMut(&[u8]);
87
88     /// Reset the buffer.
89     fn reset(&mut self);
90
91     /// Zero the buffer up until the specified index. The buffer position currently must not be
92     /// greater than that index.
93     fn zero_until(&mut self, idx: usize);
94
95     /// Get a slice of the buffer of the specified size. There must be at least that many bytes
96     /// remaining in the buffer.
97     fn next<'s>(&'s mut self, len: usize) -> &'s mut [u8];
98
99     /// Get the current buffer. The buffer must already be full. This clears the buffer as well.
100     fn full_buffer<'s>(&'s mut self) -> &'s [u8];
101
102     /// Get the current position of the buffer.
103     fn position(&self) -> usize;
104
105     /// Get the number of bytes remaining in the buffer until it is full.
106     fn remaining(&self) -> usize;
107
108     /// Get the size of the buffer
109     fn size(&self) -> usize;
110 }
111
112 /// A FixedBuffer of 64 bytes useful for implementing Sha256 which has a 64 byte blocksize.
113 struct FixedBuffer64 {
114     buffer: [u8; 64],
115     buffer_idx: usize,
116 }
117
118 impl FixedBuffer64 {
119     /// Create a new FixedBuffer64
120     fn new() -> FixedBuffer64 {
121         return FixedBuffer64 {
122             buffer: [0; 64],
123             buffer_idx: 0
124         };
125     }
126 }
127
128 impl FixedBuffer for FixedBuffer64 {
129     fn input<F>(&mut self, input: &[u8], mut func: F) where
130         F: FnMut(&[u8]),
131     {
132         let mut i = 0;
133
134         let size = self.size();
135
136         // If there is already data in the buffer, copy as much as we can into it and process
137         // the data if the buffer becomes full.
138         if self.buffer_idx != 0 {
139             let buffer_remaining = size - self.buffer_idx;
140             if input.len() >= buffer_remaining {
141                     copy_memory(
142                         &input[..buffer_remaining],
143                         &mut self.buffer[self.buffer_idx..size]);
144                 self.buffer_idx = 0;
145                 func(&self.buffer);
146                 i += buffer_remaining;
147             } else {
148                 copy_memory(
149                     input,
150                     &mut self.buffer[self.buffer_idx..self.buffer_idx + input.len()]);
151                 self.buffer_idx += input.len();
152                 return;
153             }
154         }
155
156         // While we have at least a full buffer size chunk's worth of data, process that data
157         // without copying it into the buffer
158         while input.len() - i >= size {
159             func(&input[i..i + size]);
160             i += size;
161         }
162
163         // Copy any input data into the buffer. At this point in the method, the amount of
164         // data left in the input vector will be less than the buffer size and the buffer will
165         // be empty.
166         let input_remaining = input.len() - i;
167         copy_memory(
168             &input[i..],
169             &mut self.buffer[..input_remaining]);
170         self.buffer_idx += input_remaining;
171     }
172
173     fn reset(&mut self) {
174         self.buffer_idx = 0;
175     }
176
177     fn zero_until(&mut self, idx: usize) {
178         assert!(idx >= self.buffer_idx);
179         self.buffer[self.buffer_idx..idx].set_memory(0);
180         self.buffer_idx = idx;
181     }
182
183     fn next<'s>(&'s mut self, len: usize) -> &'s mut [u8] {
184         self.buffer_idx += len;
185         return &mut self.buffer[self.buffer_idx - len..self.buffer_idx];
186     }
187
188     fn full_buffer<'s>(&'s mut self) -> &'s [u8] {
189         assert!(self.buffer_idx == 64);
190         self.buffer_idx = 0;
191         return &self.buffer[..64];
192     }
193
194     fn position(&self) -> usize { self.buffer_idx }
195
196     fn remaining(&self) -> usize { 64 - self.buffer_idx }
197
198     fn size(&self) -> usize { 64 }
199 }
200
201 /// The StandardPadding trait adds a method useful for Sha256 to a FixedBuffer struct.
202 trait StandardPadding {
203     /// Add padding to the buffer. The buffer must not be full when this method is called and is
204     /// guaranteed to have exactly rem remaining bytes when it returns. If there are not at least
205     /// rem bytes available, the buffer will be zero padded, processed, cleared, and then filled
206     /// with zeros again until only rem bytes are remaining.
207     fn standard_padding<F>(&mut self, rem: usize, func: F) where F: FnMut(&[u8]);
208 }
209
210 impl <T: FixedBuffer> StandardPadding for T {
211     fn standard_padding<F>(&mut self, rem: usize, mut func: F) where F: FnMut(&[u8]) {
212         let size = self.size();
213
214         self.next(1)[0] = 128;
215
216         if self.remaining() < rem {
217             self.zero_until(size);
218             func(self.full_buffer());
219         }
220
221         self.zero_until(size - rem);
222     }
223 }
224
225 /// The Digest trait specifies an interface common to digest functions, such as SHA-1 and the SHA-2
226 /// family of digest functions.
227 pub trait Digest {
228     /// Provide message data.
229     ///
230     /// # Arguments
231     ///
232     /// * input - A vector of message data
233     fn input(&mut self, input: &[u8]);
234
235     /// Retrieve the digest result. This method may be called multiple times.
236     ///
237     /// # Arguments
238     ///
239     /// * out - the vector to hold the result. Must be large enough to contain output_bits().
240     fn result(&mut self, out: &mut [u8]);
241
242     /// Reset the digest. This method must be called after result() and before supplying more
243     /// data.
244     fn reset(&mut self);
245
246     /// Get the output size in bits.
247     fn output_bits(&self) -> usize;
248
249     /// Convenience function that feeds a string into a digest.
250     ///
251     /// # Arguments
252     ///
253     /// * `input` The string to feed into the digest
254     fn input_str(&mut self, input: &str) {
255         self.input(input.as_bytes());
256     }
257
258     /// Convenience function that retrieves the result of a digest as a
259     /// newly allocated vec of bytes.
260     fn result_bytes(&mut self) -> Vec<u8> {
261         let mut buf: Vec<u8> = repeat(0).take((self.output_bits()+7)/8).collect();
262         self.result(&mut buf);
263         buf
264     }
265
266     /// Convenience function that retrieves the result of a digest as a
267     /// String in hexadecimal format.
268     fn result_str(&mut self) -> String {
269         self.result_bytes().to_hex().to_string()
270     }
271 }
272
273 // A structure that represents that state of a digest computation for the SHA-2 512 family of digest
274 // functions
275 struct Engine256State {
276     h0: u32,
277     h1: u32,
278     h2: u32,
279     h3: u32,
280     h4: u32,
281     h5: u32,
282     h6: u32,
283     h7: u32,
284 }
285
286 impl Engine256State {
287     fn new(h: &[u32; 8]) -> Engine256State {
288         return Engine256State {
289             h0: h[0],
290             h1: h[1],
291             h2: h[2],
292             h3: h[3],
293             h4: h[4],
294             h5: h[5],
295             h6: h[6],
296             h7: h[7]
297         };
298     }
299
300     fn reset(&mut self, h: &[u32; 8]) {
301         self.h0 = h[0];
302         self.h1 = h[1];
303         self.h2 = h[2];
304         self.h3 = h[3];
305         self.h4 = h[4];
306         self.h5 = h[5];
307         self.h6 = h[6];
308         self.h7 = h[7];
309     }
310
311     fn process_block(&mut self, data: &[u8]) {
312         fn ch(x: u32, y: u32, z: u32) -> u32 {
313             ((x & y) ^ ((!x) & z))
314         }
315
316         fn maj(x: u32, y: u32, z: u32) -> u32 {
317             ((x & y) ^ (x & z) ^ (y & z))
318         }
319
320         fn sum0(x: u32) -> u32 {
321             ((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10))
322         }
323
324         fn sum1(x: u32) -> u32 {
325             ((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7))
326         }
327
328         fn sigma0(x: u32) -> u32 {
329             ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3)
330         }
331
332         fn sigma1(x: u32) -> u32 {
333             ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10)
334         }
335
336         let mut a = self.h0;
337         let mut b = self.h1;
338         let mut c = self.h2;
339         let mut d = self.h3;
340         let mut e = self.h4;
341         let mut f = self.h5;
342         let mut g = self.h6;
343         let mut h = self.h7;
344
345         let mut w = [0; 64];
346
347         // Sha-512 and Sha-256 use basically the same calculations which are implemented
348         // by these macros. Inlining the calculations seems to result in better generated code.
349         macro_rules! schedule_round { ($t:expr) => (
350             w[$t] = sigma1(w[$t - 2]).wrapping_add(w[$t - 7])
351                 .wrapping_add(sigma0(w[$t - 15])).wrapping_add(w[$t - 16]);
352             )
353         }
354
355         macro_rules! sha2_round {
356             ($A:ident, $B:ident, $C:ident, $D:ident,
357              $E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => (
358                 {
359                     $H = $H.wrapping_add(sum1($E)).wrapping_add(ch($E, $F, $G))
360                         .wrapping_add($K[$t]).wrapping_add(w[$t]);
361                     $D = $D.wrapping_add($H);
362                     $H = $H.wrapping_add(sum0($A)).wrapping_add(maj($A, $B, $C));
363                 }
364              )
365         }
366
367         read_u32v_be(&mut w[0..16], data);
368
369         // Putting the message schedule inside the same loop as the round calculations allows for
370         // the compiler to generate better code.
371         for t in range_step(0, 48, 8) {
372             schedule_round!(t + 16);
373             schedule_round!(t + 17);
374             schedule_round!(t + 18);
375             schedule_round!(t + 19);
376             schedule_round!(t + 20);
377             schedule_round!(t + 21);
378             schedule_round!(t + 22);
379             schedule_round!(t + 23);
380
381             sha2_round!(a, b, c, d, e, f, g, h, K32, t);
382             sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1);
383             sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2);
384             sha2_round!(f, g, h, a, b, c, d, e, K32, t + 3);
385             sha2_round!(e, f, g, h, a, b, c, d, K32, t + 4);
386             sha2_round!(d, e, f, g, h, a, b, c, K32, t + 5);
387             sha2_round!(c, d, e, f, g, h, a, b, K32, t + 6);
388             sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
389         }
390
391         for t in range_step(48, 64, 8) {
392             sha2_round!(a, b, c, d, e, f, g, h, K32, t);
393             sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1);
394             sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2);
395             sha2_round!(f, g, h, a, b, c, d, e, K32, t + 3);
396             sha2_round!(e, f, g, h, a, b, c, d, K32, t + 4);
397             sha2_round!(d, e, f, g, h, a, b, c, K32, t + 5);
398             sha2_round!(c, d, e, f, g, h, a, b, K32, t + 6);
399             sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
400         }
401
402         self.h0 = self.h0.wrapping_add(a);
403         self.h1 = self.h1.wrapping_add(b);
404         self.h2 = self.h2.wrapping_add(c);
405         self.h3 = self.h3.wrapping_add(d);
406         self.h4 = self.h4.wrapping_add(e);
407         self.h5 = self.h5.wrapping_add(f);
408         self.h6 = self.h6.wrapping_add(g);
409         self.h7 = self.h7.wrapping_add(h);
410     }
411 }
412
413 static K32: [u32; 64] = [
414     0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
415     0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
416     0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
417     0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
418     0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
419     0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
420     0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
421     0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
422     0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
423     0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
424     0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
425     0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
426     0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
427     0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
428     0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
429     0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
430 ];
431
432 // A structure that keeps track of the state of the Sha-256 operation and contains the logic
433 // necessary to perform the final calculations.
434 struct Engine256 {
435     length_bits: u64,
436     buffer: FixedBuffer64,
437     state: Engine256State,
438     finished: bool,
439 }
440
441 impl Engine256 {
442     fn new(h: &[u32; 8]) -> Engine256 {
443         return Engine256 {
444             length_bits: 0,
445             buffer: FixedBuffer64::new(),
446             state: Engine256State::new(h),
447             finished: false
448         }
449     }
450
451     fn reset(&mut self, h: &[u32; 8]) {
452         self.length_bits = 0;
453         self.buffer.reset();
454         self.state.reset(h);
455         self.finished = false;
456     }
457
458     fn input(&mut self, input: &[u8]) {
459         assert!(!self.finished);
460         // Assumes that input.len() can be converted to u64 without overflow
461         self.length_bits = add_bytes_to_bits(self.length_bits, input.len() as u64);
462         let self_state = &mut self.state;
463         self.buffer.input(input, |input: &[u8]| { self_state.process_block(input) });
464     }
465
466     fn finish(&mut self) {
467         if self.finished {
468             return;
469         }
470
471         let self_state = &mut self.state;
472         self.buffer.standard_padding(8, |input: &[u8]| { self_state.process_block(input) });
473         write_u32_be(self.buffer.next(4), (self.length_bits >> 32) as u32 );
474         write_u32_be(self.buffer.next(4), self.length_bits as u32);
475         self_state.process_block(self.buffer.full_buffer());
476
477         self.finished = true;
478     }
479 }
480
481 /// The SHA-256 hash algorithm
482 pub struct Sha256 {
483     engine: Engine256
484 }
485
486 impl Sha256 {
487     /// Construct a new instance of a SHA-256 digest.
488     pub fn new() -> Sha256 {
489         Sha256 {
490             engine: Engine256::new(&H256)
491         }
492     }
493 }
494
495 impl Digest for Sha256 {
496     fn input(&mut self, d: &[u8]) {
497         self.engine.input(d);
498     }
499
500     fn result(&mut self, out: &mut [u8]) {
501         self.engine.finish();
502
503         write_u32_be(&mut out[0..4], self.engine.state.h0);
504         write_u32_be(&mut out[4..8], self.engine.state.h1);
505         write_u32_be(&mut out[8..12], self.engine.state.h2);
506         write_u32_be(&mut out[12..16], self.engine.state.h3);
507         write_u32_be(&mut out[16..20], self.engine.state.h4);
508         write_u32_be(&mut out[20..24], self.engine.state.h5);
509         write_u32_be(&mut out[24..28], self.engine.state.h6);
510         write_u32_be(&mut out[28..32], self.engine.state.h7);
511     }
512
513     fn reset(&mut self) {
514         self.engine.reset(&H256);
515     }
516
517     fn output_bits(&self) -> usize { 256 }
518 }
519
520 static H256: [u32; 8] = [
521     0x6a09e667,
522     0xbb67ae85,
523     0x3c6ef372,
524     0xa54ff53a,
525     0x510e527f,
526     0x9b05688c,
527     0x1f83d9ab,
528     0x5be0cd19
529 ];
530
531 #[cfg(test)]
532 mod tests {
533     #![allow(deprecated)]
534     extern crate rand;
535
536     use self::rand::Rng;
537     use self::rand::isaac::IsaacRng;
538     use serialize::hex::FromHex;
539     use std::iter::repeat;
540     use std::u64;
541     use super::{Digest, Sha256, FixedBuffer};
542
543     // A normal addition - no overflow occurs
544     #[test]
545     fn test_add_bytes_to_bits_ok() {
546         assert!(super::add_bytes_to_bits::<u64>(100, 10) == 180);
547     }
548
549     // A simple failure case - adding 1 to the max value
550     #[test]
551     #[should_panic]
552     fn test_add_bytes_to_bits_overflow() {
553         super::add_bytes_to_bits::<u64>(u64::MAX, 1);
554     }
555
556     struct Test {
557         input: String,
558         output_str: String,
559     }
560
561     fn test_hash<D: Digest>(sh: &mut D, tests: &[Test]) {
562         // Test that it works when accepting the message all at once
563         for t in tests {
564             sh.reset();
565             sh.input_str(&t.input);
566             let out_str = sh.result_str();
567             assert!(out_str == t.output_str);
568         }
569
570         // Test that it works when accepting the message in pieces
571         for t in tests {
572             sh.reset();
573             let len = t.input.len();
574             let mut left = len;
575             while left > 0 {
576                 let take = (left + 1) / 2;
577                 sh.input_str(&t.input[len - left..take + len - left]);
578                 left = left - take;
579             }
580             let out_str = sh.result_str();
581             assert!(out_str == t.output_str);
582         }
583     }
584
585     #[test]
586     fn test_sha256() {
587         // Examples from wikipedia
588         let wikipedia_tests = vec!(
589             Test {
590                 input: "".to_string(),
591                 output_str: "e3b0c44298fc1c149afb\
592             f4c8996fb92427ae41e4649b934ca495991b7852b855".to_string()
593             },
594             Test {
595                 input: "The quick brown fox jumps over the lazy \
596                         dog".to_string(),
597                 output_str: "d7a8fbb307d7809469ca\
598             9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592".to_string()
599             },
600             Test {
601                 input: "The quick brown fox jumps over the lazy \
602                         dog.".to_string(),
603                 output_str: "ef537f25c895bfa78252\
604             6529a9b63d97aa631564d5d789c2b765448c8635fb6c".to_string()
605             });
606
607         let tests = wikipedia_tests;
608
609         let mut sh: Box<_> = box Sha256::new();
610
611         test_hash(&mut *sh, &tests);
612     }
613
614     /// Feed 1,000,000 'a's into the digest with varying input sizes and check that the result is
615     /// correct.
616     fn test_digest_1million_random<D: Digest>(digest: &mut D, blocksize: usize, expected: &str) {
617         let total_size = 1000000;
618         let buffer: Vec<u8> = repeat('a' as u8).take(blocksize * 2).collect();
619         let mut rng = IsaacRng::new_unseeded();
620         let mut count = 0;
621
622         digest.reset();
623
624         while count < total_size {
625             let next: usize = rng.gen_range(0, 2 * blocksize + 1);
626             let remaining = total_size - count;
627             let size = if next > remaining { remaining } else { next };
628             digest.input(&buffer[..size]);
629             count += size;
630         }
631
632         let result_str = digest.result_str();
633         let result_bytes = digest.result_bytes();
634
635         assert_eq!(expected, result_str);
636
637         let expected_vec: Vec<u8> = expected.from_hex()
638                                             .unwrap()
639                                             .into_iter()
640                                             .collect();
641         assert_eq!(expected_vec, result_bytes);
642     }
643
644     #[test]
645     fn test_1million_random_sha256() {
646         let mut sh = Sha256::new();
647         test_digest_1million_random(
648             &mut sh,
649             64,
650             "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
651     }
652 }
653
654 #[cfg(test)]
655 mod bench {
656     extern crate test;
657     use self::test::Bencher;
658     use super::{Sha256, FixedBuffer, Digest};
659
660     #[bench]
661     pub fn sha256_10(b: &mut Bencher) {
662         let mut sh = Sha256::new();
663         let bytes = [1; 10];
664         b.iter(|| {
665             sh.input(&bytes);
666         });
667         b.bytes = bytes.len() as u64;
668     }
669
670     #[bench]
671     pub fn sha256_1k(b: &mut Bencher) {
672         let mut sh = Sha256::new();
673         let bytes = [1; 1024];
674         b.iter(|| {
675             sh.input(&bytes);
676         });
677         b.bytes = bytes.len() as u64;
678     }
679
680     #[bench]
681     pub fn sha256_64k(b: &mut Bencher) {
682         let mut sh = Sha256::new();
683         let bytes = [1; 65536];
684         b.iter(|| {
685             sh.input(&bytes);
686         });
687         b.bytes = bytes.len() as u64;
688     }
689 }