1#![no_std]
32#![doc(
33 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
34 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
35)]
36#![forbid(unsafe_code)]
37#![warn(missing_docs, rust_2018_idioms)]
38
39pub use digest::{self, Digest};
40
41use core::{fmt, slice::from_ref};
42use digest::{
43 block_buffer::Eager,
44 core_api::{
45 AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore,
46 OutputSizeUser, Reset, UpdateCore,
47 },
48 typenum::{Unsigned, U32, U64},
49 HashMarker, Output,
50};
51
52mod compress;
53mod consts;
54
55use compress::compress;
56
57#[derive(Clone)]
59pub struct Sm3Core {
60 block_len: u64,
61 h: [u32; 8],
62}
63
64impl HashMarker for Sm3Core {}
65
66impl BlockSizeUser for Sm3Core {
67 type BlockSize = U64;
68}
69
70impl BufferKindUser for Sm3Core {
71 type BufferKind = Eager;
72}
73
74impl OutputSizeUser for Sm3Core {
75 type OutputSize = U32;
76}
77
78impl UpdateCore for Sm3Core {
79 #[inline]
80 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
81 self.block_len += blocks.len() as u64;
82 compress(&mut self.h, blocks);
83 }
84}
85
86impl FixedOutputCore for Sm3Core {
87 #[inline]
88 fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
89 let bs = Self::BlockSize::U64;
90 let bit_len = 8 * (buffer.get_pos() as u64 + bs * self.block_len);
91
92 let mut h = self.h;
93 buffer.len64_padding_be(bit_len, |b| compress(&mut h, from_ref(b)));
94 for (chunk, v) in out.chunks_exact_mut(4).zip(h.iter()) {
95 chunk.copy_from_slice(&v.to_be_bytes());
96 }
97 }
98}
99
100impl Default for Sm3Core {
101 #[inline]
102 fn default() -> Self {
103 Self {
104 h: consts::H0,
105 block_len: 0,
106 }
107 }
108}
109
110impl Reset for Sm3Core {
111 #[inline]
112 fn reset(&mut self) {
113 *self = Default::default();
114 }
115}
116
117impl AlgorithmName for Sm3Core {
118 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 f.write_str("Sm3")
120 }
121}
122
123impl fmt::Debug for Sm3Core {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 f.write_str("Sm3Core { ... }")
126 }
127}
128
129pub type Sm3 = CoreWrapper<Sm3Core>;