diff --git a/doc/crypto.dox b/doc/crypto.dox index b793611d..88553484 100644 --- a/doc/crypto.dox +++ b/doc/crypto.dox @@ -30,6 +30,7 @@ \li Block cipher modes: CTR, CFB, CBC, OFB \li Stream ciphers: ChaCha \li Hash algorithms: SHA1, SHA256, SHA512, SHA3_256, SHA3_512, BLAKE2s, BLAKE2b (regular and HMAC modes) +\li Message authenticators: Poly1305 \li Public key algorithms: Curve25519 \li Random number generation: \link RNGClass RNG\endlink, TransistorNoiseSource, RingOscillatorNoiseSource @@ -74,6 +75,7 @@ Ardunino Mega 2560 running at 16 MHz are similar: SHA3_512229.12us 403 BLAKE2s18.54us 169 BLAKE2b50.58us 337 +Poly130526.29us 87 Where a cipher supports more than one key size (such as ChaCha), the values diff --git a/doc/mainpage.dox b/doc/mainpage.dox index fcd2647b..4b58ba47 100644 --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -95,6 +95,7 @@ realtime clock and the LCD library to implement an alarm clock. \li Block cipher modes: CTR, CFB, CBC, OFB \li Stream ciphers: ChaCha \li Hash algorithms: SHA1, SHA256, SHA512, SHA3_256, SHA3_512, BLAKE2s, BLAKE2b (regular and HMAC modes) +\li Message authenticators: Poly1305 \li Public key algorithms: Curve25519 \li Random number generation: \link RNGClass RNG\endlink, TransistorNoiseSource, RingOscillatorNoiseSource diff --git a/libraries/Crypto/Poly1305.cpp b/libraries/Crypto/Poly1305.cpp new file mode 100644 index 00000000..4b918751 --- /dev/null +++ b/libraries/Crypto/Poly1305.cpp @@ -0,0 +1,316 @@ +/* + * 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 "Poly1305.h" +#include "Crypto.h" +#include "utility/EndianUtil.h" +#include + +/** + * \class Poly1305 Poly1305.h + * \brief Poly1305 message authenticator + * + * Poly1305 is a message authenticator designed by Daniel J. Bernstein. + * An arbitrary-length message is broken up into 16-byte chunks and fed + * into a polynomial mod 2130 - 5 based on the 16-byte + * authentication key. The final polynomial value is then combined with a + * 16-byte nonce to create the authentication token. + * + * The following example demonstrates how to compute an authentication token + * for a message made up of several blocks under a specific key and nonce: + * + * \code + * Poly1305 poly1305; + * uint8_t token[16]; + * poly1305.reset(key); + * poly1305.update(block1, sizeof(block1)); + * poly1305.update(block2, sizeof(block2)); + * ... + * poly1305.update(blockN, sizeof(blockN)); + * poly1305.finalize(nonce, token, sizeof(token)); + * \endcode + * + * In the original Poly1305 specification, the nonce was encrypted with AES + * and a second 16-byte key. Since then, common practice has been for the + * caller to encrypt the nonce which gives the caller more flexibility as + * to how to derive and/or encrypt the nonce. + * + * References: http://en.wikipedia.org/wiki/Poly1305-AES, + * http://cr.yp.to/mac.html + */ + +// Useful sizes for limb array and word manipulation. +#define NUM_LIMBS_128BIT (16 / sizeof(limb_t)) +#define NUM_LIMBS_130BIT ((16 / sizeof(limb_t)) + 1) +#define LIMB_BITS (sizeof(limb_t) * 8) + +// Endian helper macros. Need modification if the size of limb_t changes. +#define lelimbtoh(x) (le16toh((x))) +#define htolelimb(x) (htole16((x))) +#if defined(CRYPTO_LITTLE_ENDIAN) +#define littleToHost(r,size) do { ; } while (0) +#else +#define littleToHost(r,size) \ + do { \ + for (uint8_t i = 0; i < (size); ++i) \ + (r)[i] = lelimbtoh((r)[i]); \ + } while (0) +#endif + +/** + * \brief Constructs a new Poly1305 message authenticator. + */ +Poly1305::Poly1305() +{ + state.chunkSize = 0; +} + +/** + * \brief Destroys this Poly1305 message authenticator after clearing all + * sensitive information. + */ +Poly1305::~Poly1305() +{ + clean(state); +} + +/** + * \brief Resets the Poly1305 message authenticator for a new session. + * + * \param key Points to the 16 byte authentication key. + * + * \sa update(), finalize() + */ +void Poly1305::reset(const void *key) +{ + // Copy the key into place and clear the bits we don't need. + uint8_t *r = (uint8_t *)state.r; + memcpy(r, key, 16); + r[3] &= 0x0F; + r[4] &= 0xFC; + r[7] &= 0x0F; + r[8] &= 0xFC; + r[11] &= 0x0F; + r[12] &= 0xFC; + r[15] &= 0x0F; + + // Convert into little-endian if necessary. + littleToHost(state.r, NUM_LIMBS_128BIT); + + // Reset the hashing process. + state.chunkSize = 0; + memset(state.h, 0, sizeof(state.h)); +} + +/** + * \brief Updates the message authenticator with more data. + * + * \param data Data to be hashed. + * \param len Number of bytes of data to be hashed. + * + * If finalize() has already been called, then the behavior of update() will + * be undefined. Call reset() first to start a new authentication process. + * + * \sa reset(), finalize() + */ +void Poly1305::update(const void *data, size_t len) +{ + // Break the input up into 128-bit chunks and process each in turn. + const uint8_t *d = (const uint8_t *)data; + while (len > 0) { + uint8_t size = 16 - state.chunkSize; + if (size > len) + size = len; + memcpy(((uint8_t *)state.c) + state.chunkSize, d, size); + state.chunkSize += size; + len -= size; + d += size; + if (state.chunkSize == 16) { + littleToHost(state.c, NUM_LIMBS_128BIT); + state.c[NUM_LIMBS_128BIT] = 1; + processChunk(); + state.chunkSize = 0; + } + } +} + +/** + * \brief Finalizes the authentication process and returns the token. + * + * \param nonce Points to the 16-bit nonce to combine with the token. + * \param token The buffer to return the token value in. + * \param len The length of the \a token buffer between 0 and 16. + * + * If \a len is less than 16, then the token value will be truncated to + * the first \a len bytes. If \a len is greater than 16, then the remaining + * bytes will left unchanged. + * + * If finalize() is called again, then the returned \a token value is + * undefined. Call reset() first to start a new authentication process. + * + * \sa reset(), update() + */ +void Poly1305::finalize(const void *nonce, void *token, size_t len) +{ + dlimb_t carry; + uint8_t i; + + // Pad and flush the final chunk. + if (state.chunkSize > 0) { + uint8_t *c = (uint8_t *)state.c; + c[state.chunkSize] = 1; + memset(c + state.chunkSize + 1, 0, 16 - state.chunkSize - 1); + littleToHost(state.c, NUM_LIMBS_128BIT); + state.c[NUM_LIMBS_128BIT] = 0; + processChunk(); + } + + // At this point, processChunk() has left h as a partially reduced + // result that is less than (2^130 - 5) * 6. Perform one more + // reduction and a trial subtraction to produce the final result. + + // Multiply the high bits of h by 5 and add them to the 130 low bits. + carry = (dlimb_t)((state.h[NUM_LIMBS_128BIT] >> 2) + + (state.h[NUM_LIMBS_128BIT] & ~((limb_t)3))); + state.h[NUM_LIMBS_128BIT] &= 0x0003; + for (i = 0; i < NUM_LIMBS_128BIT; ++i) { + carry += state.h[i]; + state.h[i] = (limb_t)carry; + carry >>= LIMB_BITS; + } + state.h[i] += (limb_t)carry; + + // Subtract (2^130 - 5) from h by computing t = h + 5 - 2^130. + // The "minus 2^130" step is implicit. + carry = 5; + for (i = 0; i < NUM_LIMBS_130BIT; ++i) { + carry += state.h[i]; + state.t[i] = (limb_t)carry; + carry >>= LIMB_BITS; + } + + // Borrow occurs if bit 2^130 of the previous t result is zero. + // Carefully turn this into a selection mask so we can select either + // h or t as the final result. We don't care about the highest word + // of the result because we are about to drop it in the next step. + // We have to do it this way to avoid giving away any information + // about the value of h in the instruction timing. + limb_t mask = (~((state.t[NUM_LIMBS_128BIT] >> 2) & 1)) + 1; + limb_t nmask = ~mask; + for (i = 0; i < NUM_LIMBS_128BIT; ++i) { + state.h[i] = (state.h[i] & nmask) | (state.t[i] & mask); + } + + // Add the encrypted nonce and format the final hash. + memcpy(state.c, nonce, 16); + littleToHost(state.c, NUM_LIMBS_128BIT); + carry = 0; + for (i = 0; i < NUM_LIMBS_128BIT; ++i) { + carry += state.h[i]; + carry += state.c[i]; + state.h[i] = htolelimb((limb_t)carry); + carry >>= LIMB_BITS; + } + if (len > 16) + len = 16; + memcpy(token, state.h, len); +} + +/** + * \brief Clears the authenticator's state, removing all sensitive data. + */ +void Poly1305::clear() +{ + clean(state); +} + +/** + * \brief Processes a single 128-bit chunk of input data. + */ +void Poly1305::processChunk() +{ + // Compute h = ((h + c) * r) mod (2^130 - 5). + + // Start with h += c. We assume that h is less than (2^130 - 5) * 6 + // and that c is less than 2^129, so the result will be less than 2^133. + dlimb_t carry = 0; + uint8_t i, j; + for (i = 0; i < NUM_LIMBS_130BIT; ++i) { + carry += state.h[i]; + carry += state.c[i]; + state.h[i] = (limb_t)carry; + carry >>= LIMB_BITS; + } + + // Multiply h by r. We know that r is less than 2^124 because the + // top 4 bits were AND-ed off by reset(). That makes h * r less + // than 2^257. Which is less than the (2^130 - 6)^2 we want for + // the modulo reduction step that follows. + carry = 0; + limb_t word = state.r[0]; + for (i = 0; i < NUM_LIMBS_130BIT; ++i) { + carry += ((dlimb_t)(state.h[i])) * word; + state.t[i] = (limb_t)carry; + carry >>= LIMB_BITS; + } + state.t[NUM_LIMBS_130BIT] = (limb_t)carry; + for (i = 1; i < NUM_LIMBS_128BIT; ++i) { + word = state.r[i]; + carry = 0; + for (j = 0; j < NUM_LIMBS_130BIT; ++j) { + carry += ((dlimb_t)(state.h[j])) * word; + carry += state.t[i + j]; + state.t[i + j] = (limb_t)carry; + carry >>= LIMB_BITS; + } + state.t[i + NUM_LIMBS_130BIT] = (limb_t)carry; + } + + // Reduce h * r modulo (2^130 - 5) by multiplying the high 130 bits by 5 + // and adding them to the low 130 bits. See the explaination in the + // comments for Curve25519::reduce() for a description of how this works. + carry = ((dlimb_t)(state.t[NUM_LIMBS_128BIT] >> 2)) + + (state.t[NUM_LIMBS_128BIT] & ~((limb_t)3)); + state.t[NUM_LIMBS_128BIT] &= 0x0003; + for (i = 0; i < NUM_LIMBS_128BIT; ++i) { + // Shift the next word of t up by (LIMB_BITS - 2) bits and then + // multiply it by 5. Breaking it down, we can add the results + // of shifting up by LIMB_BITS and shifting up by (LIMB_BITS - 2). + // The main wrinkle here is that this can result in an intermediate + // carry that is (LIMB_BITS * 2 + 1) bits in size which doesn't + // fit within a dlimb_t variable. However, we can defer adding + // (word << LIMB_BITS) until after the "carry >>= LIMB_BITS" step + // because it won't affect the low bits of the carry. + word = state.t[i + NUM_LIMBS_130BIT]; + carry += ((dlimb_t)word) << (LIMB_BITS - 2); + carry += state.t[i]; + state.h[i] = (limb_t)carry; + carry >>= LIMB_BITS; + carry += word; + } + state.h[i] = (limb_t)(carry + state.t[NUM_LIMBS_128BIT]); + + // At this point, h is either the answer of reducing modulo (2^130 - 5) + // or it is at most 5 subtractions away from the answer we want. + // Leave it as-is for now with h less than (2^130 - 5) * 6. It is + // still within a range where the next h * r step will not overflow. +} diff --git a/libraries/Crypto/Poly1305.h b/libraries/Crypto/Poly1305.h new file mode 100644 index 00000000..9dde521a --- /dev/null +++ b/libraries/Crypto/Poly1305.h @@ -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_POLY1305_h +#define CRYPTO_POLY1305_h + +#include +#include + +class Poly1305 +{ +public: + Poly1305(); + ~Poly1305(); + + void reset(const void *key); + void update(const void *data, size_t len); + void finalize(const void *nonce, void *token, size_t len); + + void clear(); + +private: + typedef uint16_t limb_t; + typedef int16_t slimb_t; + typedef uint32_t dlimb_t; + struct { + limb_t h[(16 / sizeof(limb_t)) + 1]; + limb_t c[(16 / sizeof(limb_t)) + 1]; + limb_t r[(16 / sizeof(limb_t))]; + limb_t t[(32 / sizeof(limb_t)) + 1]; + uint8_t chunkSize; + } state; + + void processChunk(); +}; + +#endif diff --git a/libraries/Crypto/examples/TestPoly1305/TestPoly1305.ino b/libraries/Crypto/examples/TestPoly1305/TestPoly1305.ino new file mode 100644 index 00000000..0c07cc3d --- /dev/null +++ b/libraries/Crypto/examples/TestPoly1305/TestPoly1305.ino @@ -0,0 +1,190 @@ +/* + * 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 Poly1305 implementation to verify correct behaviour. +*/ + +#include +#include +#include + +// Test vectors from the Poly1305 specification. + +struct TestPoly1305Vector +{ + const char *name; + uint8_t key[16]; + uint8_t nonce[16]; + uint8_t data[64]; + size_t dataLen; + uint8_t hash[16]; +}; + +static TestPoly1305Vector const testVectorPoly1305_1 = { + .name = "Poly1305 #1", + .key = {0x85, 0x1f, 0xc4, 0x0c, 0x34, 0x67, 0xac, 0x0b, + 0xe0, 0x5c, 0xc2, 0x04, 0x04, 0xf3, 0xf7, 0x00}, + .nonce = {0x58, 0x0b, 0x3b, 0x0f, 0x94, 0x47, 0xbb, 0x1e, + 0x69, 0xd0, 0x95, 0xb5, 0x92, 0x8b, 0x6d, 0xbc}, + .data = {0xf3, 0xf6}, + .dataLen = 2, + .hash = {0xf4, 0xc6, 0x33, 0xc3, 0x04, 0x4f, 0xc1, 0x45, + 0xf8, 0x4f, 0x33, 0x5c, 0xb8, 0x19, 0x53, 0xde} + +}; +static TestPoly1305Vector const testVectorPoly1305_2 = { + .name = "Poly1305 #2", + .key = {0xa0, 0xf3, 0x08, 0x00, 0x00, 0xf4, 0x64, 0x00, + 0xd0, 0xc7, 0xe9, 0x07, 0x6c, 0x83, 0x44, 0x03}, + .nonce = {0xdd, 0x3f, 0xab, 0x22, 0x51, 0xf1, 0x1a, 0xc7, + 0x59, 0xf0, 0x88, 0x71, 0x29, 0xcc, 0x2e, 0xe7}, + .data = {0}, + .dataLen = 0, + .hash = {0xdd, 0x3f, 0xab, 0x22, 0x51, 0xf1, 0x1a, 0xc7, + 0x59, 0xf0, 0x88, 0x71, 0x29, 0xcc, 0x2e, 0xe7} +}; +static TestPoly1305Vector const testVectorPoly1305_3 = { + .name = "Poly1305 #3", + .key = {0x48, 0x44, 0x3d, 0x0b, 0xb0, 0xd2, 0x11, 0x09, + 0xc8, 0x9a, 0x10, 0x0b, 0x5c, 0xe2, 0xc2, 0x08}, + .nonce = {0x83, 0x14, 0x9c, 0x69, 0xb5, 0x61, 0xdd, 0x88, + 0x29, 0x8a, 0x17, 0x98, 0xb1, 0x07, 0x16, 0xef}, + .data = {0x66, 0x3c, 0xea, 0x19, 0x0f, 0xfb, 0x83, 0xd8, + 0x95, 0x93, 0xf3, 0xf4, 0x76, 0xb6, 0xbc, 0x24, + 0xd7, 0xe6, 0x79, 0x10, 0x7e, 0xa2, 0x6a, 0xdb, + 0x8c, 0xaf, 0x66, 0x52, 0xd0, 0x65, 0x61, 0x36}, + .dataLen = 32, + .hash = {0x0e, 0xe1, 0xc1, 0x6b, 0xb7, 0x3f, 0x0f, 0x4f, + 0xd1, 0x98, 0x81, 0x75, 0x3c, 0x01, 0xcd, 0xbe} +}; +static TestPoly1305Vector const testVectorPoly1305_4 = { + .name = "Poly1305 #4", + .key = {0x12, 0x97, 0x6a, 0x08, 0xc4, 0x42, 0x6d, 0x0c, + 0xe8, 0xa8, 0x24, 0x07, 0xc4, 0xf4, 0x82, 0x07}, + .nonce = {0x80, 0xf8, 0xc2, 0x0a, 0xa7, 0x12, 0x02, 0xd1, + 0xe2, 0x91, 0x79, 0xcb, 0xcb, 0x55, 0x5a, 0x57}, + .data = {0xab, 0x08, 0x12, 0x72, 0x4a, 0x7f, 0x1e, 0x34, + 0x27, 0x42, 0xcb, 0xed, 0x37, 0x4d, 0x94, 0xd1, + 0x36, 0xc6, 0xb8, 0x79, 0x5d, 0x45, 0xb3, 0x81, + 0x98, 0x30, 0xf2, 0xc0, 0x44, 0x91, 0xfa, 0xf0, + 0x99, 0x0c, 0x62, 0xe4, 0x8b, 0x80, 0x18, 0xb2, + 0xc3, 0xe4, 0xa0, 0xfa, 0x31, 0x34, 0xcb, 0x67, + 0xfa, 0x83, 0xe1, 0x58, 0xc9, 0x94, 0xd9, 0x61, + 0xc4, 0xcb, 0x21, 0x09, 0x5c, 0x1b, 0xf9}, + .dataLen = 63, + .hash = {0x51, 0x54, 0xad, 0x0d, 0x2c, 0xb2, 0x6e, 0x01, + 0x27, 0x4f, 0xc5, 0x11, 0x48, 0x49, 0x1f, 0x1b} +}; + +Poly1305 poly1305; + +byte buffer[128]; + +bool testPoly1305_N(Poly1305 *hash, const struct TestPoly1305Vector *test, size_t inc) +{ + size_t size = test->dataLen; + size_t posn, len; + + hash->reset(test->key); + + for (posn = 0; posn < size; posn += inc) { + len = size - posn; + if (len > inc) + len = inc; + hash->update(test->data + posn, len); + } + + hash->finalize(test->nonce, buffer, 16); + + return !memcmp(buffer, test->hash, 16); +} + +void testPoly1305(Poly1305 *hash, const struct TestPoly1305Vector *test) +{ + bool ok; + + Serial.print(test->name); + Serial.print(" ... "); + + ok = testPoly1305_N(hash, test, test->dataLen); + ok &= testPoly1305_N(hash, test, 1); + ok &= testPoly1305_N(hash, test, 2); + ok &= testPoly1305_N(hash, test, 5); + ok &= testPoly1305_N(hash, test, 8); + ok &= testPoly1305_N(hash, test, 13); + ok &= testPoly1305_N(hash, test, 16); + ok &= testPoly1305_N(hash, test, 24); + ok &= testPoly1305_N(hash, test, 63); + ok &= testPoly1305_N(hash, test, 64); + + if (ok) + Serial.println("Passed"); + else + Serial.println("Failed"); +} + +void perfPoly1305(Poly1305 *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(testVectorPoly1305_1.key); + start = micros(); + for (count = 0; count < 1000; ++count) { + hash->update(buffer, sizeof(buffer)); + } + elapsed = micros() - start; + + Serial.print(elapsed / (sizeof(buffer) * 1000.0)); + Serial.print("us per byte, "); + Serial.print((sizeof(buffer) * 1000.0 * 1000000.0) / elapsed); + Serial.println(" bytes per second"); +} + +void setup() +{ + Serial.begin(9600); + + Serial.println(); + + Serial.println("Test Vectors:"); + testPoly1305(&poly1305, &testVectorPoly1305_1); + testPoly1305(&poly1305, &testVectorPoly1305_2); + testPoly1305(&poly1305, &testVectorPoly1305_3); + testPoly1305(&poly1305, &testVectorPoly1305_4); + + Serial.println(); + + Serial.println("Performance Tests:"); + perfPoly1305(&poly1305); +} + +void loop() +{ +} diff --git a/libraries/Crypto/utility/EndianUtil.h b/libraries/Crypto/utility/EndianUtil.h index b64f9726..29c2c150 100644 --- a/libraries/Crypto/utility/EndianUtil.h +++ b/libraries/Crypto/utility/EndianUtil.h @@ -30,6 +30,16 @@ #define CRYPTO_LITTLE_ENDIAN 1 +#define htole16(x) (x) +#define le16toh(x) (x) +#define htobe16(x) \ + (__extension__ ({ \ + uint16_t _temp = (x); \ + ((_temp >> 8) & 0x00FF) | \ + ((_temp << 8) & 0xFF00); \ + })) +#define be16toh(x) (htobe16((x))) + #define htole32(x) (x) #define le32toh(x) (x) #define htobe32(x) \