Skip to content

Commit ed242ca

Browse files
committed
correct blocks
1 parent 5fb54c8 commit ed242ca

File tree

2 files changed

+18
-34
lines changed

2 files changed

+18
-34
lines changed

src/sha224.nr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub fn sha224_var<let N: u32>(msg: [u8; N], message_size: u64) -> sha224_constan
2121
let (mut h, mut msg_block) =
2222
process_full_blocks(msg, message_size, sha224_constants::INITIAL_STATE_SHA224);
2323

24-
let hash: HASH = finalize_sha256_blocks(msg, message_size, N, h, msg_block);
24+
let hash: HASH = finalize_sha256_blocks::<N>(message_size, h, msg_block);
2525
// Convert 32-byte hash to 28-byte hash for SHA-224
2626
let mut hash_sha224: sha224_constants::HASH_SHA224 = [0; 28];
2727
for i in 0..28 {

src/sha256.nr

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub fn sha256_var<let N: u32>(msg: [u8; N], message_size: u64) -> HASH {
3939
} else {
4040
let (mut h, mut msg_block) = process_full_blocks(msg, message_size, INITIAL_STATE);
4141

42-
finalize_sha256_blocks(msg, message_size, N, h, msg_block)
42+
finalize_sha256_blocks::<N>(message_size, h, msg_block)
4343
}
4444
}
4545

@@ -119,14 +119,14 @@ pub(crate) fn process_full_blocks<let N: u32>(
119119
// 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.
120120
// - `states[i]` should then be the state after processing the first `i` blocks.
121121
// - `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.
122123
//
123124
// In other words:
124125
//
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]
126127
// states = [INITIAL_STATE, state after block 1, state after block 2, ..., state after block N / BLOCK_SIZE]
127128
//
128129
// 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.
130130
let mut blocks: [MSG_BLOCK; N / BLOCK_SIZE + 1] = std::mem::zeroed();
131131
let mut states: [STATE; N / BLOCK_SIZE + 1] = [h; N / BLOCK_SIZE + 1];
132132

@@ -153,6 +153,19 @@ pub(crate) fn process_full_blocks<let N: u32>(
153153
states[i + 1] = sha256_compression(new_msg_block, states[i]);
154154
}
155155

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+
156169
(states[first_partially_filled_block_index], blocks[first_partially_filled_block_index])
157170
}
158171

@@ -241,13 +254,6 @@ fn verify_msg_block<let N: u32>(
241254
}
242255
}
243256

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-
251257
// Verify that a region of ints in the message block are (partially) zeroed,
252258
// up to an (exclusive) maximum which can either be the end of the block
253259
// 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 {
512518
}
513519

514520
pub(crate) fn finalize_sha256_blocks<let N: u32>(
515-
msg: [u8; N],
516521
message_size: u32,
517-
total_len: u32,
518522
mut h: STATE,
519523
mut msg_block: MSG_BLOCK,
520524
) -> HASH {
521525
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-
}
542526

543527
// If we had modulo == 0 then it means the last block was full,
544528
// and we can reset the pointer to zero to overwrite it.
@@ -630,7 +614,7 @@ pub fn partial_sha256_var_end<let N: u32>(
630614
}
631615
} else {
632616
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)
634618
}
635619
}
636620

0 commit comments

Comments
 (0)