99#![ warn( missing_docs) ]
1010
1111pub use digest:: { self , Digest } ;
12-
13- use core:: { convert:: TryInto , fmt} ;
14- #[ cfg( feature = "zeroize" ) ]
15- use digest:: zeroize:: { Zeroize , ZeroizeOnDrop } ;
1612use digest:: {
17- HashMarker , InvalidOutputSize , Output ,
18- block_buffer:: Eager ,
19- core_api:: {
20- AlgorithmName , Block , BlockSizeUser , Buffer , BufferKindUser , CoreWrapper ,
21- CtVariableCoreWrapper , OutputSizeUser , RtVariableCoreWrapper , TruncSide , UpdateCore ,
22- VariableOutputCore ,
23- } ,
24- crypto_common:: hazmat:: { DeserializeStateError , SerializableState , SerializedState } ,
25- typenum:: { U28 , U32 , U48 , U64 , U72 , U128 , U136 , Unsigned } ,
13+ core_api:: { CoreWrapper , CtVariableCoreWrapper , RtVariableCoreWrapper } ,
14+ typenum:: { U28 , U32 , U48 , U64 } ,
2615} ;
2716
28- mod compress1024;
29- mod compress512;
30- mod tables;
17+ mod consts;
18+ mod long;
19+ mod long_compress;
20+ mod short;
21+ mod short_compress;
22+ pub ( crate ) mod utils;
3123
32- /// Lowest-level core hasher state of the short Kupyna variant.
33- #[ derive( Clone ) ]
34- pub struct KupynaShortVarCore {
35- state : [ u64 ; compress512:: COLS ] ,
36- blocks_len : u64 ,
37- }
24+ pub use long:: KupynaLongVarCore ;
25+ pub use short:: KupynaShortVarCore ;
3826
3927/// Short Kupyna variant which allows to choose output size at runtime.
4028pub type KupynaShortVar = RtVariableCoreWrapper < KupynaShortVarCore > ;
@@ -43,279 +31,18 @@ pub type KupynaShortCore<OutSize> = CtVariableCoreWrapper<KupynaShortVarCore, Ou
4331/// Hasher state of the short Kupyna variant generic over output size.
4432pub type KupynaShort < OutSize > = CoreWrapper < KupynaShortCore < OutSize > > ;
4533
46- /// Kupyna-224 hasher state.
47- pub type Kupyna224 = CoreWrapper < KupynaShortCore < U28 > > ;
48- /// Kupyna-256 hasher state.
49- pub type Kupyna256 = CoreWrapper < KupynaShortCore < U32 > > ;
50-
51- impl HashMarker for KupynaShortVarCore { }
52-
53- impl BlockSizeUser for KupynaShortVarCore {
54- type BlockSize = U64 ;
55- }
56-
57- impl BufferKindUser for KupynaShortVarCore {
58- type BufferKind = Eager ;
59- }
60-
61- impl UpdateCore for KupynaShortVarCore {
62- #[ inline]
63- fn update_blocks ( & mut self , blocks : & [ Block < Self > ] ) {
64- self . blocks_len += blocks. len ( ) as u64 ;
65- for block in blocks {
66- compress512:: compress ( & mut self . state , block. as_ref ( ) ) ;
67- }
68- }
69- }
70-
71- impl OutputSizeUser for KupynaShortVarCore {
72- type OutputSize = U32 ;
73- }
74-
75- impl VariableOutputCore for KupynaShortVarCore {
76- const TRUNC_SIDE : TruncSide = TruncSide :: Right ;
77-
78- #[ inline]
79- fn new ( output_size : usize ) -> Result < Self , InvalidOutputSize > {
80- if output_size > Self :: OutputSize :: USIZE {
81- return Err ( InvalidOutputSize ) ;
82- }
83- let mut state = [ 0 ; compress512:: COLS ] ;
84- state[ 0 ] = 0x40 ;
85- state[ 0 ] <<= 56 ;
86- let blocks_len = 0 ;
87- Ok ( Self { state, blocks_len } )
88- }
89-
90- fn finalize_variable_core ( & mut self , buffer : & mut Buffer < Self > , out : & mut Output < Self > ) {
91- let block_size = Self :: BlockSize :: USIZE as u128 ;
92- let msg_len_bytes = ( self . blocks_len as u128 ) * block_size + ( buffer. get_pos ( ) as u128 ) ;
93- let msg_len_bits = 8 * msg_len_bytes;
94-
95- buffer. digest_pad ( 0x80 , & msg_len_bits. to_le_bytes ( ) [ 0 ..12 ] , |block| {
96- compress512:: compress ( & mut self . state , block. as_ref ( ) ) ;
97- } ) ;
98-
99- let mut state_u8 = [ 0u8 ; 64 ] ;
100- for ( src, dst) in self . state . iter ( ) . zip ( state_u8. chunks_exact_mut ( 8 ) ) {
101- dst. copy_from_slice ( & src. to_be_bytes ( ) ) ;
102- }
103-
104- // Call t_xor_l with u8 array
105- let t_xor_ult_processed_block = compress512:: t_xor_l ( state_u8) ;
106-
107- let result_u8 = compress512:: xor_bytes ( state_u8, t_xor_ult_processed_block) ;
108-
109- // Convert result back to u64s
110- let mut res = [ 0u64 ; 8 ] ;
111- for ( dst, src) in res. iter_mut ( ) . zip ( result_u8. chunks_exact ( 8 ) ) {
112- * dst = u64:: from_be_bytes ( src. try_into ( ) . unwrap ( ) ) ;
113- }
114- let n = compress512:: COLS / 2 ;
115- for ( chunk, v) in out. chunks_exact_mut ( 8 ) . zip ( res[ n..] . iter ( ) ) {
116- chunk. copy_from_slice ( & v. to_be_bytes ( ) ) ;
117- }
118- }
119- }
120-
121- impl AlgorithmName for KupynaShortVarCore {
122- #[ inline]
123- fn write_alg_name ( f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
124- f. write_str ( "KupynaShort" )
125- }
126- }
127-
128- impl fmt:: Debug for KupynaShortVarCore {
129- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
130- f. write_str ( "KupynaShortVarCore { ... }" )
131- }
132- }
133-
134- impl Drop for KupynaShortVarCore {
135- fn drop ( & mut self ) {
136- #[ cfg( feature = "zeroize" ) ]
137- {
138- self . state . zeroize ( ) ;
139- self . blocks_len . zeroize ( ) ;
140- }
141- }
142- }
143-
144- impl SerializableState for KupynaShortVarCore {
145- type SerializedStateSize = U72 ;
146-
147- fn serialize ( & self ) -> SerializedState < Self > {
148- let mut serialized_state = SerializedState :: < Self > :: default ( ) ;
149-
150- for ( val, chunk) in self . state . iter ( ) . zip ( serialized_state. chunks_exact_mut ( 8 ) ) {
151- chunk. copy_from_slice ( & val. to_le_bytes ( ) ) ;
152- }
153-
154- serialized_state[ 64 ..] . copy_from_slice ( & self . blocks_len . to_le_bytes ( ) ) ;
155- serialized_state
156- }
157-
158- fn deserialize (
159- serialized_state : & SerializedState < Self > ,
160- ) -> Result < Self , DeserializeStateError > {
161- let ( serialized_state, serialized_block_len) = serialized_state. split :: < U64 > ( ) ;
162-
163- let mut state = [ 0 ; compress512:: COLS ] ;
164- for ( val, chunk) in state. iter_mut ( ) . zip ( serialized_state. chunks_exact ( 8 ) ) {
165- * val = u64:: from_le_bytes ( chunk. try_into ( ) . unwrap ( ) ) ;
166- }
167-
168- let blocks_len = u64:: from_le_bytes ( * serialized_block_len. as_ref ( ) ) ;
169-
170- Ok ( Self { state, blocks_len } )
171- }
172- }
173-
174- #[ cfg( feature = "zeroize" ) ]
175- impl ZeroizeOnDrop for KupynaShortVarCore { }
176-
177- /// Lowest-level core hasher state of the long Kupyna variant.
178- #[ derive( Clone ) ]
179- pub struct KupynaLongVarCore {
180- state : [ u64 ; compress1024:: COLS ] ,
181- blocks_len : u64 ,
182- }
183-
18434/// Long Kupyna variant which allows to choose output size at runtime.
18535pub type KupynaLongVar = RtVariableCoreWrapper < KupynaLongVarCore > ;
18636/// Core hasher state of the long Kupyna variant generic over output size.
18737pub type KupynaLongCore < OutSize > = CtVariableCoreWrapper < KupynaLongVarCore , OutSize > ;
18838/// Hasher state of the long Kupyna variant generic over output size.
18939pub type KupynaLong < OutSize > = CoreWrapper < KupynaLongCore < OutSize > > ;
19040
41+ /// Kupyna-224 hasher state.
42+ pub type Kupyna224 = CoreWrapper < KupynaShortCore < U28 > > ;
43+ /// Kupyna-256 hasher state.
44+ pub type Kupyna256 = CoreWrapper < KupynaShortCore < U32 > > ;
19145/// Kupyna-384 hasher state.
19246pub type Kupyna384 = CoreWrapper < KupynaLongCore < U48 > > ;
19347/// Kupyna-512 hasher state.
19448pub type Kupyna512 = CoreWrapper < KupynaLongCore < U64 > > ;
195-
196- impl HashMarker for KupynaLongVarCore { }
197-
198- impl BlockSizeUser for KupynaLongVarCore {
199- type BlockSize = U128 ;
200- }
201-
202- impl BufferKindUser for KupynaLongVarCore {
203- type BufferKind = Eager ;
204- }
205-
206- impl UpdateCore for KupynaLongVarCore {
207- #[ inline]
208- fn update_blocks ( & mut self , blocks : & [ Block < Self > ] ) {
209- self . blocks_len += blocks. len ( ) as u64 ;
210- for block in blocks {
211- compress1024:: compress ( & mut self . state , block. as_ref ( ) ) ;
212- }
213- }
214- }
215-
216- impl OutputSizeUser for KupynaLongVarCore {
217- type OutputSize = U64 ;
218- }
219-
220- impl VariableOutputCore for KupynaLongVarCore {
221- const TRUNC_SIDE : TruncSide = TruncSide :: Right ;
222-
223- #[ inline]
224- fn new ( output_size : usize ) -> Result < Self , InvalidOutputSize > {
225- if output_size > Self :: OutputSize :: USIZE {
226- return Err ( InvalidOutputSize ) ;
227- }
228- let mut state = [ 0 ; compress1024:: COLS ] ;
229- state[ 0 ] = 0x80 ;
230- state[ 0 ] <<= 56 ;
231- let blocks_len = 0 ;
232- Ok ( Self { state, blocks_len } )
233- }
234-
235- #[ inline]
236- fn finalize_variable_core ( & mut self , buffer : & mut Buffer < Self > , out : & mut Output < Self > ) {
237- let block_size = Self :: BlockSize :: USIZE as u128 ;
238- let msg_len_bytes = ( self . blocks_len as u128 ) * block_size + ( buffer. get_pos ( ) as u128 ) ;
239- let msg_len_bits = 8 * msg_len_bytes;
240-
241- buffer. digest_pad ( 0x80 , & msg_len_bits. to_le_bytes ( ) [ 0 ..12 ] , |block| {
242- compress1024:: compress ( & mut self . state , block. as_ref ( ) ) ;
243- } ) ;
244-
245- let mut state_u8 = [ 0u8 ; 128 ] ;
246- for ( src, dst) in self . state . iter ( ) . zip ( state_u8. chunks_exact_mut ( 8 ) ) {
247- dst. copy_from_slice ( & src. to_be_bytes ( ) ) ;
248- }
249-
250- // Call t_xor_l with u8 array
251- let t_xor_ult_processed_block = compress1024:: t_xor_l ( state_u8) ;
252-
253- let result_u8 = compress1024:: xor_bytes ( state_u8, t_xor_ult_processed_block) ;
254-
255- // Convert result back to u64s
256- let mut res = [ 0u64 ; 16 ] ;
257- for ( dst, src) in res. iter_mut ( ) . zip ( result_u8. chunks_exact ( 8 ) ) {
258- * dst = u64:: from_be_bytes ( src. try_into ( ) . unwrap ( ) ) ;
259- }
260- let n = compress1024:: COLS / 2 ;
261- for ( chunk, v) in out. chunks_exact_mut ( 8 ) . zip ( res[ n..] . iter ( ) ) {
262- chunk. copy_from_slice ( & v. to_be_bytes ( ) ) ;
263- }
264- }
265- }
266-
267- impl AlgorithmName for KupynaLongVarCore {
268- #[ inline]
269- fn write_alg_name ( f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
270- f. write_str ( "KupynaLong" )
271- }
272- }
273-
274- impl fmt:: Debug for KupynaLongVarCore {
275- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
276- f. write_str ( "KupynaLongVarCore { ... }" )
277- }
278- }
279-
280- impl Drop for KupynaLongVarCore {
281- fn drop ( & mut self ) {
282- #[ cfg( feature = "zeroize" ) ]
283- {
284- self . state . zeroize ( ) ;
285- self . blocks_len . zeroize ( ) ;
286- }
287- }
288- }
289-
290- impl SerializableState for KupynaLongVarCore {
291- type SerializedStateSize = U136 ;
292-
293- fn serialize ( & self ) -> SerializedState < Self > {
294- let mut serialized_state = SerializedState :: < Self > :: default ( ) ;
295-
296- for ( val, chunk) in self . state . iter ( ) . zip ( serialized_state. chunks_exact_mut ( 8 ) ) {
297- chunk. copy_from_slice ( & val. to_le_bytes ( ) ) ;
298- }
299-
300- serialized_state[ 128 ..] . copy_from_slice ( & self . blocks_len . to_le_bytes ( ) ) ;
301- serialized_state
302- }
303-
304- fn deserialize (
305- serialized_state : & SerializedState < Self > ,
306- ) -> Result < Self , DeserializeStateError > {
307- let ( serialized_state, serialized_block_len) = serialized_state. split :: < U128 > ( ) ;
308-
309- let mut state = [ 0 ; compress1024:: COLS ] ;
310- for ( val, chunk) in state. iter_mut ( ) . zip ( serialized_state. chunks_exact ( 8 ) ) {
311- * val = u64:: from_le_bytes ( chunk. try_into ( ) . unwrap ( ) ) ;
312- }
313-
314- let blocks_len = u64:: from_le_bytes ( * serialized_block_len. as_ref ( ) ) ;
315-
316- Ok ( Self { state, blocks_len } )
317- }
318- }
319-
320- #[ cfg( feature = "zeroize" ) ]
321- impl ZeroizeOnDrop for KupynaLongVarCore { }
0 commit comments