From 3bcfbcd43b422167b32327327682bc2ff707b469 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Tue, 31 Mar 2015 09:43:09 +1000 Subject: [PATCH] Centralize the definition of big number limb types --- libraries/Crypto/BigNumberUtil.h | 51 +++++++++++++++++++ libraries/Crypto/Curve25519.cpp | 20 ++++---- libraries/Crypto/Curve25519.h | 25 +-------- libraries/Crypto/Poly1305.cpp | 10 +++- libraries/Crypto/Poly1305.h | 5 +- .../TestCurve25519Math/TestCurve25519Math.ino | 16 +++--- 6 files changed, 79 insertions(+), 48 deletions(-) create mode 100644 libraries/Crypto/BigNumberUtil.h diff --git a/libraries/Crypto/BigNumberUtil.h b/libraries/Crypto/BigNumberUtil.h new file mode 100644 index 00000000..65719478 --- /dev/null +++ b/libraries/Crypto/BigNumberUtil.h @@ -0,0 +1,51 @@ +/* + * 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_BIGNUMBERUTIL_h +#define CRYPTO_BIGNUMBERUTIL_h + +#include + +// Define exactly one of these to 1 to set the size of the basic limb type. +// 16-bit limbs seem to give the best performance on 8-bit AVR micros. +#define BIGNUMBER_LIMB_8BIT 0 +#define BIGNUMBER_LIMB_16BIT 1 +#define BIGNUMBER_LIMB_32BIT 0 + +// Define the limb types to use on this platform. +#if BIGNUMBER_LIMB_8BIT +typedef uint8_t limb_t; +typedef int8_t slimb_t; +typedef uint16_t dlimb_t; +#elif BIGNUMBER_LIMB_16BIT +typedef uint16_t limb_t; +typedef int16_t slimb_t; +typedef uint32_t dlimb_t; +#elif BIGNUMBER_LIMB_32BIT +typedef uint32_t limb_t; +typedef int32_t slimb_t; +typedef uint64_t dlimb_t; +#else +#error "limb_t must be 8, 16, or 32 bits in size" +#endif + +#endif diff --git a/libraries/Crypto/Curve25519.cpp b/libraries/Crypto/Curve25519.cpp index d68bfda1..64ee1597 100644 --- a/libraries/Crypto/Curve25519.cpp +++ b/libraries/Crypto/Curve25519.cpp @@ -468,7 +468,7 @@ void Curve25519::reduce(limb_t *result, limb_t *x, uint8_t size) * the caller knows that \a x is within the described range. A single * trial subtraction is all that is needed to reduce the number. */ -Curve25519::limb_t Curve25519::reduceQuick(limb_t *x) +limb_t Curve25519::reduceQuick(limb_t *x) { limb_t temp[NUM_LIMBS]; dlimb_t carry; @@ -570,13 +570,13 @@ void Curve25519::mul(limb_t *result, const limb_t *x, const limb_t *y) void Curve25519::mulA24(limb_t *result, const limb_t *x) { // The constant a24 = 121665 (0x1DB41) as a limb array. -#if CURVE25519_LIMB_8BIT +#if BIGNUMBER_LIMB_8BIT static limb_t const a24[3] PROGMEM = {0x41, 0xDB, 0x01}; #define pgm_read_a24(index) (pgm_read_byte(&(a24[(index)]))) -#elif CURVE25519_LIMB_16BIT +#elif BIGNUMBER_LIMB_16BIT static limb_t const a24[2] PROGMEM = {0xDB41, 0x0001}; #define pgm_read_a24(index) (pgm_read_word(&(a24[(index)]))) -#elif CURVE25519_LIMB_32BIT +#elif BIGNUMBER_LIMB_32BIT static limb_t const a24[1] PROGMEM = {0x0001DB41}; #define pgm_read_a24(index) (pgm_read_dword(&(a24[(index)]))) #else @@ -781,15 +781,15 @@ void Curve25519::recip(limb_t *result, const limb_t *x) */ void Curve25519::unpack(limb_t *result, const uint8_t *x) { -#if CURVE25519_LIMB_8BIT +#if BIGNUMBER_LIMB_8BIT memcpy(result, x, 32); result[31] &= 0x7F; -#elif CURVE25519_LIMB_16BIT +#elif BIGNUMBER_LIMB_16BIT for (uint8_t posn = 0; posn < 16; ++posn) { result[posn] = ((limb_t)x[posn * 2]) | (((limb_t)x[posn * 2 + 1]) << 8); } result[15] &= 0x7FFF; -#elif CURVE25519_LIMB_32BIT +#elif BIGNUMBER_LIMB_32BIT for (uint8_t posn = 0; posn < 8; ++posn) { result[posn] = ((limb_t)x[posn * 4]) | (((limb_t)x[posn * 4 + 1]) << 8) | @@ -811,15 +811,15 @@ void Curve25519::unpack(limb_t *result, const uint8_t *x) */ void Curve25519::pack(uint8_t *result, const limb_t *x) { -#if CURVE25519_LIMB_8BIT +#if BIGNUMBER_LIMB_8BIT memcpy(result, x, 32); -#elif CURVE25519_LIMB_16BIT +#elif BIGNUMBER_LIMB_16BIT for (uint8_t posn = 0; posn < 16; ++posn) { limb_t value = x[posn]; result[posn * 2] = (uint8_t)value; result[posn * 2 + 1] = (uint8_t)(value >> 8); } -#elif CURVE25519_LIMB_32BIT +#elif BIGNUMBER_LIMB_32BIT for (uint8_t posn = 0; posn < 8; ++posn) { limb_t value = x[posn]; result[posn * 4] = (uint8_t)value; diff --git a/libraries/Crypto/Curve25519.h b/libraries/Crypto/Curve25519.h index 4f702c47..567fae5c 100644 --- a/libraries/Crypto/Curve25519.h +++ b/libraries/Crypto/Curve25519.h @@ -23,15 +23,9 @@ #ifndef CRYPTO_CURVE15519_h #define CRYPTO_CURVE15519_h -#include +#include "BigNumberUtil.h" #include -// Define exactly one of these to 1 to set the size of the basic limb type. -// 16-bit limbs seems to give the best performance on 8-bit AVR micros. -#define CURVE25519_LIMB_8BIT 0 -#define CURVE25519_LIMB_16BIT 1 -#define CURVE25519_LIMB_32BIT 0 - class Curve25519 { public: @@ -45,23 +39,6 @@ public: #else private: #endif - // Define the limb types to use on this platform. - #if CURVE25519_LIMB_8BIT - typedef uint8_t limb_t; - typedef int8_t slimb_t; - typedef uint16_t dlimb_t; - #elif CURVE25519_LIMB_16BIT - typedef uint16_t limb_t; - typedef int16_t slimb_t; - typedef uint32_t dlimb_t; - #elif CURVE25519_LIMB_32BIT - typedef uint32_t limb_t; - typedef int32_t slimb_t; - typedef uint64_t dlimb_t; - #else - #error "limb_t must be 8, 16, or 32 bits in size" - #endif - static uint8_t isWeakPoint(const uint8_t k[32]); static void reduce(limb_t *result, limb_t *x, uint8_t size); diff --git a/libraries/Crypto/Poly1305.cpp b/libraries/Crypto/Poly1305.cpp index 4b918751..a0a143ca 100644 --- a/libraries/Crypto/Poly1305.cpp +++ b/libraries/Crypto/Poly1305.cpp @@ -63,9 +63,17 @@ #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. +// Endian helper macros for limbs and arrays of limbs. +#if BIGNUMBER_LIMB_8BIT +#define lelimbtoh(x) (x) +#define htolelimb(x) (x) +#elif BIGNUMBER_LIMB_16BIT #define lelimbtoh(x) (le16toh((x))) #define htolelimb(x) (htole16((x))) +#elif BIGNUMBER_LIMB_32BIT +#define lelimbtoh(x) (le32toh((x))) +#define htolelimb(x) (htole32((x))) +#endif #if defined(CRYPTO_LITTLE_ENDIAN) #define littleToHost(r,size) do { ; } while (0) #else diff --git a/libraries/Crypto/Poly1305.h b/libraries/Crypto/Poly1305.h index 9dde521a..babae205 100644 --- a/libraries/Crypto/Poly1305.h +++ b/libraries/Crypto/Poly1305.h @@ -23,7 +23,7 @@ #ifndef CRYPTO_POLY1305_h #define CRYPTO_POLY1305_h -#include +#include "BigNumberUtil.h" #include class Poly1305 @@ -39,9 +39,6 @@ public: 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]; diff --git a/libraries/Crypto/examples/TestCurve25519Math/TestCurve25519Math.ino b/libraries/Crypto/examples/TestCurve25519Math/TestCurve25519Math.ino index 06a2e977..9bb30dfd 100644 --- a/libraries/Crypto/examples/TestCurve25519Math/TestCurve25519Math.ino +++ b/libraries/Crypto/examples/TestCurve25519Math/TestCurve25519Math.ino @@ -34,19 +34,17 @@ of the full curve operation itself. #include // Copy some definitions from the Curve25519 class for convenience. -#define NUM_LIMBS (32 / sizeof(Curve25519::limb_t)) -#define LIMB_BITS (8 * sizeof(Curve25519::limb_t)) -#define limb_t Curve25519::limb_t -#define dlimb_t Curve25519::dlimb_t +#define NUM_LIMBS (32 / sizeof(limb_t)) +#define LIMB_BITS (8 * sizeof(limb_t)) #define INVERSE_LIMB (~((limb_t)0)) // For simpleMod() below we need a type that is 4 times the size of limb_t. -#if CURVE25519_LIMB_8BIT +#if BIGNUMBER_LIMB_8BIT #define qlimb_t uint32_t -#elif CURVE25519_LIMB_16BIT +#elif BIGNUMBER_LIMB_16BIT #define qlimb_t uint64_t #else -#define CURVE25519_NO_QLIMB 1 +#define BIGNUMBER_NO_QLIMB 1 #endif limb_t arg1[NUM_LIMBS]; @@ -222,7 +220,7 @@ void simpleMul(limb_t *result, const limb_t *x, const limb_t *y) } } -#if defined(CURVE25519_NO_QLIMB) +#if defined(BIGNUMBER_NO_QLIMB) // Quick check to correct the estimate on a quotient word. static inline limb_t correctEstimate @@ -314,7 +312,7 @@ void simpleMod(limb_t *x) // One subtlety of Knuth's algorithm is that it looks like the test // is working with double-word quantities but it is actually using // double-word plus a carry bit. So we need to use qlimb_t for this. -#if !defined(CURVE25519_NO_QLIMB) +#if !defined(BIGNUMBER_NO_QLIMB) qlimb_t test = ((((qlimb_t)uword) - ((dlimb_t)q) * v[1]) << LIMB_BITS) + u[0]; if ((((dlimb_t)q) * v[0]) > test) { --q;