summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/block/noekeon/noekeon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/src/lib/block/noekeon/noekeon.cpp')
-rw-r--r--comm/third_party/botan/src/lib/block/noekeon/noekeon.cpp267
1 files changed, 267 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/block/noekeon/noekeon.cpp b/comm/third_party/botan/src/lib/block/noekeon/noekeon.cpp
new file mode 100644
index 0000000000..0a820c7014
--- /dev/null
+++ b/comm/third_party/botan/src/lib/block/noekeon/noekeon.cpp
@@ -0,0 +1,267 @@
+/*
+* Noekeon
+* (C) 1999-2008 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/noekeon.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+#include <botan/cpuid.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* Noekeon's Theta Operation
+*/
+inline void theta(uint32_t& A0, uint32_t& A1,
+ uint32_t& A2, uint32_t& A3,
+ const uint32_t EK[4])
+ {
+ uint32_t T = A0 ^ A2;
+ T ^= rotl<8>(T) ^ rotr<8>(T);
+ A1 ^= T;
+ A3 ^= T;
+
+ A0 ^= EK[0];
+ A1 ^= EK[1];
+ A2 ^= EK[2];
+ A3 ^= EK[3];
+
+ T = A1 ^ A3;
+ T ^= rotl<8>(T) ^ rotr<8>(T);
+ A0 ^= T;
+ A2 ^= T;
+ }
+
+/*
+* Theta With Null Key
+*/
+inline void theta(uint32_t& A0, uint32_t& A1,
+ uint32_t& A2, uint32_t& A3)
+ {
+ uint32_t T = A0 ^ A2;
+ T ^= rotl<8>(T) ^ rotr<8>(T);
+ A1 ^= T;
+ A3 ^= T;
+
+ T = A1 ^ A3;
+ T ^= rotl<8>(T) ^ rotr<8>(T);
+ A0 ^= T;
+ A2 ^= T;
+ }
+
+/*
+* Noekeon's Gamma S-Box Layer
+*/
+inline void gamma(uint32_t& A0, uint32_t& A1, uint32_t& A2, uint32_t& A3)
+ {
+ A1 ^= ~A3 & ~A2;
+ A0 ^= A2 & A1;
+
+ uint32_t T = A3;
+ A3 = A0;
+ A0 = T;
+
+ A2 ^= A0 ^ A1 ^ A3;
+
+ A1 ^= ~A3 & ~A2;
+ A0 ^= A2 & A1;
+ }
+
+}
+
+size_t Noekeon::parallelism() const
+ {
+#if defined(BOTAN_HAS_NOEKEON_SIMD)
+ if(CPUID::has_simd_32())
+ {
+ return 4;
+ }
+#endif
+
+ return 1;
+ }
+
+std::string Noekeon::provider() const
+ {
+#if defined(BOTAN_HAS_NOEKEON_SIMD)
+ if(CPUID::has_simd_32())
+ {
+ return "simd";
+ }
+#endif
+
+ return "base";
+ }
+
+/*
+* Noekeon Round Constants
+*/
+const uint8_t Noekeon::RC[] = {
+ 0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A,
+ 0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A,
+ 0xD4 };
+
+/*
+* Noekeon Encryption
+*/
+void Noekeon::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
+ {
+ verify_key_set(m_EK.empty() == false);
+
+#if defined(BOTAN_HAS_NOEKEON_SIMD)
+ if(CPUID::has_simd_32())
+ {
+ while(blocks >= 4)
+ {
+ simd_encrypt_4(in, out);
+ in += 4 * BLOCK_SIZE;
+ out += 4 * BLOCK_SIZE;
+ blocks -= 4;
+ }
+ }
+#endif
+
+ for(size_t i = 0; i != blocks; ++i)
+ {
+ uint32_t A0 = load_be<uint32_t>(in, 0);
+ uint32_t A1 = load_be<uint32_t>(in, 1);
+ uint32_t A2 = load_be<uint32_t>(in, 2);
+ uint32_t A3 = load_be<uint32_t>(in, 3);
+
+ for(size_t j = 0; j != 16; ++j)
+ {
+ A0 ^= RC[j];
+ theta(A0, A1, A2, A3, m_EK.data());
+
+ A1 = rotl<1>(A1);
+ A2 = rotl<5>(A2);
+ A3 = rotl<2>(A3);
+
+ gamma(A0, A1, A2, A3);
+
+ A1 = rotr<1>(A1);
+ A2 = rotr<5>(A2);
+ A3 = rotr<2>(A3);
+ }
+
+ A0 ^= RC[16];
+ theta(A0, A1, A2, A3, m_EK.data());
+
+ store_be(out, A0, A1, A2, A3);
+
+ in += BLOCK_SIZE;
+ out += BLOCK_SIZE;
+ }
+ }
+
+/*
+* Noekeon Encryption
+*/
+void Noekeon::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
+ {
+ verify_key_set(m_DK.empty() == false);
+
+#if defined(BOTAN_HAS_NOEKEON_SIMD)
+ if(CPUID::has_simd_32())
+ {
+ while(blocks >= 4)
+ {
+ simd_decrypt_4(in, out);
+ in += 4 * BLOCK_SIZE;
+ out += 4 * BLOCK_SIZE;
+ blocks -= 4;
+ }
+ }
+#endif
+
+ for(size_t i = 0; i != blocks; ++i)
+ {
+ uint32_t A0 = load_be<uint32_t>(in, 0);
+ uint32_t A1 = load_be<uint32_t>(in, 1);
+ uint32_t A2 = load_be<uint32_t>(in, 2);
+ uint32_t A3 = load_be<uint32_t>(in, 3);
+
+ for(size_t j = 16; j != 0; --j)
+ {
+ theta(A0, A1, A2, A3, m_DK.data());
+ A0 ^= RC[j];
+
+ A1 = rotl<1>(A1);
+ A2 = rotl<5>(A2);
+ A3 = rotl<2>(A3);
+
+ gamma(A0, A1, A2, A3);
+
+ A1 = rotr<1>(A1);
+ A2 = rotr<5>(A2);
+ A3 = rotr<2>(A3);
+ }
+
+ theta(A0, A1, A2, A3, m_DK.data());
+ A0 ^= RC[0];
+
+ store_be(out, A0, A1, A2, A3);
+
+ in += BLOCK_SIZE;
+ out += BLOCK_SIZE;
+ }
+ }
+
+/*
+* Noekeon Key Schedule
+*/
+void Noekeon::key_schedule(const uint8_t key[], size_t)
+ {
+ uint32_t A0 = load_be<uint32_t>(key, 0);
+ uint32_t A1 = load_be<uint32_t>(key, 1);
+ uint32_t A2 = load_be<uint32_t>(key, 2);
+ uint32_t A3 = load_be<uint32_t>(key, 3);
+
+ for(size_t i = 0; i != 16; ++i)
+ {
+ A0 ^= RC[i];
+ theta(A0, A1, A2, A3);
+
+ A1 = rotl<1>(A1);
+ A2 = rotl<5>(A2);
+ A3 = rotl<2>(A3);
+
+ gamma(A0, A1, A2, A3);
+
+ A1 = rotr<1>(A1);
+ A2 = rotr<5>(A2);
+ A3 = rotr<2>(A3);
+ }
+
+ A0 ^= RC[16];
+
+ m_DK.resize(4);
+ m_DK[0] = A0;
+ m_DK[1] = A1;
+ m_DK[2] = A2;
+ m_DK[3] = A3;
+
+ theta(A0, A1, A2, A3);
+
+ m_EK.resize(4);
+ m_EK[0] = A0;
+ m_EK[1] = A1;
+ m_EK[2] = A2;
+ m_EK[3] = A3;
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void Noekeon::clear()
+ {
+ zap(m_EK);
+ zap(m_DK);
+ }
+
+}