diff --git a/src/hashes/sha1.c b/src/hashes/sha1.c index 38920965..72ef692d 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 00000000..5f9bcc4d --- /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 00000000..8f65665d --- /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/headers/tomcrypt_cfg.h b/src/headers/tomcrypt_cfg.h index 8875ee18..e874b340 100644 --- a/src/headers/tomcrypt_cfg.h +++ b/src/headers/tomcrypt_cfg.h @@ -307,8 +307,13 @@ 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 #endif #if defined(__GNUC__) @@ -375,8 +380,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 9996245a..ee31b028 100644 --- a/src/headers/tomcrypt_hash.h +++ b/src/headers/tomcrypt_hash.h @@ -45,8 +45,9 @@ struct sha256_state { #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 +175,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; @@ -398,7 +399,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 1414c333..b118d9d9 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -182,6 +182,9 @@ 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 /* tomcrypt_mac.h */ diff --git a/src/misc/crypt/crypt.c b/src/misc/crypt/crypt.c index 085e3346..01bdad6f 100644 --- a/src/misc/crypt/crypt.c +++ b/src/misc/crypt/crypt.c @@ -502,6 +502,9 @@ const char *crypt_build_settings = #if defined(LTC_PEM_SSH) " OpenSSH-PEM " #endif +#if defined(LTC_SHA1_X86) + " SHA1-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 93d32fc3..00a89ede 100644 --- a/src/misc/crypt/crypt_register_all_hashes.c +++ b/src/misc/crypt/crypt_register_all_hashes.c @@ -40,6 +40,9 @@ int register_all_hashes(void) 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 a26604ec..1fc5b1b9 100644 --- a/tests/test.c +++ b/tests/test.c @@ -204,6 +204,10 @@ 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