sm3/
lib.rs

1//! An implementation of the [SM3] cryptographic hash function defined
2//! in OSCCA GM/T 0004-2012.
3//!
4//! # Usage
5//! Hasher functionality is expressed via traits defined in the [`digest`]
6//! crate.
7//!
8//! ```rust
9//! use hex_literal::hex;
10//! use sm3::{Digest, Sm3};
11//!
12//! // create a hasher object, to use it do not forget to import `Digest` trait
13//! let mut hasher = Sm3::new();
14//!
15//! // write input message
16//! hasher.update(b"hello world");
17//!
18//! // read hash digest and consume hasher
19//! let result = hasher.finalize();
20//!
21//! assert_eq!(result[..], hex!("
22//!     44f0061e69fa6fdfc290c494654a05dc0c053da7e5c52b84ef93a9d67d3fff88
23//! ")[..]);
24//! ```
25//!
26//! Also see [RustCrypto/hashes] readme.
27//!
28//! [SM3]: https://en.wikipedia.org/wiki/SM3_(hash_function)
29//! [RustCrypto/hashes]: https://github.com/RustCrypto/hashes
30
31#![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/// Core SM3 hasher state.
58#[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
129/// Sm3 hasher state.
130pub type Sm3 = CoreWrapper<Sm3Core>;