diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/hash/hash.cpp | 11 | ||||
-rw-r--r-- | src/lib/hash/sm3/info.txt | 5 | ||||
-rw-r--r-- | src/lib/hash/sm3/sm3.cpp | 150 | ||||
-rw-r--r-- | src/lib/hash/sm3/sm3.h | 52 | ||||
-rw-r--r-- | src/tests/data/hash/sm3.vec | 6 |
5 files changed, 224 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 diff --git a/src/tests/data/hash/sm3.vec b/src/tests/data/hash/sm3.vec new file mode 100644 index 000000000..a2f4a957c --- /dev/null +++ b/src/tests/data/hash/sm3.vec @@ -0,0 +1,6 @@ +[SM3] +In = 616263 +Out = 66C7F0F462EEEDD9D1F2D46BDC10E4E24167C4875CF2F7A2297DA02B8F4BA8E0 + +In = 61626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364 +Out = DEBE9FF92275B8A138604889C18E5A4D6FDB70E5387E5765293dCbA39C0C5732 |