summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Walton <noloader@gmail.com>2017-11-23 23:19:09 -0500
committerJeffrey Walton <noloader@gmail.com>2017-11-23 23:19:09 -0500
commit5267723a4923464f677d22f73f97a9e975a187a9 (patch)
tree87322ddc7214bc854d85f73985de18181511c6e6
parent13652cf9bf8d0d15f4aacd7a3e0426c4b2e553f7 (diff)
downloadcryptopp-git-5267723a4923464f677d22f73f97a9e975a187a9.tar.gz
Add SM3 hash function (GH #541)
-rw-r--r--Filelist.txt3
-rw-r--r--TestVectors/all.txt1
-rw-r--r--TestVectors/sm3.txt19
-rw-r--r--bench1.cpp9
-rw-r--r--cryptest.nmake4
-rw-r--r--cryptest.vcxproj1
-rw-r--r--cryptest.vcxproj.filters20
-rw-r--r--cryptlib.vcxproj2
-rw-r--r--cryptlib.vcxproj.filters24
-rw-r--r--regtest1.cpp3
-rw-r--r--sm3.cpp254
-rw-r--r--sm3.h61
-rw-r--r--test.cpp13
-rw-r--r--validat1.cpp2
-rw-r--r--validat3.cpp5
-rw-r--r--validate.h1
16 files changed, 392 insertions, 30 deletions
diff --git a/Filelist.txt b/Filelist.txt
index 4b82562c..0a59f47d 100644
--- a/Filelist.txt
+++ b/Filelist.txt
@@ -277,6 +277,8 @@ simon.cpp
simon.h
skipjack.cpp
skipjack.h
+sm3.cpp
+sm3.h
sm4.cpp
sm4.h
smartptr.h
@@ -463,6 +465,7 @@ TestVectors/sha3_512_fips_202.txt
TestVectors/shacal2.txt
TestVectors/simon.txt
TestVectors/siphash.txt
+TestVectors/sm3.txt
TestVectors/sm4.txt
TestVectors/sosemanuk.txt
TestVectors/speck.txt
diff --git a/TestVectors/all.txt b/TestVectors/all.txt
index 1581bd95..5bbdda4f 100644
--- a/TestVectors/all.txt
+++ b/TestVectors/all.txt
@@ -24,6 +24,7 @@ Test: TestVectors/sha1_fips_180.txt
Test: TestVectors/sha2_fips_180.txt
Test: TestVectors/sha3_fips_202.txt
Test: TestVectors/panama.txt
+Test: TestVectors/sm3.txt
Test: TestVectors/aes.txt
Test: TestVectors/aria.txt
Test: TestVectors/kalyna.txt
diff --git a/TestVectors/sm3.txt b/TestVectors/sm3.txt
new file mode 100644
index 00000000..227a0486
--- /dev/null
+++ b/TestVectors/sm3.txt
@@ -0,0 +1,19 @@
+AlgorithmType: MessageDigest
+Name: SM3
+#
+Source: SM3 Hash function, https://tools.ietf.org/html/draft-shen-sm3-hash
+Comment: Appendix B, test vector 1
+Message: 616263
+Digest: 66c7f0f4 62eeedd9 d1f2d46b dc10e4e2 4167c487 5cf2f7a2 297da02b 8f4ba8e0
+Test: Verify
+Digest: 00000000 62eeedd9 d1f2d46b dc10e4e2 4167c487 5cf2f7a2 297da02b 8f4ba8e0
+Test: NotVerify
+#
+Source: SM3 Hash function, https://tools.ietf.org/html/draft-shen-sm3-hash
+Comment: Appendix B, test vector 1
+Message: 61626364 61626364 61626364 61626364 61626364 61626364 61626364 61626364 \
+ 61626364 61626364 61626364 61626364 61626364 61626364 61626364 61626364
+Digest: debe9ff9 2275b8a1 38604889 c18e5a4d 6fdb70e5 387e5765 293dcba3 9c0c5732
+Test: Verify
+Digest: 00000000 2275b8a1 38604889 c18e5a4d 6fdb70e5 387e5765 293dcba3 9c0c5732
+Test: NotVerify \ No newline at end of file
diff --git a/bench1.cpp b/bench1.cpp
index 99244a80..510cd81c 100644
--- a/bench1.cpp
+++ b/bench1.cpp
@@ -471,20 +471,21 @@ void Benchmark1(double t, double hertz)
BenchMarkByNameKeyLess<HashTransformation>("SHA-1");
BenchMarkByNameKeyLess<HashTransformation>("SHA-256");
BenchMarkByNameKeyLess<HashTransformation>("SHA-512");
- BenchMarkByNameKeyLess<HashTransformation>("Keccak-224");
- BenchMarkByNameKeyLess<HashTransformation>("Keccak-256");
- BenchMarkByNameKeyLess<HashTransformation>("Keccak-384");
- BenchMarkByNameKeyLess<HashTransformation>("Keccak-512");
BenchMarkByNameKeyLess<HashTransformation>("SHA3-224");
BenchMarkByNameKeyLess<HashTransformation>("SHA3-256");
BenchMarkByNameKeyLess<HashTransformation>("SHA3-384");
BenchMarkByNameKeyLess<HashTransformation>("SHA3-512");
+ BenchMarkByNameKeyLess<HashTransformation>("Keccak-224");
+ BenchMarkByNameKeyLess<HashTransformation>("Keccak-256");
+ BenchMarkByNameKeyLess<HashTransformation>("Keccak-384");
+ BenchMarkByNameKeyLess<HashTransformation>("Keccak-512");
BenchMarkByNameKeyLess<HashTransformation>("Tiger");
BenchMarkByNameKeyLess<HashTransformation>("Whirlpool");
BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-160");
BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-320");
BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-128");
BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-256");
+ BenchMarkByNameKeyLess<HashTransformation>("SM3");
BenchMarkByNameKeyLess<HashTransformation>("BLAKE2s");
BenchMarkByNameKeyLess<HashTransformation>("BLAKE2b");
}
diff --git a/cryptest.nmake b/cryptest.nmake
index 411a3ffa..c1ff63ec 100644
--- a/cryptest.nmake
+++ b/cryptest.nmake
@@ -47,9 +47,9 @@
# If you use 'make sources' from Linux makefile, then add 'winpipes.cpp' to the list below.
-LIB_SRCS = cryptlib.cpp cpu.cpp integer.cpp 3way.cpp adler32.cpp algebra.cpp algparam.cpp arc4.cpp aria-simd.cpp aria.cpp ariatab.cpp asn.cpp authenc.cpp base32.cpp base64.cpp basecode.cpp bfinit.cpp blake2-simd.cpp blake2.cpp blowfish.cpp blumshub.cpp camellia.cpp cast.cpp casts.cpp cbcmac.cpp ccm.cpp chacha.cpp channels.cpp cmac.cpp crc-simd.cpp crc.cpp default.cpp des.cpp dessp.cpp dh.cpp dh2.cpp dll.cpp dsa.cpp eax.cpp ec2n.cpp eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp esign.cpp files.cpp filters.cpp fips140.cpp fipstest.cpp gcm-simd.cpp gcm.cpp gf256.cpp gf2_32.cpp gf2n.cpp gfpcrypt.cpp gost.cpp gzip.cpp hex.cpp hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp kalyna.cpp kalynatab.cpp keccak.cpp luc.cpp mars.cpp marss.cpp md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp mqueue.cpp mqv.cpp nbtheory.cpp neon-simd.cpp network.cpp oaep.cpp osrng.cpp padlkrng.cpp panama.cpp pkcspad.cpp poly1305.cpp polynomi.cpp pssr.cpp pubkey.cpp queue.cpp rabin.cpp randpool.cpp rc2.cpp rc5.cpp rc6.cpp rdrand.cpp rdtables.cpp rijndael-simd.cpp rijndael.cpp ripemd.cpp rng.cpp rsa.cpp rw.cpp safer.cpp salsa.cpp seal.cpp seed.cpp serpent.cpp sha-simd.cpp sha.cpp sha3.cpp shacal2-simd.cpp shacal2.cpp shark.cpp sharkbox.cpp simon.cpp skipjack.cpp socketft.cpp sosemanuk.cpp speck.cpp speck-simd.cpp square.cpp squaretb.cpp sse-simd.cpp strciphr.cpp tea.cpp tftables.cpp threefish.cpp tiger.cpp tigertab.cpp trdlocal.cpp ttmac.cpp twofish.cpp vmac.cpp wait.cpp wake.cpp whrlpool.cpp winpipes.cpp xtr.cpp xtrcrypt.cpp zdeflate.cpp zinflate.cpp zlib.cpp
+LIB_SRCS = cryptlib.cpp cpu.cpp integer.cpp 3way.cpp adler32.cpp algebra.cpp algparam.cpp arc4.cpp aria-simd.cpp aria.cpp ariatab.cpp asn.cpp authenc.cpp base32.cpp base64.cpp basecode.cpp bfinit.cpp blake2-simd.cpp blake2.cpp blowfish.cpp blumshub.cpp camellia.cpp cast.cpp casts.cpp cbcmac.cpp ccm.cpp chacha.cpp channels.cpp cmac.cpp crc-simd.cpp crc.cpp default.cpp des.cpp dessp.cpp dh.cpp dh2.cpp dll.cpp dsa.cpp eax.cpp ec2n.cpp eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp esign.cpp files.cpp filters.cpp fips140.cpp fipstest.cpp gcm-simd.cpp gcm.cpp gf256.cpp gf2_32.cpp gf2n.cpp gfpcrypt.cpp gost.cpp gzip.cpp hex.cpp hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp kalyna.cpp kalynatab.cpp keccak.cpp luc.cpp mars.cpp marss.cpp md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp mqueue.cpp mqv.cpp nbtheory.cpp neon-simd.cpp network.cpp oaep.cpp osrng.cpp padlkrng.cpp panama.cpp pkcspad.cpp poly1305.cpp polynomi.cpp pssr.cpp pubkey.cpp queue.cpp rabin.cpp randpool.cpp rc2.cpp rc5.cpp rc6.cpp rdrand.cpp rdtables.cpp rijndael-simd.cpp rijndael.cpp ripemd.cpp rng.cpp rsa.cpp rw.cpp safer.cpp salsa.cpp seal.cpp seed.cpp serpent.cpp sha-simd.cpp sha.cpp sha3.cpp shacal2-simd.cpp shacal2.cpp shark.cpp sharkbox.cpp simon.cpp skipjack.cpp sm3.cpp sm4.cpp socketft.cpp sosemanuk.cpp speck.cpp speck-simd.cpp square.cpp squaretb.cpp sse-simd.cpp strciphr.cpp tea.cpp tftables.cpp threefish.cpp tiger.cpp tigertab.cpp trdlocal.cpp ttmac.cpp twofish.cpp vmac.cpp wait.cpp wake.cpp whrlpool.cpp winpipes.cpp xtr.cpp xtrcrypt.cpp zdeflate.cpp zinflate.cpp zlib.cpp
-LIB_OBJS = cryptlib.obj cpu.obj integer.obj 3way.obj adler32.obj algebra.obj algparam.obj arc4.obj aria-simd.obj aria.obj ariatab.obj asn.obj authenc.obj base32.obj base64.obj basecode.obj bfinit.obj blake2-simd.obj blake2.obj blowfish.obj blumshub.obj camellia.obj cast.obj casts.obj cbcmac.obj ccm.obj chacha.obj channels.obj cmac.obj crc-simd.obj crc.obj default.obj des.obj dessp.obj dh.obj dh2.obj dll.obj dsa.obj eax.obj ec2n.obj eccrypto.obj ecp.obj elgamal.obj emsa2.obj eprecomp.obj esign.obj files.obj filters.obj fips140.obj fipstest.obj gcm-simd.obj gcm.obj gf256.obj gf2_32.obj gf2n.obj gfpcrypt.obj gost.obj gzip.obj hex.obj hmac.obj hrtimer.obj ida.obj idea.obj iterhash.obj kalyna.obj kalynatab.obj keccak.obj luc.obj mars.obj marss.obj md2.obj md4.obj md5.obj misc.obj modes.obj mqueue.obj mqv.obj nbtheory.obj neon-simd.obj network.obj oaep.obj osrng.obj padlkrng.obj panama.obj pkcspad.obj poly1305.obj polynomi.obj pssr.obj pubkey.obj queue.obj rabin.obj randpool.obj rc2.obj rc5.obj rc6.obj rdrand.obj rdtables.obj rijndael-simd.obj rijndael.obj ripemd.obj rng.obj rsa.obj rw.obj safer.obj salsa.obj seal.obj seed.obj serpent.obj sha-simd.obj sha.obj sha3.obj shacal2-simd.obj shacal2.obj shark.obj sharkbox.obj simon.obj skipjack.obj socketft.obj sosemanuk.obj speck.obj speck-simd.obj square.obj squaretb.obj sse-simd.obj strciphr.obj tea.obj tftables.obj threefish.obj tiger.obj tigertab.obj trdlocal.obj ttmac.obj twofish.obj vmac.obj wait.obj wake.obj whrlpool.obj winpipes.obj xtr.obj xtrcrypt.obj zdeflate.obj zinflate.obj zlib.obj
+LIB_OBJS = cryptlib.obj cpu.obj integer.obj 3way.obj adler32.obj algebra.obj algparam.obj arc4.obj aria-simd.obj aria.obj ariatab.obj asn.obj authenc.obj base32.obj base64.obj basecode.obj bfinit.obj blake2-simd.obj blake2.obj blowfish.obj blumshub.obj camellia.obj cast.obj casts.obj cbcmac.obj ccm.obj chacha.obj channels.obj cmac.obj crc-simd.obj crc.obj default.obj des.obj dessp.obj dh.obj dh2.obj dll.obj dsa.obj eax.obj ec2n.obj eccrypto.obj ecp.obj elgamal.obj emsa2.obj eprecomp.obj esign.obj files.obj filters.obj fips140.obj fipstest.obj gcm-simd.obj gcm.obj gf256.obj gf2_32.obj gf2n.obj gfpcrypt.obj gost.obj gzip.obj hex.obj hmac.obj hrtimer.obj ida.obj idea.obj iterhash.obj kalyna.obj kalynatab.obj keccak.obj luc.obj mars.obj marss.obj md2.obj md4.obj md5.obj misc.obj modes.obj mqueue.obj mqv.obj nbtheory.obj neon-simd.obj network.obj oaep.obj osrng.obj padlkrng.obj panama.obj pkcspad.obj poly1305.obj polynomi.obj pssr.obj pubkey.obj queue.obj rabin.obj randpool.obj rc2.obj rc5.obj rc6.obj rdrand.obj rdtables.obj rijndael-simd.obj rijndael.obj ripemd.obj rng.obj rsa.obj rw.obj safer.obj salsa.obj seal.obj seed.obj serpent.obj sha-simd.obj sha.obj sha3.obj shacal2-simd.obj shacal2.obj shark.obj sharkbox.obj simon.obj skipjack.obj sm3.obj sm4.obj socketft.obj sosemanuk.obj speck.obj speck-simd.obj square.obj squaretb.obj sse-simd.obj strciphr.obj tea.obj tftables.obj threefish.obj tiger.obj tigertab.obj trdlocal.obj ttmac.obj twofish.obj vmac.obj wait.obj wake.obj whrlpool.obj winpipes.obj xtr.obj xtrcrypt.obj zdeflate.obj zinflate.obj zlib.obj
TEST_SRCS = bench1.cpp bench2.cpp test.cpp validat0.cpp validat1.cpp validat2.cpp validat3.cpp datatest.cpp regtest1.cpp regtest2.cpp regtest3.cpp fipsalgt.cpp dlltest.cpp fipstest.cpp
diff --git a/cryptest.vcxproj b/cryptest.vcxproj
index 3b4d5080..40078795 100644
--- a/cryptest.vcxproj
+++ b/cryptest.vcxproj
@@ -258,6 +258,7 @@
<None Include="TestVectors\shacal2.txt" />
<None Include="TestVectors\simon.txt" />
<None Include="TestVectors\siphash.txt" />
+ <Text Include="TestVectors\sm3.txt" />
<None Include="TestVectors\sm4.txt" />
<None Include="TestVectors\sosemanuk.txt" />
<None Include="TestVectors\speck.txt" />
diff --git a/cryptest.vcxproj.filters b/cryptest.vcxproj.filters
index 9fced422..894c4ce5 100644
--- a/cryptest.vcxproj.filters
+++ b/cryptest.vcxproj.filters
@@ -1,20 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
- <Filter Include="TestVectors">
- <UniqueIdentifier>{2e247f14-f75a-4e15-9804-dccce165306f}</UniqueIdentifier>
- <Extensions>.txt</Extensions>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{1f4eac20-7b40-40db-a264-4a9256229c5a}</UniqueIdentifier>
+ <Extensions>.h;.hpp</Extensions>
</Filter>
<Filter Include="Source Code">
<UniqueIdentifier>{4c6077b5-a2d6-498c-bc42-10af523a06cb}</UniqueIdentifier>
- <Extensions>.cpp;.h</Extensions>
+ <Extensions>.cpp</Extensions>
</Filter>
<Filter Include="TestData">
<UniqueIdentifier>{a634d4f4-ddc0-44b4-9c37-d9ffdddc7b06}</UniqueIdentifier>
<Extensions>.dat</Extensions>
</Filter>
- <Filter Include="Header Files">
- <UniqueIdentifier>{1f4eac20-7b40-40db-a264-4a9256229c5a}</UniqueIdentifier>
+ <Filter Include="TestVectors">
+ <UniqueIdentifier>{2e247f14-f75a-4e15-9804-dccce165306f}</UniqueIdentifier>
+ <Extensions>.txt</Extensions>
+ </Filter>
+ <Filter Include="Miscellaneous">
+ <UniqueIdentifier>{5e447502-2b0f-49c8-9df5-56ea9e7a8fbd}</UniqueIdentifier>
+ <Extensions>.proto</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
@@ -129,6 +134,9 @@
<None Include="TestVectors\simon.txt">
<Filter>TestVectors</Filter>
</None>
+ <Text Include="TestVectors\sm3.txt">
+ <Filter>TestVectors</Filter>
+ </Text>
<None Include="TestVectors\sm4.txt">
<Filter>TestVectors</Filter>
</None>
diff --git a/cryptlib.vcxproj b/cryptlib.vcxproj
index 6d1811cd..ccdb3c2c 100644
--- a/cryptlib.vcxproj
+++ b/cryptlib.vcxproj
@@ -291,6 +291,7 @@
<ClCompile Include="simon.cpp" />
<ClCompile Include="simple.cpp" />
<ClCompile Include="skipjack.cpp" />
+ <ClCompile Include="sm3.cpp" />
<ClCompile Include="sm4.cpp" />
<ClCompile Include="socketft.cpp" />
<ClCompile Include="sosemanuk.cpp" />
@@ -476,6 +477,7 @@
<ClInclude Include="simon.h" />
<ClInclude Include="siphash.h" />
<ClInclude Include="skipjack.h" />
+ <ClInclude Include="sm3.h" />
<ClInclude Include="sm4.h" />
<ClInclude Include="smartptr.h" />
<ClInclude Include="socketft.h" />
diff --git a/cryptlib.vcxproj.filters b/cryptlib.vcxproj.filters
index ff86bced..ad4ac081 100644
--- a/cryptlib.vcxproj.filters
+++ b/cryptlib.vcxproj.filters
@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{1e9e61cf-0e3c-4b79-955f-9f077eabdb3e}</UniqueIdentifier>
+ <Extensions>.h;.hpp</Extensions>
+ </Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{0465ef4f-be03-463e-81e5-5a399f32620f}</UniqueIdentifier>
<Extensions>.cpp</Extensions>
</Filter>
- <Filter Include="Header Files">
- <UniqueIdentifier>{1e9e61cf-0e3c-4b79-955f-9f077eabdb3e}</UniqueIdentifier>
- <Extensions>.;.h</Extensions>
- </Filter>
<Filter Include="Miscellaneous">
<UniqueIdentifier>{5e447502-2b0f-49c8-9df5-45ea9e7fcfbd}</UniqueIdentifier>
</Filter>
@@ -368,6 +368,9 @@
<ClCompile Include="skipjack.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="sm3.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="sm4.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -825,6 +828,9 @@
<ClInclude Include="skipjack.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="sm3.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="sm4.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -911,17 +917,11 @@
</ClInclude>
</ItemGroup>
<ItemGroup>
- <CustomBuild Include="adhoc.cpp.proto">
- <Filter>Source Files</Filter>
- </CustomBuild>
<CustomBuild Include="rdrand.asm">
<Filter>Source Files</Filter>
</CustomBuild>
- <CustomBuild Include="x64dll.asm">
- <Filter>Source Files</Filter>
- </CustomBuild>
- <CustomBuild Include="x64masm.asm">
- <Filter>Source Files</Filter>
+ <CustomBuild Include="adhoc.cpp.proto">
+ <Filter>Miscellaneous</Filter>
</CustomBuild>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/regtest1.cpp b/regtest1.cpp
index a8fdc9ef..3daa810e 100644
--- a/regtest1.cpp
+++ b/regtest1.cpp
@@ -16,6 +16,8 @@
#include "sha3.h"
#include "blake2.h"
#include "sha.h"
+#include "sha3.h"
+#include "sm3.h"
#include "tiger.h"
#include "ripemd.h"
#include "panama.h"
@@ -96,6 +98,7 @@ void RegisterFactories1()
RegisterDefaultFactoryFor<HashTransformation, SHA3_256>();
RegisterDefaultFactoryFor<HashTransformation, SHA3_384>();
RegisterDefaultFactoryFor<HashTransformation, SHA3_512>();
+ RegisterDefaultFactoryFor<HashTransformation, SM3>();
RegisterDefaultFactoryFor<HashTransformation, BLAKE2s>();
RegisterDefaultFactoryFor<HashTransformation, BLAKE2b>();
diff --git a/sm3.cpp b/sm3.cpp
new file mode 100644
index 00000000..12e18cb0
--- /dev/null
+++ b/sm3.cpp
@@ -0,0 +1,254 @@
+// sm3.cpp - written and placed in the public domain by Jeffrey Walton and Han Lulu
+// Based on the specification provided by Sean Shen and Xiaodong Lee.
+// Based on code by Krzysztof Kwiatkowski and Jack Lloyd.
+// Also see https://tools.ietf.org/html/draft-shen-sm3-hash.
+
+#include "pch.h"
+#include "config.h"
+
+#include "sm3.h"
+#include "misc.h"
+#include "cpu.h"
+
+ANONYMOUS_NAMESPACE_BEGIN
+
+using CryptoPP::byte;
+using CryptoPP::word32;
+using CryptoPP::rotlFixed;
+
+using CryptoPP::SM3;
+using CryptoPP::GetBlock;
+using CryptoPP::BigEndian;
+
+inline word32 P0(word32 X)
+{
+ return X ^ rotlFixed(X, 9) ^ rotlFixed(X, 17);
+}
+
+inline word32 FF1(word32 X, word32 Y, word32 Z)
+{
+ return (X & Y) | ((X | Y) & Z);
+}
+
+inline word32 GG1(word32 X, word32 Y, word32 Z)
+{
+ return ((Z ^ (X & (Y ^ Z))));
+}
+
+inline void R1(word32 A, word32& B, word32 C, word32& D, word32 E, word32& F,
+ word32 G, word32& H, word32 TJ, word32 Wi, word32 Wj)
+{
+ const word32 A12 = rotlFixed(A, 12);
+ const word32 SS1 = rotlFixed(A12 + E + TJ, 7);
+ const word32 TT1 = (A ^ B ^ C) + D + (SS1 ^ A12) + Wj;
+ const word32 TT2 = (E ^ F ^ G) + H + SS1 + Wi;
+
+ B = rotlFixed(B, 9);
+ D = TT1;
+ F= rotlFixed(F, 19);
+ H = P0(TT2);
+}
+
+inline void R2(word32 A, word32& B, word32 C, word32& D, word32 E, word32& F,
+ word32 G, word32& H, word32 TJ, word32 Wi, word32 Wj)
+{
+ const word32 A12 = rotlFixed(A, 12);
+ const word32 SS1 = rotlFixed(A12 + E + TJ, 7);
+ const word32 TT1 = FF1(A, B, C) + D + (SS1 ^ A12) + Wj;
+ const word32 TT2 = GG1(E, F, G) + H + SS1 + Wi;
+
+ B = rotlFixed(B, 9);
+ D = TT1;
+ F = rotlFixed(F, 19);
+ H = P0(TT2);
+}
+
+inline word32 P1(word32 X)
+{
+ return X ^ rotlFixed(X, 15) ^ rotlFixed(X, 23);
+}
+
+inline word32 SM3_E(word32 W0, word32 W7, word32 W13, word32 W3, word32 W10)
+{
+ return P1(W0 ^ W7 ^ rotlFixed(W13, 15)) ^ rotlFixed(W3, 7) ^ W10;
+}
+
+static size_t SM3_HashMultipleBlocks_CXX(word32 *state, const word32 *input, size_t length)
+{
+ CRYPTOPP_ASSERT(input);
+
+ word32 A = state[0], B = state[1], C = state[2], D = state[3];
+ word32 E = state[4], F = state[5], G = state[6], H = state[7];
+
+ size_t blocks = length / SM3::BLOCKSIZE;
+ for(size_t i = 0; i < blocks; ++i)
+ {
+ // Reverse bytes on LittleEndian; align pointer on BigEndian
+ typedef GetBlock<word32, BigEndian, false> InBlock;
+ InBlock iblk(input);
+
+ word32 W00, W01, W02, W03, W04, W05, W06, W07, W08, W09, W10, W11, W12, W13, W14, W15;
+ iblk(W00)(W01)(W02)(W03)(W04)(W05)(W06)(W07)(W08)(W09)(W10)(W11)(W12)(W13)(W14)(W15);
+
+ R1(A, B, C, D, E, F, G, H, 0x79CC4519, W00, W00 ^ W04);
+ W00 = SM3_E(W00, W07, W13, W03, W10);
+ R1(D, A, B, C, H, E, F, G, 0xF3988A32, W01, W01 ^ W05);
+ W01 = SM3_E(W01, W08, W14, W04, W11);
+ R1(C, D, A, B, G, H, E, F, 0xE7311465, W02, W02 ^ W06);
+ W02 = SM3_E(W02, W09, W15, W05, W12);
+ R1(B, C, D, A, F, G, H, E, 0xCE6228CB, W03, W03 ^ W07);
+ W03 = SM3_E(W03, W10, W00, W06, W13);
+ R1(A, B, C, D, E, F, G, H, 0x9CC45197, W04, W04 ^ W08);
+ W04 = SM3_E(W04, W11, W01, W07, W14);
+ R1(D, A, B, C, H, E, F, G, 0x3988A32F, W05, W05 ^ W09);
+ W05 = SM3_E(W05, W12, W02, W08, W15);
+ R1(C, D, A, B, G, H, E, F, 0x7311465E, W06, W06 ^ W10);
+ W06 = SM3_E(W06, W13, W03, W09, W00);
+ R1(B, C, D, A, F, G, H, E, 0xE6228CBC, W07, W07 ^ W11);
+ W07 = SM3_E(W07, W14, W04, W10, W01);
+ R1(A, B, C, D, E, F, G, H, 0xCC451979, W08, W08 ^ W12);
+ W08 = SM3_E(W08, W15, W05, W11, W02);
+ R1(D, A, B, C, H, E, F, G, 0x988A32F3, W09, W09 ^ W13);
+ W09 = SM3_E(W09, W00, W06, W12, W03);
+ R1(C, D, A, B, G, H, E, F, 0x311465E7, W10, W10 ^ W14);
+ W10 = SM3_E(W10, W01, W07, W13, W04);
+ R1(B, C, D, A, F, G, H, E, 0x6228CBCE, W11, W11 ^ W15);
+ W11 = SM3_E(W11, W02, W08, W14, W05);
+ R1(A, B, C, D, E, F, G, H, 0xC451979C, W12, W12 ^ W00);
+ W12 = SM3_E(W12, W03, W09, W15, W06);
+ R1(D, A, B, C, H, E, F, G, 0x88A32F39, W13, W13 ^ W01);
+ W13 = SM3_E(W13, W04, W10, W00, W07);
+ R1(C, D, A, B, G, H, E, F, 0x11465E73, W14, W14 ^ W02);
+ W14 = SM3_E(W14, W05, W11, W01, W08);
+ R1(B, C, D, A, F, G, H, E, 0x228CBCE6, W15, W15 ^ W03);
+ W15 = SM3_E(W15, W06, W12, W02, W09);
+ R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W00, W00 ^ W04);
+ W00 = SM3_E(W00, W07, W13, W03, W10);
+ R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W01, W01 ^ W05);
+ W01 = SM3_E(W01, W08, W14, W04, W11);
+ R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W02, W02 ^ W06);
+ W02 = SM3_E(W02, W09, W15, W05, W12);
+ R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W03, W03 ^ W07);
+ W03 = SM3_E(W03, W10, W00, W06, W13);
+ R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W04, W04 ^ W08);
+ W04 = SM3_E(W04, W11, W01, W07, W14);
+ R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W05, W05 ^ W09);
+ W05 = SM3_E(W05, W12, W02, W08, W15);
+ R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W06, W06 ^ W10);
+ W06 = SM3_E(W06, W13, W03, W09, W00);
+ R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W07, W07 ^ W11);
+ W07 = SM3_E(W07, W14, W04, W10, W01);
+ R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W08, W08 ^ W12);
+ W08 = SM3_E(W08, W15, W05, W11, W02);
+ R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W09, W09 ^ W13);
+ W09 = SM3_E(W09, W00, W06, W12, W03);
+ R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W10, W10 ^ W14);
+ W10 = SM3_E(W10, W01, W07, W13, W04);
+ R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W11, W11 ^ W15);
+ W11 = SM3_E(W11, W02, W08, W14, W05);
+ R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W12, W12 ^ W00);
+ W12 = SM3_E(W12, W03, W09, W15, W06);
+ R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W13, W13 ^ W01);
+ W13 = SM3_E(W13, W04, W10, W00, W07);
+ R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W14, W14 ^ W02);
+ W14 = SM3_E(W14, W05, W11, W01, W08);
+ R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W15, W15 ^ W03);
+ W15 = SM3_E(W15, W06, W12, W02, W09);
+ R2(A, B, C, D, E, F, G, H, 0x7A879D8A, W00, W00 ^ W04);
+ W00 = SM3_E(W00, W07, W13, W03, W10);
+ R2(D, A, B, C, H, E, F, G, 0xF50F3B14, W01, W01 ^ W05);
+ W01 = SM3_E(W01, W08, W14, W04, W11);
+ R2(C, D, A, B, G, H, E, F, 0xEA1E7629, W02, W02 ^ W06);
+ W02 = SM3_E(W02, W09, W15, W05, W12);
+ R2(B, C, D, A, F, G, H, E, 0xD43CEC53, W03, W03 ^ W07);
+ W03 = SM3_E(W03, W10, W00, W06, W13);
+ R2(A, B, C, D, E, F, G, H, 0xA879D8A7, W04, W04 ^ W08);
+ W04 = SM3_E(W04, W11, W01, W07, W14);
+ R2(D, A, B, C, H, E, F, G, 0x50F3B14F, W05, W05 ^ W09);
+ W05 = SM3_E(W05, W12, W02, W08, W15);
+ R2(C, D, A, B, G, H, E, F, 0xA1E7629E, W06, W06 ^ W10);
+ W06 = SM3_E(W06, W13, W03, W09, W00);
+ R2(B, C, D, A, F, G, H, E, 0x43CEC53D, W07, W07 ^ W11);
+ W07 = SM3_E(W07, W14, W04, W10, W01);
+ R2(A, B, C, D, E, F, G, H, 0x879D8A7A, W08, W08 ^ W12);
+ W08 = SM3_E(W08, W15, W05, W11, W02);
+ R2(D, A, B, C, H, E, F, G, 0x0F3B14F5, W09, W09 ^ W13);
+ W09 = SM3_E(W09, W00, W06, W12, W03);
+ R2(C, D, A, B, G, H, E, F, 0x1E7629EA, W10, W10 ^ W14);
+ W10 = SM3_E(W10, W01, W07, W13, W04);
+ R2(B, C, D, A, F, G, H, E, 0x3CEC53D4, W11, W11 ^ W15);
+ W11 = SM3_E(W11, W02, W08, W14, W05);
+ R2(A, B, C, D, E, F, G, H, 0x79D8A7A8, W12, W12 ^ W00);
+ W12 = SM3_E(W12, W03, W09, W15, W06);
+ R2(D, A, B, C, H, E, F, G, 0xF3B14F50, W13, W13 ^ W01);
+ W13 = SM3_E(W13, W04, W10, W00, W07);
+ R2(C, D, A, B, G, H, E, F, 0xE7629EA1, W14, W14 ^ W02);
+ W14 = SM3_E(W14, W05, W11, W01, W08);
+ R2(B, C, D, A, F, G, H, E, 0xCEC53D43, W15, W15 ^ W03);
+ W15 = SM3_E(W15, W06, W12, W02, W09);
+ R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W00, W00 ^ W04);
+ W00 = SM3_E(W00, W07, W13, W03, W10);
+ R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W01, W01 ^ W05);
+ W01 = SM3_E(W01, W08, W14, W04, W11);
+ R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W02, W02 ^ W06);
+ W02 = SM3_E(W02, W09, W15, W05, W12);
+ R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W03, W03 ^ W07);
+ W03 = SM3_E(W03, W10, W00, W06, W13);
+ R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W04, W04 ^ W08);
+ R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W05, W05 ^ W09);
+ R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W06, W06 ^ W10);
+ R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W07, W07 ^ W11);
+ R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W08, W08 ^ W12);
+ R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W09, W09 ^ W13);
+ R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W10, W10 ^ W14);
+ R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W11, W11 ^ W15);
+ R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W12, W12 ^ W00);
+ R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W13, W13 ^ W01);
+ R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W14, W14 ^ W02);
+ R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W15, W15 ^ W03);
+
+ A = (state[0] ^= A);
+ B = (state[1] ^= B);
+ C = (state[2] ^= C);
+ D = (state[3] ^= D);
+ E = (state[4] ^= E);
+ F = (state[5] ^= F);
+ G = (state[6] ^= G);
+ H = (state[7] ^= H);
+
+ input += SM3::BLOCKSIZE/sizeof(word32);
+ }
+
+ return length & (SM3::BLOCKSIZE-1);
+}
+
+ANONYMOUS_NAMESPACE_END
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void SM3::InitState(HashWordType *state)
+{
+ const word32 s[] = {
+ 0x7380166fU, 0x4914b2b9U, 0x172442d7U, 0xda8a0600U,
+ 0xa96f30bcU, 0x163138aaU, 0xe38dee4dU, 0xb0fb0e4eU
+ };
+
+ std::memcpy(state, s, sizeof(s));
+}
+
+void SM3::Transform(word32 *state, const word32 *data)
+{
+ CRYPTOPP_ASSERT(state);
+ CRYPTOPP_ASSERT(data);
+
+ SM3_HashMultipleBlocks_CXX(state, data, SM3::BLOCKSIZE);
+}
+
+size_t SM3::HashMultipleBlocks(const HashWordType *input, size_t length)
+{
+ const size_t res = length & (SM3::BLOCKSIZE - 1);
+ SM3_HashMultipleBlocks_CXX(m_state, input, length-res);
+ return res;
+}
+
+NAMESPACE_END
diff --git a/sm3.h b/sm3.h
new file mode 100644
index 00000000..9a21f88a
--- /dev/null
+++ b/sm3.h
@@ -0,0 +1,61 @@
+// sm3.h - written and placed in the public domain by Jeffrey Walton and Han Lulu
+// Based on the specification provided by Sean Shen and Xiaodong Lee.
+// Based on code by Krzysztof Kwiatkowski and Jack Lloyd.
+// Also see https://tools.ietf.org/html/draft-shen-sm3-hash.
+
+//! \file sm3.h
+//! \brief Classes for the SM3 hash function
+//! \details SM3 is a Chinese national hash function designed by Xiaoyun Wang, et al.
+//! \sa <A HREF="https://tools.ietf.org/html/draft-shen-sm3-hash">SM3 Hash Function</A>
+//! \since Crypto++ 6.0
+
+#ifndef CRYPTOPP_SM3_H
+#define CRYPTOPP_SM3_H
+
+#include "config.h"
+#include "iterhash.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! \class SM3
+//! \brief SM3 hash function
+//! \details SM3 is a Chinese national hash function designed by Xiaoyun Wang, et al.
+//! \sa <A HREF="https://tools.ietf.org/html/draft-shen-sm3-hash">SM3 Hash Function</A>
+//! \since Crypto++ 6.0
+class SM3 : public IteratedHashWithStaticTransform<word32, BigEndian, 64, 32, SM3, 32, true>
+{
+public:
+ //! \brief Initialize state array
+ //! \param state the state of the hash
+ //! \details InitState sets a state array to SHA256 initial values
+ //! \details Hashes which derive from IteratedHashWithStaticTransform provide static
+ //! member functions InitState and Transform. External classes, like SEAL and MDC,
+ //! can initialize state with a user provided key and operate the hash on the data
+ //! with the user supplied state.
+ //! \note On Intel platforms the state array must be 16-byte aligned for SSE2.
+ static void InitState(HashWordType *state);
+
+ //! \brief Operate the hash
+ //! \param digest the state of the hash
+ //! \param data the data to be digested
+ //! \details Transform operates the hash on <tt>data</tt>. When the call is invoked
+ //! <tt>digest</tt> holds initial state. Upon return <tt>digest</tt> holds the hash
+ //! or updated state.
+ //! \details Hashes which derive from IteratedHashWithStaticTransform provide static
+ //! member functions InitState and Transform. External classes, like SEAL and MDC,
+ //! can initialize state with a user provided key and operate the hash on the data
+ //! with the user supplied state.
+ //! \note On Intel platforms the state array and data must be 16-byte aligned for SSE2.
+ static void Transform(HashWordType *digest, const HashWordType *data);
+
+ //! \brief The algorithm name
+ //! \returns C-style string "SM3"
+ CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "SM3"; }
+
+protected:
+ size_t HashMultipleBlocks(const HashWordType *input, size_t length);
+};
+
+NAMESPACE_END
+
+#endif // CRYPTOPP_SM3_H
diff --git a/test.cpp b/test.cpp
index 4a390811..d3c57c07 100644
--- a/test.cpp
+++ b/test.cpp
@@ -939,12 +939,13 @@ bool Validate(int alg, bool thorough, const char *seedInput)
case 71: result = ValidateGCM(); break;
case 72: result = ValidateCMAC(); break;
case 73: result = ValidateHKDF(); break;
- case 74: result = ValidateBLAKE2s(); break;
- case 75: result = ValidateBLAKE2b(); break;
- case 76: result = ValidatePoly1305(); break;
- case 77: result = ValidateSipHash(); break;
- case 78: result = ValidateHashDRBG(); break;
- case 79: result = ValidateHmacDRBG(); break;
+ case 74: result = ValidateSM3(); break;
+ case 75: result = ValidateBLAKE2s(); break;
+ case 76: result = ValidateBLAKE2b(); break;
+ case 77: result = ValidatePoly1305(); break;
+ case 78: result = ValidateSipHash(); break;
+ case 79: result = ValidateHashDRBG(); break;
+ case 80: result = ValidateHmacDRBG(); break;
#if defined(CRYPTOPP_EXTENDED_VALIDATION)
// http://github.com/weidai11/cryptopp/issues/92
diff --git a/validat1.cpp b/validat1.cpp
index c9494e3a..f2ab8737 100644
--- a/validat1.cpp
+++ b/validat1.cpp
@@ -132,6 +132,7 @@ bool ValidateAll(bool thorough)
pass=ValidatePanama() && pass;
pass=ValidateWhirlpool() && pass;
+ pass=ValidateSM3() && pass;
pass=ValidateBLAKE2s() && pass;
pass=ValidateBLAKE2b() && pass;
pass=ValidatePoly1305() && pass;
@@ -173,6 +174,7 @@ bool ValidateAll(bool thorough)
pass=RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/kalyna.txt") && pass;
pass=RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/simon.txt") && pass;
pass=RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/speck.txt") && pass;
+ pass=RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/sm4.txt") && pass;
pass=ValidateVMAC() && pass;
pass=ValidateCCM() && pass;
pass=ValidateGCM() && pass;
diff --git a/validat3.cpp b/validat3.cpp
index 660d3be7..902d073e 100644
--- a/validat3.cpp
+++ b/validat3.cpp
@@ -1939,5 +1939,10 @@ bool ValidateBLAKE2b()
return pass;
}
+bool ValidateSM3()
+{
+ return RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/sm3.txt");
+}
+
NAMESPACE_END // Test
NAMESPACE_END // CryptoPP
diff --git a/validate.h b/validate.h
index 46c7f573..733674f2 100644
--- a/validate.h
+++ b/validate.h
@@ -44,6 +44,7 @@ bool ValidateRIPEMD();
bool ValidatePanama();
bool ValidateWhirlpool();
+bool ValidateSM3();
bool ValidateBLAKE2s();
bool ValidateBLAKE2b();
bool ValidatePoly1305();