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}
;
11 /// Structure that keeps state of the Sha-256 operation and
12 /// contains the logic necessary to perform the final calculations.
16 buffer
: BlockBuffer
<BlockSize
>,
21 fn new(h
: &[u32; STATE_LEN
]) -> Engine256
{
24 buffer
: Default
::default(),
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
));
36 fn finish(&mut self) {
37 let s
= &mut self.state
;
40 .len64_padding_be(l
, |b
| compress256(s
, from_ref(b
)));
43 fn reset(&mut self, h
: &[u32; STATE_LEN
]) {
50 /// The SHA-256 hash algorithm with the SHA-256 initial hash value.
56 impl Default
for Sha256
{
57 fn default() -> Self {
59 engine
: Engine256
::new(&H256
),
64 impl BlockInput
for Sha256
{
65 type BlockSize
= BlockSize
;
68 impl Update
for Sha256
{
69 fn update(&mut self, input
: impl AsRef
<[u8]>) {
70 self.engine
.update(input
.as_ref());
74 impl FixedOutputDirty
for Sha256
{
75 type OutputSize
= U32
;
77 fn finalize_into_dirty(&mut self, out
: &mut digest
::Output
<Self>) {
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());
86 impl Reset
for Sha256
{
88 self.engine
.reset(&H256
);
92 /// The SHA-256 hash algorithm with the SHA-224 initial hash value. The result
93 /// is truncated to 224 bits.
99 impl Default
for Sha224
{
100 fn default() -> Self {
102 engine
: Engine256
::new(&H224
),
107 impl BlockInput
for Sha224
{
108 type BlockSize
= BlockSize
;
111 impl Update
for Sha224
{
112 fn update(&mut self, input
: impl AsRef
<[u8]>) {
113 self.engine
.update(input
.as_ref());
117 impl FixedOutputDirty
for Sha224
{
118 type OutputSize
= U28
;
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());
129 impl Reset
for Sha224
{
130 fn reset(&mut self) {
131 self.engine
.reset(&H224
);
135 opaque_debug
::implement
!(Sha224
);
136 opaque_debug
::implement
!(Sha256
);
138 digest
::impl_write
!(Sha224
);
139 digest
::impl_write
!(Sha256
);
142 if #[cfg(all(feature = "asm", target_arch = "aarch64", target_os = "linux"))] {
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
);
153 } else if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
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
)