1#![no_std]
35#![doc(
36 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
37 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
38)]
39#![warn(missing_docs, rust_2018_idioms)]
40
41mod compressor;
42mod consts;
43
44pub use compressor::f8_impl;
46
47pub use digest::{self, Digest};
48
49use crate::compressor::Compressor;
50use core::fmt;
51use digest::{
52 block_buffer::Eager,
53 core_api::{
54 AlgorithmName, Block, Buffer, BufferKindUser, CoreWrapper, CtVariableCoreWrapper,
55 TruncSide, UpdateCore, VariableOutputCore,
56 },
57 crypto_common::{BlockSizeUser, OutputSizeUser},
58 generic_array::typenum::{Unsigned, U28, U32, U48, U64},
59 HashMarker, InvalidOutputSize, Output,
60};
61
62#[derive(Clone)]
64pub struct JhCore {
65 state: Compressor,
66 block_len: u64,
67}
68
69impl HashMarker for JhCore {}
70
71impl BlockSizeUser for JhCore {
72 type BlockSize = U64;
73}
74
75impl BufferKindUser for JhCore {
76 type BufferKind = Eager;
77}
78
79impl OutputSizeUser for JhCore {
80 type OutputSize = U64;
81}
82
83impl UpdateCore for JhCore {
84 #[inline]
85 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
86 self.block_len = self.block_len.wrapping_add(blocks.len() as u64);
87 for b in blocks {
88 self.state.update(b);
89 }
90 }
91}
92
93impl VariableOutputCore for JhCore {
94 const TRUNC_SIDE: TruncSide = TruncSide::Right;
95
96 #[inline]
97 fn new(output_size: usize) -> Result<Self, InvalidOutputSize> {
98 let h0 = match output_size {
99 28 => consts::JH224_H0,
100 32 => consts::JH256_H0,
101 48 => consts::JH384_H0,
102 64 => consts::JH512_H0,
103 _ => return Err(InvalidOutputSize),
104 };
105 Ok(Self {
106 state: Compressor::new(h0),
107 block_len: 0,
108 })
109 }
110
111 #[inline]
112 fn finalize_variable_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
113 let Self { state, block_len } = self;
114 let bit_len = block_len
115 .wrapping_mul(Self::BlockSize::U64)
116 .wrapping_add(buffer.get_pos() as u64)
117 .wrapping_mul(8);
118 if buffer.get_pos() == 0 {
119 buffer.len64_padding_be(bit_len, |b| state.update(b));
120 } else {
121 buffer.digest_pad(0x80, &[], |b| state.update(b));
122 buffer.digest_pad(0, &bit_len.to_be_bytes(), |b| state.update(b));
123 }
124 out.copy_from_slice(&self.state.finalize()[64..]);
125 }
126}
127
128impl AlgorithmName for JhCore {
129 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 f.write_str("Jh")
131 }
132}
133
134impl fmt::Debug for JhCore {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 f.write_str("JhCore { ... }")
137 }
138}
139
140pub type Jh224 = CoreWrapper<CtVariableCoreWrapper<JhCore, U28>>;
142pub type Jh256 = CoreWrapper<CtVariableCoreWrapper<JhCore, U32>>;
144pub type Jh384 = CoreWrapper<CtVariableCoreWrapper<JhCore, U48>>;
146pub type Jh512 = CoreWrapper<CtVariableCoreWrapper<JhCore, U64>>;