diff --git a/doc/crypto.dox b/doc/crypto.dox
index ab416a45..8ea74699 100644
--- a/doc/crypto.dox
+++ b/doc/crypto.dox
@@ -63,13 +63,13 @@ Ardunino Mega 2560 running at 16 MHz are similar:
ChaCha (20 rounds) | 14.87us | 14.88us | 43.74us | 130 |
ChaCha (12 rounds) | 10.38us | 10.38us | 43.74us | 130 |
ChaCha (8 rounds) | 8.13us | 8.14us | 43.74us | 130 |
-SHA1 | 21.90us | | | 94 |
-SHA256 | 43.85us | | | 106 |
-SHA512 | 123.25us | | | 210 |
+SHA1 | 21.90us | | | 93 |
+SHA256 | 43.85us | | | 105 |
+SHA512 | 123.24us | | | 209 |
SHA3_256 | 121.69us | | | 403 |
SHA3_512 | 229.12us | | | 403 |
-BLAKE2s | 18.54us | | | 170 |
-BLAKE2b | 50.59us | | | 338 |
+BLAKE2s | 18.54us | | | 169 |
+BLAKE2b | 50.58us | | | 337 |
Where a cipher supports more than one key size (such as ChaCha), the values
diff --git a/libraries/Crypto/BLAKE2b.cpp b/libraries/Crypto/BLAKE2b.cpp
index ec0fbe64..569cb518 100644
--- a/libraries/Crypto/BLAKE2b.cpp
+++ b/libraries/Crypto/BLAKE2b.cpp
@@ -89,7 +89,6 @@ void BLAKE2b::reset()
state.h[6] = BLAKE2b_IV6;
state.h[7] = BLAKE2b_IV7;
state.chunkSize = 0;
- state.finalized = false;
state.lengthLow = 0;
state.lengthHigh = 0;
}
@@ -112,17 +111,12 @@ void BLAKE2b::reset(uint8_t outputLength)
state.h[6] = BLAKE2b_IV6;
state.h[7] = BLAKE2b_IV7;
state.chunkSize = 0;
- state.finalized = false;
state.lengthLow = 0;
state.lengthHigh = 0;
}
void BLAKE2b::update(const void *data, size_t len)
{
- // Reset the hashing process if finalize() was called previously.
- if (state.finalized)
- reset();
-
// Break the input up into 1024-bit chunks and process each in turn.
const uint8_t *d = (const uint8_t *)data;
while (len > 0) {
@@ -148,17 +142,13 @@ void BLAKE2b::update(const void *data, size_t len)
void BLAKE2b::finalize(void *hash, size_t len)
{
- // Finalize the hash if necessary.
- if (!state.finalized) {
- // Pad the last chunk and hash it with f0 set to all-ones.
- memset(((uint8_t *)state.m) + state.chunkSize, 0, 128 - state.chunkSize);
- processChunk(0xFFFFFFFFFFFFFFFFULL);
+ // Pad the last chunk and hash it with f0 set to all-ones.
+ memset(((uint8_t *)state.m) + state.chunkSize, 0, 128 - state.chunkSize);
+ processChunk(0xFFFFFFFFFFFFFFFFULL);
- // Convert the hash into little-endian in the message buffer.
- for (uint8_t posn = 0; posn < 8; ++posn)
- state.m[posn] = htole64(state.h[posn]);
- state.finalized = true;
- }
+ // Convert the hash into little-endian in the message buffer.
+ for (uint8_t posn = 0; posn < 8; ++posn)
+ state.m[posn] = htole64(state.h[posn]);
// Copy the hash to the caller's return buffer.
if (len > 64)
diff --git a/libraries/Crypto/BLAKE2b.h b/libraries/Crypto/BLAKE2b.h
index 781b6761..67d7e887 100644
--- a/libraries/Crypto/BLAKE2b.h
+++ b/libraries/Crypto/BLAKE2b.h
@@ -46,10 +46,9 @@ private:
uint64_t h[8];
uint64_t m[16];
uint64_t v[16];
- uint8_t chunkSize;
- bool finalized;
uint64_t lengthLow;
uint64_t lengthHigh;
+ uint8_t chunkSize;
} state;
void processChunk(uint64_t f0);
diff --git a/libraries/Crypto/BLAKE2s.cpp b/libraries/Crypto/BLAKE2s.cpp
index 762dfa1a..a3244611 100644
--- a/libraries/Crypto/BLAKE2s.cpp
+++ b/libraries/Crypto/BLAKE2s.cpp
@@ -89,7 +89,6 @@ void BLAKE2s::reset()
state.h[6] = BLAKE2s_IV6;
state.h[7] = BLAKE2s_IV7;
state.chunkSize = 0;
- state.finalized = false;
state.length = 0;
}
@@ -111,16 +110,11 @@ void BLAKE2s::reset(uint8_t outputLength)
state.h[6] = BLAKE2s_IV6;
state.h[7] = BLAKE2s_IV7;
state.chunkSize = 0;
- state.finalized = false;
state.length = 0;
}
void BLAKE2s::update(const void *data, size_t len)
{
- // Reset the hashing process if finalize() was called previously.
- if (state.finalized)
- reset();
-
// Break the input up into 512-bit chunks and process each in turn.
const uint8_t *d = (const uint8_t *)data;
while (len > 0) {
@@ -143,17 +137,13 @@ void BLAKE2s::update(const void *data, size_t len)
void BLAKE2s::finalize(void *hash, size_t len)
{
- // Finalize the hash if necessary.
- if (!state.finalized) {
- // Pad the last chunk and hash it with f0 set to all-ones.
- memset(((uint8_t *)state.m) + state.chunkSize, 0, 64 - state.chunkSize);
- processChunk(0xFFFFFFFF);
+ // Pad the last chunk and hash it with f0 set to all-ones.
+ memset(((uint8_t *)state.m) + state.chunkSize, 0, 64 - state.chunkSize);
+ processChunk(0xFFFFFFFF);
- // Convert the hash into little-endian in the message buffer.
- for (uint8_t posn = 0; posn < 8; ++posn)
- state.m[posn] = htole32(state.h[posn]);
- state.finalized = true;
- }
+ // Convert the hash into little-endian in the message buffer.
+ for (uint8_t posn = 0; posn < 8; ++posn)
+ state.m[posn] = htole32(state.h[posn]);
// Copy the hash to the caller's return buffer.
if (len > 32)
diff --git a/libraries/Crypto/BLAKE2s.h b/libraries/Crypto/BLAKE2s.h
index 51f8df14..a996fff1 100644
--- a/libraries/Crypto/BLAKE2s.h
+++ b/libraries/Crypto/BLAKE2s.h
@@ -46,9 +46,8 @@ private:
uint32_t h[8];
uint32_t m[16];
uint32_t v[16];
- uint8_t chunkSize;
- bool finalized;
uint64_t length;
+ uint8_t chunkSize;
} state;
void processChunk(uint32_t f0);
diff --git a/libraries/Crypto/Hash.cpp b/libraries/Crypto/Hash.cpp
index e6801107..f0f3b3ab 100644
--- a/libraries/Crypto/Hash.cpp
+++ b/libraries/Crypto/Hash.cpp
@@ -76,8 +76,8 @@ Hash::~Hash()
* \param data Data to be hashed.
* \param len Number of bytes of data to be hashed.
*
- * If finalize() has already been called, then calling update() will
- * reset() the hash and start a new hashing process.
+ * If finalize() has already been called, then the behavior of update() will
+ * be undefined. Call reset() first to start a new hashing process.
*
* \sa reset(), finalize()
*/
@@ -93,8 +93,8 @@ Hash::~Hash()
* truncated to the first \a len bytes. If \a len is greater than
* hashSize(), then the remaining bytes will left unchanged.
*
- * If finalize() is called again, the same hash value is returned again until
- * the next call to reset() or update().
+ * If finalize() is called again, then the returned \a hash value is
+ * undefined. Call reset() first to start a new hashing process.
*
* \sa reset(), update()
*/
diff --git a/libraries/Crypto/SHA1.cpp b/libraries/Crypto/SHA1.cpp
index 8783fdad..ab5ac575 100644
--- a/libraries/Crypto/SHA1.cpp
+++ b/libraries/Crypto/SHA1.cpp
@@ -69,16 +69,11 @@ void SHA1::reset()
state.h[3] = 0x10325476;
state.h[4] = 0xC3D2E1F0;
state.chunkSize = 0;
- state.finalized = false;
state.length = 0;
}
void SHA1::update(const void *data, size_t len)
{
- // Reset the hashing process if finalize() was called previously.
- if (state.finalized)
- reset();
-
// Update the total length (in bits, not bytes).
state.length += ((uint64_t)len) << 3;
@@ -101,33 +96,29 @@ void SHA1::update(const void *data, size_t len)
void SHA1::finalize(void *hash, size_t len)
{
- // Finalize the hash if necessary.
- if (!state.finalized) {
- // Pad the last chunk. We may need two padding chunks if there
- // isn't enough room in the first for the padding and length.
- uint8_t *wbytes = (uint8_t *)state.w;
- if (state.chunkSize <= (64 - 9)) {
- wbytes[state.chunkSize] = 0x80;
- memset(wbytes + state.chunkSize + 1, 0x00, 64 - 8 - (state.chunkSize + 1));
- state.w[14] = htobe32((uint32_t)(state.length >> 32));
- state.w[15] = htobe32((uint32_t)state.length);
- processChunk();
- } else {
- wbytes[state.chunkSize] = 0x80;
- memset(wbytes + state.chunkSize + 1, 0x00, 64 - (state.chunkSize + 1));
- processChunk();
- memset(wbytes, 0x00, 64 - 8);
- state.w[14] = htobe32((uint32_t)(state.length >> 32));
- state.w[15] = htobe32((uint32_t)state.length);
- processChunk();
- }
-
- // Convert the result into big endian and return it.
- for (uint8_t posn = 0; posn < 5; ++posn)
- state.w[posn] = htobe32(state.h[posn]);
- state.finalized = true;
+ // Pad the last chunk. We may need two padding chunks if there
+ // isn't enough room in the first for the padding and length.
+ uint8_t *wbytes = (uint8_t *)state.w;
+ if (state.chunkSize <= (64 - 9)) {
+ wbytes[state.chunkSize] = 0x80;
+ memset(wbytes + state.chunkSize + 1, 0x00, 64 - 8 - (state.chunkSize + 1));
+ state.w[14] = htobe32((uint32_t)(state.length >> 32));
+ state.w[15] = htobe32((uint32_t)state.length);
+ processChunk();
+ } else {
+ wbytes[state.chunkSize] = 0x80;
+ memset(wbytes + state.chunkSize + 1, 0x00, 64 - (state.chunkSize + 1));
+ processChunk();
+ memset(wbytes, 0x00, 64 - 8);
+ state.w[14] = htobe32((uint32_t)(state.length >> 32));
+ state.w[15] = htobe32((uint32_t)state.length);
+ processChunk();
}
+ // Convert the result into big endian and return it.
+ for (uint8_t posn = 0; posn < 5; ++posn)
+ state.w[posn] = htobe32(state.h[posn]);
+
// Copy the hash to the caller's return buffer.
if (len > 20)
len = 20;
diff --git a/libraries/Crypto/SHA1.h b/libraries/Crypto/SHA1.h
index 83ed362f..1a81a0cb 100644
--- a/libraries/Crypto/SHA1.h
+++ b/libraries/Crypto/SHA1.h
@@ -44,9 +44,8 @@ private:
struct {
uint32_t h[5];
uint32_t w[16];
- uint8_t chunkSize;
- bool finalized;
uint64_t length;
+ uint8_t chunkSize;
} state;
void processChunk();
diff --git a/libraries/Crypto/SHA256.cpp b/libraries/Crypto/SHA256.cpp
index 30257620..26b1b500 100644
--- a/libraries/Crypto/SHA256.cpp
+++ b/libraries/Crypto/SHA256.cpp
@@ -74,16 +74,11 @@ void SHA256::reset()
state.h[6] = 0x1f83d9ab;
state.h[7] = 0x5be0cd19;
state.chunkSize = 0;
- state.finalized = false;
state.length = 0;
}
void SHA256::update(const void *data, size_t len)
{
- // Reset the hashing process if finalize() was called previously.
- if (state.finalized)
- reset();
-
// Update the total length (in bits, not bytes).
state.length += ((uint64_t)len) << 3;
@@ -106,33 +101,29 @@ void SHA256::update(const void *data, size_t len)
void SHA256::finalize(void *hash, size_t len)
{
- // Finalize the hash if necessary.
- if (!state.finalized) {
- // Pad the last chunk. We may need two padding chunks if there
- // isn't enough room in the first for the padding and length.
- uint8_t *wbytes = (uint8_t *)state.w;
- if (state.chunkSize <= (64 - 9)) {
- wbytes[state.chunkSize] = 0x80;
- memset(wbytes + state.chunkSize + 1, 0x00, 64 - 8 - (state.chunkSize + 1));
- state.w[14] = htobe32((uint32_t)(state.length >> 32));
- state.w[15] = htobe32((uint32_t)state.length);
- processChunk();
- } else {
- wbytes[state.chunkSize] = 0x80;
- memset(wbytes + state.chunkSize + 1, 0x00, 64 - (state.chunkSize + 1));
- processChunk();
- memset(wbytes, 0x00, 64 - 8);
- state.w[14] = htobe32((uint32_t)(state.length >> 32));
- state.w[15] = htobe32((uint32_t)state.length);
- processChunk();
- }
-
- // Convert the result into big endian and return it.
- for (uint8_t posn = 0; posn < 8; ++posn)
- state.w[posn] = htobe32(state.h[posn]);
- state.finalized = true;
+ // Pad the last chunk. We may need two padding chunks if there
+ // isn't enough room in the first for the padding and length.
+ uint8_t *wbytes = (uint8_t *)state.w;
+ if (state.chunkSize <= (64 - 9)) {
+ wbytes[state.chunkSize] = 0x80;
+ memset(wbytes + state.chunkSize + 1, 0x00, 64 - 8 - (state.chunkSize + 1));
+ state.w[14] = htobe32((uint32_t)(state.length >> 32));
+ state.w[15] = htobe32((uint32_t)state.length);
+ processChunk();
+ } else {
+ wbytes[state.chunkSize] = 0x80;
+ memset(wbytes + state.chunkSize + 1, 0x00, 64 - (state.chunkSize + 1));
+ processChunk();
+ memset(wbytes, 0x00, 64 - 8);
+ state.w[14] = htobe32((uint32_t)(state.length >> 32));
+ state.w[15] = htobe32((uint32_t)state.length);
+ processChunk();
}
+ // Convert the result into big endian and return it.
+ for (uint8_t posn = 0; posn < 8; ++posn)
+ state.w[posn] = htobe32(state.h[posn]);
+
// Copy the hash to the caller's return buffer.
if (len > 32)
len = 32;
diff --git a/libraries/Crypto/SHA256.h b/libraries/Crypto/SHA256.h
index f65a08cf..c4a2504b 100644
--- a/libraries/Crypto/SHA256.h
+++ b/libraries/Crypto/SHA256.h
@@ -44,9 +44,8 @@ private:
struct {
uint32_t h[8];
uint32_t w[16];
- uint8_t chunkSize;
- bool finalized;
uint64_t length;
+ uint8_t chunkSize;
} state;
void processChunk();
diff --git a/libraries/Crypto/SHA512.cpp b/libraries/Crypto/SHA512.cpp
index d9588dda..cfe8859c 100644
--- a/libraries/Crypto/SHA512.cpp
+++ b/libraries/Crypto/SHA512.cpp
@@ -72,17 +72,12 @@ void SHA512::reset()
};
memcpy_P(state.h, hashStart, sizeof(hashStart));
state.chunkSize = 0;
- state.finalized = false;
state.lengthLow = 0;
state.lengthHigh = 0;
}
void SHA512::update(const void *data, size_t len)
{
- // Reset the hashing process if finalize() was called previously.
- if (state.finalized)
- reset();
-
// Update the total length in bits, not bytes.
uint64_t temp = state.lengthLow;
state.lengthLow += (((uint64_t)len) << 3);
@@ -109,33 +104,29 @@ void SHA512::update(const void *data, size_t len)
void SHA512::finalize(void *hash, size_t len)
{
- // Finalize the hash if necessary.
- if (!state.finalized) {
- // Pad the last chunk. We may need two padding chunks if there
- // isn't enough room in the first for the padding and length.
- uint8_t *wbytes = (uint8_t *)state.w;
- if (state.chunkSize <= (128 - 17)) {
- wbytes[state.chunkSize] = 0x80;
- memset(wbytes + state.chunkSize + 1, 0x00, 128 - 16 - (state.chunkSize + 1));
- state.w[14] = htobe64(state.lengthHigh);
- state.w[15] = htobe64(state.lengthLow);
- processChunk();
- } else {
- wbytes[state.chunkSize] = 0x80;
- memset(wbytes + state.chunkSize + 1, 0x00, 128 - (state.chunkSize + 1));
- processChunk();
- memset(wbytes, 0x00, 128 - 16);
- state.w[14] = htobe64(state.lengthHigh);
- state.w[15] = htobe64(state.lengthLow);
- processChunk();
- }
-
- // Convert the result into big endian and return it.
- for (uint8_t posn = 0; posn < 8; ++posn)
- state.w[posn] = htobe64(state.h[posn]);
- state.finalized = true;
+ // Pad the last chunk. We may need two padding chunks if there
+ // isn't enough room in the first for the padding and length.
+ uint8_t *wbytes = (uint8_t *)state.w;
+ if (state.chunkSize <= (128 - 17)) {
+ wbytes[state.chunkSize] = 0x80;
+ memset(wbytes + state.chunkSize + 1, 0x00, 128 - 16 - (state.chunkSize + 1));
+ state.w[14] = htobe64(state.lengthHigh);
+ state.w[15] = htobe64(state.lengthLow);
+ processChunk();
+ } else {
+ wbytes[state.chunkSize] = 0x80;
+ memset(wbytes + state.chunkSize + 1, 0x00, 128 - (state.chunkSize + 1));
+ processChunk();
+ memset(wbytes, 0x00, 128 - 16);
+ state.w[14] = htobe64(state.lengthHigh);
+ state.w[15] = htobe64(state.lengthLow);
+ processChunk();
}
+ // Convert the result into big endian and return it.
+ for (uint8_t posn = 0; posn < 8; ++posn)
+ state.w[posn] = htobe64(state.h[posn]);
+
// Copy the hash to the caller's return buffer.
if (len > 64)
len = 64;
diff --git a/libraries/Crypto/SHA512.h b/libraries/Crypto/SHA512.h
index ae37118a..d394ae45 100644
--- a/libraries/Crypto/SHA512.h
+++ b/libraries/Crypto/SHA512.h
@@ -44,10 +44,9 @@ private:
struct {
uint64_t h[8];
uint64_t w[16];
- uint8_t chunkSize;
- bool finalized;
uint64_t lengthLow;
uint64_t lengthHigh;
+ uint8_t chunkSize;
} state;
void processChunk();
diff --git a/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino b/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino
index adfe1418..e40c0a92 100644
--- a/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino
+++ b/libraries/Crypto/examples/TestBLAKE2b/TestBLAKE2b.ino
@@ -98,17 +98,7 @@ bool testHash_N(Hash *hash, const struct TestHashVector *test, size_t inc)
size_t posn, len;
uint8_t value[HASH_SIZE];
- for (posn = 0; posn < size; posn += inc) {
- len = size - posn;
- if (len > inc)
- len = inc;
- hash->update(test->data + posn, len);
- }
- hash->finalize(value, sizeof(value));
- if (memcmp(value, test->hash, sizeof(value)) != 0)
- return false;
-
- // Try again to make sure the hash resets.
+ hash->reset();
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)
diff --git a/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino b/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino
index d7eb6839..26d4c9ee 100644
--- a/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino
+++ b/libraries/Crypto/examples/TestBLAKE2s/TestBLAKE2s.ino
@@ -82,17 +82,7 @@ bool testHash_N(Hash *hash, const struct TestHashVector *test, size_t inc)
size_t posn, len;
uint8_t value[HASH_SIZE];
- for (posn = 0; posn < size; posn += inc) {
- len = size - posn;
- if (len > inc)
- len = inc;
- hash->update(test->data + posn, len);
- }
- hash->finalize(value, sizeof(value));
- if (memcmp(value, test->hash, sizeof(value)) != 0)
- return false;
-
- // Try again to make sure the hash resets.
+ hash->reset();
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)
diff --git a/libraries/Crypto/examples/TestSHA1/TestSHA1.ino b/libraries/Crypto/examples/TestSHA1/TestSHA1.ino
index 033b2fdd..da398f1a 100644
--- a/libraries/Crypto/examples/TestSHA1/TestSHA1.ino
+++ b/libraries/Crypto/examples/TestSHA1/TestSHA1.ino
@@ -62,17 +62,7 @@ bool testHash_N(Hash *hash, const struct TestHashVector *test, size_t inc)
size_t posn, len;
uint8_t value[HASH_SIZE];
- for (posn = 0; posn < size; posn += inc) {
- len = size - posn;
- if (len > inc)
- len = inc;
- hash->update(test->data + posn, len);
- }
- hash->finalize(value, sizeof(value));
- if (memcmp(value, test->hash, sizeof(value)) != 0)
- return false;
-
- // Try again to make sure the hash resets.
+ hash->reset();
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)
diff --git a/libraries/Crypto/examples/TestSHA256/TestSHA256.ino b/libraries/Crypto/examples/TestSHA256/TestSHA256.ino
index 767acd5c..6117ee2b 100644
--- a/libraries/Crypto/examples/TestSHA256/TestSHA256.ino
+++ b/libraries/Crypto/examples/TestSHA256/TestSHA256.ino
@@ -64,17 +64,7 @@ bool testHash_N(Hash *hash, const struct TestHashVector *test, size_t inc)
size_t posn, len;
uint8_t value[HASH_SIZE];
- for (posn = 0; posn < size; posn += inc) {
- len = size - posn;
- if (len > inc)
- len = inc;
- hash->update(test->data + posn, len);
- }
- hash->finalize(value, sizeof(value));
- if (memcmp(value, test->hash, sizeof(value)) != 0)
- return false;
-
- // Try again to make sure the hash resets.
+ hash->reset();
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)
diff --git a/libraries/Crypto/examples/TestSHA512/TestSHA512.ino b/libraries/Crypto/examples/TestSHA512/TestSHA512.ino
index 9e47701d..e1876459 100644
--- a/libraries/Crypto/examples/TestSHA512/TestSHA512.ino
+++ b/libraries/Crypto/examples/TestSHA512/TestSHA512.ino
@@ -85,17 +85,7 @@ bool testHash_N(Hash *hash, const struct TestHashVector *test, size_t inc)
size_t posn, len;
uint8_t value[HASH_SIZE];
- for (posn = 0; posn < size; posn += inc) {
- len = size - posn;
- if (len > inc)
- len = inc;
- hash->update(test->data + posn, len);
- }
- hash->finalize(value, sizeof(value));
- if (memcmp(value, test->hash, sizeof(value)) != 0)
- return false;
-
- // Try again to make sure the hash resets.
+ hash->reset();
for (posn = 0; posn < size; posn += inc) {
len = size - posn;
if (len > inc)