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