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