diff --git a/libtomcrypt_VS2008.vcproj b/libtomcrypt_VS2008.vcproj
index 69a5e2d69..987f3a33e 100644
--- a/libtomcrypt_VS2008.vcproj
+++ b/libtomcrypt_VS2008.vcproj
@@ -887,6 +887,14 @@
RelativePath="src\hashes\sha1.c"
>
+
+
+
+
@@ -934,10 +942,26 @@
RelativePath="src\hashes\sha2\sha224.c"
>
+
+
+
+
+
+
+
+
diff --git a/makefile.mingw b/makefile.mingw
index 5d388f55e..1d3135eec 100644
--- a/makefile.mingw
+++ b/makefile.mingw
@@ -69,7 +69,9 @@ src/hashes/blake2b.o src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper
src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \
src/hashes/helper/hash_memory_multi.o src/hashes/md2.o src/hashes/md4.o src/hashes/md5.o \
src/hashes/rmd128.o src/hashes/rmd160.o src/hashes/rmd256.o src/hashes/rmd320.o src/hashes/sha1.o \
-src/hashes/sha2/sha224.o src/hashes/sha2/sha256.o src/hashes/sha2/sha384.o src/hashes/sha2/sha512.o \
+src/hashes/sha1_desc.o src/hashes/sha1_x86.o src/hashes/sha2/sha224.o src/hashes/sha2/sha224_desc.o \
+src/hashes/sha2/sha224_x86.o src/hashes/sha2/sha256.o src/hashes/sha2/sha256_desc.o \
+src/hashes/sha2/sha256_x86.o src/hashes/sha2/sha384.o src/hashes/sha2/sha512.o \
src/hashes/sha2/sha512_224.o src/hashes/sha2/sha512_256.o src/hashes/sha3.o src/hashes/sha3_test.o \
src/hashes/tiger.o src/hashes/whirl/whirl.o src/mac/blake2/blake2bmac.o \
src/mac/blake2/blake2bmac_file.o src/mac/blake2/blake2bmac_memory.o \
diff --git a/makefile.msvc b/makefile.msvc
index 9f530931c..5770c4682 100644
--- a/makefile.msvc
+++ b/makefile.msvc
@@ -62,7 +62,9 @@ src/hashes/blake2b.obj src/hashes/blake2s.obj src/hashes/chc/chc.obj src/hashes/
src/hashes/helper/hash_filehandle.obj src/hashes/helper/hash_memory.obj \
src/hashes/helper/hash_memory_multi.obj src/hashes/md2.obj src/hashes/md4.obj src/hashes/md5.obj \
src/hashes/rmd128.obj src/hashes/rmd160.obj src/hashes/rmd256.obj src/hashes/rmd320.obj src/hashes/sha1.obj \
-src/hashes/sha2/sha224.obj src/hashes/sha2/sha256.obj src/hashes/sha2/sha384.obj src/hashes/sha2/sha512.obj \
+src/hashes/sha1_desc.obj src/hashes/sha1_x86.obj src/hashes/sha2/sha224.obj src/hashes/sha2/sha224_desc.obj \
+src/hashes/sha2/sha224_x86.obj src/hashes/sha2/sha256.obj src/hashes/sha2/sha256_desc.obj \
+src/hashes/sha2/sha256_x86.obj src/hashes/sha2/sha384.obj src/hashes/sha2/sha512.obj \
src/hashes/sha2/sha512_224.obj src/hashes/sha2/sha512_256.obj src/hashes/sha3.obj src/hashes/sha3_test.obj \
src/hashes/tiger.obj src/hashes/whirl/whirl.obj src/mac/blake2/blake2bmac.obj \
src/mac/blake2/blake2bmac_file.obj src/mac/blake2/blake2bmac_memory.obj \
diff --git a/makefile.unix b/makefile.unix
index df169e288..5130bef3b 100644
--- a/makefile.unix
+++ b/makefile.unix
@@ -83,7 +83,9 @@ src/hashes/blake2b.o src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper
src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \
src/hashes/helper/hash_memory_multi.o src/hashes/md2.o src/hashes/md4.o src/hashes/md5.o \
src/hashes/rmd128.o src/hashes/rmd160.o src/hashes/rmd256.o src/hashes/rmd320.o src/hashes/sha1.o \
-src/hashes/sha2/sha224.o src/hashes/sha2/sha256.o src/hashes/sha2/sha384.o src/hashes/sha2/sha512.o \
+src/hashes/sha1_desc.o src/hashes/sha1_x86.o src/hashes/sha2/sha224.o src/hashes/sha2/sha224_desc.o \
+src/hashes/sha2/sha224_x86.o src/hashes/sha2/sha256.o src/hashes/sha2/sha256_desc.o \
+src/hashes/sha2/sha256_x86.o src/hashes/sha2/sha384.o src/hashes/sha2/sha512.o \
src/hashes/sha2/sha512_224.o src/hashes/sha2/sha512_256.o src/hashes/sha3.o src/hashes/sha3_test.o \
src/hashes/tiger.o src/hashes/whirl/whirl.o src/mac/blake2/blake2bmac.o \
src/mac/blake2/blake2bmac_file.o src/mac/blake2/blake2bmac_memory.o \
diff --git a/makefile_include.mk b/makefile_include.mk
index 52013d7f3..b849f810d 100644
--- a/makefile_include.mk
+++ b/makefile_include.mk
@@ -254,7 +254,9 @@ src/hashes/blake2b.o src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper
src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \
src/hashes/helper/hash_memory_multi.o src/hashes/md2.o src/hashes/md4.o src/hashes/md5.o \
src/hashes/rmd128.o src/hashes/rmd160.o src/hashes/rmd256.o src/hashes/rmd320.o src/hashes/sha1.o \
-src/hashes/sha2/sha224.o src/hashes/sha2/sha256.o src/hashes/sha2/sha384.o src/hashes/sha2/sha512.o \
+src/hashes/sha1_desc.o src/hashes/sha1_x86.o src/hashes/sha2/sha224.o src/hashes/sha2/sha224_desc.o \
+src/hashes/sha2/sha224_x86.o src/hashes/sha2/sha256.o src/hashes/sha2/sha256_desc.o \
+src/hashes/sha2/sha256_x86.o src/hashes/sha2/sha384.o src/hashes/sha2/sha512.o \
src/hashes/sha2/sha512_224.o src/hashes/sha2/sha512_256.o src/hashes/sha3.o src/hashes/sha3_test.o \
src/hashes/tiger.o src/hashes/whirl/whirl.o src/mac/blake2/blake2bmac.o \
src/mac/blake2/blake2bmac_file.o src/mac/blake2/blake2bmac_memory.o \
diff --git a/sources.cmake b/sources.cmake
index a192ed391..38c5d9b25 100644
--- a/sources.cmake
+++ b/sources.cmake
@@ -101,8 +101,14 @@ src/hashes/rmd160.c
src/hashes/rmd256.c
src/hashes/rmd320.c
src/hashes/sha1.c
+src/hashes/sha1_desc.c
+src/hashes/sha1_x86.c
src/hashes/sha2/sha224.c
+src/hashes/sha2/sha224_desc.c
+src/hashes/sha2/sha224_x86.c
src/hashes/sha2/sha256.c
+src/hashes/sha2/sha256_desc.c
+src/hashes/sha2/sha256_x86.c
src/hashes/sha2/sha384.c
src/hashes/sha2/sha512.c
src/hashes/sha2/sha512_224.c
diff --git a/src/hashes/sha1.c b/src/hashes/sha1.c
index 389209655..72ef692d1 100644
--- a/src/hashes/sha1.c
+++ b/src/hashes/sha1.c
@@ -18,7 +18,7 @@
#define LTC_SMALL_STACK_SHA1
#endif
-const struct ltc_hash_descriptor sha1_desc =
+const struct ltc_hash_descriptor sha1_portable_desc =
{
"sha1",
2,
@@ -29,10 +29,10 @@ const struct ltc_hash_descriptor sha1_desc =
{ 1, 3, 14, 3, 2, 26, },
6,
- &sha1_init,
- &sha1_process,
- &sha1_done,
- &sha1_test,
+ &sha1_c_init,
+ &sha1_c_process,
+ &sha1_c_done,
+ &sha1_c_test,
NULL
};
@@ -42,9 +42,9 @@ const struct ltc_hash_descriptor sha1_desc =
#define F3(x,y,z) (x ^ y ^ z)
#ifdef LTC_CLEAN_STACK
-static int ss_sha1_compress(hash_state *md, const unsigned char *buf)
+static int ss_sha1_c_compress(hash_state *md, const unsigned char *buf)
#else
-static int s_sha1_compress(hash_state *md, const unsigned char *buf)
+static int s_sha1_c_compress(hash_state *md, const unsigned char *buf)
#endif
{
ulong32 a,b,c,d,e,i;
@@ -170,10 +170,10 @@ static int s_sha1_compress(hash_state *md, const unsigned char *buf)
}
#ifdef LTC_CLEAN_STACK
-static int s_sha1_compress(hash_state *md, const unsigned char *buf)
+static int s_sha1_c_compress(hash_state *md, const unsigned char *buf)
{
int err;
- err = ss_sha1_compress(md, buf);
+ err = ss_sha1_c_compress(md, buf);
burn_stack(sizeof(ulong32) * 87);
return err;
}
@@ -184,9 +184,12 @@ static int s_sha1_compress(hash_state *md, const unsigned char *buf)
@param md The hash state you wish to initialize
@return CRYPT_OK if successful
*/
-int sha1_init(hash_state * md)
+int sha1_c_init(hash_state * md)
{
LTC_ARGCHK(md != NULL);
+
+ md->sha1.state = LTC_ALIGN_BUF(md->sha1.state_buf, 16);
+
md->sha1.state[0] = 0x67452301UL;
md->sha1.state[1] = 0xefcdab89UL;
md->sha1.state[2] = 0x98badcfeUL;
@@ -204,7 +207,7 @@ int sha1_init(hash_state * md)
@param inlen The length of the data (octets)
@return CRYPT_OK if successful
*/
-HASH_PROCESS(sha1_process, s_sha1_compress, sha1, 64)
+HASH_PROCESS(sha1_c_process, s_sha1_c_compress, sha1, 64)
/**
Terminate the hash to get the digest
@@ -212,7 +215,7 @@ HASH_PROCESS(sha1_process, s_sha1_compress, sha1, 64)
@param out [out] The destination of the hash (20 bytes)
@return CRYPT_OK if successful
*/
-int sha1_done(hash_state * md, unsigned char *out)
+int sha1_c_done(hash_state * md, unsigned char *out)
{
int i;
@@ -237,7 +240,7 @@ int sha1_done(hash_state * md, unsigned char *out)
while (md->sha1.curlen < 64) {
md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
}
- s_sha1_compress(md, md->sha1.buf);
+ s_sha1_c_compress(md, md->sha1.buf);
md->sha1.curlen = 0;
}
@@ -248,7 +251,7 @@ int sha1_done(hash_state * md, unsigned char *out)
/* store length */
STORE64H(md->sha1.length, md->sha1.buf+56);
- s_sha1_compress(md, md->sha1.buf);
+ s_sha1_c_compress(md, md->sha1.buf);
/* copy output */
for (i = 0; i < 5; i++) {
@@ -264,41 +267,9 @@ int sha1_done(hash_state * md, unsigned char *out)
Self-test the hash
@return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
*/
-int sha1_test(void)
+int sha1_c_test(void)
{
- #ifndef LTC_TEST
- return CRYPT_NOP;
- #else
- static const struct {
- const char *msg;
- unsigned char hash[20];
- } tests[] = {
- { "abc",
- { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
- 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
- 0x9c, 0xd0, 0xd8, 0x9d }
- },
- { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
- { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
- 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
- 0xE5, 0x46, 0x70, 0xF1 }
- }
- };
-
- int i;
- unsigned char tmp[20];
- hash_state md;
-
- for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
- sha1_init(&md);
- sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
- sha1_done(&md, tmp);
- if (ltc_compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA1", i)) {
- return CRYPT_FAIL_TESTVECTOR;
- }
- }
- return CRYPT_OK;
- #endif
+ return sha1_test_desc(&sha1_portable_desc, "SHA1 portable");
}
#undef F0
diff --git a/src/hashes/sha1_desc.c b/src/hashes/sha1_desc.c
new file mode 100644
index 000000000..5f9bcc4dd
--- /dev/null
+++ b/src/hashes/sha1_desc.c
@@ -0,0 +1,175 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SHA1
+
+const struct ltc_hash_descriptor sha1_desc =
+{
+ "sha1",
+ 2,
+ 20,
+ 64,
+
+ /* OID */
+ { 1, 3, 14, 3, 2, 26, },
+ 6,
+
+ &sha1_init,
+ &sha1_process,
+ &sha1_done,
+ &sha1_test,
+ NULL
+};
+
+#if defined LTC_SHA1_X86
+
+#if !defined (LTC_S_X86_CPUID)
+#define LTC_S_X86_CPUID
+static LTC_INLINE void s_x86_cpuid(int* regs, int leaf)
+{
+#if defined _MSC_VER
+ __cpuid(regs, leaf);
+#else
+ int a, b, c, d;
+
+ a = leaf;
+ b = c = d = 0;
+ asm volatile ("cpuid"
+ :"=a"(a), "=b"(b), "=c"(c), "=d"(d)
+ :"a"(a), "c"(c)
+ );
+ regs[0] = a;
+ regs[1] = b;
+ regs[2] = c;
+ regs[3] = d;
+#endif
+}
+#endif /* LTC_S_X86_CPUID */
+
+static LTC_INLINE int s_sha1_x86_is_supported(void)
+{
+ static int initialized = 0;
+ static int is_supported = 0;
+
+ if (initialized == 0) {
+ int regs[4];
+ int sse2, ssse3, sse41, sha;
+ /* Leaf 0, Reg 0 contains the number of leafs available */
+ s_x86_cpuid(regs, 0);
+ if(regs[0] >= 7) {
+ s_x86_cpuid(regs, 1);
+ sse2 = ((((unsigned int)(regs[3])) >> 26) & 1u) != 0; /* SSE2, leaf 1, edx, bit 26 */
+ ssse3 = ((((unsigned int)(regs[2])) >> 9) & 1u) != 0; /* SSSE3, leaf 1, ecx, bit 9 */
+ sse41 = ((((unsigned int)(regs[2])) >> 19) & 1u) != 0; /* SSE4.1, leaf 1, ecx, bit 19 */
+ s_x86_cpuid(regs, 7);
+ sha = ((((unsigned int)(regs[1])) >> 29) & 1u) != 0; /* SHA, leaf 7, ebx, bit 29 */
+ is_supported = sse2 && ssse3 && sse41 && sha;
+ }
+ initialized = 1;
+ }
+ return is_supported;
+}
+#endif /* LTC_SHA1_X86 */
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha1_init(hash_state * md)
+{
+#if defined LTC_SHA1_X86
+ if(s_sha1_x86_is_supported()) {
+ return sha1_x86_init(md);
+ }
+#endif
+ return sha1_c_init(md);
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+int sha1_process(hash_state * md, const unsigned char *in, unsigned long inlen)
+{
+#if defined LTC_SHA1_X86
+ if(s_sha1_x86_is_supported()) {
+ return sha1_x86_process(md, in, inlen);
+ }
+#endif
+ return sha1_c_process(md, in, inlen);
+}
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (20 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha1_done(hash_state * md, unsigned char *out)
+{
+#if defined LTC_SHA1_X86
+ if(s_sha1_x86_is_supported()) {
+ return sha1_x86_done(md, out);
+ }
+#endif
+ return sha1_c_done(md, out);
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha1_test(void)
+{
+ return sha1_test_desc(&sha1_desc, "SHA1");
+}
+
+int sha1_test_desc(const struct ltc_hash_descriptor *desc, const char *name)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ const char *msg;
+ unsigned char hash[20];
+ } tests[] = {
+ { "abc",
+ { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
+ 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
+ 0x9c, 0xd0, 0xd8, 0x9d }
+ },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
+ 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
+ 0xE5, 0x46, 0x70, 0xF1 }
+ }
+ };
+
+ int i;
+ unsigned char tmp[20];
+ hash_state md;
+
+ LTC_ARGCHK(desc != NULL);
+ LTC_ARGCHK(desc->init != NULL);
+ LTC_ARGCHK(desc->process != NULL);
+ LTC_ARGCHK(desc->done != NULL);
+ LTC_ARGCHK(name != NULL);
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ desc->init(&md);
+ desc->process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ desc->done(&md, tmp);
+ if (ltc_compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), name, i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/src/hashes/sha1_x86.c b/src/hashes/sha1_x86.c
new file mode 100644
index 000000000..8f65665da
--- /dev/null
+++ b/src/hashes/sha1_x86.c
@@ -0,0 +1,287 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file sha1_x86.c
+ SHA1 code by Marek Knapek
+*/
+
+
+#ifdef LTC_SHA1_X86
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#elif defined(_MSC_VER)
+#include
+#endif
+#include /* SSE2 _mm_load_si128 _mm_loadu_si128 _mm_store_si128 _mm_set_epi32 _mm_set_epi64x _mm_setzero_si128 _mm_xor_si128 _mm_add_epi32 _mm_shuffle_epi32 */
+#include /* SSSE3 _mm_shuffle_epi8 */
+#include /* SSE4.1 _mm_extract_epi32 */
+#include /* SHA _mm_sha1msg1_epu32 _mm_sha1msg2_epu32 _mm_sha1rnds4_epu32 _mm_sha1nexte_epu32 */
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+const struct ltc_hash_descriptor sha1_x86_desc =
+{
+ "sha1",
+ 2,
+ 20,
+ 64,
+
+ /* OID */
+ { 1, 3, 14, 3, 2, 26, },
+ 6,
+
+ &sha1_x86_init,
+ &sha1_x86_process,
+ &sha1_x86_done,
+ &sha1_x86_test,
+ NULL
+};
+
+#ifdef LTC_CLEAN_STACK
+static int LTC_SHA_TARGET ss_sha1_x86_compress(hash_state *md, const unsigned char *buf)
+#else
+static int LTC_SHA_TARGET s_sha1_x86_compress(hash_state *md, const unsigned char *buf)
+#endif
+{
+#define k_reverse_32 ((0x0 << (3 * 2)) | (0x1 << (2 * 2)) | (0x2 << (1 * 2)) | (0x3 << (0 * 2)))
+
+ __m128i reverse_8;
+ __m128i abcdx;
+ __m128i e;
+ __m128i old_abcd;
+ __m128i old_e;
+ __m128i msg_0;
+ __m128i abcdy;
+ __m128i msg_1;
+ __m128i msg_2;
+ __m128i msg_3;
+
+ reverse_8 = _mm_set_epi64x(0x0001020304050607ull, 0x08090a0b0c0d0e0full);
+ abcdx = _mm_load_si128(((__m128i const*)(&md->sha1.state[0])));
+ abcdx = _mm_shuffle_epi32(abcdx, k_reverse_32);
+ e = _mm_set_epi32(*((int const*)(&md->sha1.state[4])), 0, 0, 0);
+
+ old_abcd = abcdx;
+ old_e = e;
+ msg_0 = _mm_loadu_si128(((__m128i const*)(&buf[0 * 16])));
+ msg_0 = _mm_shuffle_epi8(msg_0, reverse_8);
+ e = _mm_add_epi32(e, msg_0);
+ abcdy = _mm_sha1rnds4_epu32(abcdx, e, 0);
+ msg_1 = _mm_loadu_si128(((__m128i const*)(&buf[1 * 16])));
+ msg_1 = _mm_shuffle_epi8(msg_1, reverse_8);
+ e = _mm_sha1nexte_epu32(abcdx, msg_1);
+ abcdx = _mm_sha1rnds4_epu32(abcdy, e, 0);
+ msg_2 = _mm_loadu_si128(((__m128i const*)(&buf[2 * 16])));
+ msg_2 = _mm_shuffle_epi8(msg_2, reverse_8);
+ e = _mm_sha1nexte_epu32(abcdy, msg_2);
+ abcdy = _mm_sha1rnds4_epu32(abcdx, e, 0);
+ msg_3 = _mm_loadu_si128(((__m128i const*)(&buf[3 * 16])));
+ msg_3 = _mm_shuffle_epi8(msg_3, reverse_8);
+ e = _mm_sha1nexte_epu32(abcdx, msg_3);
+ abcdx = _mm_sha1rnds4_epu32(abcdy, e, 0);
+ msg_0 = _mm_sha1msg1_epu32(msg_0, msg_1);
+ msg_0 = _mm_xor_si128(msg_0, msg_2);
+ msg_0 = _mm_sha1msg2_epu32(msg_0, msg_3);
+ e = _mm_sha1nexte_epu32(abcdy, msg_0);
+ abcdy = _mm_sha1rnds4_epu32(abcdx, e, 0);
+ msg_1 = _mm_sha1msg1_epu32(msg_1, msg_2);
+ msg_1 = _mm_xor_si128(msg_1, msg_3);
+ msg_1 = _mm_sha1msg2_epu32(msg_1, msg_0);
+ e = _mm_sha1nexte_epu32(abcdx, msg_1);
+ abcdx = _mm_sha1rnds4_epu32(abcdy, e, 1);
+ msg_2 = _mm_sha1msg1_epu32(msg_2, msg_3);
+ msg_2 = _mm_xor_si128(msg_2, msg_0);
+ msg_2 = _mm_sha1msg2_epu32(msg_2, msg_1);
+ e = _mm_sha1nexte_epu32(abcdy, msg_2);
+ abcdy = _mm_sha1rnds4_epu32(abcdx, e, 1);
+ msg_3 = _mm_sha1msg1_epu32(msg_3, msg_0);
+ msg_3 = _mm_xor_si128(msg_3, msg_1);
+ msg_3 = _mm_sha1msg2_epu32(msg_3, msg_2);
+ e = _mm_sha1nexte_epu32(abcdx, msg_3);
+ abcdx = _mm_sha1rnds4_epu32(abcdy, e, 1);
+ msg_0 = _mm_sha1msg1_epu32(msg_0, msg_1);
+ msg_0 = _mm_xor_si128(msg_0, msg_2);
+ msg_0 = _mm_sha1msg2_epu32(msg_0, msg_3);
+ e = _mm_sha1nexte_epu32(abcdy, msg_0);
+ abcdy = _mm_sha1rnds4_epu32(abcdx, e, 1);
+ msg_1 = _mm_sha1msg1_epu32(msg_1, msg_2);
+ msg_1 = _mm_xor_si128(msg_1, msg_3);
+ msg_1 = _mm_sha1msg2_epu32(msg_1, msg_0);
+ e = _mm_sha1nexte_epu32(abcdx, msg_1);
+ abcdx = _mm_sha1rnds4_epu32(abcdy, e, 1);
+ msg_2 = _mm_sha1msg1_epu32(msg_2, msg_3);
+ msg_2 = _mm_xor_si128(msg_2, msg_0);
+ msg_2 = _mm_sha1msg2_epu32(msg_2, msg_1);
+ e = _mm_sha1nexte_epu32(abcdy, msg_2);
+ abcdy = _mm_sha1rnds4_epu32(abcdx, e, 2);
+ msg_3 = _mm_sha1msg1_epu32(msg_3, msg_0);
+ msg_3 = _mm_xor_si128(msg_3, msg_1);
+ msg_3 = _mm_sha1msg2_epu32(msg_3, msg_2);
+ e = _mm_sha1nexte_epu32(abcdx, msg_3);
+ abcdx = _mm_sha1rnds4_epu32(abcdy, e, 2);
+ msg_0 = _mm_sha1msg1_epu32(msg_0, msg_1);
+ msg_0 = _mm_xor_si128(msg_0, msg_2);
+ msg_0 = _mm_sha1msg2_epu32(msg_0, msg_3);
+ e = _mm_sha1nexte_epu32(abcdy, msg_0);
+ abcdy = _mm_sha1rnds4_epu32(abcdx, e, 2);
+ msg_1 = _mm_sha1msg1_epu32(msg_1, msg_2);
+ msg_1 = _mm_xor_si128(msg_1, msg_3);
+ msg_1 = _mm_sha1msg2_epu32(msg_1, msg_0);
+ e = _mm_sha1nexte_epu32(abcdx, msg_1);
+ abcdx = _mm_sha1rnds4_epu32(abcdy, e, 2);
+ msg_2 = _mm_sha1msg1_epu32(msg_2, msg_3);
+ msg_2 = _mm_xor_si128(msg_2, msg_0);
+ msg_2 = _mm_sha1msg2_epu32(msg_2, msg_1);
+ e = _mm_sha1nexte_epu32(abcdy, msg_2);
+ abcdy = _mm_sha1rnds4_epu32(abcdx, e, 2);
+ msg_3 = _mm_sha1msg1_epu32(msg_3, msg_0);
+ msg_3 = _mm_xor_si128(msg_3, msg_1);
+ msg_3 = _mm_sha1msg2_epu32(msg_3, msg_2);
+ e = _mm_sha1nexte_epu32(abcdx, msg_3);
+ abcdx = _mm_sha1rnds4_epu32(abcdy, e, 3);
+ msg_0 = _mm_sha1msg1_epu32(msg_0, msg_1);
+ msg_0 = _mm_xor_si128(msg_0, msg_2);
+ msg_0 = _mm_sha1msg2_epu32(msg_0, msg_3);
+ e = _mm_sha1nexte_epu32(abcdy, msg_0);
+ abcdy = _mm_sha1rnds4_epu32(abcdx, e, 3);
+ msg_1 = _mm_sha1msg1_epu32(msg_1, msg_2);
+ msg_1 = _mm_xor_si128(msg_1, msg_3);
+ msg_1 = _mm_sha1msg2_epu32(msg_1, msg_0);
+ e = _mm_sha1nexte_epu32(abcdx, msg_1);
+ abcdx = _mm_sha1rnds4_epu32(abcdy, e, 3);
+ msg_2 = _mm_sha1msg1_epu32(msg_2, msg_3);
+ msg_2 = _mm_xor_si128(msg_2, msg_0);
+ msg_2 = _mm_sha1msg2_epu32(msg_2, msg_1);
+ e = _mm_sha1nexte_epu32(abcdy, msg_2);
+ abcdy = _mm_sha1rnds4_epu32(abcdx, e, 3);
+ msg_3 = _mm_sha1msg1_epu32(msg_3, msg_0);
+ msg_3 = _mm_xor_si128(msg_3, msg_1);
+ msg_3 = _mm_sha1msg2_epu32(msg_3, msg_2);
+ e = _mm_sha1nexte_epu32(abcdx, msg_3);
+ abcdx = _mm_sha1rnds4_epu32(abcdy, e, 3);
+ msg_0 = _mm_setzero_si128();
+ e = _mm_sha1nexte_epu32(abcdy, msg_0);
+ abcdx = _mm_add_epi32(abcdx, old_abcd);
+ e = _mm_add_epi32(e, old_e);
+
+ abcdx = _mm_shuffle_epi32(abcdx, k_reverse_32);
+ _mm_store_si128(((__m128i*)(&md->sha1.state[0])), abcdx);
+ *((int*)(&md->sha1.state[4])) = _mm_extract_epi32(e, 3);
+
+ return CRYPT_OK;
+
+#undef k_reverse_32
+}
+
+#ifdef LTC_CLEAN_STACK
+static int s_sha1_x86_compress(hash_state *md, const unsigned char *buf)
+{
+ int err;
+ err = ss_sha1_x86_compress(md, buf);
+ burn_stack(sizeof(ulong32) * 87);
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha1_x86_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+
+ md->sha1.state = LTC_ALIGN_BUF(md->sha1.state_buf, 16);
+
+ md->sha1.state[0] = 0x67452301UL;
+ md->sha1.state[1] = 0xefcdab89UL;
+ md->sha1.state[2] = 0x98badcfeUL;
+ md->sha1.state[3] = 0x10325476UL;
+ md->sha1.state[4] = 0xc3d2e1f0UL;
+ md->sha1.curlen = 0;
+ md->sha1.length = 0;
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(sha1_x86_process, s_sha1_x86_compress, sha1, 64)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (20 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha1_x86_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->sha1.curlen >= ((int)(sizeof(md->sha1.buf)))) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* increase the length of the message */
+ md->sha1.length += md->sha1.curlen * 8;
+
+ /* append the '1' bit */
+ md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 56 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->sha1.curlen > 56) {
+ while (md->sha1.curlen < 64) {
+ md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
+ }
+ s_sha1_x86_compress(md, md->sha1.buf);
+ md->sha1.curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes */
+ while (md->sha1.curlen < 56) {
+ md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64H(md->sha1.length, md->sha1.buf+56);
+ s_sha1_x86_compress(md, md->sha1.buf);
+
+ /* copy output */
+ for (i = 0; i < 5; i++) {
+ STORE32H(md->sha1.state[i], out+(4*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha1_x86_test(void)
+{
+ return sha1_test_desc(&sha1_x86_desc, "SHA1 x86");
+}
+
+#endif
diff --git a/src/hashes/sha2/sha224.c b/src/hashes/sha2/sha224.c
index ba3f5b678..15fc36767 100644
--- a/src/hashes/sha2/sha224.c
+++ b/src/hashes/sha2/sha224.c
@@ -9,7 +9,7 @@
#if defined(LTC_SHA224) && defined(LTC_SHA256)
-const struct ltc_hash_descriptor sha224_desc =
+const struct ltc_hash_descriptor sha224_portable_desc =
{
"sha224",
10,
@@ -20,9 +20,9 @@ const struct ltc_hash_descriptor sha224_desc =
{ 2, 16, 840, 1, 101, 3, 4, 2, 4, },
9,
- &sha224_init,
- &sha256_process,
- &sha224_done,
+ &sha224_c_init,
+ &sha256_c_process,
+ &sha224_c_done,
&sha224_test,
NULL
};
@@ -33,10 +33,12 @@ const struct ltc_hash_descriptor sha224_desc =
@param md The hash state you wish to initialize
@return CRYPT_OK if successful
*/
-int sha224_init(hash_state * md)
+int sha224_c_init(hash_state * md)
{
LTC_ARGCHK(md != NULL);
+ md->sha256.state = LTC_ALIGN_BUF(md->sha256.state_buf, 16);
+
md->sha256.curlen = 0;
md->sha256.length = 0;
md->sha256.state[0] = 0xc1059ed8UL;
@@ -56,7 +58,7 @@ int sha224_init(hash_state * md)
@param out [out] The destination of the hash (28 bytes)
@return CRYPT_OK if successful
*/
-int sha224_done(hash_state * md, unsigned char *out)
+int sha224_c_done(hash_state * md, unsigned char *out)
{
unsigned char buf[32];
int err;
@@ -76,43 +78,9 @@ int sha224_done(hash_state * md, unsigned char *out)
Self-test the hash
@return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
*/
-int sha224_test(void)
+int sha224_c_test(void)
{
- #ifndef LTC_TEST
- return CRYPT_NOP;
- #else
- static const struct {
- const char *msg;
- unsigned char hash[28];
- } tests[] = {
- { "abc",
- { 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8,
- 0x22, 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2,
- 0x55, 0xb3, 0x2a, 0xad, 0xbc, 0xe4, 0xbd,
- 0xa0, 0xb3, 0xf7, 0xe3, 0x6c, 0x9d, 0xa7 }
- },
- { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
- { 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76,
- 0xcc, 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89,
- 0x01, 0x50, 0xb0, 0xc6, 0x45, 0x5c, 0xb4,
- 0xf5, 0x8b, 0x19, 0x52, 0x52, 0x25, 0x25 }
- },
- };
-
- int i;
- unsigned char tmp[28];
- hash_state md;
-
- for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
- sha224_init(&md);
- sha224_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
- sha224_done(&md, tmp);
- if (ltc_compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA224", i)) {
- return CRYPT_FAIL_TESTVECTOR;
- }
- }
- return CRYPT_OK;
- #endif
+ return sha224_test_desc(&sha224_portable_desc, "SHA224 portable");
}
#endif /* defined(LTC_SHA224) && defined(LTC_SHA256) */
diff --git a/src/hashes/sha2/sha224_desc.c b/src/hashes/sha2/sha224_desc.c
new file mode 100644
index 000000000..ccf4b9e89
--- /dev/null
+++ b/src/hashes/sha2/sha224_desc.c
@@ -0,0 +1,167 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+/**
+ @param sha224.c
+ LTC_SHA-224 new NIST standard based off of LTC_SHA-256 truncated to 224 bits (Tom St Denis)
+*/
+
+#include "tomcrypt_private.h"
+
+#if defined(LTC_SHA224) && defined(LTC_SHA256)
+
+const struct ltc_hash_descriptor sha224_desc =
+{
+ "sha224",
+ 10,
+ 28,
+ 64,
+
+ /* OID */
+ { 2, 16, 840, 1, 101, 3, 4, 2, 4, },
+ 9,
+
+ &sha224_init,
+ &sha256_process,
+ &sha224_done,
+ &sha224_test,
+ NULL
+};
+
+#if defined LTC_SHA256_X86
+
+#if !defined (LTC_S_X86_CPUID)
+#define LTC_S_X86_CPUID
+static LTC_INLINE void s_x86_cpuid(int* regs, int leaf)
+{
+#if defined _MSC_VER
+ __cpuid(regs, leaf);
+#else
+ int a, b, c, d;
+
+ a = leaf;
+ b = c = d = 0;
+ asm volatile ("cpuid"
+ :"=a"(a), "=b"(b), "=c"(c), "=d"(d)
+ :"a"(a), "c"(c)
+ );
+ regs[0] = a;
+ regs[1] = b;
+ regs[2] = c;
+ regs[3] = d;
+#endif
+}
+#endif /* LTC_S_X86_CPUID */
+
+static LTC_INLINE int s_sha224_x86_is_supported(void)
+{
+ static int initialized = 0;
+ static int is_supported = 0;
+
+ if (initialized == 0) {
+ int regs[4];
+ int sse2, ssse3, sse41, sha;
+ /* Leaf 0, Reg 0 contains the number of leafs available */
+ s_x86_cpuid(regs, 0);
+ if(regs[0] >= 7) {
+ s_x86_cpuid(regs, 1);
+ sse2 = ((((unsigned int)(regs[3])) >> 26) & 1u) != 0; /* SSE2, leaf 1, edx, bit 26 */
+ ssse3 = ((((unsigned int)(regs[2])) >> 9) & 1u) != 0; /* SSSE3, leaf 1, ecx, bit 9 */
+ sse41 = ((((unsigned int)(regs[2])) >> 19) & 1u) != 0; /* SSE4.1, leaf 1, ecx, bit 19 */
+ s_x86_cpuid(regs, 7);
+ sha = ((((unsigned int)(regs[1])) >> 29) & 1u) != 0; /* SHA, leaf 7, ebx, bit 29 */
+ is_supported = sse2 && ssse3 && sse41 && sha;
+ }
+ initialized = 1;
+ }
+ return is_supported;
+}
+#endif /* LTC_SHA224_X86 */
+
+/* init the sha256 er... sha224 state ;-) */
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha224_init(hash_state * md)
+{
+#if defined LTC_SHA224_X86
+ if(s_sha224_x86_is_supported()) {
+ return sha224_x86_init(md);
+ }
+#endif
+ return sha224_c_init(md);
+}
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (28 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha224_done(hash_state * md, unsigned char *out)
+{
+#if defined LTC_SHA224_X86
+ if(s_sha224_x86_is_supported()) {
+ return sha224_x86_done(md, out);
+ }
+#endif
+ return sha224_c_done(md, out);
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha224_test(void)
+{
+ return sha224_test_desc(&sha224_desc, "SHA224");
+}
+
+int sha224_test_desc(const struct ltc_hash_descriptor *desc, const char *name)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ const char *msg;
+ unsigned char hash[28];
+ } tests[] = {
+ { "abc",
+ { 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8,
+ 0x22, 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2,
+ 0x55, 0xb3, 0x2a, 0xad, 0xbc, 0xe4, 0xbd,
+ 0xa0, 0xb3, 0xf7, 0xe3, 0x6c, 0x9d, 0xa7 }
+ },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ { 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76,
+ 0xcc, 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89,
+ 0x01, 0x50, 0xb0, 0xc6, 0x45, 0x5c, 0xb4,
+ 0xf5, 0x8b, 0x19, 0x52, 0x52, 0x25, 0x25 }
+ },
+ };
+
+ int i;
+ unsigned char tmp[32];
+ hash_state md;
+
+ LTC_ARGCHK(desc != NULL);
+ LTC_ARGCHK(desc->init != NULL);
+ LTC_ARGCHK(desc->process != NULL);
+ LTC_ARGCHK(desc->done != NULL);
+ LTC_ARGCHK(name != NULL);
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ desc->init(&md);
+ desc->process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ desc->done(&md, tmp);
+ if (ltc_compare_testvector(tmp, 28, tests[i].hash, sizeof(tests[i].hash), name, i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif /* defined(LTC_SHA224) && defined(LTC_SHA256) */
+
diff --git a/src/hashes/sha2/sha224_x86.c b/src/hashes/sha2/sha224_x86.c
new file mode 100644
index 000000000..8f9dd831b
--- /dev/null
+++ b/src/hashes/sha2/sha224_x86.c
@@ -0,0 +1,87 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+/**
+ @param sha224.c
+ LTC_SHA-224 new NIST standard based off of LTC_SHA-256 truncated to 224 bits (Tom St Denis)
+*/
+
+#include "tomcrypt_private.h"
+
+#if defined(LTC_SHA224) && defined(LTC_SHA256) && defined(LTC_SHA224_X86)
+
+const struct ltc_hash_descriptor sha224_x86_desc =
+{
+ "sha224",
+ 10,
+ 28,
+ 64,
+
+ /* OID */
+ { 2, 16, 840, 1, 101, 3, 4, 2, 4, },
+ 9,
+
+ &sha224_x86_init,
+ &sha256_x86_process,
+ &sha224_x86_done,
+ &sha224_x86_test,
+ NULL
+};
+
+/* init the sha256 er... sha224 state ;-) */
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha224_x86_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+
+ md->sha256.state = LTC_ALIGN_BUF(md->sha256.state_buf, 16);
+
+ md->sha256.curlen = 0;
+ md->sha256.length = 0;
+ md->sha256.state[0] = 0xc1059ed8UL;
+ md->sha256.state[1] = 0x367cd507UL;
+ md->sha256.state[2] = 0x3070dd17UL;
+ md->sha256.state[3] = 0xf70e5939UL;
+ md->sha256.state[4] = 0xffc00b31UL;
+ md->sha256.state[5] = 0x68581511UL;
+ md->sha256.state[6] = 0x64f98fa7UL;
+ md->sha256.state[7] = 0xbefa4fa4UL;
+ return CRYPT_OK;
+}
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (28 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha224_x86_done(hash_state * md, unsigned char *out)
+{
+ unsigned char buf[32];
+ int err;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ err = sha256_done(md, buf);
+ XMEMCPY(out, buf, 28);
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, sizeof(buf));
+#endif
+ return err;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha224_x86_test(void)
+{
+ return sha224_test_desc(&sha224_x86_desc, "SHA224 x86");
+}
+
+#endif /* defined(LTC_SHA224) && defined(LTC_SHA256) */
+
diff --git a/src/hashes/sha2/sha256.c b/src/hashes/sha2/sha256.c
index ffd8d6f8b..a37028d64 100644
--- a/src/hashes/sha2/sha256.c
+++ b/src/hashes/sha2/sha256.c
@@ -9,7 +9,7 @@
#ifdef LTC_SHA256
-const struct ltc_hash_descriptor sha256_desc =
+const struct ltc_hash_descriptor sha256_portable_desc =
{
"sha256",
0,
@@ -20,10 +20,10 @@ const struct ltc_hash_descriptor sha256_desc =
{ 2, 16, 840, 1, 101, 3, 4, 2, 1, },
9,
- &sha256_init,
- &sha256_process,
- &sha256_done,
- &sha256_test,
+ &sha256_c_init,
+ &sha256_c_process,
+ &sha256_c_done,
+ &sha256_c_test,
NULL
};
@@ -231,10 +231,12 @@ static int s_sha256_compress(hash_state * md, const unsigned char *buf)
@param md The hash state you wish to initialize
@return CRYPT_OK if successful
*/
-int sha256_init(hash_state * md)
+int sha256_c_init(hash_state * md)
{
LTC_ARGCHK(md != NULL);
+ md->sha256.state = LTC_ALIGN_BUF(md->sha256.state_buf, 16);
+
md->sha256.curlen = 0;
md->sha256.length = 0;
md->sha256.state[0] = 0x6A09E667UL;
@@ -255,7 +257,7 @@ int sha256_init(hash_state * md)
@param inlen The length of the data (octets)
@return CRYPT_OK if successful
*/
-HASH_PROCESS(sha256_process,s_sha256_compress, sha256, 64)
+HASH_PROCESS(sha256_c_process,s_sha256_compress, sha256, 64)
/**
Terminate the hash to get the digest
@@ -263,7 +265,7 @@ HASH_PROCESS(sha256_process,s_sha256_compress, sha256, 64)
@param out [out] The destination of the hash (32 bytes)
@return CRYPT_OK if successful
*/
-int sha256_done(hash_state * md, unsigned char *out)
+int sha256_c_done(hash_state * md, unsigned char *out)
{
int i;
@@ -316,43 +318,9 @@ int sha256_done(hash_state * md, unsigned char *out)
Self-test the hash
@return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
*/
-int sha256_test(void)
+int sha256_c_test(void)
{
- #ifndef LTC_TEST
- return CRYPT_NOP;
- #else
- static const struct {
- const char *msg;
- unsigned char hash[32];
- } tests[] = {
- { "abc",
- { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
- 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
- 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
- 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }
- },
- { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
- { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
- 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
- 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
- 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }
- },
- };
-
- int i;
- unsigned char tmp[32];
- hash_state md;
-
- for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
- sha256_init(&md);
- sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
- sha256_done(&md, tmp);
- if (ltc_compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA256", i)) {
- return CRYPT_FAIL_TESTVECTOR;
- }
- }
- return CRYPT_OK;
- #endif
+ return sha256_test_desc(&sha256_portable_desc, "SHA256 portable");
}
#undef Ch
diff --git a/src/hashes/sha2/sha256_desc.c b/src/hashes/sha2/sha256_desc.c
new file mode 100644
index 000000000..7367ec20b
--- /dev/null
+++ b/src/hashes/sha2/sha256_desc.c
@@ -0,0 +1,177 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_SHA256
+
+const struct ltc_hash_descriptor sha256_desc =
+{
+ "sha256",
+ 0,
+ 32,
+ 64,
+
+ /* OID */
+ { 2, 16, 840, 1, 101, 3, 4, 2, 1, },
+ 9,
+
+ &sha256_init,
+ &sha256_process,
+ &sha256_done,
+ &sha256_test,
+ NULL
+};
+
+#if defined LTC_SHA256_X86
+
+#if !defined (LTC_S_X86_CPUID)
+#define LTC_S_X86_CPUID
+static LTC_INLINE void s_x86_cpuid(int* regs, int leaf)
+{
+#if defined _MSC_VER
+ __cpuid(regs, leaf);
+#else
+ int a, b, c, d;
+
+ a = leaf;
+ b = c = d = 0;
+ asm volatile ("cpuid"
+ :"=a"(a), "=b"(b), "=c"(c), "=d"(d)
+ :"a"(a), "c"(c)
+ );
+ regs[0] = a;
+ regs[1] = b;
+ regs[2] = c;
+ regs[3] = d;
+#endif
+}
+#endif /* LTC_S_X86_CPUID */
+
+static LTC_INLINE int s_sha256_x86_is_supported(void)
+{
+ static int initialized = 0;
+ static int is_supported = 0;
+
+ if (initialized == 0) {
+ int regs[4];
+ int sse2, ssse3, sse41, sha;
+ /* Leaf 0, Reg 0 contains the number of leafs available */
+ s_x86_cpuid(regs, 0);
+ if(regs[0] >= 7) {
+ s_x86_cpuid(regs, 1);
+ sse2 = ((((unsigned int)(regs[3])) >> 26) & 1u) != 0; /* SSE2, leaf 1, edx, bit 26 */
+ ssse3 = ((((unsigned int)(regs[2])) >> 9) & 1u) != 0; /* SSSE3, leaf 1, ecx, bit 9 */
+ sse41 = ((((unsigned int)(regs[2])) >> 19) & 1u) != 0; /* SSE4.1, leaf 1, ecx, bit 19 */
+ s_x86_cpuid(regs, 7);
+ sha = ((((unsigned int)(regs[1])) >> 29) & 1u) != 0; /* SHA, leaf 7, ebx, bit 29 */
+ is_supported = sse2 && ssse3 && sse41 && sha;
+ }
+ initialized = 1;
+ }
+ return is_supported;
+}
+#endif /* LTC_SHA256_X86 */
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha256_init(hash_state * md)
+{
+#if defined LTC_SHA256_X86
+ if(s_sha256_x86_is_supported()) {
+ return sha256_x86_init(md);
+ }
+#endif
+ return sha256_c_init(md);
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen)
+{
+#if defined LTC_SHA256_X86
+ if(s_sha256_x86_is_supported()) {
+ return sha256_x86_process(md, in, inlen);
+ }
+#endif
+ return sha256_c_process(md, in, inlen);
+}
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (32 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha256_done(hash_state * md, unsigned char *out)
+{
+#if defined LTC_SHA256_X86
+ if(s_sha256_x86_is_supported()) {
+ return sha256_x86_done(md, out);
+ }
+#endif
+ return sha256_c_done(md, out);
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha256_test(void)
+{
+ return sha256_test_desc(&sha256_desc, "SHA256");
+}
+
+int sha256_test_desc(const struct ltc_hash_descriptor *desc, const char *name)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ static const struct {
+ const char *msg;
+ unsigned char hash[32];
+ } tests[] = {
+ { "abc",
+ { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
+ 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
+ 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
+ 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }
+ },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
+ 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
+ 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
+ 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }
+ },
+ };
+
+ int i;
+ unsigned char tmp[32];
+ hash_state md;
+
+ LTC_ARGCHK(desc != NULL);
+ LTC_ARGCHK(desc->init != NULL);
+ LTC_ARGCHK(desc->process != NULL);
+ LTC_ARGCHK(desc->done != NULL);
+ LTC_ARGCHK(name != NULL);
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ desc->init(&md);
+ desc->process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
+ desc->done(&md, tmp);
+ if (ltc_compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), name, i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+#endif
+}
+
+#endif
diff --git a/src/hashes/sha2/sha256_x86.c b/src/hashes/sha2/sha256_x86.c
new file mode 100644
index 000000000..de79b4167
--- /dev/null
+++ b/src/hashes/sha2/sha256_x86.c
@@ -0,0 +1,357 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+ @file sha256_x86.c
+ SHA256 by Marek Knapek
+*/
+
+#if defined(LTC_SHA256) && defined(LTC_SHA256_X86)
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#elif defined(_MSC_VER)
+#include
+#endif
+#include /* SSE2 _mm_load_si128 _mm_loadu_si128 _mm_store_si128 _mm_set_epi64x _mm_add_epi32 _mm_shuffle_epi32 */
+#include /* SSSE3 _mm_alignr_epi8 _mm_shuffle_epi8 */
+#include /* SSE4.1 _mm_blend_epi16 */
+#include /* SHA _mm_sha256msg1_epu32 _mm_sha256msg2_epu32 _mm_sha256rnds2_epu32 */
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+const struct ltc_hash_descriptor sha256_x86_desc =
+{
+ "sha256",
+ 0,
+ 32,
+ 64,
+
+ /* OID */
+ { 2, 16, 840, 1, 101, 3, 4, 2, 1, },
+ 9,
+
+ &sha256_x86_init,
+ &sha256_x86_process,
+ &sha256_x86_done,
+ &sha256_x86_test,
+ NULL
+};
+
+/* the K array */
+#define K sha256_x86_K
+LTC_ALIGN_MSVC(16)
+static const ulong32 K[64] LTC_ALIGN(16) = {
+ 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
+ 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
+ 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
+ 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+ 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
+ 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
+ 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
+ 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+ 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
+ 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
+ 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
+ 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+ 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/* compress 512-bits */
+#ifdef LTC_CLEAN_STACK
+static int LTC_SHA_TARGET ss_sha256_x86_compress(hash_state * md, const unsigned char *buf)
+#else
+static int LTC_SHA_TARGET s_sha256_x86_compress(hash_state * md, const unsigned char *buf)
+#endif
+{
+#define k_blend_epi16(a, b, c, d, e, f, g, h) ((((a) & 0x1) << 7) | (((b) & 0x1) << 6) | (((c) & 0x1) << 5) | (((d) & 0x1) << 4) | (((e) & 0x1) << 3) | (((f) & 0x1) << 2) | (((g) & 0x1) << 1) | (((h) & 0x1) << 0))
+#define ltc_mm_blend_epi32(a, b, c) _mm_blend_epi16((a), (b), k_blend_epi16((((c) >> 3) & 0x1), (((c) >> 3) & 0x1), (((c) >> 2) & 0x1), (((c) >> 2) & 0x1), (((c) >> 1) & 0x1), (((c) >> 1) & 0x1), (((c) >> 0) & 0x1), (((c) >> 0) & 0x1)))
+#define k_shuffle_epi32(a, b, c, d) ((((a) & 0x3) << (3 * 2)) | (((b) & 0x3) << (2 * 2)) | (((c) & 0x3) << (1 * 2)) | (((d) & 0x3) << (0 * 2)))
+#define k_blend_epi32(a, b, c, d) ((((a) & 0x1) << (3 * 1)) | (((b) & 0x1) << (2 * 1)) | (((c) & 0x1) << (1 * 1)) | (((d) & 0x1) << (0 * 1)))
+#define k_alignr_epi8(a) (((a) & 0x3) * 4)
+#define k_any 0x0
+
+ __m128i reverse;
+ __m128i state_0;
+ __m128i state_1;
+ __m128i tmp;
+ __m128i old_0;
+ __m128i old_1;
+ __m128i msg_0;
+ __m128i msg;
+ __m128i msg_1;
+ __m128i msg_2;
+ __m128i msg_3;
+
+ reverse = _mm_set_epi64x(0x0c0d0e0f08090a0bull, 0x0405060700010203ull);
+ state_0 = _mm_load_si128(((__m128i const*)(&md->sha256.state[0])));
+ state_1 = _mm_load_si128(((__m128i const*)(&md->sha256.state[4])));
+ tmp = _mm_shuffle_epi32(state_0, k_shuffle_epi32(0x2, 0x3, 0x0, 0x1));
+ state_1 = _mm_shuffle_epi32(state_1, k_shuffle_epi32(0x0, 0x1, 0x2, 0x3));
+ state_0 = _mm_alignr_epi8(tmp, state_1, k_alignr_epi8(2));
+ state_1 = ltc_mm_blend_epi32(state_1, tmp, k_blend_epi32(0x1, 0x1, 0x0, 0x0));
+
+ old_0 = state_0;
+ old_1 = state_1;
+ msg_0 = _mm_loadu_si128(((__m128i const*)(&buf[0 * 16])));
+ msg_0 = _mm_shuffle_epi8(msg_0, reverse);
+ tmp = _mm_load_si128(((__m128i const*)(&K[0 * 4])));
+ msg = _mm_add_epi32(msg_0, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_1 = _mm_loadu_si128(((__m128i const*)(&buf[1 * 16])));
+ msg_1 = _mm_shuffle_epi8(msg_1, reverse);
+ tmp = _mm_load_si128(((__m128i const*)(&K[1 * 4])));
+ msg = _mm_add_epi32(msg_1, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_2 = _mm_loadu_si128(((__m128i const*)(&buf[2 * 16])));
+ msg_2 = _mm_shuffle_epi8(msg_2, reverse);
+ tmp = _mm_load_si128(((__m128i const*)(&K[2 * 4])));
+ msg = _mm_add_epi32(msg_2, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_3 = _mm_loadu_si128(((__m128i const*)(&buf[3 * 16])));
+ msg_3 = _mm_shuffle_epi8(msg_3, reverse);
+ tmp = _mm_load_si128(((__m128i const*)(&K[3 * 4])));
+ msg = _mm_add_epi32(msg_3, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_0 = _mm_sha256msg1_epu32(msg_0, msg_1);
+ tmp = _mm_alignr_epi8(msg_3, msg_2, k_alignr_epi8(1));
+ msg_0 = _mm_add_epi32(msg_0, tmp);
+ msg_0 = _mm_sha256msg2_epu32(msg_0, msg_3);
+ tmp = _mm_load_si128(((__m128i const*)(&K[4 * 4])));
+ msg = _mm_add_epi32(msg_0, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_1 = _mm_sha256msg1_epu32(msg_1, msg_2);
+ tmp = _mm_alignr_epi8(msg_0, msg_3, k_alignr_epi8(1));
+ msg_1 = _mm_add_epi32(msg_1, tmp);
+ msg_1 = _mm_sha256msg2_epu32(msg_1, msg_0);
+ tmp = _mm_load_si128(((__m128i const*)(&K[5 * 4])));
+ msg = _mm_add_epi32(msg_1, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_2 = _mm_sha256msg1_epu32(msg_2, msg_3);
+ tmp = _mm_alignr_epi8(msg_1, msg_0, k_alignr_epi8(1));
+ msg_2 = _mm_add_epi32(msg_2, tmp);
+ msg_2 = _mm_sha256msg2_epu32(msg_2, msg_1);
+ tmp = _mm_load_si128(((__m128i const*)(&K[6 * 4])));
+ msg = _mm_add_epi32(msg_2, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_3 = _mm_sha256msg1_epu32(msg_3, msg_0);
+ tmp = _mm_alignr_epi8(msg_2, msg_1, k_alignr_epi8(1));
+ msg_3 = _mm_add_epi32(msg_3, tmp);
+ msg_3 = _mm_sha256msg2_epu32(msg_3, msg_2);
+ tmp = _mm_load_si128(((__m128i const*)(&K[7 * 4])));
+ msg = _mm_add_epi32(msg_3, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_0 = _mm_sha256msg1_epu32(msg_0, msg_1);
+ tmp = _mm_alignr_epi8(msg_3, msg_2, k_alignr_epi8(1));
+ msg_0 = _mm_add_epi32(msg_0, tmp);
+ msg_0 = _mm_sha256msg2_epu32(msg_0, msg_3);
+ tmp = _mm_load_si128(((__m128i const*)(&K[8 * 4])));
+ msg = _mm_add_epi32(msg_0, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_1 = _mm_sha256msg1_epu32(msg_1, msg_2);
+ tmp = _mm_alignr_epi8(msg_0, msg_3, k_alignr_epi8(1));
+ msg_1 = _mm_add_epi32(msg_1, tmp);
+ msg_1 = _mm_sha256msg2_epu32(msg_1, msg_0);
+ tmp = _mm_load_si128(((__m128i const*)(&K[9 * 4])));
+ msg = _mm_add_epi32(msg_1, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_2 = _mm_sha256msg1_epu32(msg_2, msg_3);
+ tmp = _mm_alignr_epi8(msg_1, msg_0, k_alignr_epi8(1));
+ msg_2 = _mm_add_epi32(msg_2, tmp);
+ msg_2 = _mm_sha256msg2_epu32(msg_2, msg_1);
+ tmp = _mm_load_si128(((__m128i const*)(&K[10 * 4])));
+ msg = _mm_add_epi32(msg_2, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_3 = _mm_sha256msg1_epu32(msg_3, msg_0);
+ tmp = _mm_alignr_epi8(msg_2, msg_1, k_alignr_epi8(1));
+ msg_3 = _mm_add_epi32(msg_3, tmp);
+ msg_3 = _mm_sha256msg2_epu32(msg_3, msg_2);
+ tmp = _mm_load_si128(((__m128i const*)(&K[11 * 4])));
+ msg = _mm_add_epi32(msg_3, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_0 = _mm_sha256msg1_epu32(msg_0, msg_1);
+ tmp = _mm_alignr_epi8(msg_3, msg_2, k_alignr_epi8(1));
+ msg_0 = _mm_add_epi32(msg_0, tmp);
+ msg_0 = _mm_sha256msg2_epu32(msg_0, msg_3);
+ tmp = _mm_load_si128(((__m128i const*)(&K[12 * 4])));
+ msg = _mm_add_epi32(msg_0, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_1 = _mm_sha256msg1_epu32(msg_1, msg_2);
+ tmp = _mm_alignr_epi8(msg_0, msg_3, k_alignr_epi8(1));
+ msg_1 = _mm_add_epi32(msg_1, tmp);
+ msg_1 = _mm_sha256msg2_epu32(msg_1, msg_0);
+ tmp = _mm_load_si128(((__m128i const*)(&K[13 * 4])));
+ msg = _mm_add_epi32(msg_1, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_2 = _mm_sha256msg1_epu32(msg_2, msg_3);
+ tmp = _mm_alignr_epi8(msg_1, msg_0, k_alignr_epi8(1));
+ msg_2 = _mm_add_epi32(msg_2, tmp);
+ msg_2 = _mm_sha256msg2_epu32(msg_2, msg_1);
+ tmp = _mm_load_si128(((__m128i const*)(&K[14 * 4])));
+ msg = _mm_add_epi32(msg_2, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ msg_3 = _mm_sha256msg1_epu32(msg_3, msg_0);
+ tmp = _mm_alignr_epi8(msg_2, msg_1, k_alignr_epi8(1));
+ msg_3 = _mm_add_epi32(msg_3, tmp);
+ msg_3 = _mm_sha256msg2_epu32(msg_3, msg_2);
+ tmp = _mm_load_si128(((__m128i const*)(&K[15 * 4])));
+ msg = _mm_add_epi32(msg_3, tmp);
+ state_1 = _mm_sha256rnds2_epu32(state_1, state_0, msg);
+ msg = _mm_shuffle_epi32(msg, k_shuffle_epi32(k_any, k_any, 0x3, 0x2));
+ state_0 = _mm_sha256rnds2_epu32(state_0, state_1, msg);
+ state_0 = _mm_add_epi32(state_0, old_0);
+ state_1 = _mm_add_epi32(state_1, old_1);
+
+ tmp = _mm_shuffle_epi32(state_0, k_shuffle_epi32(0x0, 0x1, 0x2, 0x3));
+ state_1 = _mm_shuffle_epi32(state_1, k_shuffle_epi32(0x2, 0x3, 0x0, 0x1));
+ state_0 = ltc_mm_blend_epi32(tmp, state_1, k_blend_epi32(0x1, 0x1, 0x0, 0x0));
+ state_1 = _mm_alignr_epi8(state_1, tmp, k_alignr_epi8(2));
+ _mm_store_si128(((__m128i*)(&md->sha256.state[0])), state_0);
+ _mm_store_si128(((__m128i*)(&md->sha256.state[4])), state_1);
+ return CRYPT_OK;
+}
+#undef K
+
+#ifdef LTC_CLEAN_STACK
+static int s_sha256_compress(hash_state * md, const unsigned char *buf)
+{
+ int err;
+ err = ss_sha256_compress(md, buf);
+ burn_stack(sizeof(ulong32) * 74);
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha256_x86_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+
+ md->sha256.state = LTC_ALIGN_BUF(md->sha256.state_buf, 16);
+
+ md->sha256.curlen = 0;
+ md->sha256.length = 0;
+ md->sha256.state[0] = 0x6A09E667UL;
+ md->sha256.state[1] = 0xBB67AE85UL;
+ md->sha256.state[2] = 0x3C6EF372UL;
+ md->sha256.state[3] = 0xA54FF53AUL;
+ md->sha256.state[4] = 0x510E527FUL;
+ md->sha256.state[5] = 0x9B05688CUL;
+ md->sha256.state[6] = 0x1F83D9ABUL;
+ md->sha256.state[7] = 0x5BE0CD19UL;
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(sha256_x86_process,s_sha256_x86_compress, sha256, 64)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (32 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha256_x86_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->sha256.curlen >= sizeof(md->sha256.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+
+ /* increase the length of the message */
+ md->sha256.length += md->sha256.curlen * 8;
+
+ /* append the '1' bit */
+ md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 56 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->sha256.curlen > 56) {
+ while (md->sha256.curlen < 64) {
+ md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
+ }
+ s_sha256_x86_compress(md, md->sha256.buf);
+ md->sha256.curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes */
+ while (md->sha256.curlen < 56) {
+ md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64H(md->sha256.length, md->sha256.buf+56);
+ s_sha256_x86_compress(md, md->sha256.buf);
+
+ /* copy output */
+ for (i = 0; i < 8; i++) {
+ STORE32H(md->sha256.state[i], out+(4*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha256_x86_test(void)
+{
+ return sha256_test_desc(&sha256_x86_desc, "SHA256 x86");
+}
+
+#endif
diff --git a/src/hashes/sha2/sha512.c b/src/hashes/sha2/sha512.c
index d4a16a36d..5086a823e 100644
--- a/src/hashes/sha2/sha512.c
+++ b/src/hashes/sha2/sha512.c
@@ -28,6 +28,7 @@ const struct ltc_hash_descriptor sha512_desc =
};
/* the K array */
+#define K sha512_K
static const ulong64 K[80] = {
CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
@@ -186,6 +187,7 @@ static int s_sha512_compress(hash_state * md, const unsigned char *buf)
return CRYPT_OK;
}
+#undef K
/* compress 1024-bits */
#ifdef LTC_CLEAN_STACK
diff --git a/src/headers/tomcrypt_cfg.h b/src/headers/tomcrypt_cfg.h
index 8875ee18b..6f82aa9a3 100644
--- a/src/headers/tomcrypt_cfg.h
+++ b/src/headers/tomcrypt_cfg.h
@@ -307,13 +307,29 @@ typedef unsigned long ltc_mp_digit;
#define LTC_HAVE_CTZL_BUILTIN
#endif
-#if !defined(LTC_NO_AES_NI) && (defined(__x86_64__) || defined(_M_X64))
-#define LTC_AES_NI
+#if (defined(__x86_64__) || defined(_M_X64))
+ #if !defined(LTC_NO_AES_NI)
+ #define LTC_AES_NI
+ #endif
+ #if !defined(LTC_NO_SHA1_X86)
+ #define LTC_SHA1_X86
+ #endif
+ #if !defined(LTC_NO_SHA224_X86)
+ #define LTC_SHA224_X86
+ #endif
+ #if !defined(LTC_NO_SHA256_X86)
+ #define LTC_SHA256_X86
+ #endif
#endif
#if defined(__GNUC__)
+ #define LTC_ALIGN_MSVC(n)
#define LTC_ALIGN(n) __attribute__((aligned(n)))
+#elif defined(_MSC_VER)
+ #define LTC_ALIGN_MSVC(n) __declspec(align(n))
+ #define LTC_ALIGN(n)
#else
+ #define LTC_ALIGN_MSVC(n)
#define LTC_ALIGN(n)
#endif
@@ -375,8 +391,10 @@ typedef unsigned long ltc_mp_digit;
#if defined(__clang__) || defined(__GNUC__)
#define LTC_GCM_PCLMUL_TARGET __attribute__((target("pclmul,ssse3")))
+#define LTC_SHA_TARGET __attribute__((__target__("sse2,ssse3,sse4.1,sha")))
#else
#define LTC_GCM_PCLMUL_TARGET
+#define LTC_SHA_TARGET
#endif
#if !defined(LTC_NO_GCM_PMULL) && (defined(__aarch64__) || defined(_M_ARM64))
diff --git a/src/headers/tomcrypt_hash.h b/src/headers/tomcrypt_hash.h
index 9996245a8..a6bd75028 100644
--- a/src/headers/tomcrypt_hash.h
+++ b/src/headers/tomcrypt_hash.h
@@ -37,16 +37,18 @@ struct sha512_state {
#ifdef LTC_SHA256
struct sha256_state {
ulong64 length;
- ulong32 state[8], curlen;
+ ulong32 *state, curlen;
unsigned char buf[64];
+ unsigned char state_buf[LTC_ALIGNED_BUF_SIZE(ulong32, 8, 16)];
};
#endif
#ifdef LTC_SHA1
struct sha1_state {
ulong64 length;
- ulong32 state[5], curlen;
+ ulong32 *state, curlen;
unsigned char buf[64];
+ unsigned char state_buf[LTC_ALIGNED_BUF_SIZE(ulong32, 5, 16)];
};
#endif
@@ -174,7 +176,7 @@ typedef union Hash_state {
struct sha256_state sha256;
#endif
#ifdef LTC_SHA1
- struct sha1_state sha1;
+ struct sha1_state sha1;
#endif
#ifdef LTC_MD5
struct md5_state md5;
@@ -360,7 +362,7 @@ int sha512_256_init(hash_state * md);
int sha512_256_done(hash_state * md, unsigned char *out);
int sha512_256_test(void);
extern const struct ltc_hash_descriptor sha512_256_desc;
-#endif
+#endif /* LTC_SHA512_256 */
#ifdef LTC_SHA512_224
#ifndef LTC_SHA512
@@ -371,7 +373,7 @@ int sha512_224_init(hash_state * md);
int sha512_224_done(hash_state * md, unsigned char *out);
int sha512_224_test(void);
extern const struct ltc_hash_descriptor sha512_224_desc;
-#endif
+#endif /* LTC_SHA512_224 */
#ifdef LTC_SHA256
int sha256_init(hash_state * md);
@@ -380,6 +382,21 @@ int sha256_done(hash_state * md, unsigned char *out);
int sha256_test(void);
extern const struct ltc_hash_descriptor sha256_desc;
+int sha256_c_init(hash_state * md);
+int sha256_c_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int sha256_c_done(hash_state * md, unsigned char *out);
+int sha256_c_test(void);
+extern const struct ltc_hash_descriptor sha256_portable_desc;
+
+#ifdef LTC_SHA256_X86
+int sha256_x86_init(hash_state * md);
+int sha256_x86_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int sha256_x86_done(hash_state * md, unsigned char *out);
+int sha256_x86_test(void);
+extern const struct ltc_hash_descriptor sha256_x86_desc;
+#endif /* LTC_SHA256_X86 */
+#endif /* LTC_SHA256 */
+
#ifdef LTC_SHA224
#ifndef LTC_SHA256
#error LTC_SHA256 is required for LTC_SHA224
@@ -389,8 +406,21 @@ int sha224_init(hash_state * md);
int sha224_done(hash_state * md, unsigned char *out);
int sha224_test(void);
extern const struct ltc_hash_descriptor sha224_desc;
-#endif
-#endif
+
+int sha224_c_init(hash_state * md);
+#define sha224_c_process sha256_c_process
+int sha224_c_done(hash_state * md, unsigned char *out);
+int sha224_c_test(void);
+extern const struct ltc_hash_descriptor sha224_portable_desc;
+
+#ifdef LTC_SHA224_X86
+int sha224_x86_init(hash_state * md);
+#define sha224_x86_process sha256_x86_process
+int sha224_x86_done(hash_state * md, unsigned char *out);
+int sha224_x86_test(void);
+extern const struct ltc_hash_descriptor sha224_x86_desc;
+#endif /* LTC_SHA224_X86 */
+#endif /* LTC_SHA224 */
#ifdef LTC_SHA1
int sha1_init(hash_state * md);
@@ -398,7 +428,21 @@ int sha1_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int sha1_done(hash_state * md, unsigned char *out);
int sha1_test(void);
extern const struct ltc_hash_descriptor sha1_desc;
-#endif
+
+int sha1_c_init(hash_state * md);
+int sha1_c_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int sha1_c_done(hash_state * md, unsigned char *out);
+int sha1_c_test(void);
+extern const struct ltc_hash_descriptor sha1_portable_desc;
+
+#ifdef LTC_SHA1_X86
+int sha1_x86_init(hash_state * md);
+int sha1_x86_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int sha1_x86_done(hash_state * md, unsigned char *out);
+int sha1_x86_test(void);
+extern const struct ltc_hash_descriptor sha1_x86_desc;
+#endif /* LTC_SHA1_X86 */
+#endif /* LTC_SHA1 */
#ifdef LTC_BLAKE2S
extern const struct ltc_hash_descriptor blake2s_256_desc;
diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h
index 1414c333f..1658cca7a 100644
--- a/src/headers/tomcrypt_private.h
+++ b/src/headers/tomcrypt_private.h
@@ -182,6 +182,15 @@ int func_name (hash_state * md, const unsigned char *in, unsigned long inlen)
return CRYPT_OK; \
}
+#ifdef LTC_SHA1
+int sha1_test_desc(const struct ltc_hash_descriptor *desc, const char *name);
+#endif
+#ifdef LTC_SHA224
+int sha224_test_desc(const struct ltc_hash_descriptor *desc, const char *name);
+#endif
+#ifdef LTC_SHA256
+int sha256_test_desc(const struct ltc_hash_descriptor *desc, const char *name);
+#endif
/* tomcrypt_mac.h */
diff --git a/src/misc/crypt/crypt.c b/src/misc/crypt/crypt.c
index 085e3346c..ccef4a0c7 100644
--- a/src/misc/crypt/crypt.c
+++ b/src/misc/crypt/crypt.c
@@ -502,6 +502,15 @@ const char *crypt_build_settings =
#if defined(LTC_PEM_SSH)
" OpenSSH-PEM "
#endif
+#if defined(LTC_SHA1_X86)
+ " SHA1-NI "
+#endif
+#if defined(LTC_SHA224_X86)
+ " SHA224-NI "
+#endif
+#if defined(LTC_SHA256_X86)
+ " SHA256-NI "
+#endif
#if defined(LTC_DEVRANDOM)
" LTC_DEVRANDOM "
#endif
diff --git a/src/misc/crypt/crypt_register_all_hashes.c b/src/misc/crypt/crypt_register_all_hashes.c
index 93d32fc34..91f1cadb1 100644
--- a/src/misc/crypt/crypt_register_all_hashes.c
+++ b/src/misc/crypt/crypt_register_all_hashes.c
@@ -19,6 +19,9 @@ int register_all_hashes(void)
REGISTER_HASH(&sha512_desc);
#endif
#ifdef LTC_SHA256
+ /* `sha256_desc` does the multiplexing into `sha256_x86_desc` resp. `sha256_portable_desc`
+ * depending on the capabilities of the CPU.
+ */
REGISTER_HASH(&sha256_desc);
#endif
#ifdef LTC_SHA3
@@ -34,12 +37,18 @@ int register_all_hashes(void)
REGISTER_HASH(&sha512_224_desc);
#endif
#ifdef LTC_SHA224
+ /* `sha224_desc` does the multiplexing into `sha224_x86_desc` resp. `sha224_portable_desc`
+ * depending on the capabilities of the CPU.
+ */
REGISTER_HASH(&sha224_desc);
#endif
#ifdef LTC_SHA384
REGISTER_HASH(&sha384_desc);
#endif
#ifdef LTC_SHA1
+ /* `sha1_desc` does the multiplexing into `sha1_x86_desc` resp. `sha1_portable_desc`
+ * depending on the capabilities of the CPU.
+ */
REGISTER_HASH(&sha1_desc);
#endif
#ifdef LTC_MD5
diff --git a/tests/test.c b/tests/test.c
index a26604ec4..8eb7d7d0b 100644
--- a/tests/test.c
+++ b/tests/test.c
@@ -204,12 +204,24 @@ static void s_unregister_all(void)
unregister_hash(&md5_desc);
#endif
#ifdef LTC_SHA1
+ /* `register_all_hashes()` does not register
+ * - `sha1_portable_desc`
+ * - `sha1_x86_desc`
+ * so we don't have to unregister them */
unregister_hash(&sha1_desc);
#endif
#ifdef LTC_SHA224
+ /* `register_all_hashes()` does not register
+ * - `sha224_portable_desc`
+ * - `sha224_x86_desc`
+ * so we don't have to unregister them */
unregister_hash(&sha224_desc);
#endif
#ifdef LTC_SHA256
+ /* `register_all_hashes()` does not register
+ * - `sha256_portable_desc`
+ * - `sha256_x86_desc`
+ * so we don't have to unregister them */
unregister_hash(&sha256_desc);
#endif
#ifdef LTC_SHA384