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