summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorakuchling <akuchling@rivest.dlitz.net>2005-11-29 19:16:21 -0700
committerakuchling <akuchling@rivest.dlitz.net>2005-11-29 19:16:21 -0700
commit1f1909536d0082fc29ba7d53c6226125a7451039 (patch)
tree66e280aa176b9b6bc1fbbbd7f120965a3b8afdf7
parent3adc521d6f6b5e674028716b5d3d899b8100c7f6 (diff)
downloadpycrypto-1f1909536d0082fc29ba7d53c6226125a7451039.tar.gz
[project @ akuchling-20051130021621-801cd274a9838593]
[project @ 2005-11-29 18:16:21 by akuchling] Fix 32-bit length limitation in SHA256
-rw-r--r--ChangeLog3
-rw-r--r--src/SHA256.c33
2 files changed, 24 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 1977955..f4dfafc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,9 @@
* Fix padding bug in SHA256; this resulted in bad digests whenever
(the number of bytes hashed) mod 64 == 55.
+ * Fix a 32-bit limitation on the length of messages the SHA256 module
+ could hash.
+
2.0.1
=====
diff --git a/src/SHA256.c b/src/SHA256.c
index 2b472ef..99744b4 100644
--- a/src/SHA256.c
+++ b/src/SHA256.c
@@ -25,7 +25,8 @@ typedef unsigned int U32;
#endif
typedef struct {
- U32 state[8], length, curlen;
+ U32 state[8], curlen;
+ U32 length_upper, length_lower;
unsigned char buf[64];
}
hash_state;
@@ -100,7 +101,7 @@ static void sha_compress(hash_state * md)
/* init the SHA state */
void sha_init(hash_state * md)
{
- md->curlen = md->length = 0;
+ md->curlen = md->length_upper = md->length_lower = 0;
md->state[0] = 0x6A09E667UL;
md->state[1] = 0xBB67AE85UL;
md->state[2] = 0x3C6EF372UL;
@@ -119,8 +120,13 @@ void sha_process(hash_state * md, unsigned char *buf, int len)
/* is 64 bytes full? */
if (md->curlen == 64) {
+ U32 orig_length;
sha_compress(md);
- md->length += 512;
+ orig_length = md->length_lower;
+ md->length_lower += 512;
+ if (orig_length > md->length_lower) {
+ md->length_upper++;
+ }
md->curlen = 0;
}
}
@@ -129,17 +135,22 @@ void sha_process(hash_state * md, unsigned char *buf, int len)
void sha_done(hash_state * md, unsigned char *hash)
{
int i;
+ U32 orig_length;
/* increase the length of the message */
- md->length += md->curlen * 8;
+ orig_length = md->length_lower;
+ md->length_lower += md->curlen * 8;
+ if (orig_length > md->length_lower) {
+ md->length_upper++;
+ }
/* append the '1' bit */
md->buf[md->curlen++] = 0x80;
/* if the length is currently above 56 bytes we append zeros
- * then compress. Then we can fall back to padding zeros and length
- * encoding like normal.
- */
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
if (md->curlen > 56) {
for (; md->curlen < 64;)
md->buf[md->curlen++] = 0;
@@ -151,13 +162,11 @@ void sha_done(hash_state * md, unsigned char *hash)
for (; md->curlen < 56;)
md->buf[md->curlen++] = 0;
- /* since all messages are under 2^32 bits we mark the top bits zero */
- for (i = 56; i < 60; i++)
- md->buf[i] = 0;
-
/* append length */
+ for (i = 56; i < 60; i++)
+ md->buf[i] = (md->length_upper >> ((59 - i) * 8)) & 255;
for (i = 60; i < 64; i++)
- md->buf[i] = (md->length >> ((63 - i) * 8)) & 255;
+ md->buf[i] = (md->length_lower >> ((63 - i) * 8)) & 255;
sha_compress(md);
/* copy output */