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