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
27use crate::{c, cpu, debug, polyfill};
28use core::num::Wrapping;
29
30mod sha1;
31mod sha2;
32
33#[derive(Clone)]
34pub(crate) struct BlockContext {
35 state: State,
36
37 // Note that SHA-512 has a 128-bit input bit counter, but this
38 // implementation only supports up to 2^64-1 input bits for all algorithms,
39 // so a 64-bit counter is more than sufficient.
40 completed_data_blocks: u64,
41
42 /// The context's algorithm.
43 pub algorithm: &'static Algorithm,
44}
45
46impl BlockContext {
47 pub(crate) fn new(algorithm: &'static Algorithm) -> Self {
48 Self {
49 state: algorithm.initial_state,
50 completed_data_blocks: 0,
51 algorithm,
52 }
53 }
54
55 #[inline]
56 pub(crate) fn update(&mut self, input: &[u8]) {
57 let num_blocks = input.len() / self.algorithm.block_len;
58 assert_eq!(num_blocks * self.algorithm.block_len, input.len());
59
60 if num_blocks > 0 {
61 unsafe {
62 self.block_data_order(input.as_ptr(), num_blocks, cpu::features());
63 }
64 self.completed_data_blocks = self
65 .completed_data_blocks
66 .checked_add(polyfill::u64_from_usize(num_blocks))
67 .unwrap();
68 }
69 }
70
71 pub(crate) fn finish(mut self, pending: &mut [u8], num_pending: usize) -> Digest {
72 let block_len = self.algorithm.block_len;
73 assert_eq!(pending.len(), block_len);
74 assert!(num_pending <= pending.len());
75
76 let mut padding_pos = num_pending;
77 pending[padding_pos] = 0x80;
78 padding_pos += 1;
79
80 if padding_pos > block_len - self.algorithm.len_len {
81 pending[padding_pos..block_len].fill(0);
82 unsafe { self.block_data_order(pending.as_ptr(), 1, cpu::features()) };
83 // We don't increase |self.completed_data_blocks| because the
84 // padding isn't data, and so it isn't included in the data length.
85 padding_pos = 0;
86 }
87
88 pending[padding_pos..(block_len - 8)].fill(0);
89
90 // Output the length, in bits, in big endian order.
91 let completed_data_bits = self
92 .completed_data_blocks
93 .checked_mul(polyfill::u64_from_usize(block_len))
94 .unwrap()
95 .checked_add(polyfill::u64_from_usize(num_pending))
96 .unwrap()
97 .checked_mul(8)
98 .unwrap();
99 pending[(block_len - 8)..block_len].copy_from_slice(&u64::to_be_bytes(completed_data_bits));
100
101 unsafe { self.block_data_order(pending.as_ptr(), 1, cpu::features()) };
102
103 Digest {
104 algorithm: self.algorithm,
105 value: (self.algorithm.format_output)(self.state),
106 }
107 }
108
109 unsafe fn block_data_order(
110 &mut self,
111 pending: *const u8,
112 num_blocks: usize,
113 _cpu_features: cpu::Features,
114 ) {
115 // CPU features are inspected by assembly implementations.
116 unsafe {
117 (self.algorithm.block_data_order)(&mut self.state, pending, num_blocks);
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)]
140pub 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
147impl Context {
148 /// Constructs a new context.
149 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
157 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`.
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.
197 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)]
205 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/// ```
225pub fn digest(algorithm: &'static Algorithm, data: &[u8]) -> Digest {
226 let mut ctx: Context = 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)]
235pub struct Digest {
236 value: Output,
237 algorithm: &'static Algorithm,
238}
239
240impl Digest {
241 /// The algorithm that was used to calculate the digest value.
242 #[inline(always)]
243 pub fn algorithm(&self) -> &'static Algorithm {
244 self.algorithm
245 }
246}
247
248impl AsRef<[u8]> for Digest {
249 #[inline(always)]
250 fn as_ref(&self) -> &[u8] {
251 &self.value.0[..self.algorithm.output_len]
252 }
253}
254
255impl core::fmt::Debug for Digest {
256 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
257 write!(fmt, "{:?}:", self.algorithm)?;
258 debug::write_hex_bytes(fmt, self.as_ref())
259 }
260}
261
262/// A digest algorithm.
263pub struct Algorithm {
264 output_len: usize,
265 chaining_len: usize,
266 block_len: usize,
267
268 /// The length of the length in the padding.
269 len_len: usize,
270
271 block_data_order: unsafe extern "C" fn(state: &mut State, data: *const u8, num: c::size_t),
272 format_output: fn(input: State) -> Output,
273
274 initial_state: State,
275
276 id: AlgorithmID,
277}
278
279#[derive(Debug, Eq, PartialEq)]
280enum AlgorithmID {
281 SHA1,
282 SHA256,
283 SHA384,
284 SHA512,
285 SHA512_256,
286}
287
288impl PartialEq for Algorithm {
289 fn eq(&self, other: &Self) -> bool {
290 self.id == other.id
291 }
292}
293
294impl Eq for Algorithm {}
295
296derive_debug_via_id!(Algorithm);
297
298impl Algorithm {
299 /// The internal block length.
300 pub fn block_len(&self) -> usize {
301 self.block_len
302 }
303
304 /// The size of the chaining value of the digest function, in bytes.
305 ///
306 /// For non-truncated algorithms (SHA-1, SHA-256, SHA-512), this is equal
307 /// to [`Self::output_len()`]. For truncated algorithms (e.g. SHA-384,
308 /// SHA-512/256), this is equal to the length before truncation. This is
309 /// mostly helpful for determining the size of an HMAC key that is
310 /// appropriate for the digest algorithm.
311 pub fn chaining_len(&self) -> usize {
312 self.chaining_len
313 }
314
315 /// The length of a finalized digest.
316 pub fn output_len(&self) -> usize {
317 self.output_len
318 }
319}
320
321/// SHA-1 as specified in [FIPS 180-4]. Deprecated.
322///
323/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
324pub static SHA1_FOR_LEGACY_USE_ONLY: Algorithm = Algorithm {
325 output_len: sha1::OUTPUT_LEN,
326 chaining_len: sha1::CHAINING_LEN,
327 block_len: sha1::BLOCK_LEN,
328 len_len: 64 / 8,
329 block_data_order: sha1::block_data_order,
330 format_output: sha256_format_output,
331 initial_state: State {
332 as32: [
333 Wrapping(0x67452301u32),
334 Wrapping(0xefcdab89u32),
335 Wrapping(0x98badcfeu32),
336 Wrapping(0x10325476u32),
337 Wrapping(0xc3d2e1f0u32),
338 Wrapping(0),
339 Wrapping(0),
340 Wrapping(0),
341 ],
342 },
343 id: AlgorithmID::SHA1,
344};
345
346/// SHA-256 as specified in [FIPS 180-4].
347///
348/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
349pub static SHA256: Algorithm = Algorithm {
350 output_len: SHA256_OUTPUT_LEN,
351 chaining_len: SHA256_OUTPUT_LEN,
352 block_len: 512 / 8,
353 len_len: 64 / 8,
354 block_data_order: sha2::sha256_block_data_order,
355 format_output: sha256_format_output,
356 initial_state: State {
357 as32: [
358 Wrapping(0x6a09e667u32),
359 Wrapping(0xbb67ae85u32),
360 Wrapping(0x3c6ef372u32),
361 Wrapping(0xa54ff53au32),
362 Wrapping(0x510e527fu32),
363 Wrapping(0x9b05688cu32),
364 Wrapping(0x1f83d9abu32),
365 Wrapping(0x5be0cd19u32),
366 ],
367 },
368 id: AlgorithmID::SHA256,
369};
370
371/// SHA-384 as specified in [FIPS 180-4].
372///
373/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
374pub static SHA384: Algorithm = Algorithm {
375 output_len: SHA384_OUTPUT_LEN,
376 chaining_len: SHA512_OUTPUT_LEN,
377 block_len: SHA512_BLOCK_LEN,
378 len_len: SHA512_LEN_LEN,
379 block_data_order: sha2::sha512_block_data_order,
380 format_output: sha512_format_output,
381 initial_state: State {
382 as64: [
383 Wrapping(0xcbbb9d5dc1059ed8),
384 Wrapping(0x629a292a367cd507),
385 Wrapping(0x9159015a3070dd17),
386 Wrapping(0x152fecd8f70e5939),
387 Wrapping(0x67332667ffc00b31),
388 Wrapping(0x8eb44a8768581511),
389 Wrapping(0xdb0c2e0d64f98fa7),
390 Wrapping(0x47b5481dbefa4fa4),
391 ],
392 },
393 id: AlgorithmID::SHA384,
394};
395
396/// SHA-512 as specified in [FIPS 180-4].
397///
398/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
399pub static SHA512: Algorithm = Algorithm {
400 output_len: SHA512_OUTPUT_LEN,
401 chaining_len: SHA512_OUTPUT_LEN,
402 block_len: SHA512_BLOCK_LEN,
403 len_len: SHA512_LEN_LEN,
404 block_data_order: sha2::sha512_block_data_order,
405 format_output: sha512_format_output,
406 initial_state: State {
407 as64: [
408 Wrapping(0x6a09e667f3bcc908),
409 Wrapping(0xbb67ae8584caa73b),
410 Wrapping(0x3c6ef372fe94f82b),
411 Wrapping(0xa54ff53a5f1d36f1),
412 Wrapping(0x510e527fade682d1),
413 Wrapping(0x9b05688c2b3e6c1f),
414 Wrapping(0x1f83d9abfb41bd6b),
415 Wrapping(0x5be0cd19137e2179),
416 ],
417 },
418 id: AlgorithmID::SHA512,
419};
420
421/// SHA-512/256 as specified in [FIPS 180-4].
422///
423/// This is *not* the same as just truncating the output of SHA-512, as
424/// SHA-512/256 has its own initial state distinct from SHA-512's initial
425/// state.
426///
427/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
428pub static SHA512_256: Algorithm = Algorithm {
429 output_len: SHA512_256_OUTPUT_LEN,
430 chaining_len: SHA512_OUTPUT_LEN,
431 block_len: SHA512_BLOCK_LEN,
432 len_len: SHA512_LEN_LEN,
433 block_data_order: sha2::sha512_block_data_order,
434 format_output: sha512_format_output,
435 initial_state: State {
436 as64: [
437 Wrapping(0x22312194fc2bf72c),
438 Wrapping(0x9f555fa3c84c64c2),
439 Wrapping(0x2393b86b6f53b151),
440 Wrapping(0x963877195940eabd),
441 Wrapping(0x96283ee2a88effe3),
442 Wrapping(0xbe5e1e2553863992),
443 Wrapping(0x2b0199fc2c85b8aa),
444 Wrapping(0x0eb72ddc81c52ca2),
445 ],
446 },
447 id: AlgorithmID::SHA512_256,
448};
449
450#[derive(Clone, Copy)] // XXX: Why do we need to be `Copy`?
451#[repr(C)]
452union State {
453 as64: [Wrapping<u64>; sha2::CHAINING_WORDS],
454 as32: [Wrapping<u32>; sha2::CHAINING_WORDS],
455}
456
457#[derive(Clone, Copy)]
458struct Output([u8; MAX_OUTPUT_LEN]);
459
460/// The maximum block length ([`Algorithm::block_len()`]) of all the algorithms
461/// in this module.
462pub const MAX_BLOCK_LEN: usize = 1024 / 8;
463
464/// The maximum output length ([`Algorithm::output_len()`]) of all the
465/// algorithms in this module.
466pub const MAX_OUTPUT_LEN: usize = 512 / 8;
467
468/// The maximum chaining length ([`Algorithm::chaining_len()`]) of all the
469/// algorithms in this module.
470pub const MAX_CHAINING_LEN: usize = MAX_OUTPUT_LEN;
471
472fn sha256_format_output(input: State) -> Output {
473 let input: [Wrapping; 8] = unsafe { input.as32 };
474 format_output::<_, _, { core::mem::size_of::<u32>() }>(input, f:u32::to_be_bytes)
475}
476
477fn sha512_format_output(input: State) -> Output {
478 let input: [Wrapping; 8] = unsafe { input.as64 };
479 format_output::<_, _, { core::mem::size_of::<u64>() }>(input, f:u64::to_be_bytes)
480}
481
482#[inline]
483fn format_output<T, F, const N: usize>(input: [Wrapping<T>; sha2::CHAINING_WORDS], f: F) -> Output
484where
485 F: Fn(T) -> [u8; N],
486 T: Copy,
487{
488 let mut output: Output = Output([0; MAX_OUTPUT_LEN]);
489 outputimpl Iterator
490 .0
491 .chunks_mut(N)
492 .zip(input.iter().copied().map(|Wrapping(w: T)| f(w)))
493 .for_each(|(o: &mut [u8], i: [u8; N])| {
494 o.copy_from_slice(&i);
495 });
496 output
497}
498
499/// The length of the output of SHA-1, in bytes.
500pub const SHA1_OUTPUT_LEN: usize = sha1::OUTPUT_LEN;
501
502/// The length of the output of SHA-256, in bytes.
503pub const SHA256_OUTPUT_LEN: usize = 256 / 8;
504
505/// The length of the output of SHA-384, in bytes.
506pub const SHA384_OUTPUT_LEN: usize = 384 / 8;
507
508/// The length of the output of SHA-512, in bytes.
509pub const SHA512_OUTPUT_LEN: usize = 512 / 8;
510
511/// The length of the output of SHA-512/256, in bytes.
512pub const SHA512_256_OUTPUT_LEN: usize = 256 / 8;
513
514/// The length of a block for SHA-512-based algorithms, in bytes.
515const SHA512_BLOCK_LEN: usize = 1024 / 8;
516
517/// The length of the length field for SHA-512-based algorithms, in bytes.
518const SHA512_LEN_LEN: usize = 128 / 8;
519
520#[cfg(test)]
521mod tests {
522 mod max_input {
523 extern crate alloc;
524 use super::super::super::digest;
525 use crate::polyfill;
526 use alloc::vec;
527
528 macro_rules! max_input_tests {
529 ( $algorithm_name:ident ) => {
530 mod $algorithm_name {
531 use super::super::super::super::digest;
532
533 #[test]
534 fn max_input_test() {
535 super::max_input_test(&digest::$algorithm_name);
536 }
537
538 #[test]
539 #[should_panic]
540 fn too_long_input_test_block() {
541 super::too_long_input_test_block(&digest::$algorithm_name);
542 }
543
544 #[test]
545 #[should_panic]
546 fn too_long_input_test_byte() {
547 super::too_long_input_test_byte(&digest::$algorithm_name);
548 }
549 }
550 };
551 }
552
553 fn max_input_test(alg: &'static digest::Algorithm) {
554 let mut context = nearly_full_context(alg);
555 let next_input = vec![0u8; alg.block_len - 1];
556 context.update(&next_input);
557 let _ = context.finish(); // no panic
558 }
559
560 fn too_long_input_test_block(alg: &'static digest::Algorithm) {
561 let mut context = nearly_full_context(alg);
562 let next_input = vec![0u8; alg.block_len];
563 context.update(&next_input);
564 let _ = context.finish(); // should panic
565 }
566
567 fn too_long_input_test_byte(alg: &'static digest::Algorithm) {
568 let mut context = nearly_full_context(alg);
569 let next_input = vec![0u8; alg.block_len - 1];
570 context.update(&next_input); // no panic
571 context.update(&[0]);
572 let _ = context.finish(); // should panic
573 }
574
575 fn nearly_full_context(alg: &'static digest::Algorithm) -> digest::Context {
576 // All implementations currently support up to 2^64-1 bits
577 // of input; according to the spec, SHA-384 and SHA-512
578 // support up to 2^128-1, but that's not implemented yet.
579 let max_bytes = 1u64 << (64 - 3);
580 let max_blocks = max_bytes / polyfill::u64_from_usize(alg.block_len);
581 digest::Context {
582 block: digest::BlockContext {
583 state: alg.initial_state,
584 completed_data_blocks: max_blocks - 1,
585 algorithm: alg,
586 },
587 pending: [0u8; digest::MAX_BLOCK_LEN],
588 num_pending: 0,
589 }
590 }
591
592 max_input_tests!(SHA1_FOR_LEGACY_USE_ONLY);
593 max_input_tests!(SHA256);
594 max_input_tests!(SHA384);
595 max_input_tests!(SHA512);
596 }
597}
598