1 // Copyright 2015-2019 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 //! SHA-2 and the legacy SHA-1 digest algorithm.
16 //!
17 //! If all the data is available in a single contiguous slice then the `digest`
18 //! function should be used. Otherwise, the digest can be calculated in
19 //! multiple steps using `Context`.
20 
21 // Note on why are we doing things the hard way: It would be easy to implement
22 // this using the C `EVP_MD`/`EVP_MD_CTX` interface. However, if we were to do
23 // things that way, we'd have a hard dependency on `malloc` and other overhead.
24 // The goal for this implementation is to drive the overhead as close to zero
25 // as possible.
26 
27 use crate::{
28     c, cpu, debug,
29     endian::{ArrayEncoding, BigEndian},
30     polyfill,
31 };
32 use core::num::Wrapping;
33 
34 mod sha1;
35 mod sha2;
36 
37 #[derive(Clone)]
38 pub(crate) struct BlockContext {
39     state: State,
40 
41     // Note that SHA-512 has a 128-bit input bit counter, but this
42     // implementation only supports up to 2^64-1 input bits for all algorithms,
43     // so a 64-bit counter is more than sufficient.
44     completed_data_blocks: u64,
45 
46     /// The context's algorithm.
47     pub algorithm: &'static Algorithm,
48 
49     cpu_features: cpu::Features,
50 }
51 
52 impl BlockContext {
new(algorithm: &'static Algorithm) -> Self53     pub(crate) fn new(algorithm: &'static Algorithm) -> Self {
54         Self {
55             state: algorithm.initial_state,
56             completed_data_blocks: 0,
57             algorithm,
58             cpu_features: cpu::features(),
59         }
60     }
61 
62     #[inline]
update(&mut self, input: &[u8])63     pub(crate) fn update(&mut self, input: &[u8]) {
64         let num_blocks = input.len() / self.algorithm.block_len;
65         assert_eq!(num_blocks * self.algorithm.block_len, input.len());
66 
67         if num_blocks > 0 {
68             let _cpu_features = self.cpu_features;
69             unsafe {
70                 (self.algorithm.block_data_order)(&mut self.state, input.as_ptr(), num_blocks);
71             }
72             self.completed_data_blocks = self
73                 .completed_data_blocks
74                 .checked_add(polyfill::u64_from_usize(num_blocks))
75                 .unwrap();
76         }
77     }
78 
finish(mut self, pending: &mut [u8], num_pending: usize) -> Digest79     pub(crate) fn finish(mut self, pending: &mut [u8], num_pending: usize) -> Digest {
80         let block_len = self.algorithm.block_len;
81         assert_eq!(pending.len(), block_len);
82         assert!(num_pending <= pending.len());
83 
84         let mut padding_pos = num_pending;
85         pending[padding_pos] = 0x80;
86         padding_pos += 1;
87 
88         if padding_pos > block_len - self.algorithm.len_len {
89             pending[padding_pos..block_len].fill(0);
90             unsafe {
91                 (self.algorithm.block_data_order)(&mut self.state, pending.as_ptr(), 1);
92             }
93             // We don't increase |self.completed_data_blocks| because the
94             // padding isn't data, and so it isn't included in the data length.
95             padding_pos = 0;
96         }
97 
98         pending[padding_pos..(block_len - 8)].fill(0);
99 
100         // Output the length, in bits, in big endian order.
101         let completed_data_bits = self
102             .completed_data_blocks
103             .checked_mul(polyfill::u64_from_usize(block_len))
104             .unwrap()
105             .checked_add(polyfill::u64_from_usize(num_pending))
106             .unwrap()
107             .checked_mul(8)
108             .unwrap();
109         pending[(block_len - 8)..block_len].copy_from_slice(&u64::to_be_bytes(completed_data_bits));
110 
111         unsafe {
112             (self.algorithm.block_data_order)(&mut self.state, pending.as_ptr(), 1);
113         }
114 
115         Digest {
116             algorithm: self.algorithm,
117             value: (self.algorithm.format_output)(self.state),
118         }
119     }
120 }
121 
122 /// A context for multi-step (Init-Update-Finish) digest calculations.
123 ///
124 /// # Examples
125 ///
126 /// ```
127 /// use ring::digest;
128 ///
129 /// let one_shot = digest::digest(&digest::SHA384, b"hello, world");
130 ///
131 /// let mut ctx = digest::Context::new(&digest::SHA384);
132 /// ctx.update(b"hello");
133 /// ctx.update(b", ");
134 /// ctx.update(b"world");
135 /// let multi_part = ctx.finish();
136 ///
137 /// assert_eq!(&one_shot.as_ref(), &multi_part.as_ref());
138 /// ```
139 #[derive(Clone)]
140 pub struct Context {
141     block: BlockContext,
142     // TODO: More explicitly force 64-bit alignment for |pending|.
143     pending: [u8; MAX_BLOCK_LEN],
144     num_pending: usize,
145 }
146 
147 impl Context {
148     /// Constructs a new context.
new(algorithm: &'static Algorithm) -> Self149     pub fn new(algorithm: &'static Algorithm) -> Self {
150         Self {
151             block: BlockContext::new(algorithm),
152             pending: [0u8; MAX_BLOCK_LEN],
153             num_pending: 0,
154         }
155     }
156 
clone_from(block: &BlockContext) -> Self157     pub(crate) fn clone_from(block: &BlockContext) -> Self {
158         Self {
159             block: block.clone(),
160             pending: [0u8; MAX_BLOCK_LEN],
161             num_pending: 0,
162         }
163     }
164 
165     /// Updates the digest with all the data in `data`.
update(&mut self, data: &[u8])166     pub fn update(&mut self, data: &[u8]) {
167         let block_len = self.block.algorithm.block_len;
168         if data.len() < block_len - self.num_pending {
169             self.pending[self.num_pending..(self.num_pending + data.len())].copy_from_slice(data);
170             self.num_pending += data.len();
171             return;
172         }
173 
174         let mut remaining = data;
175         if self.num_pending > 0 {
176             let to_copy = block_len - self.num_pending;
177             self.pending[self.num_pending..block_len].copy_from_slice(&data[..to_copy]);
178             self.block.update(&self.pending[..block_len]);
179             remaining = &remaining[to_copy..];
180             self.num_pending = 0;
181         }
182 
183         let num_blocks = remaining.len() / block_len;
184         let num_to_save_for_later = remaining.len() % block_len;
185         self.block.update(&remaining[..(num_blocks * block_len)]);
186         if num_to_save_for_later > 0 {
187             self.pending[..num_to_save_for_later]
188                 .copy_from_slice(&remaining[(remaining.len() - num_to_save_for_later)..]);
189             self.num_pending = num_to_save_for_later;
190         }
191     }
192 
193     /// Finalizes the digest calculation and returns the digest value.
194     ///
195     /// `finish` consumes the context so it cannot be (mis-)used after `finish`
196     /// has been called.
finish(mut self) -> Digest197     pub fn finish(mut self) -> Digest {
198         let block_len = self.block.algorithm.block_len;
199         self.block
200             .finish(&mut self.pending[..block_len], self.num_pending)
201     }
202 
203     /// The algorithm that this context is using.
204     #[inline(always)]
algorithm(&self) -> &'static Algorithm205     pub fn algorithm(&self) -> &'static Algorithm {
206         self.block.algorithm
207     }
208 }
209 
210 /// Returns the digest of `data` using the given digest algorithm.
211 ///
212 /// # Examples:
213 ///
214 /// ```
215 /// # #[cfg(feature = "alloc")]
216 /// # {
217 /// use ring::{digest, test};
218 /// let expected_hex = "09ca7e4eaa6e8ae9c7d261167129184883644d07dfba7cbfbc4c8a2e08360d5b";
219 /// let expected: Vec<u8> = test::from_hex(expected_hex).unwrap();
220 /// let actual = digest::digest(&digest::SHA256, b"hello, world");
221 ///
222 /// assert_eq!(&expected, &actual.as_ref());
223 /// # }
224 /// ```
digest(algorithm: &'static Algorithm, data: &[u8]) -> Digest225 pub fn digest(algorithm: &'static Algorithm, data: &[u8]) -> Digest {
226     let mut ctx = Context::new(algorithm);
227     ctx.update(data);
228     ctx.finish()
229 }
230 
231 /// A calculated digest value.
232 ///
233 /// Use [`Self::as_ref`] to get the value as a `&[u8]`.
234 #[derive(Clone, Copy)]
235 pub struct Digest {
236     value: Output,
237     algorithm: &'static Algorithm,
238 }
239 
240 impl Digest {
241     /// The algorithm that was used to calculate the digest value.
242     #[inline(always)]
algorithm(&self) -> &'static Algorithm243     pub fn algorithm(&self) -> &'static Algorithm {
244         self.algorithm
245     }
246 }
247 
248 impl AsRef<[u8]> for Digest {
249     #[inline(always)]
as_ref(&self) -> &[u8]250     fn as_ref(&self) -> &[u8] {
251         let as64 = unsafe { &self.value.as64 };
252         &as64.as_byte_array()[..self.algorithm.output_len]
253     }
254 }
255 
256 impl core::fmt::Debug for Digest {
fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result257     fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
258         write!(fmt, "{:?}:", self.algorithm)?;
259         debug::write_hex_bytes(fmt, self.as_ref())
260     }
261 }
262 
263 /// A digest algorithm.
264 pub struct Algorithm {
265     output_len: usize,
266     chaining_len: usize,
267     block_len: usize,
268 
269     /// The length of the length in the padding.
270     len_len: usize,
271 
272     block_data_order: unsafe extern "C" fn(state: &mut State, data: *const u8, num: c::size_t),
273     format_output: fn(input: State) -> Output,
274 
275     initial_state: State,
276 
277     id: AlgorithmID,
278 }
279 
280 #[derive(Debug, Eq, PartialEq)]
281 enum AlgorithmID {
282     SHA1,
283     SHA256,
284     SHA384,
285     SHA512,
286     SHA512_256,
287 }
288 
289 impl PartialEq for Algorithm {
eq(&self, other: &Self) -> bool290     fn eq(&self, other: &Self) -> bool {
291         self.id == other.id
292     }
293 }
294 
295 impl Eq for Algorithm {}
296 
297 derive_debug_via_id!(Algorithm);
298 
299 impl Algorithm {
300     /// The internal block length.
block_len(&self) -> usize301     pub fn block_len(&self) -> usize {
302         self.block_len
303     }
304 
305     /// The size of the chaining value of the digest function, in bytes.
306     ///
307     /// For non-truncated algorithms (SHA-1, SHA-256, SHA-512), this is equal
308     /// to [`Self::output_len()`]. For truncated algorithms (e.g. SHA-384,
309     /// SHA-512/256), this is equal to the length before truncation. This is
310     /// mostly helpful for determining the size of an HMAC key that is
311     /// appropriate for the digest algorithm.
chaining_len(&self) -> usize312     pub fn chaining_len(&self) -> usize {
313         self.chaining_len
314     }
315 
316     /// The length of a finalized digest.
output_len(&self) -> usize317     pub fn output_len(&self) -> usize {
318         self.output_len
319     }
320 }
321 
322 /// SHA-1 as specified in [FIPS 180-4]. Deprecated.
323 ///
324 /// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
325 pub static SHA1_FOR_LEGACY_USE_ONLY: Algorithm = Algorithm {
326     output_len: sha1::OUTPUT_LEN,
327     chaining_len: sha1::CHAINING_LEN,
328     block_len: sha1::BLOCK_LEN,
329     len_len: 64 / 8,
330     block_data_order: sha1::block_data_order,
331     format_output: sha256_format_output,
332     initial_state: State {
333         as32: [
334             Wrapping(0x67452301u32),
335             Wrapping(0xefcdab89u32),
336             Wrapping(0x98badcfeu32),
337             Wrapping(0x10325476u32),
338             Wrapping(0xc3d2e1f0u32),
339             Wrapping(0),
340             Wrapping(0),
341             Wrapping(0),
342         ],
343     },
344     id: AlgorithmID::SHA1,
345 };
346 
347 /// SHA-256 as specified in [FIPS 180-4].
348 ///
349 /// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
350 pub static SHA256: Algorithm = Algorithm {
351     output_len: SHA256_OUTPUT_LEN,
352     chaining_len: SHA256_OUTPUT_LEN,
353     block_len: 512 / 8,
354     len_len: 64 / 8,
355     block_data_order: sha2::sha256_block_data_order,
356     format_output: sha256_format_output,
357     initial_state: State {
358         as32: [
359             Wrapping(0x6a09e667u32),
360             Wrapping(0xbb67ae85u32),
361             Wrapping(0x3c6ef372u32),
362             Wrapping(0xa54ff53au32),
363             Wrapping(0x510e527fu32),
364             Wrapping(0x9b05688cu32),
365             Wrapping(0x1f83d9abu32),
366             Wrapping(0x5be0cd19u32),
367         ],
368     },
369     id: AlgorithmID::SHA256,
370 };
371 
372 /// SHA-384 as specified in [FIPS 180-4].
373 ///
374 /// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
375 pub static SHA384: Algorithm = Algorithm {
376     output_len: SHA384_OUTPUT_LEN,
377     chaining_len: SHA512_OUTPUT_LEN,
378     block_len: SHA512_BLOCK_LEN,
379     len_len: SHA512_LEN_LEN,
380     block_data_order: sha2::sha512_block_data_order,
381     format_output: sha512_format_output,
382     initial_state: State {
383         as64: [
384             Wrapping(0xcbbb9d5dc1059ed8),
385             Wrapping(0x629a292a367cd507),
386             Wrapping(0x9159015a3070dd17),
387             Wrapping(0x152fecd8f70e5939),
388             Wrapping(0x67332667ffc00b31),
389             Wrapping(0x8eb44a8768581511),
390             Wrapping(0xdb0c2e0d64f98fa7),
391             Wrapping(0x47b5481dbefa4fa4),
392         ],
393     },
394     id: AlgorithmID::SHA384,
395 };
396 
397 /// SHA-512 as specified in [FIPS 180-4].
398 ///
399 /// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
400 pub static SHA512: Algorithm = Algorithm {
401     output_len: SHA512_OUTPUT_LEN,
402     chaining_len: SHA512_OUTPUT_LEN,
403     block_len: SHA512_BLOCK_LEN,
404     len_len: SHA512_LEN_LEN,
405     block_data_order: sha2::sha512_block_data_order,
406     format_output: sha512_format_output,
407     initial_state: State {
408         as64: [
409             Wrapping(0x6a09e667f3bcc908),
410             Wrapping(0xbb67ae8584caa73b),
411             Wrapping(0x3c6ef372fe94f82b),
412             Wrapping(0xa54ff53a5f1d36f1),
413             Wrapping(0x510e527fade682d1),
414             Wrapping(0x9b05688c2b3e6c1f),
415             Wrapping(0x1f83d9abfb41bd6b),
416             Wrapping(0x5be0cd19137e2179),
417         ],
418     },
419     id: AlgorithmID::SHA512,
420 };
421 
422 /// SHA-512/256 as specified in [FIPS 180-4].
423 ///
424 /// This is *not* the same as just truncating the output of SHA-512, as
425 /// SHA-512/256 has its own initial state distinct from SHA-512's initial
426 /// state.
427 ///
428 /// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
429 pub static SHA512_256: Algorithm = Algorithm {
430     output_len: SHA512_256_OUTPUT_LEN,
431     chaining_len: SHA512_OUTPUT_LEN,
432     block_len: SHA512_BLOCK_LEN,
433     len_len: SHA512_LEN_LEN,
434     block_data_order: sha2::sha512_block_data_order,
435     format_output: sha512_format_output,
436     initial_state: State {
437         as64: [
438             Wrapping(0x22312194fc2bf72c),
439             Wrapping(0x9f555fa3c84c64c2),
440             Wrapping(0x2393b86b6f53b151),
441             Wrapping(0x963877195940eabd),
442             Wrapping(0x96283ee2a88effe3),
443             Wrapping(0xbe5e1e2553863992),
444             Wrapping(0x2b0199fc2c85b8aa),
445             Wrapping(0x0eb72ddc81c52ca2),
446         ],
447     },
448     id: AlgorithmID::SHA512_256,
449 };
450 
451 #[derive(Clone, Copy)] // XXX: Why do we need to be `Copy`?
452 #[repr(C)]
453 union State {
454     as64: [Wrapping<u64>; sha2::CHAINING_WORDS],
455     as32: [Wrapping<u32>; sha2::CHAINING_WORDS],
456 }
457 
458 #[derive(Clone, Copy)]
459 #[repr(C)]
460 union Output {
461     as64: [BigEndian<u64>; 512 / 8 / core::mem::size_of::<BigEndian<u64>>()],
462     as32: [BigEndian<u32>; 256 / 8 / core::mem::size_of::<BigEndian<u32>>()],
463 }
464 
465 /// The maximum block length ([`Algorithm::block_len()`]) of all the algorithms
466 /// in this module.
467 pub const MAX_BLOCK_LEN: usize = 1024 / 8;
468 
469 /// The maximum output length ([`Algorithm::output_len()`]) of all the
470 /// algorithms in this module.
471 pub const MAX_OUTPUT_LEN: usize = 512 / 8;
472 
473 /// The maximum chaining length ([`Algorithm::chaining_len()`]) of all the
474 /// algorithms in this module.
475 pub const MAX_CHAINING_LEN: usize = MAX_OUTPUT_LEN;
476 
sha256_format_output(input: State) -> Output477 fn sha256_format_output(input: State) -> Output {
478     let input = unsafe { &input.as32 };
479     Output {
480         as32: input.map(BigEndian::from),
481     }
482 }
483 
sha512_format_output(input: State) -> Output484 fn sha512_format_output(input: State) -> Output {
485     let input = unsafe { &input.as64 };
486     Output {
487         as64: input.map(BigEndian::from),
488     }
489 }
490 
491 /// The length of the output of SHA-1, in bytes.
492 pub const SHA1_OUTPUT_LEN: usize = sha1::OUTPUT_LEN;
493 
494 /// The length of the output of SHA-256, in bytes.
495 pub const SHA256_OUTPUT_LEN: usize = 256 / 8;
496 
497 /// The length of the output of SHA-384, in bytes.
498 pub const SHA384_OUTPUT_LEN: usize = 384 / 8;
499 
500 /// The length of the output of SHA-512, in bytes.
501 pub const SHA512_OUTPUT_LEN: usize = 512 / 8;
502 
503 /// The length of the output of SHA-512/256, in bytes.
504 pub const SHA512_256_OUTPUT_LEN: usize = 256 / 8;
505 
506 /// The length of a block for SHA-512-based algorithms, in bytes.
507 const SHA512_BLOCK_LEN: usize = 1024 / 8;
508 
509 /// The length of the length field for SHA-512-based algorithms, in bytes.
510 const SHA512_LEN_LEN: usize = 128 / 8;
511 
512 #[cfg(test)]
513 mod tests {
514     mod max_input {
515         extern crate alloc;
516         use super::super::super::digest;
517         use crate::polyfill;
518         use alloc::vec;
519 
520         macro_rules! max_input_tests {
521             ( $algorithm_name:ident ) => {
522                 mod $algorithm_name {
523                     use super::super::super::super::digest;
524 
525                     #[test]
526                     fn max_input_test() {
527                         super::max_input_test(&digest::$algorithm_name);
528                     }
529 
530                     #[test]
531                     #[should_panic]
532                     fn too_long_input_test_block() {
533                         super::too_long_input_test_block(&digest::$algorithm_name);
534                     }
535 
536                     #[test]
537                     #[should_panic]
538                     fn too_long_input_test_byte() {
539                         super::too_long_input_test_byte(&digest::$algorithm_name);
540                     }
541                 }
542             };
543         }
544 
max_input_test(alg: &'static digest::Algorithm)545         fn max_input_test(alg: &'static digest::Algorithm) {
546             let mut context = nearly_full_context(alg);
547             let next_input = vec![0u8; alg.block_len - 1];
548             context.update(&next_input);
549             let _ = context.finish(); // no panic
550         }
551 
too_long_input_test_block(alg: &'static digest::Algorithm)552         fn too_long_input_test_block(alg: &'static digest::Algorithm) {
553             let mut context = nearly_full_context(alg);
554             let next_input = vec![0u8; alg.block_len];
555             context.update(&next_input);
556             let _ = context.finish(); // should panic
557         }
558 
too_long_input_test_byte(alg: &'static digest::Algorithm)559         fn too_long_input_test_byte(alg: &'static digest::Algorithm) {
560             let mut context = nearly_full_context(alg);
561             let next_input = vec![0u8; alg.block_len - 1];
562             context.update(&next_input); // no panic
563             context.update(&[0]);
564             let _ = context.finish(); // should panic
565         }
566 
nearly_full_context(alg: &'static digest::Algorithm) -> digest::Context567         fn nearly_full_context(alg: &'static digest::Algorithm) -> digest::Context {
568             // All implementations currently support up to 2^64-1 bits
569             // of input; according to the spec, SHA-384 and SHA-512
570             // support up to 2^128-1, but that's not implemented yet.
571             let max_bytes = 1u64 << (64 - 3);
572             let max_blocks = max_bytes / polyfill::u64_from_usize(alg.block_len);
573             digest::Context {
574                 block: digest::BlockContext {
575                     state: alg.initial_state,
576                     completed_data_blocks: max_blocks - 1,
577                     algorithm: alg,
578                     cpu_features: crate::cpu::features(),
579                 },
580                 pending: [0u8; digest::MAX_BLOCK_LEN],
581                 num_pending: 0,
582             }
583         }
584 
585         max_input_tests!(SHA1_FOR_LEGACY_USE_ONLY);
586         max_input_tests!(SHA256);
587         max_input_tests!(SHA384);
588         max_input_tests!(SHA512);
589     }
590 }
591