aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/hash
diff options
context:
space:
mode:
authorDaniel Wyatt <[email protected]>2017-04-02 12:06:15 -0400
committerRonald Tse <[email protected]>2017-04-03 08:09:14 +0900
commit80e2864358df6be840b4b6c7a6f5c331c4a375f4 (patch)
treea0bac9c0c240cb7cdd6b49034f14cebb2e6a99ac /src/lib/hash
parentc8bec4132b1b7937438263fee14bd8e039d4c0b7 (diff)
Add SM3 hash function
Diffstat (limited to 'src/lib/hash')
-rw-r--r--src/lib/hash/hash.cpp11
-rw-r--r--src/lib/hash/sm3/info.txt5
-rw-r--r--src/lib/hash/sm3/sm3.cpp150
-rw-r--r--src/lib/hash/sm3/sm3.h52
4 files changed, 218 insertions, 0 deletions
diff --git a/src/lib/hash/hash.cpp b/src/lib/hash/hash.cpp
index 112554127..c8dd58a66 100644
--- a/src/lib/hash/hash.cpp
+++ b/src/lib/hash/hash.cpp
@@ -64,6 +64,10 @@
#include <botan/skein_512.h>
#endif
+#if defined(BOTAN_HAS_SM3)
+ #include <botan/sm3.h>
+#endif
+
#if defined(BOTAN_HAS_TIGER)
#include <botan/tiger.h>
#endif
@@ -257,6 +261,13 @@ std::unique_ptr<HashFunction> HashFunction::create(const std::string& algo_spec,
}
#endif
+#if defined(BOTAN_HAS_SM3)
+ if(algo_spec == "SM3")
+ {
+ return std::unique_ptr<HashFunction>(new SM3);
+ }
+#endif
+
#if defined(BOTAN_HAS_WHIRLPOOL)
if(req.algo_name() == "Whirlpool")
{
diff --git a/src/lib/hash/sm3/info.txt b/src/lib/hash/sm3/info.txt
new file mode 100644
index 000000000..d0057456d
--- /dev/null
+++ b/src/lib/hash/sm3/info.txt
@@ -0,0 +1,5 @@
+define SM3 20131128
+
+<requires>
+mdx_hash
+</requires>
diff --git a/src/lib/hash/sm3/sm3.cpp b/src/lib/hash/sm3/sm3.cpp
new file mode 100644
index 000000000..cb4039789
--- /dev/null
+++ b/src/lib/hash/sm3/sm3.cpp
@@ -0,0 +1,150 @@
+/*
+* SM3
+* (C) 2017 Ribose Inc.
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/sm3.h>
+
+namespace Botan {
+
+namespace {
+
+const uint32_t SM3_IV[] = {
+ 0x7380166fUL, 0x4914b2b9UL, 0x172442d7UL, 0xda8a0600UL,
+ 0xa96f30bcUL, 0x163138aaUL, 0xe38dee4dUL, 0xb0fb0e4eUL
+};
+
+const uint32_t SM3_TJ_0_15 = 0x79cc4519;
+const uint32_t SM3_TJ_16_63 = 0x7a879d8a;
+
+inline uint32_t P0(uint32_t X)
+ {
+ return X ^ rotate_left(X, 9) ^ rotate_left(X, 17);
+ }
+
+inline uint32_t P1(uint32_t X)
+ {
+ return X ^ rotate_left(X, 15) ^ rotate_left(X, 23);
+ }
+
+inline uint32_t FF0(uint32_t X, uint32_t Y, uint32_t Z)
+ {
+ return X ^ Y ^ Z;
+ }
+
+inline uint32_t FF1(uint32_t X, uint32_t Y, uint32_t Z)
+ {
+ return (X & Y) | (X & Z) | (Y & Z);
+ }
+
+inline uint32_t GG0(uint32_t X, uint32_t Y, uint32_t Z)
+ {
+ return X ^ Y ^ Z;
+ }
+
+inline uint32_t GG1(uint32_t X, uint32_t Y, uint32_t Z)
+ {
+ return (X & Y) | (~X & Z);
+ }
+
+}
+
+/*
+* SM3 Compression Function
+*/
+void SM3::compress_n(const uint8_t input[], size_t blocks)
+ {
+ uint32_t W[68], W1[64];
+ uint32_t SS1, SS2, TT1, TT2, T[64];
+
+ for(size_t i = 0; i != blocks; ++i)
+ {
+ uint32_t A = m_digest[0], B = m_digest[1], C = m_digest[2], D = m_digest[3],
+ E = m_digest[4], F = m_digest[5], G = m_digest[6], H = m_digest[7];
+
+ load_be(m_M.data(), input, m_M.size());
+
+ // Message Extension (a)
+ for (size_t j = 0; j < 16; j++)
+ {
+ W[j] = m_M[j];
+ }
+ // Message Extension (b)
+ for (size_t j = 16; j < 68; j++)
+ {
+ W[j] = P1(W[j-16] ^ W[j-9] ^ rotate_left(W[j-3], 15)) ^ rotate_left(W[j-13], 7) ^ W[j-6];
+ }
+ // Message Extension (c)
+ for (size_t j = 0; j < 64; j++)
+ {
+ W1[j] = W[j] ^ W[j+4];
+ }
+
+ for (size_t j = 0; j < 16; j++)
+ {
+ T[j] = SM3_TJ_0_15;
+ SS1 = rotate_left(rotate_left(A, 12) + E + rotate_left(T[j], j), 7);
+ SS2 = SS1 ^ rotate_left(A, 12);
+ TT1 = FF0(A, B, C) + D + SS2 + W1[j];
+ TT2 = GG0(E, F, G) + H + SS1 + W[j];
+ D = C;
+ C = rotate_left(B, 9);
+ B = A;
+ A = TT1;
+ H = G;
+ G = rotate_left(F, 19);
+ F = E;
+ E = P0(TT2);
+ }
+
+ for (size_t j = 16; j < 64; j++)
+ {
+ T[j] = SM3_TJ_16_63;
+ SS1 = rotate_left(rotate_left(A, 12) + E + rotate_left(T[j], j), 7);
+ SS2 = SS1 ^ rotate_left(A, 12);
+ TT1 = FF1(A, B, C) + D + SS2 + W1[j];
+ TT2 = GG1(E, F, G) + H + SS1 + W[j];
+ D = C;
+ C = rotate_left(B, 9);
+ B = A;
+ A = TT1;
+ H = G;
+ G = rotate_left(F, 19);
+ F = E;
+ E = P0(TT2);
+ }
+
+ m_digest[0] ^= A;
+ m_digest[1] ^= B;
+ m_digest[2] ^= C;
+ m_digest[3] ^= D;
+ m_digest[4] ^= E;
+ m_digest[5] ^= F;
+ m_digest[6] ^= G;
+ m_digest[7] ^= H;
+
+ input += hash_block_size();
+ }
+ }
+
+/*
+* Copy out the digest
+*/
+void SM3::copy_out(uint8_t output[])
+ {
+ copy_out_vec_be(output, output_length(), m_digest);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void SM3::clear()
+ {
+ MDx_HashFunction::clear();
+ zeroise(m_M);
+ std::copy(std::begin(SM3_IV), std::end(SM3_IV), m_digest.begin());
+ }
+
+}
diff --git a/src/lib/hash/sm3/sm3.h b/src/lib/hash/sm3/sm3.h
new file mode 100644
index 000000000..896482332
--- /dev/null
+++ b/src/lib/hash/sm3/sm3.h
@@ -0,0 +1,52 @@
+/*
+* SM3
+* (C) 2017 Ribose Inc.
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_SM3_H__
+#define BOTAN_SM3_H__
+
+#include <botan/mdx_hash.h>
+
+namespace Botan {
+
+enum {
+ SM3_BLOCK_BYTES = 64,
+ SM3_DIGEST_BYTES = 32
+};
+
+/**
+* SM3
+*/
+class BOTAN_DLL SM3 final : public MDx_HashFunction
+ {
+ public:
+ std::string name() const override { return "SM3"; }
+ size_t output_length() const override { return SM3_DIGEST_BYTES; }
+ HashFunction* clone() const override { return new SM3; }
+
+ void clear() override;
+
+ SM3() : MDx_HashFunction(SM3_BLOCK_BYTES, true, true), m_M(16), m_digest(SM3_DIGEST_BYTES)
+ { clear(); }
+ protected:
+ void compress_n(const uint8_t[], size_t blocks) override;
+ void copy_out(uint8_t[]) override;
+
+ private:
+ /**
+ * The message buffer
+ */
+ secure_vector<uint32_t> m_M;
+
+ /**
+ * The digest value
+ */
+ secure_vector<uint32_t> m_digest;
+ };
+
+}
+
+#endif