SHA-256 & SHA-224 x86

This commit is contained in:
Marek Knápek 2026-04-13 17:04:54 +02:00 committed by Steffen Jaeckel
parent 7ac05df902
commit 874e095a19
13 changed files with 883 additions and 91 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 <intrin.h>
#endif
#include <emmintrin.h> /* SSE2 _mm_load_si128 _mm_loadu_si128 _mm_store_si128 _mm_set_epi64x _mm_add_epi32 _mm_shuffle_epi32 */
#include <tmmintrin.h> /* SSSE3 _mm_alignr_epi8 _mm_shuffle_epi8 */
#include <smmintrin.h> /* SSE4.1 _mm_blend_epi16 */
#include <immintrin.h> /* 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

View file

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

View file

@ -314,11 +314,22 @@ typedef unsigned long ltc_mp_digit;
#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

View file

@ -37,8 +37,9 @@ 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
@ -361,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
@ -372,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);
@ -381,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
@ -390,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);

View file

@ -185,6 +185,12 @@ int func_name (hash_state * md, const unsigned char *in, unsigned long inlen)
#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 */

View file

@ -505,6 +505,12 @@ const char *crypt_build_settings =
#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

View file

@ -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,6 +37,9 @@ 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

View file

@ -211,9 +211,17 @@ static void s_unregister_all(void)
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