]> git.proxmox.com Git - rustc.git/blob - vendor/sha2/src/sha256.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / vendor / sha2 / src / sha256.rs
1 //! SHA-256
2 use crate::consts::{H224, H256, STATE_LEN};
3 use block_buffer::BlockBuffer;
4 use core::slice::from_ref;
5 use digest::consts::{U28, U32, U64};
6 use digest::generic_array::GenericArray;
7 use digest::{BlockInput, FixedOutputDirty, Reset, Update};
8
9 type BlockSize = U64;
10
11 /// Structure that keeps state of the Sha-256 operation and
12 /// contains the logic necessary to perform the final calculations.
13 #[derive(Clone)]
14 struct Engine256 {
15 len: u64,
16 buffer: BlockBuffer<BlockSize>,
17 state: [u32; 8],
18 }
19
20 impl Engine256 {
21 fn new(h: &[u32; STATE_LEN]) -> Engine256 {
22 Engine256 {
23 len: 0,
24 buffer: Default::default(),
25 state: *h,
26 }
27 }
28
29 fn update(&mut self, input: &[u8]) {
30 // Assumes that input.len() can be converted to u64 without overflow
31 self.len += (input.len() as u64) << 3;
32 let s = &mut self.state;
33 self.buffer.input_blocks(input, |b| compress256(s, b));
34 }
35
36 fn finish(&mut self) {
37 let s = &mut self.state;
38 let l = self.len;
39 self.buffer
40 .len64_padding_be(l, |b| compress256(s, from_ref(b)));
41 }
42
43 fn reset(&mut self, h: &[u32; STATE_LEN]) {
44 self.len = 0;
45 self.buffer.reset();
46 self.state = *h;
47 }
48 }
49
50 /// The SHA-256 hash algorithm with the SHA-256 initial hash value.
51 #[derive(Clone)]
52 pub struct Sha256 {
53 engine: Engine256,
54 }
55
56 impl Default for Sha256 {
57 fn default() -> Self {
58 Sha256 {
59 engine: Engine256::new(&H256),
60 }
61 }
62 }
63
64 impl BlockInput for Sha256 {
65 type BlockSize = BlockSize;
66 }
67
68 impl Update for Sha256 {
69 fn update(&mut self, input: impl AsRef<[u8]>) {
70 self.engine.update(input.as_ref());
71 }
72 }
73
74 impl FixedOutputDirty for Sha256 {
75 type OutputSize = U32;
76
77 fn finalize_into_dirty(&mut self, out: &mut digest::Output<Self>) {
78 self.engine.finish();
79 let s = self.engine.state;
80 for (chunk, v) in out.chunks_exact_mut(4).zip(s.iter()) {
81 chunk.copy_from_slice(&v.to_be_bytes());
82 }
83 }
84 }
85
86 impl Reset for Sha256 {
87 fn reset(&mut self) {
88 self.engine.reset(&H256);
89 }
90 }
91
92 /// The SHA-256 hash algorithm with the SHA-224 initial hash value. The result
93 /// is truncated to 224 bits.
94 #[derive(Clone)]
95 pub struct Sha224 {
96 engine: Engine256,
97 }
98
99 impl Default for Sha224 {
100 fn default() -> Self {
101 Sha224 {
102 engine: Engine256::new(&H224),
103 }
104 }
105 }
106
107 impl BlockInput for Sha224 {
108 type BlockSize = BlockSize;
109 }
110
111 impl Update for Sha224 {
112 fn update(&mut self, input: impl AsRef<[u8]>) {
113 self.engine.update(input.as_ref());
114 }
115 }
116
117 impl FixedOutputDirty for Sha224 {
118 type OutputSize = U28;
119
120 fn finalize_into_dirty(&mut self, out: &mut digest::Output<Self>) {
121 self.engine.finish();
122 let s = &self.engine.state[..7];
123 for (chunk, v) in out.chunks_exact_mut(4).zip(s.iter()) {
124 chunk.copy_from_slice(&v.to_be_bytes());
125 }
126 }
127 }
128
129 impl Reset for Sha224 {
130 fn reset(&mut self) {
131 self.engine.reset(&H224);
132 }
133 }
134
135 opaque_debug::implement!(Sha224);
136 opaque_debug::implement!(Sha256);
137
138 digest::impl_write!(Sha224);
139 digest::impl_write!(Sha256);
140
141 cfg_if::cfg_if! {
142 if #[cfg(all(feature = "asm", target_arch = "aarch64", target_os = "linux"))] {
143 mod soft;
144 mod aarch64;
145 use aarch64::compress;
146 } else if #[cfg(all(feature = "asm", any(target_arch = "x86", target_arch = "x86_64")))] {
147 // TODO: replace after sha2-asm rework
148 fn compress(state: &mut [u32; 8], blocks: &[[u8; 64]]) {
149 for block in blocks {
150 sha2_asm::compress256(state, block);
151 }
152 }
153 } else if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
154 mod soft;
155 mod x86;
156 use x86::compress;
157 } else {
158 mod soft;
159 use soft::compress;
160 }
161 }
162
163 pub fn compress256(state: &mut [u32; 8], blocks: &[GenericArray<u8, U64>]) {
164 // SAFETY: GenericArray<u8, U64> and [u8; 64] have
165 // exactly the same memory layout
166 #[allow(unsafe_code)]
167 let blocks: &[[u8; 64]] = unsafe { &*(blocks as *const _ as *const [[u8; 64]]) };
168 compress(state, blocks)
169 }