From c009d4a2b4f71c1f56fc4865e47b966301f8016a Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Sun, 4 Jan 2015 08:32:01 +1000 Subject: [PATCH] Move static tables into program space --- libraries/Crypto/AESCommon.cpp | 87 +++++++++++++++++----------------- libraries/Crypto/ChaCha.cpp | 9 ++-- libraries/Crypto/ProgMemUtil.h | 35 ++++++++++++++ libraries/Crypto/SHA256.cpp | 7 +-- 4 files changed, 88 insertions(+), 50 deletions(-) create mode 100644 libraries/Crypto/ProgMemUtil.h diff --git a/libraries/Crypto/AESCommon.cpp b/libraries/Crypto/AESCommon.cpp index e583b3b9..5c571ccf 100644 --- a/libraries/Crypto/AESCommon.cpp +++ b/libraries/Crypto/AESCommon.cpp @@ -22,6 +22,7 @@ #include "AES.h" #include "Crypto.h" +#include "ProgMemUtil.h" /** * \class AESCommon AES.h @@ -43,7 +44,7 @@ */ // AES S-box (http://en.wikipedia.org/wiki/Rijndael_S-box) -static uint8_t const sbox[256] = { +static uint8_t const sbox[256] PROGMEM = { 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, // 0x00 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, // 0x10 @@ -79,7 +80,7 @@ static uint8_t const sbox[256] = { }; // AES inverse S-box (http://en.wikipedia.org/wiki/Rijndael_S-box) -static uint8_t const sbox_inverse[256] = { +static uint8_t const sbox_inverse[256] PROGMEM = { 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, // 0x00 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, // 0x10 @@ -178,42 +179,42 @@ static uint8_t const K[8] = { static void subBytesAndShiftRows(uint8_t *output, const uint8_t *input) { - OUT(0, 0) = sbox[IN(0, 0)]; - OUT(0, 1) = sbox[IN(1, 1)]; - OUT(0, 2) = sbox[IN(2, 2)]; - OUT(0, 3) = sbox[IN(3, 3)]; - OUT(1, 0) = sbox[IN(1, 0)]; - OUT(1, 1) = sbox[IN(2, 1)]; - OUT(1, 2) = sbox[IN(3, 2)]; - OUT(1, 3) = sbox[IN(0, 3)]; - OUT(2, 0) = sbox[IN(2, 0)]; - OUT(2, 1) = sbox[IN(3, 1)]; - OUT(2, 2) = sbox[IN(0, 2)]; - OUT(2, 3) = sbox[IN(1, 3)]; - OUT(3, 0) = sbox[IN(3, 0)]; - OUT(3, 1) = sbox[IN(0, 1)]; - OUT(3, 2) = sbox[IN(1, 2)]; - OUT(3, 3) = sbox[IN(2, 3)]; + OUT(0, 0) = pgm_read_byte(sbox + IN(0, 0)); + OUT(0, 1) = pgm_read_byte(sbox + IN(1, 1)); + OUT(0, 2) = pgm_read_byte(sbox + IN(2, 2)); + OUT(0, 3) = pgm_read_byte(sbox + IN(3, 3)); + OUT(1, 0) = pgm_read_byte(sbox + IN(1, 0)); + OUT(1, 1) = pgm_read_byte(sbox + IN(2, 1)); + OUT(1, 2) = pgm_read_byte(sbox + IN(3, 2)); + OUT(1, 3) = pgm_read_byte(sbox + IN(0, 3)); + OUT(2, 0) = pgm_read_byte(sbox + IN(2, 0)); + OUT(2, 1) = pgm_read_byte(sbox + IN(3, 1)); + OUT(2, 2) = pgm_read_byte(sbox + IN(0, 2)); + OUT(2, 3) = pgm_read_byte(sbox + IN(1, 3)); + OUT(3, 0) = pgm_read_byte(sbox + IN(3, 0)); + OUT(3, 1) = pgm_read_byte(sbox + IN(0, 1)); + OUT(3, 2) = pgm_read_byte(sbox + IN(1, 2)); + OUT(3, 3) = pgm_read_byte(sbox + IN(2, 3)); } static void inverseShiftRowsAndSubBytes(uint8_t *output, const uint8_t *input) { - OUT(0, 0) = sbox_inverse[IN(0, 0)]; - OUT(0, 1) = sbox_inverse[IN(3, 1)]; - OUT(0, 2) = sbox_inverse[IN(2, 2)]; - OUT(0, 3) = sbox_inverse[IN(1, 3)]; - OUT(1, 0) = sbox_inverse[IN(1, 0)]; - OUT(1, 1) = sbox_inverse[IN(0, 1)]; - OUT(1, 2) = sbox_inverse[IN(3, 2)]; - OUT(1, 3) = sbox_inverse[IN(2, 3)]; - OUT(2, 0) = sbox_inverse[IN(2, 0)]; - OUT(2, 1) = sbox_inverse[IN(1, 1)]; - OUT(2, 2) = sbox_inverse[IN(0, 2)]; - OUT(2, 3) = sbox_inverse[IN(3, 3)]; - OUT(3, 0) = sbox_inverse[IN(3, 0)]; - OUT(3, 1) = sbox_inverse[IN(2, 1)]; - OUT(3, 2) = sbox_inverse[IN(1, 2)]; - OUT(3, 3) = sbox_inverse[IN(0, 3)]; + OUT(0, 0) = pgm_read_byte(sbox_inverse + IN(0, 0)); + OUT(0, 1) = pgm_read_byte(sbox_inverse + IN(3, 1)); + OUT(0, 2) = pgm_read_byte(sbox_inverse + IN(2, 2)); + OUT(0, 3) = pgm_read_byte(sbox_inverse + IN(1, 3)); + OUT(1, 0) = pgm_read_byte(sbox_inverse + IN(1, 0)); + OUT(1, 1) = pgm_read_byte(sbox_inverse + IN(0, 1)); + OUT(1, 2) = pgm_read_byte(sbox_inverse + IN(3, 2)); + OUT(1, 3) = pgm_read_byte(sbox_inverse + IN(2, 3)); + OUT(2, 0) = pgm_read_byte(sbox_inverse + IN(2, 0)); + OUT(2, 1) = pgm_read_byte(sbox_inverse + IN(1, 1)); + OUT(2, 2) = pgm_read_byte(sbox_inverse + IN(0, 2)); + OUT(2, 3) = pgm_read_byte(sbox_inverse + IN(3, 3)); + OUT(3, 0) = pgm_read_byte(sbox_inverse + IN(3, 0)); + OUT(3, 1) = pgm_read_byte(sbox_inverse + IN(2, 1)); + OUT(3, 2) = pgm_read_byte(sbox_inverse + IN(1, 2)); + OUT(3, 3) = pgm_read_byte(sbox_inverse + IN(0, 3)); } static void mixColumn(uint8_t *output, uint8_t *input) @@ -329,22 +330,22 @@ void AESCommon::keyScheduleCore(uint8_t *output, const uint8_t *input, uint8_t i { // Rcon(i), 2^i in the Rijndael finite field, for i = 0..10. // http://en.wikipedia.org/wiki/Rijndael_key_schedule - static uint8_t const rcon[11] = { + static uint8_t const rcon[11] PROGMEM = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, // 0x00 0x80, 0x1B, 0x36 }; - output[0] = sbox[input[1]] ^ rcon[iteration]; - output[1] = sbox[input[2]]; - output[2] = sbox[input[3]]; - output[3] = sbox[input[0]]; + output[0] = pgm_read_byte(sbox + input[1]) ^ pgm_read_byte(rcon + iteration); + output[1] = pgm_read_byte(sbox + input[2]); + output[2] = pgm_read_byte(sbox + input[3]); + output[3] = pgm_read_byte(sbox + input[0]); } void AESCommon::applySbox(uint8_t *output, const uint8_t *input) { - output[0] = sbox[input[0]]; - output[1] = sbox[input[1]]; - output[2] = sbox[input[2]]; - output[3] = sbox[input[3]]; + output[0] = pgm_read_byte(sbox + input[0]); + output[1] = pgm_read_byte(sbox + input[1]); + output[2] = pgm_read_byte(sbox + input[2]); + output[3] = pgm_read_byte(sbox + input[3]); } /** @endcond */ diff --git a/libraries/Crypto/ChaCha.cpp b/libraries/Crypto/ChaCha.cpp index fa53b563..9cc8973a 100644 --- a/libraries/Crypto/ChaCha.cpp +++ b/libraries/Crypto/ChaCha.cpp @@ -24,6 +24,7 @@ #include "Crypto.h" #include "RotateUtil.h" #include "EndianUtil.h" +#include "ProgMemUtil.h" #include /** @@ -85,10 +86,10 @@ size_t ChaCha::ivSize() const bool ChaCha::setKey(const uint8_t *key, size_t len) { - static const char tag128[] = "expand 16-byte k"; - static const char tag256[] = "expand 32-byte k"; + static const char tag128[] PROGMEM = "expand 16-byte k"; + static const char tag256[] PROGMEM = "expand 32-byte k"; if (len <= 16) { - memcpy(block, tag128, 16); + memcpy_P(block, tag128, 16); memcpy(block + 16, key, len); memcpy(block + 32, key, len); if (len < 16) { @@ -98,7 +99,7 @@ bool ChaCha::setKey(const uint8_t *key, size_t len) } else { if (len > 32) len = 32; - memcpy(block, tag256, 16); + memcpy_P(block, tag256, 16); memcpy(block + 16, key, len); if (len < 32) memset(block + 16 + len, 0, 32 - len); diff --git a/libraries/Crypto/ProgMemUtil.h b/libraries/Crypto/ProgMemUtil.h new file mode 100644 index 00000000..a36fa9d3 --- /dev/null +++ b/libraries/Crypto/ProgMemUtil.h @@ -0,0 +1,35 @@ +/* + * 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_PROGMEMUTIL_H +#define CRYPTO_PROGMEMUTIL_H + +#if defined(__AVR__) +#include +#else +#define PROGMEM +#define pgm_read_byte(x) (*(x)) +#define pgm_read_word(x) (*(x)) +#define pgm_read_dword(x) (*(x)) +#endif + +#endif diff --git a/libraries/Crypto/SHA256.cpp b/libraries/Crypto/SHA256.cpp index 9d3f929b..ca301a96 100644 --- a/libraries/Crypto/SHA256.cpp +++ b/libraries/Crypto/SHA256.cpp @@ -24,6 +24,7 @@ #include "Crypto.h" #include "RotateUtil.h" #include "EndianUtil.h" +#include "ProgMemUtil.h" #include /** @@ -152,7 +153,7 @@ void SHA256::clear() void SHA256::processChunk() { // Round constants for SHA-256. - static uint32_t const k[64] = { + static uint32_t const k[64] PROGMEM = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, @@ -189,7 +190,7 @@ void SHA256::processChunk() // Perform the first 16 rounds of the compression function main loop. uint32_t temp1, temp2; for (index = 0; index < 16; ++index) { - temp1 = h + k[index] + state.w[index] + + temp1 = h + pgm_read_dword(k + index) + state.w[index] + (rightRotate6(e) ^ rightRotate11(e) ^ rightRotate25(e)) + ((e & f) ^ ((~e) & g)); temp2 = (rightRotate2(a) ^ rightRotate13(a) ^ rightRotate22(a)) + @@ -217,7 +218,7 @@ void SHA256::processChunk() (rightRotate17(temp2) ^ rightRotate19(temp2) ^ (temp2 >> 10)); // Perform the round. - temp1 = h + k[index] + temp1 + + temp1 = h + pgm_read_dword(k + index) + temp1 + (rightRotate6(e) ^ rightRotate11(e) ^ rightRotate25(e)) + ((e & f) ^ ((~e) & g)); temp2 = (rightRotate2(a) ^ rightRotate13(a) ^ rightRotate22(a)) +