mirror of
https://github.com/taigrr/arduinolibs
synced 2025-01-18 04:33:12 -08:00
SHA512 hash algorithm
This commit is contained in:
parent
436e597d83
commit
72901a91f9
@ -29,15 +29,15 @@
|
|||||||
\li Block ciphers: AES128, AES192, AES256
|
\li Block ciphers: AES128, AES192, AES256
|
||||||
\li Block cipher modes: CTR, CFB, CBC, OFB
|
\li Block cipher modes: CTR, CFB, CBC, OFB
|
||||||
\li Stream ciphers: ChaCha
|
\li Stream ciphers: ChaCha
|
||||||
\li Hash algorithms: SHA1, SHA256, BLAKE2s
|
\li Hash algorithms: SHA1, SHA256, SHA512, BLAKE2s
|
||||||
\li Public key algorithms: Curve25519
|
\li Public key algorithms: Curve25519
|
||||||
\li Random number generation: \link RNGClass RNG\endlink, TransistorNoiseSource
|
\li Random number generation: \link RNGClass RNG\endlink, TransistorNoiseSource
|
||||||
|
|
||||||
All cryptographic algorithms have been optimized for 8-bit Arduino platforms
|
All cryptographic algorithms have been optimized for 8-bit Arduino platforms
|
||||||
like the Uno. Memory usage is also reduced, particularly for SHA1 and SHA256
|
like the Uno. Memory usage is also reduced, particularly for SHA1, SHA256,
|
||||||
which save 256 and 192 bytes respectively over traditional implementations.
|
and SHA512 which save 256, 192, and 512 bytes respectively over traditional
|
||||||
For other algorithms, static sbox tables and the like are placed into
|
implementations. For other algorithms, static sbox tables and the like are
|
||||||
program memory to further reduce data memory usage.
|
placed into program memory to further reduce data memory usage.
|
||||||
|
|
||||||
ChaCha with 20 rounds and 256-bit keys is the recommended
|
ChaCha with 20 rounds and 256-bit keys is the recommended
|
||||||
symmetric encryption algorithm because it is twice as fast as AES128,
|
symmetric encryption algorithm because it is twice as fast as AES128,
|
||||||
@ -65,6 +65,7 @@ Ardunino Mega 2560 running at 16 MHz are similar:
|
|||||||
<tr><td>ChaCha (8 rounds)</td><td align="right">8.13us</td><td align="right">8.14us</td><td align="right">43.74us</td><td align="right">130</td></tr>
|
<tr><td>ChaCha (8 rounds)</td><td align="right">8.13us</td><td align="right">8.14us</td><td align="right">43.74us</td><td align="right">130</td></tr>
|
||||||
<tr><td>SHA1</td><td align="right">21.90us</td><td> </td><td align="right"> </td><td align="right">94</td></tr>
|
<tr><td>SHA1</td><td align="right">21.90us</td><td> </td><td align="right"> </td><td align="right">94</td></tr>
|
||||||
<tr><td>SHA256</td><td align="right">43.85us</td><td> </td><td align="right"> </td><td align="right">106</td></tr>
|
<tr><td>SHA256</td><td align="right">43.85us</td><td> </td><td align="right"> </td><td align="right">106</td></tr>
|
||||||
|
<tr><td>SHA512</td><td align="right">123.25us</td><td> </td><td align="right"> </td><td align="right">210</td></tr>
|
||||||
<tr><td>BLAKE2s</td><td align="right">18.54us</td><td> </td><td align="right"> </td><td align="right">170</td></tr>
|
<tr><td>BLAKE2s</td><td align="right">18.54us</td><td> </td><td align="right"> </td><td align="right">170</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ realtime clock and the LCD library to implement an alarm clock.
|
|||||||
\li Block ciphers: AES128, AES192, AES256
|
\li Block ciphers: AES128, AES192, AES256
|
||||||
\li Block cipher modes: CTR, CFB, CBC, OFB
|
\li Block cipher modes: CTR, CFB, CBC, OFB
|
||||||
\li Stream ciphers: ChaCha
|
\li Stream ciphers: ChaCha
|
||||||
\li Hash algorithms: SHA1, SHA256, BLAKE2s
|
\li Hash algorithms: SHA1, SHA256, SHA512, BLAKE2s
|
||||||
\li Public key algorithms: Curve25519
|
\li Public key algorithms: Curve25519
|
||||||
\li Random number generation: \link RNGClass RNG\endlink, TransistorNoiseSource
|
\li Random number generation: \link RNGClass RNG\endlink, TransistorNoiseSource
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
*
|
*
|
||||||
* Reference: http://en.wikipedia.org/wiki/SHA-1
|
* Reference: http://en.wikipedia.org/wiki/SHA-1
|
||||||
*
|
*
|
||||||
* \sa SHA256
|
* \sa SHA256, SHA512
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
*
|
*
|
||||||
* Reference: http://en.wikipedia.org/wiki/SHA-2
|
* Reference: http://en.wikipedia.org/wiki/SHA-2
|
||||||
*
|
*
|
||||||
* \sa SHA1, BLAKE2s
|
* \sa SHA512, SHA1, BLAKE2s
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
264
libraries/Crypto/SHA512.cpp
Normal file
264
libraries/Crypto/SHA512.cpp
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Southern Storm Software, Pty Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SHA512.h"
|
||||||
|
#include "Crypto.h"
|
||||||
|
#include "utility/RotateUtil.h"
|
||||||
|
#include "utility/EndianUtil.h"
|
||||||
|
#include "utility/ProgMemUtil.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class SHA512 SHA512.h <SHA512.h>
|
||||||
|
* \brief SHA-512 hash algorithm.
|
||||||
|
*
|
||||||
|
* Reference: http://en.wikipedia.org/wiki/SHA-2
|
||||||
|
*
|
||||||
|
* \sa SHA256, SHA1
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Constructs a SHA-512 hash object.
|
||||||
|
*/
|
||||||
|
SHA512::SHA512()
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Destroys this SHA-512 hash object after clearing
|
||||||
|
* sensitive information.
|
||||||
|
*/
|
||||||
|
SHA512::~SHA512()
|
||||||
|
{
|
||||||
|
clean(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SHA512::hashSize() const
|
||||||
|
{
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SHA512::blockSize() const
|
||||||
|
{
|
||||||
|
return 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHA512::reset()
|
||||||
|
{
|
||||||
|
static uint64_t const hashStart[8] PROGMEM = {
|
||||||
|
0x6A09E667F3BCC908ULL, 0xBB67AE8584CAA73BULL, 0x3C6EF372FE94F82BULL,
|
||||||
|
0xA54FF53A5F1D36F1ULL, 0x510E527FADE682D1ULL, 0x9B05688C2B3E6C1FULL,
|
||||||
|
0x1F83D9ABFB41BD6BULL, 0x5BE0CD19137E2179ULL
|
||||||
|
};
|
||||||
|
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);
|
||||||
|
state.lengthHigh += (((uint64_t)len) >> 61);
|
||||||
|
if (state.lengthLow < temp)
|
||||||
|
++state.lengthHigh;
|
||||||
|
|
||||||
|
// Break the input up into 1024-bit chunks and process each in turn.
|
||||||
|
const uint8_t *d = (const uint8_t *)data;
|
||||||
|
while (len > 0) {
|
||||||
|
uint8_t size = 128 - state.chunkSize;
|
||||||
|
if (size > len)
|
||||||
|
size = len;
|
||||||
|
memcpy(((uint8_t *)state.w) + state.chunkSize, d, size);
|
||||||
|
state.chunkSize += size;
|
||||||
|
len -= size;
|
||||||
|
d += size;
|
||||||
|
if (state.chunkSize == 128) {
|
||||||
|
processChunk();
|
||||||
|
state.chunkSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the hash to the caller's return buffer.
|
||||||
|
if (len > 64)
|
||||||
|
len = 64;
|
||||||
|
memcpy(hash, state.w, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHA512::clear()
|
||||||
|
{
|
||||||
|
clean(state);
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Processes a single 1024-bit chunk with the core SHA-512 algorithm.
|
||||||
|
*
|
||||||
|
* Reference: http://en.wikipedia.org/wiki/SHA-2
|
||||||
|
*/
|
||||||
|
void SHA512::processChunk()
|
||||||
|
{
|
||||||
|
// Round constants for SHA-512.
|
||||||
|
static uint64_t const k[80] PROGMEM = {
|
||||||
|
0x428A2F98D728AE22ULL, 0x7137449123EF65CDULL, 0xB5C0FBCFEC4D3B2FULL,
|
||||||
|
0xE9B5DBA58189DBBCULL, 0x3956C25BF348B538ULL, 0x59F111F1B605D019ULL,
|
||||||
|
0x923F82A4AF194F9BULL, 0xAB1C5ED5DA6D8118ULL, 0xD807AA98A3030242ULL,
|
||||||
|
0x12835B0145706FBEULL, 0x243185BE4EE4B28CULL, 0x550C7DC3D5FFB4E2ULL,
|
||||||
|
0x72BE5D74F27B896FULL, 0x80DEB1FE3B1696B1ULL, 0x9BDC06A725C71235ULL,
|
||||||
|
0xC19BF174CF692694ULL, 0xE49B69C19EF14AD2ULL, 0xEFBE4786384F25E3ULL,
|
||||||
|
0x0FC19DC68B8CD5B5ULL, 0x240CA1CC77AC9C65ULL, 0x2DE92C6F592B0275ULL,
|
||||||
|
0x4A7484AA6EA6E483ULL, 0x5CB0A9DCBD41FBD4ULL, 0x76F988DA831153B5ULL,
|
||||||
|
0x983E5152EE66DFABULL, 0xA831C66D2DB43210ULL, 0xB00327C898FB213FULL,
|
||||||
|
0xBF597FC7BEEF0EE4ULL, 0xC6E00BF33DA88FC2ULL, 0xD5A79147930AA725ULL,
|
||||||
|
0x06CA6351E003826FULL, 0x142929670A0E6E70ULL, 0x27B70A8546D22FFCULL,
|
||||||
|
0x2E1B21385C26C926ULL, 0x4D2C6DFC5AC42AEDULL, 0x53380D139D95B3DFULL,
|
||||||
|
0x650A73548BAF63DEULL, 0x766A0ABB3C77B2A8ULL, 0x81C2C92E47EDAEE6ULL,
|
||||||
|
0x92722C851482353BULL, 0xA2BFE8A14CF10364ULL, 0xA81A664BBC423001ULL,
|
||||||
|
0xC24B8B70D0F89791ULL, 0xC76C51A30654BE30ULL, 0xD192E819D6EF5218ULL,
|
||||||
|
0xD69906245565A910ULL, 0xF40E35855771202AULL, 0x106AA07032BBD1B8ULL,
|
||||||
|
0x19A4C116B8D2D0C8ULL, 0x1E376C085141AB53ULL, 0x2748774CDF8EEB99ULL,
|
||||||
|
0x34B0BCB5E19B48A8ULL, 0x391C0CB3C5C95A63ULL, 0x4ED8AA4AE3418ACBULL,
|
||||||
|
0x5B9CCA4F7763E373ULL, 0x682E6FF3D6B2B8A3ULL, 0x748F82EE5DEFB2FCULL,
|
||||||
|
0x78A5636F43172F60ULL, 0x84C87814A1F0AB72ULL, 0x8CC702081A6439ECULL,
|
||||||
|
0x90BEFFFA23631E28ULL, 0xA4506CEBDE82BDE9ULL, 0xBEF9A3F7B2C67915ULL,
|
||||||
|
0xC67178F2E372532BULL, 0xCA273ECEEA26619CULL, 0xD186B8C721C0C207ULL,
|
||||||
|
0xEADA7DD6CDE0EB1EULL, 0xF57D4F7FEE6ED178ULL, 0x06F067AA72176FBAULL,
|
||||||
|
0x0A637DC5A2C898A6ULL, 0x113F9804BEF90DAEULL, 0x1B710B35131C471BULL,
|
||||||
|
0x28DB77F523047D84ULL, 0x32CAAB7B40C72493ULL, 0x3C9EBE0A15C9BEBCULL,
|
||||||
|
0x431D67C49C100D4CULL, 0x4CC5D4BECB3E42B6ULL, 0x597F299CFC657E2AULL,
|
||||||
|
0x5FCB6FAB3AD6FAECULL, 0x6C44198C4A475817ULL
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convert the first 16 words from big endian to host byte order.
|
||||||
|
uint8_t index;
|
||||||
|
for (index = 0; index < 16; ++index)
|
||||||
|
state.w[index] = be64toh(state.w[index]);
|
||||||
|
|
||||||
|
// Initialise working variables to the current hash value.
|
||||||
|
uint64_t a = state.h[0];
|
||||||
|
uint64_t b = state.h[1];
|
||||||
|
uint64_t c = state.h[2];
|
||||||
|
uint64_t d = state.h[3];
|
||||||
|
uint64_t e = state.h[4];
|
||||||
|
uint64_t f = state.h[5];
|
||||||
|
uint64_t g = state.h[6];
|
||||||
|
uint64_t h = state.h[7];
|
||||||
|
|
||||||
|
// Perform the first 16 rounds of the compression function main loop.
|
||||||
|
uint64_t temp1, temp2;
|
||||||
|
for (index = 0; index < 16; ++index) {
|
||||||
|
temp1 = h + pgm_read_qword(k + index) + state.w[index] +
|
||||||
|
(rightRotate14_64(e) ^ rightRotate18_64(e) ^
|
||||||
|
rightRotate41_64(e)) + ((e & f) ^ ((~e) & g));
|
||||||
|
temp2 = (rightRotate28_64(a) ^ rightRotate34_64(a) ^
|
||||||
|
rightRotate39_64(a)) + ((a & b) ^ (a & c) ^ (b & c));
|
||||||
|
h = g;
|
||||||
|
g = f;
|
||||||
|
f = e;
|
||||||
|
e = d + temp1;
|
||||||
|
d = c;
|
||||||
|
c = b;
|
||||||
|
b = a;
|
||||||
|
a = temp1 + temp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the 64 remaining rounds. We expand the first 16 words to
|
||||||
|
// 80 in-place in the "w" array. This saves 512 bytes of memory
|
||||||
|
// that would have otherwise need to be allocated to the "w" array.
|
||||||
|
for (; index < 80; ++index) {
|
||||||
|
// Expand the next word.
|
||||||
|
temp1 = state.w[(index - 15) & 0x0F];
|
||||||
|
temp2 = state.w[(index - 2) & 0x0F];
|
||||||
|
temp1 = state.w[index & 0x0F] =
|
||||||
|
state.w[(index - 16) & 0x0F] + state.w[(index - 7) & 0x0F] +
|
||||||
|
(rightRotate1_64(temp1) ^ rightRotate8_64(temp1) ^
|
||||||
|
(temp1 >> 7)) +
|
||||||
|
(rightRotate19_64(temp2) ^ rightRotate61_64(temp2) ^
|
||||||
|
(temp2 >> 6));
|
||||||
|
|
||||||
|
// Perform the round.
|
||||||
|
temp1 = h + pgm_read_qword(k + index) + temp1 +
|
||||||
|
(rightRotate14_64(e) ^ rightRotate18_64(e) ^
|
||||||
|
rightRotate41_64(e)) + ((e & f) ^ ((~e) & g));
|
||||||
|
temp2 = (rightRotate28_64(a) ^ rightRotate34_64(a) ^
|
||||||
|
rightRotate39_64(a)) + ((a & b) ^ (a & c) ^ (b & c));
|
||||||
|
h = g;
|
||||||
|
g = f;
|
||||||
|
f = e;
|
||||||
|
e = d + temp1;
|
||||||
|
d = c;
|
||||||
|
c = b;
|
||||||
|
b = a;
|
||||||
|
a = temp1 + temp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the compressed chunk to the current hash value.
|
||||||
|
state.h[0] += a;
|
||||||
|
state.h[1] += b;
|
||||||
|
state.h[2] += c;
|
||||||
|
state.h[3] += d;
|
||||||
|
state.h[4] += e;
|
||||||
|
state.h[5] += f;
|
||||||
|
state.h[6] += g;
|
||||||
|
state.h[7] += h;
|
||||||
|
|
||||||
|
// Attempt to clean up the stack.
|
||||||
|
a = b = c = d = e = f = g = h = temp1 = temp2 = 0;
|
||||||
|
}
|
56
libraries/Crypto/SHA512.h
Normal file
56
libraries/Crypto/SHA512.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Southern Storm Software, Pty Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CRYPTO_SHA512_h
|
||||||
|
#define CRYPTO_SHA512_h
|
||||||
|
|
||||||
|
#include "Hash.h"
|
||||||
|
|
||||||
|
class SHA512 : public Hash
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SHA512();
|
||||||
|
virtual ~SHA512();
|
||||||
|
|
||||||
|
size_t hashSize() const;
|
||||||
|
size_t blockSize() const;
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
void update(const void *data, size_t len);
|
||||||
|
void finalize(void *hash, size_t len);
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct {
|
||||||
|
uint64_t h[8];
|
||||||
|
uint64_t w[16];
|
||||||
|
uint8_t chunkSize;
|
||||||
|
bool finalized;
|
||||||
|
uint64_t lengthLow;
|
||||||
|
uint64_t lengthHigh;
|
||||||
|
} state;
|
||||||
|
|
||||||
|
void processChunk();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
179
libraries/Crypto/examples/TestSHA512/TestSHA512.ino
Normal file
179
libraries/Crypto/examples/TestSHA512/TestSHA512.ino
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Southern Storm Software, Pty Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
This example runs tests on the SHA512 implementation to verify correct behaviour.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Crypto.h>
|
||||||
|
#include <SHA512.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define HASH_SIZE 64
|
||||||
|
|
||||||
|
struct TestHashVector
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
const char *data;
|
||||||
|
uint8_t hash[HASH_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
static TestHashVector const testVectorSHA512_1 = {
|
||||||
|
"SHA-512 #1",
|
||||||
|
"",
|
||||||
|
{0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
|
||||||
|
0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
|
||||||
|
0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
|
||||||
|
0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
|
||||||
|
0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
|
||||||
|
0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
|
||||||
|
0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
|
||||||
|
0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e}
|
||||||
|
};
|
||||||
|
static TestHashVector const testVectorSHA512_2 = {
|
||||||
|
"SHA-512 #2",
|
||||||
|
"abc",
|
||||||
|
{0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
|
||||||
|
0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
|
||||||
|
0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
|
||||||
|
0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
|
||||||
|
0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
|
||||||
|
0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
|
||||||
|
0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
|
||||||
|
0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f}
|
||||||
|
};
|
||||||
|
static TestHashVector const testVectorSHA512_3 = {
|
||||||
|
"SHA-512 #3",
|
||||||
|
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
|
||||||
|
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
|
||||||
|
{0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
|
||||||
|
0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
|
||||||
|
0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
|
||||||
|
0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
|
||||||
|
0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
|
||||||
|
0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
|
||||||
|
0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
|
||||||
|
0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09}
|
||||||
|
};
|
||||||
|
|
||||||
|
SHA512 sha512;
|
||||||
|
|
||||||
|
byte buffer[128];
|
||||||
|
|
||||||
|
bool testHash_N(Hash *hash, const struct TestHashVector *test, size_t inc)
|
||||||
|
{
|
||||||
|
size_t size = strlen(test->data);
|
||||||
|
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.
|
||||||
|
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;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void testHash(Hash *hash, const struct TestHashVector *test)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
Serial.print(test->name);
|
||||||
|
Serial.print(" ... ");
|
||||||
|
|
||||||
|
ok = testHash_N(hash, test, strlen(test->data));
|
||||||
|
ok &= testHash_N(hash, test, 1);
|
||||||
|
ok &= testHash_N(hash, test, 2);
|
||||||
|
ok &= testHash_N(hash, test, 5);
|
||||||
|
ok &= testHash_N(hash, test, 8);
|
||||||
|
ok &= testHash_N(hash, test, 13);
|
||||||
|
ok &= testHash_N(hash, test, 16);
|
||||||
|
ok &= testHash_N(hash, test, 24);
|
||||||
|
ok &= testHash_N(hash, test, 63);
|
||||||
|
ok &= testHash_N(hash, test, 64);
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
Serial.println("Passed");
|
||||||
|
else
|
||||||
|
Serial.println("Failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void perfHash(Hash *hash)
|
||||||
|
{
|
||||||
|
unsigned long start;
|
||||||
|
unsigned long elapsed;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
Serial.print("Hashing ... ");
|
||||||
|
|
||||||
|
for (size_t posn = 0; posn < sizeof(buffer); ++posn)
|
||||||
|
buffer[posn] = (uint8_t)posn;
|
||||||
|
|
||||||
|
hash->reset();
|
||||||
|
start = micros();
|
||||||
|
for (count = 0; count < 250; ++count) {
|
||||||
|
hash->update(buffer, sizeof(buffer));
|
||||||
|
}
|
||||||
|
elapsed = micros() - start;
|
||||||
|
|
||||||
|
Serial.print(elapsed / (sizeof(buffer) * 250.0));
|
||||||
|
Serial.print("us per byte, ");
|
||||||
|
Serial.print((sizeof(buffer) * 250.0 * 1000000.0) / elapsed);
|
||||||
|
Serial.println(" bytes per second");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
|
Serial.println("Test Vectors:");
|
||||||
|
testHash(&sha512, &testVectorSHA512_1);
|
||||||
|
testHash(&sha512, &testVectorSHA512_2);
|
||||||
|
testHash(&sha512, &testVectorSHA512_3);
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
|
Serial.println("Performance Tests:");
|
||||||
|
perfHash(&sha512);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
}
|
@ -42,4 +42,15 @@
|
|||||||
}))
|
}))
|
||||||
#define be32toh(x) (htobe32((x)))
|
#define be32toh(x) (htobe32((x)))
|
||||||
|
|
||||||
|
#define htole64(x) (x)
|
||||||
|
#define le64toh(x) (x)
|
||||||
|
#define htobe64(x) \
|
||||||
|
(__extension__ ({ \
|
||||||
|
uint64_t __temp = (x); \
|
||||||
|
uint32_t __low = htobe32((uint32_t)__temp); \
|
||||||
|
uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \
|
||||||
|
(((uint64_t)__low) << 32) | __high; \
|
||||||
|
}))
|
||||||
|
#define be64toh(x) (htobe64((x)))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,12 +25,19 @@
|
|||||||
|
|
||||||
#if defined(__AVR__)
|
#if defined(__AVR__)
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
|
#define pgm_read_qword(x) \
|
||||||
|
(__extension__ ({ \
|
||||||
|
const uint32_t *_temp = (const uint32_t *)(x); \
|
||||||
|
((uint64_t)pgm_read_dword(_temp)) | \
|
||||||
|
(((uint64_t)pgm_read_dword(_temp + 1)) << 32); \
|
||||||
|
}))
|
||||||
#else
|
#else
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#define PROGMEM
|
#define PROGMEM
|
||||||
#define pgm_read_byte(x) (*(x))
|
#define pgm_read_byte(x) (*(x))
|
||||||
#define pgm_read_word(x) (*(x))
|
#define pgm_read_word(x) (*(x))
|
||||||
#define pgm_read_dword(x) (*(x))
|
#define pgm_read_dword(x) (*(x))
|
||||||
|
#define pgm_read_qword(x) (*(x))
|
||||||
#define memcpy_P(d,s,l) memcpy((d), (s), (l))
|
#define memcpy_P(d,s,l) memcpy((d), (s), (l))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -25,13 +25,21 @@
|
|||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#if defined(__AVR__)
|
|
||||||
|
|
||||||
// Rotation functions that are optimised for best performance on AVR.
|
// Rotation functions that are optimised for best performance on AVR.
|
||||||
// The most efficient rotations are where the number of bits is 1 or a
|
// The most efficient rotations are where the number of bits is 1 or a
|
||||||
// multiple of 8, so we compose the efficient rotations to produce all
|
// multiple of 8, so we compose the efficient rotations to produce all
|
||||||
// other rotation counts of interest.
|
// other rotation counts of interest.
|
||||||
|
|
||||||
|
#if defined(__AVR__)
|
||||||
|
#define CRYPTO_ROTATE32_COMPOSED 1
|
||||||
|
#define CRYPTO_ROTATE64_COMPOSED 0
|
||||||
|
#else
|
||||||
|
#define CRYPTO_ROTATE32_COMPOSED 0
|
||||||
|
#define CRYPTO_ROTATE64_COMPOSED 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CRYPTO_ROTATE32_COMPOSED
|
||||||
|
|
||||||
// Rotation macros for 32-bit arguments.
|
// Rotation macros for 32-bit arguments.
|
||||||
|
|
||||||
// Generic left rotate - best performance when "bits" is 1 or a multiple of 8.
|
// Generic left rotate - best performance when "bits" is 1 or a multiple of 8.
|
||||||
@ -174,6 +182,97 @@
|
|||||||
#define rightRotate30(a) (leftRotate2((a)))
|
#define rightRotate30(a) (leftRotate2((a)))
|
||||||
#define rightRotate31(a) (leftRotate1((a)))
|
#define rightRotate31(a) (leftRotate1((a)))
|
||||||
|
|
||||||
|
#else // !CRYPTO_ROTATE32_COMPOSED
|
||||||
|
|
||||||
|
// Generic rotation functions. All bit shifts are considered to have
|
||||||
|
// similar performance. Usually true of 32-bit and higher platforms.
|
||||||
|
|
||||||
|
// Rotation macros for 32-bit arguments.
|
||||||
|
|
||||||
|
// Generic left rotate.
|
||||||
|
#define leftRotate(a, bits) \
|
||||||
|
(__extension__ ({ \
|
||||||
|
uint32_t _temp = (a); \
|
||||||
|
(_temp << (bits)) | (_temp >> (32 - (bits))); \
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Generic right rotate.
|
||||||
|
#define rightRotate(a, bits) \
|
||||||
|
(__extension__ ({ \
|
||||||
|
uint32_t _temp = (a); \
|
||||||
|
(_temp >> (bits)) | (_temp << (32 - (bits))); \
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Left rotate by a specific number of bits.
|
||||||
|
#define leftRotate1(a) (leftRotate((a), 1))
|
||||||
|
#define leftRotate2(a) (leftRotate((a), 2))
|
||||||
|
#define leftRotate3(a) (leftRotate((a), 3))
|
||||||
|
#define leftRotate4(a) (leftRotate((a), 4))
|
||||||
|
#define leftRotate5(a) (leftRotate((a), 5))
|
||||||
|
#define leftRotate6(a) (leftRotate((a), 6))
|
||||||
|
#define leftRotate7(a) (leftRotate((a), 7))
|
||||||
|
#define leftRotate8(a) (leftRotate((a), 8))
|
||||||
|
#define leftRotate9(a) (leftRotate((a), 9))
|
||||||
|
#define leftRotate10(a) (leftRotate((a), 10))
|
||||||
|
#define leftRotate11(a) (leftRotate((a), 11))
|
||||||
|
#define leftRotate12(a) (leftRotate((a), 12))
|
||||||
|
#define leftRotate13(a) (leftRotate((a), 13))
|
||||||
|
#define leftRotate14(a) (leftRotate((a), 14))
|
||||||
|
#define leftRotate15(a) (leftRotate((a), 15))
|
||||||
|
#define leftRotate16(a) (leftRotate((a), 16))
|
||||||
|
#define leftRotate17(a) (leftRotate((a), 17))
|
||||||
|
#define leftRotate18(a) (leftRotate((a), 18))
|
||||||
|
#define leftRotate19(a) (leftRotate((a), 19))
|
||||||
|
#define leftRotate20(a) (leftRotate((a), 20))
|
||||||
|
#define leftRotate21(a) (leftRotate((a), 21))
|
||||||
|
#define leftRotate22(a) (leftRotate((a), 22))
|
||||||
|
#define leftRotate23(a) (leftRotate((a), 23))
|
||||||
|
#define leftRotate24(a) (leftRotate((a), 24))
|
||||||
|
#define leftRotate25(a) (leftRotate((a), 25))
|
||||||
|
#define leftRotate26(a) (leftRotate((a), 26))
|
||||||
|
#define leftRotate27(a) (leftRotate((a), 27))
|
||||||
|
#define leftRotate28(a) (leftRotate((a), 28))
|
||||||
|
#define leftRotate29(a) (leftRotate((a), 29))
|
||||||
|
#define leftRotate30(a) (leftRotate((a), 30))
|
||||||
|
#define leftRotate31(a) (leftRotate((a), 31))
|
||||||
|
|
||||||
|
// Right rotate by a specific number of bits.
|
||||||
|
#define rightRotate1(a) (rightRotate((a), 1))
|
||||||
|
#define rightRotate2(a) (rightRotate((a), 2))
|
||||||
|
#define rightRotate3(a) (rightRotate((a), 3))
|
||||||
|
#define rightRotate4(a) (rightRotate((a), 4))
|
||||||
|
#define rightRotate5(a) (rightRotate((a), 5))
|
||||||
|
#define rightRotate6(a) (rightRotate((a), 6))
|
||||||
|
#define rightRotate7(a) (rightRotate((a), 7))
|
||||||
|
#define rightRotate8(a) (rightRotate((a), 8))
|
||||||
|
#define rightRotate9(a) (rightRotate((a), 9))
|
||||||
|
#define rightRotate10(a) (rightRotate((a), 10))
|
||||||
|
#define rightRotate11(a) (rightRotate((a), 11))
|
||||||
|
#define rightRotate12(a) (rightRotate((a), 12))
|
||||||
|
#define rightRotate13(a) (rightRotate((a), 13))
|
||||||
|
#define rightRotate14(a) (rightRotate((a), 14))
|
||||||
|
#define rightRotate15(a) (rightRotate((a), 15))
|
||||||
|
#define rightRotate16(a) (rightRotate((a), 16))
|
||||||
|
#define rightRotate17(a) (rightRotate((a), 17))
|
||||||
|
#define rightRotate18(a) (rightRotate((a), 18))
|
||||||
|
#define rightRotate19(a) (rightRotate((a), 19))
|
||||||
|
#define rightRotate20(a) (rightRotate((a), 20))
|
||||||
|
#define rightRotate21(a) (rightRotate((a), 21))
|
||||||
|
#define rightRotate22(a) (rightRotate((a), 22))
|
||||||
|
#define rightRotate23(a) (rightRotate((a), 23))
|
||||||
|
#define rightRotate24(a) (rightRotate((a), 24))
|
||||||
|
#define rightRotate25(a) (rightRotate((a), 25))
|
||||||
|
#define rightRotate26(a) (rightRotate((a), 26))
|
||||||
|
#define rightRotate27(a) (rightRotate((a), 27))
|
||||||
|
#define rightRotate28(a) (rightRotate((a), 28))
|
||||||
|
#define rightRotate29(a) (rightRotate((a), 29))
|
||||||
|
#define rightRotate30(a) (rightRotate((a), 30))
|
||||||
|
#define rightRotate31(a) (rightRotate((a), 31))
|
||||||
|
|
||||||
|
#endif // !CRYPTO_ROTATE32_COMPOSED
|
||||||
|
|
||||||
|
#if CRYPTO_ROTATE64_COMPOSED
|
||||||
|
|
||||||
// Rotation macros for 64-bit arguments.
|
// Rotation macros for 64-bit arguments.
|
||||||
|
|
||||||
// Generic left rotate - best performance when "bits" is 1 or a multiple of 8.
|
// Generic left rotate - best performance when "bits" is 1 or a multiple of 8.
|
||||||
@ -272,13 +371,13 @@
|
|||||||
#define leftRotate27_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 24), 1), 1), 1))
|
#define leftRotate27_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 24), 1), 1), 1))
|
||||||
|
|
||||||
// Left rotate by 28: Rotate left by 24, then left by 4.
|
// Left rotate by 28: Rotate left by 24, then left by 4.
|
||||||
#define leftRotate28_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 1), 1), 1), 1))
|
#define leftRotate28_64(a) (leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64(leftRotate_64((a), 24), 1), 1), 1), 1))
|
||||||
|
|
||||||
// Left rotate by 29: Rotate left by 32, then right by 3.
|
// Left rotate by 29: Rotate left by 32, then right by 3.
|
||||||
#define leftRotate29_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 32), 1), 1), 1))
|
#define leftRotate29_64(a) (rightRotate_64(rightRotate_64(rightRotate_64(leftRotate_64((a), 32), 1), 1), 1))
|
||||||
|
|
||||||
// Left rotate by 30: Rotate left by 32, then right by 2.
|
// Left rotate by 30: Rotate left by 32, then right by 2.
|
||||||
#define leftRotate29_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 32), 1), 1))
|
#define leftRotate30_64(a) (rightRotate_64(rightRotate_64(leftRotate_64((a), 32), 1), 1))
|
||||||
|
|
||||||
// Left rotate by 31: Rotate left by 32, then right by 1.
|
// Left rotate by 31: Rotate left by 32, then right by 1.
|
||||||
#define leftRotate31_64(a) (rightRotate_64(leftRotate_64((a), 32), 1))
|
#define leftRotate31_64(a) (rightRotate_64(leftRotate_64((a), 32), 1))
|
||||||
@ -444,92 +543,7 @@
|
|||||||
#define rightRotate62_64(a) (leftRotate2_64((a)))
|
#define rightRotate62_64(a) (leftRotate2_64((a)))
|
||||||
#define rightRotate63_64(a) (leftRotate1_64((a)))
|
#define rightRotate63_64(a) (leftRotate1_64((a)))
|
||||||
|
|
||||||
#else
|
#else // !CRYPTO_ROTATE64_COMPOSED
|
||||||
|
|
||||||
// Generic rotation functions. All bit shifts are considered to have
|
|
||||||
// similar performance. Usually true of 32-bit and higher platforms.
|
|
||||||
|
|
||||||
// Rotation macros for 32-bit arguments.
|
|
||||||
|
|
||||||
// Generic left rotate.
|
|
||||||
#define leftRotate(a, bits) \
|
|
||||||
(__extension__ ({ \
|
|
||||||
uint32_t _temp = (a); \
|
|
||||||
(_temp << (bits)) | (_temp >> (32 - (bits))); \
|
|
||||||
}))
|
|
||||||
|
|
||||||
// Generic right rotate.
|
|
||||||
#define rightRotate(a, bits) \
|
|
||||||
(__extension__ ({ \
|
|
||||||
uint32_t _temp = (a); \
|
|
||||||
(_temp >> (bits)) | (_temp << (32 - (bits))); \
|
|
||||||
}))
|
|
||||||
|
|
||||||
// Left rotate by a specific number of bits.
|
|
||||||
#define leftRotate1(a) (leftRotate((a), 1))
|
|
||||||
#define leftRotate2(a) (leftRotate((a), 2))
|
|
||||||
#define leftRotate3(a) (leftRotate((a), 3))
|
|
||||||
#define leftRotate4(a) (leftRotate((a), 4))
|
|
||||||
#define leftRotate5(a) (leftRotate((a), 5))
|
|
||||||
#define leftRotate6(a) (leftRotate((a), 6))
|
|
||||||
#define leftRotate7(a) (leftRotate((a), 7))
|
|
||||||
#define leftRotate8(a) (leftRotate((a), 8))
|
|
||||||
#define leftRotate9(a) (leftRotate((a), 9))
|
|
||||||
#define leftRotate10(a) (leftRotate((a), 10))
|
|
||||||
#define leftRotate11(a) (leftRotate((a), 11))
|
|
||||||
#define leftRotate12(a) (leftRotate((a), 12))
|
|
||||||
#define leftRotate13(a) (leftRotate((a), 13))
|
|
||||||
#define leftRotate14(a) (leftRotate((a), 14))
|
|
||||||
#define leftRotate15(a) (leftRotate((a), 15))
|
|
||||||
#define leftRotate16(a) (leftRotate((a), 16))
|
|
||||||
#define leftRotate17(a) (leftRotate((a), 17))
|
|
||||||
#define leftRotate18(a) (leftRotate((a), 18))
|
|
||||||
#define leftRotate19(a) (leftRotate((a), 19))
|
|
||||||
#define leftRotate20(a) (leftRotate((a), 20))
|
|
||||||
#define leftRotate21(a) (leftRotate((a), 21))
|
|
||||||
#define leftRotate22(a) (leftRotate((a), 22))
|
|
||||||
#define leftRotate23(a) (leftRotate((a), 23))
|
|
||||||
#define leftRotate24(a) (leftRotate((a), 24))
|
|
||||||
#define leftRotate25(a) (leftRotate((a), 25))
|
|
||||||
#define leftRotate26(a) (leftRotate((a), 26))
|
|
||||||
#define leftRotate27(a) (leftRotate((a), 27))
|
|
||||||
#define leftRotate28(a) (leftRotate((a), 28))
|
|
||||||
#define leftRotate29(a) (leftRotate((a), 29))
|
|
||||||
#define leftRotate30(a) (leftRotate((a), 30))
|
|
||||||
#define leftRotate31(a) (leftRotate((a), 31))
|
|
||||||
|
|
||||||
// Right rotate by a specific number of bits.
|
|
||||||
#define rightRotate1(a) (rightRotate((a), 1))
|
|
||||||
#define rightRotate2(a) (rightRotate((a), 2))
|
|
||||||
#define rightRotate3(a) (rightRotate((a), 3))
|
|
||||||
#define rightRotate4(a) (rightRotate((a), 4))
|
|
||||||
#define rightRotate5(a) (rightRotate((a), 5))
|
|
||||||
#define rightRotate6(a) (rightRotate((a), 6))
|
|
||||||
#define rightRotate7(a) (rightRotate((a), 7))
|
|
||||||
#define rightRotate8(a) (rightRotate((a), 8))
|
|
||||||
#define rightRotate9(a) (rightRotate((a), 9))
|
|
||||||
#define rightRotate10(a) (rightRotate((a), 10))
|
|
||||||
#define rightRotate11(a) (rightRotate((a), 11))
|
|
||||||
#define rightRotate12(a) (rightRotate((a), 12))
|
|
||||||
#define rightRotate13(a) (rightRotate((a), 13))
|
|
||||||
#define rightRotate14(a) (rightRotate((a), 14))
|
|
||||||
#define rightRotate15(a) (rightRotate((a), 15))
|
|
||||||
#define rightRotate16(a) (rightRotate((a), 16))
|
|
||||||
#define rightRotate17(a) (rightRotate((a), 17))
|
|
||||||
#define rightRotate18(a) (rightRotate((a), 18))
|
|
||||||
#define rightRotate19(a) (rightRotate((a), 19))
|
|
||||||
#define rightRotate20(a) (rightRotate((a), 20))
|
|
||||||
#define rightRotate21(a) (rightRotate((a), 21))
|
|
||||||
#define rightRotate22(a) (rightRotate((a), 22))
|
|
||||||
#define rightRotate23(a) (rightRotate((a), 23))
|
|
||||||
#define rightRotate24(a) (rightRotate((a), 24))
|
|
||||||
#define rightRotate25(a) (rightRotate((a), 25))
|
|
||||||
#define rightRotate26(a) (rightRotate((a), 26))
|
|
||||||
#define rightRotate27(a) (rightRotate((a), 27))
|
|
||||||
#define rightRotate28(a) (rightRotate((a), 28))
|
|
||||||
#define rightRotate29(a) (rightRotate((a), 29))
|
|
||||||
#define rightRotate30(a) (rightRotate((a), 30))
|
|
||||||
#define rightRotate31(a) (rightRotate((a), 31))
|
|
||||||
|
|
||||||
// Rotation macros for 64-bit arguments.
|
// Rotation macros for 64-bit arguments.
|
||||||
|
|
||||||
@ -677,6 +691,6 @@
|
|||||||
#define rightRotate62_64(a) (rightRotate_64((a), 62))
|
#define rightRotate62_64(a) (rightRotate_64((a), 62))
|
||||||
#define rightRotate63_64(a) (rightRotate_64((a), 63))
|
#define rightRotate63_64(a) (rightRotate_64((a), 63))
|
||||||
|
|
||||||
#endif
|
#endif // !CRYPTO_ROTATE64_COMPOSED
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user