@@ -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
@@ -152,8 +152,22 @@ pub(crate) fn process_full_blocks<let N: u32>(
152
152
blocks [i ] = new_msg_block ;
153
153
states [i + 1 ] = sha256_compression (new_msg_block , states [i ]);
154
154
}
155
+ // If message_size/BLOCK_SIZE == N/BLOCK_SIZE, and there is a remainder, we need to process the last block.
156
+ if N % BLOCK_SIZE != 0 {
157
+ let new_msg_block =
158
+ // Safety: separate verification function
159
+ unsafe { build_msg_block (msg , message_size , BLOCK_SIZE * num_blocks ) };
160
+
161
+ // Verify the block we are compressing was appropriately constructed
162
+ verify_msg_block (msg , message_size , new_msg_block , BLOCK_SIZE * num_blocks );
163
+
164
+ blocks [num_blocks ] = new_msg_block ;
165
+ }
155
166
156
- (states [first_partially_filled_block_index ], blocks [first_partially_filled_block_index ])
167
+ // verify the 0 padding is correct for the last block
168
+ let final_block = blocks [first_partially_filled_block_index ];
169
+ verify_msg_block_zeros (final_block , message_size % BLOCK_SIZE , INT_BLOCK_SIZE );
170
+ (states [first_partially_filled_block_index ], final_block )
157
171
}
158
172
159
173
// Take `BLOCK_SIZE` number of bytes from `msg` starting at `msg_start` and pack them into a `MSG_BLOCK`.
@@ -241,13 +255,6 @@ fn verify_msg_block<let N: u32>(
241
255
}
242
256
}
243
257
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
258
// Verify that a region of ints in the message block are (partially) zeroed,
252
259
// up to an (exclusive) maximum which can either be the end of the block
253
260
// or just where the size is to be written.
@@ -256,11 +263,6 @@ fn verify_msg_block_zeros(
256
263
mut msg_byte_ptr : BLOCK_BYTE_PTR ,
257
264
max_int_byte_ptr : u32 ,
258
265
) {
259
- // This variable is used to get around the compiler under-constrained check giving a warning.
260
- // We want to check against a constant zero, but if it does not come from the circuit inputs
261
- // or return values the compiler check will issue a warning.
262
- let zero = msg_block [0 ] - msg_block [0 ];
263
-
264
266
// First integer which is supposed to be (partially) zero.
265
267
let mut int_byte_ptr = msg_byte_ptr / INT_SIZE ;
266
268
@@ -275,14 +277,14 @@ fn verify_msg_block_zeros(
275
277
} else {
276
278
TWO_POW_8
277
279
};
278
- assert_eq (msg_block [int_byte_ptr ] % mask , zero );
280
+ assert_eq (msg_block [int_byte_ptr ] % mask , 0 );
279
281
int_byte_ptr = int_byte_ptr + 1 ;
280
282
}
281
283
282
284
// Check the rest of the items.
283
285
for i in 0 ..max_int_byte_ptr {
284
286
if i >= int_byte_ptr {
285
- assert_eq (msg_block [i ], zero );
287
+ assert_eq (msg_block [i ], 0 );
286
288
}
287
289
}
288
290
}
@@ -499,33 +501,11 @@ fn hash_final_block(msg_block: MSG_BLOCK, mut state: STATE) -> HASH {
499
501
}
500
502
501
503
pub (crate ) fn finalize_sha256_blocks <let N : u32 >(
502
- msg : [u8 ; N ],
503
504
message_size : u32 ,
504
- total_len : u32 ,
505
505
mut h : STATE ,
506
506
mut msg_block : MSG_BLOCK ,
507
507
) -> HASH {
508
508
let mut msg_byte_ptr = message_size % BLOCK_SIZE ;
509
- let modulo = total_len % BLOCK_SIZE ;
510
- // Handle setup of the final msg block.
511
- // This case is only hit if the msg is less than the block size,
512
- // or our message cannot be evenly split into blocks.
513
- if modulo != 0 {
514
- let num_blocks = total_len / BLOCK_SIZE ;
515
- let msg_start = BLOCK_SIZE * num_blocks ;
516
- let new_msg_block =
517
- // Safety: separate verification function
518
- unsafe { build_msg_block (msg , message_size , msg_start ) };
519
-
520
- if msg_start < message_size {
521
- msg_block = new_msg_block ;
522
- }
523
-
524
- verify_msg_block (msg , message_size , msg_block , msg_start );
525
- if msg_start < message_size {
526
- verify_msg_block_padding (msg_block , msg_byte_ptr );
527
- }
528
- }
529
509
530
510
// If we had modulo == 0 then it means the last block was full,
531
511
// and we can reset the pointer to zero to overwrite it.
@@ -617,7 +597,7 @@ pub fn partial_sha256_var_end<let N: u32>(
617
597
}
618
598
} else {
619
599
let (mut h , mut msg_block ) = process_full_blocks (msg , message_size , h );
620
- finalize_sha256_blocks ( msg , real_message_size , N , h , msg_block )
600
+ finalize_sha256_blocks ::< N >( real_message_size , h , msg_block )
621
601
}
622
602
}
623
603
0 commit comments