Skip to content

Commit 28fae17

Browse files
rewrite end block logic in hash functions
1 parent cc3cabc commit 28fae17

File tree

1 file changed

+37
-50
lines changed

1 file changed

+37
-50
lines changed

src/Hash.cc

Lines changed: 37 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -152,26 +152,23 @@ MD5::MD5(const void* data, size_t size) {
152152
this->d0 += d;
153153
};
154154

155-
size_t block_offset = 0;
156-
for (; block_offset + 0x40 < size; block_offset += 0x40) {
157-
process_block(reinterpret_cast<const uint8_t*>(data) + block_offset);
155+
// Process all possible blocks from the input until just before the end
156+
size_t processed_offset;
157+
for (processed_offset = 0; processed_offset + 0x3F < size; processed_offset += 0x40) {
158+
process_block(reinterpret_cast<const uint8_t*>(data) + processed_offset);
158159
}
159160

160-
size_t remaining_bytes = size - block_offset;
161-
uint8_t last_blocks[0x80];
162-
memcpy(last_blocks, reinterpret_cast<const uint8_t*>(data) + block_offset,
163-
remaining_bytes);
164-
last_blocks[remaining_bytes] = 0x80;
165-
166-
size_t blocks_remaining = 1 + (remaining_bytes > (0x40 - 9));
167-
for (remaining_bytes++; remaining_bytes < (0x40 * blocks_remaining - 8);
168-
remaining_bytes++) {
169-
last_blocks[remaining_bytes] = 0;
161+
// Make a copy of the last (possibly incomplete) block, append the trailer,
162+
// and process what remains. This could result in either one or two blocks.
163+
StringWriter w;
164+
w.write(reinterpret_cast<const char*>(data) + processed_offset, size - processed_offset);
165+
{
166+
w.put_u8(0x80);
167+
w.extend_to((w.size() > 0x38) ? 0x80 : 0x40, '\0');
168+
w.pput_u64l(w.size() - 8, size << 3);
170169
}
171-
*reinterpret_cast<le_uint64_t*>(&last_blocks[0x40 * blocks_remaining - 8]) = size * 8;
172-
process_block(&last_blocks[0]);
173-
if (blocks_remaining > 1) {
174-
process_block(&last_blocks[0x40]);
170+
for (size_t z = 0; z < w.size(); z += 0x40) {
171+
process_block(w.str().data() + z);
175172
}
176173
}
177174

@@ -244,29 +241,23 @@ SHA1::SHA1(const void* data, size_t size) {
244241
this->h[4] += e;
245242
};
246243

247-
// process blocks from the message exactly as they are
248-
size_t block_offset = 0;
249-
for (; block_offset + 0x40 < size; block_offset += 0x40) {
250-
process_block(reinterpret_cast<const uint8_t*>(data) + block_offset);
244+
// Process all possible blocks from the input until just before the end
245+
size_t processed_offset;
246+
for (processed_offset = 0; processed_offset + 0x3F < size; processed_offset += 0x40) {
247+
process_block(reinterpret_cast<const uint8_t*>(data) + processed_offset);
251248
}
252249

253-
// we're going to append at least 9 bytes to the end. first handle the case
254-
// where doing so creates two new blocks.
255-
size_t remaining_bytes = size - block_offset;
256-
uint8_t last_blocks[0x80];
257-
memcpy(last_blocks, reinterpret_cast<const uint8_t*>(data) + block_offset,
258-
remaining_bytes);
259-
last_blocks[remaining_bytes] = 0x80;
260-
261-
size_t blocks_remaining = 1 + (remaining_bytes > (0x40 - 9));
262-
for (remaining_bytes++; remaining_bytes < (0x40 * blocks_remaining - 8);
263-
remaining_bytes++) {
264-
last_blocks[remaining_bytes] = 0;
250+
// Make a copy of the last (possibly incomplete) block, append the trailer,
251+
// and process what remains. This could result in either one or two blocks.
252+
StringWriter w;
253+
w.write(reinterpret_cast<const char*>(data) + processed_offset, size - processed_offset);
254+
{
255+
w.put_u8(0x80);
256+
w.extend_to((w.size() > 0x38) ? 0x80 : 0x40, '\0');
257+
w.pput_u64b(w.size() - 8, size << 3);
265258
}
266-
*reinterpret_cast<be_uint64_t*>(&last_blocks[0x40 * blocks_remaining - 8]) = size * 8;
267-
process_block(&last_blocks[0]);
268-
if (blocks_remaining > 1) {
269-
process_block(&last_blocks[0x40]);
259+
for (size_t z = 0; z < w.size(); z += 0x40) {
260+
process_block(w.str().data() + z);
270261
}
271262
}
272263

@@ -291,7 +282,7 @@ static inline uint32_t rotate_right(uint32_t x, uint8_t bits) {
291282
return (x >> bits) | (x << (32 - bits));
292283
}
293284

294-
SHA256::SHA256(const void* data, size_t orig_size) {
285+
SHA256::SHA256(const void* data, size_t size) {
295286
this->h[0] = 0x6A09E667;
296287
this->h[1] = 0xBB67AE85;
297288
this->h[2] = 0x3C6EF372;
@@ -356,25 +347,21 @@ SHA256::SHA256(const void* data, size_t orig_size) {
356347

357348
// Process all possible blocks from the input until just before the end
358349
size_t processed_offset;
359-
for (processed_offset = 0; processed_offset + 0x3F < orig_size; processed_offset += 0x40) {
350+
for (processed_offset = 0; processed_offset + 0x3F < size; processed_offset += 0x40) {
360351
process_block(reinterpret_cast<const uint8_t*>(data) + processed_offset);
361352
}
362353

363354
// Make a copy of the last (possibly incomplete) block, append the trailer,
364355
// and process what remains. This could result in either one or two blocks.
365-
string end_data(reinterpret_cast<const char*>(data) + processed_offset, orig_size - processed_offset);
356+
StringWriter w;
357+
w.write(reinterpret_cast<const char*>(data) + processed_offset, size - processed_offset);
366358
{
367-
end_data.push_back(0x80);
368-
size_t num_zero_bytes = ((0x40 - ((end_data.size() + 8) & 0x3F)) & 0x3F);
369-
end_data.resize(end_data.size() + num_zero_bytes, '\0');
370-
be_uint64_t size_be = orig_size << 3;
371-
end_data.append(reinterpret_cast<const char*>(&size_be), 8);
372-
}
373-
if (end_data.size() & 0x3F) {
374-
throw logic_error("padding did not result in correct length");
359+
w.put_u8(0x80);
360+
w.extend_to((w.size() > 0x38) ? 0x80 : 0x40, '\0');
361+
w.pput_u64b(w.size() - 8, size << 3);
375362
}
376-
for (size_t z = 0; z < end_data.size(); z += 0x40) {
377-
process_block(end_data.data() + z);
363+
for (size_t z = 0; z < w.size(); z += 0x40) {
364+
process_block(w.str().data() + z);
378365
}
379366
}
380367

0 commit comments

Comments
 (0)