Add x86-optimized SHA1.

This commit is contained in:
Marek Knápek 2026-04-10 21:45:00 +02:00 committed by Steffen Jaeckel
parent 68aae28a9d
commit 7ac05df902
9 changed files with 521 additions and 53 deletions

View file

@ -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

175
src/hashes/sha1_desc.c Normal file
View file

@ -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

287
src/hashes/sha1_x86.c Normal file
View file

@ -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 <intrin.h>
#endif
#include <emmintrin.h> /* 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 <tmmintrin.h> /* SSSE3 _mm_shuffle_epi8 */
#include <smmintrin.h> /* SSE4.1 _mm_extract_epi32 */
#include <immintrin.h> /* 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

View file

@ -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))

View file

@ -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;

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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