]> git.proxmox.com Git - rustc.git/blob - src/librustc_back/sha2.rs
6654a46f7c31b51cdaee38add94af4f904eb793e
[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 #![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 > Int::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: uint);
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: uint) -> &'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) -> uint;
104
105 /// Get the number of bytes remaining in the buffer until it is full.
106 fn remaining(&self) -> uint;
107
108 /// Get the size of the buffer
109 fn size(&self) -> uint;
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: uint,
116 }
117
118 impl FixedBuffer64 {
119 /// Create a new FixedBuffer64
120 fn new() -> FixedBuffer64 {
121 return FixedBuffer64 {
122 buffer: [0u8; 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 &mut self.buffer[self.buffer_idx..size],
143 &input[..buffer_remaining]);
144 self.buffer_idx = 0;
145 func(&self.buffer);
146 i += buffer_remaining;
147 } else {
148 copy_memory(
149 &mut self.buffer[self.buffer_idx..self.buffer_idx + input.len()],
150 input);
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 &mut self.buffer[..input_remaining],
169 &input[i..]);
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: uint) {
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: uint) -> &'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) -> uint { self.buffer_idx }
195
196 fn remaining(&self) -> uint { 64 - self.buffer_idx }
197
198 fn size(&self) -> uint { 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: uint, func: F) where F: FnMut(&[u8]);
208 }
209
210 impl <T: FixedBuffer> StandardPadding for T {
211 fn standard_padding<F>(&mut self, rem: uint, 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) -> uint;
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(0u8).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 = [0u32; 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]) + w[$t - 7] + sigma0(w[$t - 15]) + w[$t - 16];
351 )
352 }
353
354 macro_rules! sha2_round {
355 ($A:ident, $B:ident, $C:ident, $D:ident,
356 $E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => (
357 {
358 $H += sum1($E) + ch($E, $F, $G) + $K[$t] + w[$t];
359 $D += $H;
360 $H += sum0($A) + maj($A, $B, $C);
361 }
362 )
363 }
364
365 read_u32v_be(&mut w[0..16], data);
366
367 // Putting the message schedule inside the same loop as the round calculations allows for
368 // the compiler to generate better code.
369 for t in range_step(0, 48, 8) {
370 schedule_round!(t + 16);
371 schedule_round!(t + 17);
372 schedule_round!(t + 18);
373 schedule_round!(t + 19);
374 schedule_round!(t + 20);
375 schedule_round!(t + 21);
376 schedule_round!(t + 22);
377 schedule_round!(t + 23);
378
379 sha2_round!(a, b, c, d, e, f, g, h, K32, t);
380 sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1);
381 sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2);
382 sha2_round!(f, g, h, a, b, c, d, e, K32, t + 3);
383 sha2_round!(e, f, g, h, a, b, c, d, K32, t + 4);
384 sha2_round!(d, e, f, g, h, a, b, c, K32, t + 5);
385 sha2_round!(c, d, e, f, g, h, a, b, K32, t + 6);
386 sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
387 }
388
389 for t in range_step(48, 64, 8) {
390 sha2_round!(a, b, c, d, e, f, g, h, K32, t);
391 sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1);
392 sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2);
393 sha2_round!(f, g, h, a, b, c, d, e, K32, t + 3);
394 sha2_round!(e, f, g, h, a, b, c, d, K32, t + 4);
395 sha2_round!(d, e, f, g, h, a, b, c, K32, t + 5);
396 sha2_round!(c, d, e, f, g, h, a, b, K32, t + 6);
397 sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
398 }
399
400 self.h0 += a;
401 self.h1 += b;
402 self.h2 += c;
403 self.h3 += d;
404 self.h4 += e;
405 self.h5 += f;
406 self.h6 += g;
407 self.h7 += h;
408 }
409 }
410
411 static K32: [u32; 64] = [
412 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
413 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
414 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
415 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
416 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
417 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
418 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
419 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
420 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
421 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
422 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
423 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
424 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
425 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
426 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
427 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
428 ];
429
430 // A structure that keeps track of the state of the Sha-256 operation and contains the logic
431 // necessary to perform the final calculations.
432 struct Engine256 {
433 length_bits: u64,
434 buffer: FixedBuffer64,
435 state: Engine256State,
436 finished: bool,
437 }
438
439 impl Engine256 {
440 fn new(h: &[u32; 8]) -> Engine256 {
441 return Engine256 {
442 length_bits: 0,
443 buffer: FixedBuffer64::new(),
444 state: Engine256State::new(h),
445 finished: false
446 }
447 }
448
449 fn reset(&mut self, h: &[u32; 8]) {
450 self.length_bits = 0;
451 self.buffer.reset();
452 self.state.reset(h);
453 self.finished = false;
454 }
455
456 fn input(&mut self, input: &[u8]) {
457 assert!(!self.finished);
458 // Assumes that input.len() can be converted to u64 without overflow
459 self.length_bits = add_bytes_to_bits(self.length_bits, input.len() as u64);
460 let self_state = &mut self.state;
461 self.buffer.input(input, |input: &[u8]| { self_state.process_block(input) });
462 }
463
464 fn finish(&mut self) {
465 if self.finished {
466 return;
467 }
468
469 let self_state = &mut self.state;
470 self.buffer.standard_padding(8, |input: &[u8]| { self_state.process_block(input) });
471 write_u32_be(self.buffer.next(4), (self.length_bits >> 32) as u32 );
472 write_u32_be(self.buffer.next(4), self.length_bits as u32);
473 self_state.process_block(self.buffer.full_buffer());
474
475 self.finished = true;
476 }
477 }
478
479 /// The SHA-256 hash algorithm
480 pub struct Sha256 {
481 engine: Engine256
482 }
483
484 impl Sha256 {
485 /// Construct a new instance of a SHA-256 digest.
486 pub fn new() -> Sha256 {
487 Sha256 {
488 engine: Engine256::new(&H256)
489 }
490 }
491 }
492
493 impl Digest for Sha256 {
494 fn input(&mut self, d: &[u8]) {
495 self.engine.input(d);
496 }
497
498 fn result(&mut self, out: &mut [u8]) {
499 self.engine.finish();
500
501 write_u32_be(&mut out[0..4], self.engine.state.h0);
502 write_u32_be(&mut out[4..8], self.engine.state.h1);
503 write_u32_be(&mut out[8..12], self.engine.state.h2);
504 write_u32_be(&mut out[12..16], self.engine.state.h3);
505 write_u32_be(&mut out[16..20], self.engine.state.h4);
506 write_u32_be(&mut out[20..24], self.engine.state.h5);
507 write_u32_be(&mut out[24..28], self.engine.state.h6);
508 write_u32_be(&mut out[28..32], self.engine.state.h7);
509 }
510
511 fn reset(&mut self) {
512 self.engine.reset(&H256);
513 }
514
515 fn output_bits(&self) -> uint { 256 }
516 }
517
518 static H256: [u32; 8] = [
519 0x6a09e667,
520 0xbb67ae85,
521 0x3c6ef372,
522 0xa54ff53a,
523 0x510e527f,
524 0x9b05688c,
525 0x1f83d9ab,
526 0x5be0cd19
527 ];
528
529 #[cfg(test)]
530 mod tests {
531 #![allow(deprecated)]
532 extern crate rand;
533
534 use self::rand::Rng;
535 use self::rand::isaac::IsaacRng;
536 use serialize::hex::FromHex;
537 use std::iter::repeat;
538 use std::num::Int;
539 use super::{Digest, Sha256, FixedBuffer};
540
541 // A normal addition - no overflow occurs
542 #[test]
543 fn test_add_bytes_to_bits_ok() {
544 assert!(super::add_bytes_to_bits::<u64>(100, 10) == 180);
545 }
546
547 // A simple failure case - adding 1 to the max value
548 #[test]
549 #[should_fail]
550 fn test_add_bytes_to_bits_overflow() {
551 super::add_bytes_to_bits::<u64>(Int::max_value(), 1);
552 }
553
554 struct Test {
555 input: String,
556 output_str: String,
557 }
558
559 fn test_hash<D: Digest>(sh: &mut D, tests: &[Test]) {
560 // Test that it works when accepting the message all at once
561 for t in tests {
562 sh.reset();
563 sh.input_str(&t.input);
564 let out_str = sh.result_str();
565 assert!(out_str == t.output_str);
566 }
567
568 // Test that it works when accepting the message in pieces
569 for t in tests {
570 sh.reset();
571 let len = t.input.len();
572 let mut left = len;
573 while left > 0 {
574 let take = (left + 1) / 2;
575 sh.input_str(&t.input[len - left..take + len - left]);
576 left = left - take;
577 }
578 let out_str = sh.result_str();
579 assert!(out_str == t.output_str);
580 }
581 }
582
583 #[test]
584 fn test_sha256() {
585 // Examples from wikipedia
586 let wikipedia_tests = vec!(
587 Test {
588 input: "".to_string(),
589 output_str: "e3b0c44298fc1c149afb\
590 f4c8996fb92427ae41e4649b934ca495991b7852b855".to_string()
591 },
592 Test {
593 input: "The quick brown fox jumps over the lazy \
594 dog".to_string(),
595 output_str: "d7a8fbb307d7809469ca\
596 9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592".to_string()
597 },
598 Test {
599 input: "The quick brown fox jumps over the lazy \
600 dog.".to_string(),
601 output_str: "ef537f25c895bfa78252\
602 6529a9b63d97aa631564d5d789c2b765448c8635fb6c".to_string()
603 });
604
605 let tests = wikipedia_tests;
606
607 let mut sh = box Sha256::new();
608
609 test_hash(&mut *sh, &tests);
610 }
611
612 /// Feed 1,000,000 'a's into the digest with varying input sizes and check that the result is
613 /// correct.
614 fn test_digest_1million_random<D: Digest>(digest: &mut D, blocksize: uint, expected: &str) {
615 let total_size = 1000000;
616 let buffer: Vec<u8> = repeat('a' as u8).take(blocksize * 2).collect();
617 let mut rng = IsaacRng::new_unseeded();
618 let mut count = 0;
619
620 digest.reset();
621
622 while count < total_size {
623 let next: uint = rng.gen_range(0, 2 * blocksize + 1);
624 let remaining = total_size - count;
625 let size = if next > remaining { remaining } else { next };
626 digest.input(&buffer[..size]);
627 count += size;
628 }
629
630 let result_str = digest.result_str();
631 let result_bytes = digest.result_bytes();
632
633 assert_eq!(expected, result_str);
634
635 let expected_vec: Vec<u8> = expected.from_hex()
636 .unwrap()
637 .into_iter()
638 .collect();
639 assert_eq!(expected_vec, result_bytes);
640 }
641
642 #[test]
643 fn test_1million_random_sha256() {
644 let mut sh = Sha256::new();
645 test_digest_1million_random(
646 &mut sh,
647 64,
648 "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
649 }
650 }
651
652 #[cfg(test)]
653 mod bench {
654 extern crate test;
655 use self::test::Bencher;
656 use super::{Sha256, FixedBuffer, Digest};
657
658 #[bench]
659 pub fn sha256_10(b: &mut Bencher) {
660 let mut sh = Sha256::new();
661 let bytes = [1u8; 10];
662 b.iter(|| {
663 sh.input(&bytes);
664 });
665 b.bytes = bytes.len() as u64;
666 }
667
668 #[bench]
669 pub fn sha256_1k(b: &mut Bencher) {
670 let mut sh = Sha256::new();
671 let bytes = [1u8; 1024];
672 b.iter(|| {
673 sh.input(&bytes);
674 });
675 b.bytes = bytes.len() as u64;
676 }
677
678 #[bench]
679 pub fn sha256_64k(b: &mut Bencher) {
680 let mut sh = Sha256::new();
681 let bytes = [1u8; 65536];
682 b.iter(|| {
683 sh.input(&bytes);
684 });
685 b.bytes = bytes.len() as u64;
686 }
687 }