@@ -39,7 +39,7 @@ pub fn sha256_var<let N: u32>(msg: [u8; N], message_size: u64) -> HASH {
39
39
} else {
40
40
let (mut h , mut msg_block ) = process_full_blocks (msg , message_size , INITIAL_STATE );
41
41
42
- finalize_sha256_blocks ( msg , message_size , N , h , msg_block )
42
+ finalize_sha256_blocks ::< N >( message_size , h , msg_block )
43
43
}
44
44
}
45
45
@@ -119,14 +119,14 @@ pub(crate) fn process_full_blocks<let N: u32>(
119
119
// Consider a message with an unknown number of bytes, `msg_size. It can be seen that this will have `msg_size / BLOCK_SIZE` full blocks.
120
120
// - `states[i]` should then be the state after processing the first `i` blocks.
121
121
// - `blocks[i]` should then be the next message block after processing the first `i` blocks.
122
+ // blocks[first_partially_filled_block_index] is the last block that is partially filled or all 0 if the message is a multiple of the block size.
122
123
//
123
124
// In other words:
124
125
//
125
- // blocks = [block 1, block 2, ..., block N / BLOCK_SIZE, empty block]
126
+ // blocks = [block 1, block 2, ..., block N / BLOCK_SIZE, block N / BLOCK_SIZE + 1 ]
126
127
// states = [INITIAL_STATE, state after block 1, state after block 2, ..., state after block N / BLOCK_SIZE]
127
128
//
128
129
// We place the initial state in `states[0]` as in the case where the `message_size < BLOCK_SIZE` then there are no full blocks to process and no compressions should occur.
129
- // Similarly, we place an empty block in `blocks[N/BLOCK_SIZE]` as in the case where the `message_size == N` then the padding bits will be written to an empty block.
130
130
let mut blocks : [MSG_BLOCK ; N / BLOCK_SIZE + 1 ] = std::mem:: zeroed ();
131
131
let mut states : [STATE ; N / BLOCK_SIZE + 1 ] = [h ; N / BLOCK_SIZE + 1 ];
132
132
@@ -153,6 +153,19 @@ pub(crate) fn process_full_blocks<let N: u32>(
153
153
states [i + 1 ] = sha256_compression (new_msg_block , states [i ]);
154
154
}
155
155
156
+ // If message_size/BLOCK_SIZE == N/BLOCK_SIZE, and message_size/BLOCK_SIZE has a remainder, we need to process the last block.
157
+ if message_size % BLOCK_SIZE != 0 {
158
+ let new_msg_block =
159
+ // Safety: separate verification function
160
+ unsafe { build_msg_block (msg , message_size , BLOCK_SIZE * num_blocks ) };
161
+
162
+ // Verify the block we are compressing was appropriately constructed
163
+ verify_msg_block (msg , message_size , new_msg_block , BLOCK_SIZE * num_blocks );
164
+ verify_msg_block_zeros (new_msg_block , message_size % BLOCK_SIZE , INT_BLOCK_SIZE );
165
+
166
+ blocks [num_blocks ] = new_msg_block ;
167
+ }
168
+
156
169
(states [first_partially_filled_block_index ], blocks [first_partially_filled_block_index ])
157
170
}
158
171
@@ -241,13 +254,6 @@ fn verify_msg_block<let N: u32>(
241
254
}
242
255
}
243
256
244
- // Verify the block we are compressing was appropriately padded with zeros by `build_msg_block`.
245
- // This is only relevant for the last, potentially partially filled block.
246
- fn verify_msg_block_padding (msg_block : MSG_BLOCK , msg_byte_ptr : BLOCK_BYTE_PTR ) {
247
- // Check all the way to the end of the block.
248
- verify_msg_block_zeros (msg_block , msg_byte_ptr , INT_BLOCK_SIZE );
249
- }
250
-
251
257
// Verify that a region of ints in the message block are (partially) zeroed,
252
258
// up to an (exclusive) maximum which can either be the end of the block
253
259
// or just where the size is to be written.
@@ -512,33 +518,11 @@ fn hash_final_block(msg_block: MSG_BLOCK, mut state: STATE) -> HASH {
512
518
}
513
519
514
520
pub (crate ) fn finalize_sha256_blocks <let N : u32 >(
515
- msg : [u8 ; N ],
516
521
message_size : u32 ,
517
- total_len : u32 ,
518
522
mut h : STATE ,
519
523
mut msg_block : MSG_BLOCK ,
520
524
) -> HASH {
521
525
let mut msg_byte_ptr = message_size % BLOCK_SIZE ;
522
- let modulo = total_len % BLOCK_SIZE ;
523
- // Handle setup of the final msg block.
524
- // This case is only hit if the msg is less than the block size,
525
- // or our message cannot be evenly split into blocks.
526
- if modulo != 0 {
527
- let num_blocks = total_len / BLOCK_SIZE ;
528
- let msg_start = BLOCK_SIZE * num_blocks ;
529
- let new_msg_block =
530
- // Safety: separate verification function
531
- unsafe { build_msg_block (msg , message_size , msg_start ) };
532
-
533
- if msg_start < message_size {
534
- msg_block = new_msg_block ;
535
- }
536
-
537
- verify_msg_block (msg , message_size , msg_block , msg_start );
538
- if msg_start < message_size {
539
- verify_msg_block_padding (msg_block , msg_byte_ptr );
540
- }
541
- }
542
526
543
527
// If we had modulo == 0 then it means the last block was full,
544
528
// and we can reset the pointer to zero to overwrite it.
@@ -630,7 +614,7 @@ pub fn partial_sha256_var_end<let N: u32>(
630
614
}
631
615
} else {
632
616
let (mut h , mut msg_block ) = process_full_blocks (msg , message_size , h );
633
- finalize_sha256_blocks ( msg , real_message_size , N , h , msg_block )
617
+ finalize_sha256_blocks ::< N >( real_message_size , h , msg_block )
634
618
}
635
619
}
636
620
0 commit comments