From 5509999f44b3f77f0d798f5ac62f3c07c78296f4 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Sun, 2 Dec 2018 14:20:16 +1100 Subject: [PATCH] block: use src _and_ dest views for encyption/decryption --- block/tea.cpp | 42 ++++++++++++++++++++++------------------ block/tea.hpp | 21 ++++++++++++++++++-- block/xtea.cpp | 38 ++++++++++++++++++++---------------- block/xtea.hpp | 23 +++++++++++++++++++--- block/xxtea.cpp | 46 ++++++++++++++++++++++++++------------------ block/xxtea.hpp | 23 +++++++++++++++++++--- test/block/tea.cpp | 8 ++++---- test/block/xtea.cpp | 12 ++++++------ test/block/xxtea.cpp | 12 ++++++------ 9 files changed, 146 insertions(+), 79 deletions(-) diff --git a/block/tea.cpp b/block/tea.cpp index b93926d..d81ea13 100644 --- a/block/tea.cpp +++ b/block/tea.cpp @@ -15,11 +15,10 @@ using cruft::crypto::block::TEA; /////////////////////////////////////////////////////////////////////////////// -static const u32 MAGIC = 0x9E3779B9; +static u32 constexpr MAGIC = 0x9E3779B9; -// each iteration performs two feistel rounds, for a total of 64 -static const unsigned ITERATIONS = 32; +static int constexpr ITERATIONS = 64; /////////////////////////////////////////////////////////////////////////////// @@ -30,47 +29,52 @@ TEA::TEA (key_t _key) /////////////////////////////////////////////////////////////////////////////// void -TEA::encrypt (cruft::view data) +TEA::encrypt (cruft::view dst, cruft::view src) { - if (data.size () % 2) + if (dst.size () != src.size ()) + throw std::invalid_argument ("mismatching encode/decode buffer sizes"); + if (src.size () % 2) throw std::invalid_argument ("TEA requires even data count"); - for (auto cursor = data.begin (), last = data.end (); cursor < last; ) { + for (size_t i = 0, last = src.size (); i < last; i += 2) { word_t sum = 0; - word_t v0 = cursor[0]; - word_t v1 = cursor[1]; + word_t v0 = src[i + 0]; + word_t v1 = src[i + 1]; - for (unsigned i = 0; i < ITERATIONS; ++i) { + for (int j = 0; j < ITERATIONS; j += 2) { sum += MAGIC; + v0 += ((v1 << 4) + m_key[0]) ^ (v1 + sum) ^ ((v1 >> 5) + m_key[1]); v1 += ((v0 << 4) + m_key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + m_key[3]); } - *cursor++ = v0; - *cursor++ = v1; + dst[i + 0] = v0; + dst[i + 1] = v1; } } //----------------------------------------------------------------------------- void -TEA::decrypt (cruft::view data) +TEA::decrypt (cruft::view dst, cruft::view src) { - if (data.size () % 2) + if (dst.size () != src.size ()) + throw std::invalid_argument ("mismatching encode/decode buffer sizes"); + if (src.size () % 2) throw std::invalid_argument ("TEA requires even data count"); - for (auto cursor = data.begin (), last = data.end (); cursor < last; ) { + for (size_t i = 0, last = src.size (); i < last; i += 2) { word_t sum = MAGIC << 5; - word_t v0 = cursor[0]; - word_t v1 = cursor[1]; + word_t v0 = src[i + 0]; + word_t v1 = src[i + 1]; - for (unsigned i = 0; i < ITERATIONS; ++i) { + for (int j = 0; j < ITERATIONS; j += 2) { v1 -= ((v0 << 4) + m_key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + m_key[3]); v0 -= ((v1 << 4) + m_key[0]) ^ (v1 + sum) ^ ((v1 >> 5) + m_key[1]); sum -= MAGIC; } - *cursor++ = v0; - *cursor++ = v1; + dst[i + 0] = v0; + dst[i + 1] = v1; } } diff --git a/block/tea.hpp b/block/tea.hpp index 8dd4853..b3cd7cb 100644 --- a/block/tea.hpp +++ b/block/tea.hpp @@ -24,11 +24,28 @@ namespace cruft::crypto::block { public: using key_t = std::array; using word_t = u32; + static constexpr std::size_t block_size = sizeof (word_t) * 2; explicit TEA (key_t); - void encrypt (cruft::view data); - void decrypt (cruft::view data); + /// Encrypt the contents of `src` into the buffer `dst`. + /// + /// src and dst are assumed to be equal sizes, multiples of block_size + /// bytes, and suitably aligned for SIMD. + /// + /// \param dst The location of the output + /// \param src The location of the input + void encrypt (cruft::view dst, cruft::view src); + + + /// Decrypt the contents of `src` into the buffer `dst`. + /// + /// src and dst are assumed to be equal sizes, multiples of block_size + /// bytes, and suitably aligned for SIMD. + /// + /// \param dst The location of the output + /// \param src The location of the input + void decrypt (cruft::view dst, cruft::view src); private: key_t const m_key; diff --git a/block/xtea.cpp b/block/xtea.cpp index 8d369b5..254f95f 100644 --- a/block/xtea.cpp +++ b/block/xtea.cpp @@ -12,7 +12,7 @@ using cruft::crypto::block::XTEA; /////////////////////////////////////////////////////////////////////////////// -static const u32 MAGIC = 0x9E3779B9; +static const uint32_t MAGIC = 0x9E3779B9; // each iteration performs two feistel rounds, for a total of 64 static const unsigned ITERATIONS = 32; @@ -26,47 +26,51 @@ XTEA::XTEA (key_t _key): //----------------------------------------------------------------------------- void -XTEA::encrypt (cruft::view data) +XTEA::encrypt (cruft::view dst, cruft::view src) { - if (data.size () % 2) + if (dst.size () != src.size ()) + throw std::invalid_argument ("mismatching encode/decode buffer sizes"); + if (src.size () % 2) throw std::invalid_argument ("XTEA requires even data count"); - for (auto cursor = data.begin (), last = data.end (); cursor < last; ) { + for (size_t i = 0, last = src.size (); i != last; i += 2) { uint32_t sum = 0; - uint32_t v0 = cursor[0]; - uint32_t v1 = cursor[1]; + uint32_t v0 = src[i + 0]; + uint32_t v1 = src[i + 1]; - for (unsigned i = 0; i < ITERATIONS; ++i) { + for (unsigned j = 0; j < ITERATIONS; ++j) { v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + m_key[sum & 3]); sum += MAGIC; v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + m_key[(sum >> 11) & 3]); } - *cursor++ = v0; - *cursor++ = v1; + dst[i + 0] = v0; + dst[i + 1] = v1; } } //----------------------------------------------------------------------------- void -XTEA::decrypt (cruft::view data) +XTEA::decrypt (cruft::view dst, cruft::view src) { - if (data.size () % 2) + if (dst.size () != src.size ()) + throw std::invalid_argument ("mismatching encode/decode buffer sizes"); + if (src.size () % 2) throw std::invalid_argument ("XTEA requires even data count"); - for (auto cursor = data.begin (), last = data.end (); cursor < last; ) { + for (size_t i = 0, last = src.size (); i != last; i += 2) { uint32_t sum = ITERATIONS * MAGIC; - uint32_t v0 = cursor[0]; - uint32_t v1 = cursor[1]; + uint32_t v0 = src[i + 0]; + uint32_t v1 = src[i + 1]; - for (unsigned i = 0; i < ITERATIONS; ++i) { + for (unsigned j = 0; j < ITERATIONS; ++j) { v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + m_key[(sum >> 11) & 3]); sum -= MAGIC; v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + m_key[sum & 3]); } - *cursor++ = v0; - *cursor++ = v1; + dst[i + 0] = v0; + dst[i + 1] = v1; } } diff --git a/block/xtea.hpp b/block/xtea.hpp index fe51be3..8dee049 100644 --- a/block/xtea.hpp +++ b/block/xtea.hpp @@ -24,13 +24,30 @@ namespace cruft::crypto::block { public: using key_t = std::array; using word_t = u32; + static constexpr std::size_t block_size = sizeof (word_t) * 2; explicit XTEA (key_t); - void encrypt (cruft::view data); - void decrypt (cruft::view data); + /// Encrypt the contents of `src` into the buffer `dst`. + /// + /// src and dst are assumed to be equal sizes, multiples of block_size + /// bytes, and suitably aligned for SIMD. + /// + /// \param dst The location of the output + /// \param src The location of the input + void encrypt (cruft::view dst, cruft::view src); + + + /// Decrypt the contents of `src` into the buffer `dst`. + /// + /// src and dst are assumed to be equal sizes, multiples of block_size + /// bytes, and suitably aligned for SIMD. + /// + /// \param dst The location of the output + /// \param src The location of the input + void decrypt (cruft::view dst, cruft::view src); private: - key_t m_key; + key_t const m_key; }; } diff --git a/block/xxtea.cpp b/block/xxtea.cpp index 3711a1a..583d006 100644 --- a/block/xxtea.cpp +++ b/block/xxtea.cpp @@ -15,7 +15,7 @@ using cruft::crypto::block::XXTEA; -//----------------------------------------------------------------------------- +/////////////////////////////////////////////////////////////////////////////// static const u32 MAGIC = 0x9E3779B9; @@ -33,22 +33,26 @@ mix (u32 Z, } -//----------------------------------------------------------------------------- +/////////////////////////////////////////////////////////////////////////////// XXTEA::XXTEA (key_t _key): m_key (_key) { ; } -//----------------------------------------------------------------------------- +/////////////////////////////////////////////////////////////////////////////// void -XXTEA::encrypt (cruft::view data) +XXTEA::encrypt (cruft::view dst, cruft::view src) { - if (data.size () < 2) + if (dst.size () != src.size ()) + throw std::invalid_argument ("mismatching encode/decode buffer sizes"); + if (src.size () < 2) throw std::invalid_argument ("minimum blocksize is 64 bits"); - auto const count = data.size (); + std::copy (src.begin (), src.end (), dst.begin ()); + + auto const count = src.size (); uint32_t sum = 0; - uint32_t z = data[count - 1]; + uint32_t z = dst[count - 1]; uint32_t y, p; unsigned rounds = 6 + 52 / count; @@ -58,42 +62,46 @@ XXTEA::encrypt (cruft::view data) uint32_t e = (sum >> 2) & 3; for (p = 0; p < count - 1; p++) { - y = data[p + 1]; - z = data[p] += ::mix (z, y, sum, e, p, m_key.data ()); + y = dst[p + 1]; + z = dst[p ] += ::mix (z, y, sum, e, p, m_key.data ()); } - y = data[0]; - z = data[count - 1] += ::mix (z, y, sum, e, p, m_key.data ()); + y = dst[0]; + z = dst[count - 1] += ::mix (z, y, sum, e, p, m_key.data ()); } while (--rounds); } //----------------------------------------------------------------------------- void -XXTEA::decrypt (cruft::view data) +XXTEA::decrypt (cruft::view dst, cruft::view src) { - if (data.size () < 2) + if (dst.size () != src.size ()) + throw std::invalid_argument ("mismatching encode/decode buffer sizes"); + if (src.size () < 2) throw std::invalid_argument ("minimum blocksize is 64 bits"); - auto const count = data.size (); + std::copy (src.begin (), src.end (), dst.begin ()); + + auto const count = src.size (); uint32_t y, z, sum; uint32_t rounds; size_t p; rounds = 6 + 52 / count; sum = rounds * MAGIC; - y = data[0]; + y = dst[0]; do { uint32_t e = (sum >> 2) & 3; for (p = count - 1; p > 0; p--) { - z = data[p - 1]; - y = data[p ] -= ::mix (z, y, sum, e, p, m_key.data ()); + z = dst[p - 1]; + y = dst[p ] -= ::mix (z, y, sum, e, p, m_key.data ()); } - z = data[count - 1]; - y = data[ 0] -= ::mix (z, y, sum, e, p, m_key.data ()); + z = dst[count - 1]; + y = dst[ 0] -= ::mix (z, y, sum, e, p, m_key.data ()); sum -= MAGIC; } while (--rounds); diff --git a/block/xxtea.hpp b/block/xxtea.hpp index 94c8925..c81344b 100644 --- a/block/xxtea.hpp +++ b/block/xxtea.hpp @@ -24,13 +24,30 @@ namespace cruft::crypto::block { public: using key_t = std::array; using word_t = u32; + static constexpr std::size_t block_size = sizeof (word_t) * 2; explicit XXTEA (key_t); - void encrypt (cruft::view data); - void decrypt (cruft::view data); + /// Encrypt the contents of `src` into the buffer `dst`. + /// + /// src and dst are assumed to be equal sizes, multiples of block_size + /// bytes, and suitably aligned for SIMD. + /// + /// \param dst The location of the output + /// \param src The location of the input + void encrypt (cruft::view dst, cruft::view src); + + + /// Decrypt the contents of `src` into the buffer `dst`. + /// + /// src and dst are assumed to be equal sizes, multiples of block_size + /// bytes, and suitably aligned for SIMD. + /// + /// \param dst The location of the output + /// \param src The location of the input + void decrypt (cruft::view dst, cruft::view src); private: - key_t m_key; + key_t const m_key; }; } diff --git a/test/block/tea.cpp b/test/block/tea.cpp index 35a6173..f8736d9 100644 --- a/test/block/tea.cpp +++ b/test/block/tea.cpp @@ -47,11 +47,11 @@ main () const auto &t = TESTS[i]; TEA gen (t.key); - std::array enc (t.dec); - gen.encrypt (cruft::view (enc)); + std::array enc; + gen.encrypt (cruft::view (enc), cruft::view (t.dec)); - std::array dec (t.enc); - gen.decrypt (cruft::view (dec)); + std::array dec; + gen.decrypt (cruft::view (dec), cruft::view (t.enc)); tap.expect (enc == t.enc, "TEA_enc %zu", i); tap.expect (dec == t.dec, "TEA_dec %zu", i); diff --git a/test/block/xtea.cpp b/test/block/xtea.cpp index 3ba7cb9..d79fdd7 100644 --- a/test/block/xtea.cpp +++ b/test/block/xtea.cpp @@ -45,14 +45,14 @@ main () const auto &t = TESTS[i]; cruft::crypto::block::XTEA gen (t.key); - std::array enc (t.dec); - gen.encrypt (cruft::view (enc)); + std::array enc_result; + gen.encrypt (cruft::view (enc_result), cruft::view (t.dec)); - std::array dec (t.enc); - gen.decrypt (cruft::view (dec)); + std::array dec_result; + gen.decrypt (cruft::view (dec_result), cruft::view (enc_result)); - tap.expect (enc == t.enc, "XTEA_enc %zu", i); - tap.expect (dec == t.dec, "XTEA_dec %zu", i); + tap.expect (enc_result == t.enc, "XTEA_enc %zu", i); + tap.expect (dec_result == t.dec, "XTEA_dec %zu", i); } return tap.status (); diff --git a/test/block/xxtea.cpp b/test/block/xxtea.cpp index 0f9c9fa..9b8c88e 100644 --- a/test/block/xxtea.cpp +++ b/test/block/xxtea.cpp @@ -103,14 +103,14 @@ main () XXTEA gen (t.key); - std::vector enc (t.dec); - gen.encrypt (cruft::view (enc)); + std::vector enc_result (t.dec.size ()); + gen.encrypt (cruft::view (enc_result), cruft::view (t.dec)); - std::vector dec (enc); - gen.decrypt (cruft::view (dec)); + std::vector dec_result (t.enc.size ()); + gen.decrypt (cruft::view (dec_result), cruft::view (t.enc)); - tap.expect (enc == t.enc, "XXTEA_enc %zu", i); - tap.expect (dec == t.dec, "XXTEA_dec %zu", i); + tap.expect (enc_result == t.enc, "XXTEA_enc %zu", i); + tap.expect (dec_result == t.dec, "XXTEA_dec %zu", i); } return tap.status ();