summaryrefslogtreecommitdiff
path: root/plugins/MirOTR/Libgcrypt/cipher/sha1.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/MirOTR/Libgcrypt/cipher/sha1.c')
-rw-r--r--plugins/MirOTR/Libgcrypt/cipher/sha1.c264
1 files changed, 124 insertions, 140 deletions
diff --git a/plugins/MirOTR/Libgcrypt/cipher/sha1.c b/plugins/MirOTR/Libgcrypt/cipher/sha1.c
index 67cbaff3b3..2e0b030c31 100644
--- a/plugins/MirOTR/Libgcrypt/cipher/sha1.c
+++ b/plugins/MirOTR/Libgcrypt/cipher/sha1.c
@@ -32,17 +32,25 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#ifdef HAVE_STDINT_H
+#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include "g10lib.h"
-#include "memory.h"
#include "bithelp.h"
+#include "bufhelp.h"
#include "cipher.h"
#include "hash-common.h"
+/* USE_SSSE3 indicates whether to compile with Intel SSSE3 code. */
+#undef USE_SSSE3
+#if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && \
+ defined(HAVE_GCC_INLINE_ASM_SSSE3)
+# define USE_SSSE3 1
+#endif
+
+
/* A macro to test whether P is properly aligned for an u32 type.
Note that config.h provides a suitable replacement for uintptr_t if
it does not exist in stdint.h. */
@@ -52,31 +60,41 @@
/* # define U32_ALIGNED_P(p) (!(((uintptr_t)p) % sizeof (u32))) */
/* #endif */
-#define TRANSFORM(x,d,n) transform ((x), (d), (n))
-
-
-typedef struct
+typedef struct
{
+ gcry_md_block_ctx_t bctx;
u32 h0,h1,h2,h3,h4;
- u32 nblocks;
- unsigned char buf[64];
- int count;
+#ifdef USE_SSSE3
+ unsigned int use_ssse3:1;
+#endif
} SHA1_CONTEXT;
+static unsigned int
+transform (void *c, const unsigned char *data);
static void
-mir_sha1_init (void *context)
+sha1_init (void *context, unsigned int flags)
{
SHA1_CONTEXT *hd = context;
+ (void)flags;
+
hd->h0 = 0x67452301;
hd->h1 = 0xefcdab89;
hd->h2 = 0x98badcfe;
hd->h3 = 0x10325476;
hd->h4 = 0xc3d2e1f0;
- hd->nblocks = 0;
- hd->count = 0;
+
+ hd->bctx.nblocks = 0;
+ hd->bctx.nblocks_high = 0;
+ hd->bctx.count = 0;
+ hd->bctx.blocksize = 64;
+ hd->bctx.bwrite = transform;
+
+#ifdef USE_SSSE3
+ hd->use_ssse3 = (_gcry_get_hw_features () & HWF_INTEL_SSSE3) != 0;
+#endif
}
@@ -105,33 +123,17 @@ mir_sha1_init (void *context)
/*
* Transform NBLOCKS of each 64 bytes (16 32-bit words) at DATA.
*/
-static void
-transform (SHA1_CONTEXT *hd, const unsigned char *data, size_t nblocks)
+static unsigned int
+_transform (void *ctx, const unsigned char *data)
{
+ SHA1_CONTEXT *hd = ctx;
+ const u32 *idata = (const void *)data;
register u32 a, b, c, d, e; /* Local copies of the chaining variables. */
register u32 tm; /* Helper. */
u32 x[16]; /* The array we work on. */
-
- /* Loop over all blocks. */
- for ( ;nblocks; nblocks--)
- {
-#ifdef WORDS_BIGENDIAN
- memcpy (x, data, 64);
- data += 64;
-#else
- {
- int i;
- unsigned char *p;
-
- for(i=0, p=(unsigned char*)x; i < 16; i++, p += 4 )
- {
- p[3] = *data++;
- p[2] = *data++;
- p[1] = *data++;
- p[0] = *data++;
- }
- }
-#endif
+
+#define I(i) (x[i] = buf_get_be32(idata + i))
+
/* Get the values of the chaining variables. */
a = hd->h0;
b = hd->h1;
@@ -140,22 +142,22 @@ transform (SHA1_CONTEXT *hd, const unsigned char *data, size_t nblocks)
e = hd->h4;
/* Transform. */
- R( a, b, c, d, e, F1, K1, x[ 0] );
- R( e, a, b, c, d, F1, K1, x[ 1] );
- R( d, e, a, b, c, F1, K1, x[ 2] );
- R( c, d, e, a, b, F1, K1, x[ 3] );
- R( b, c, d, e, a, F1, K1, x[ 4] );
- R( a, b, c, d, e, F1, K1, x[ 5] );
- R( e, a, b, c, d, F1, K1, x[ 6] );
- R( d, e, a, b, c, F1, K1, x[ 7] );
- R( c, d, e, a, b, F1, K1, x[ 8] );
- R( b, c, d, e, a, F1, K1, x[ 9] );
- R( a, b, c, d, e, F1, K1, x[10] );
- R( e, a, b, c, d, F1, K1, x[11] );
- R( d, e, a, b, c, F1, K1, x[12] );
- R( c, d, e, a, b, F1, K1, x[13] );
- R( b, c, d, e, a, F1, K1, x[14] );
- R( a, b, c, d, e, F1, K1, x[15] );
+ R( a, b, c, d, e, F1, K1, I( 0) );
+ R( e, a, b, c, d, F1, K1, I( 1) );
+ R( d, e, a, b, c, F1, K1, I( 2) );
+ R( c, d, e, a, b, F1, K1, I( 3) );
+ R( b, c, d, e, a, F1, K1, I( 4) );
+ R( a, b, c, d, e, F1, K1, I( 5) );
+ R( e, a, b, c, d, F1, K1, I( 6) );
+ R( d, e, a, b, c, F1, K1, I( 7) );
+ R( c, d, e, a, b, F1, K1, I( 8) );
+ R( b, c, d, e, a, F1, K1, I( 9) );
+ R( a, b, c, d, e, F1, K1, I(10) );
+ R( e, a, b, c, d, F1, K1, I(11) );
+ R( d, e, a, b, c, F1, K1, I(12) );
+ R( c, d, e, a, b, F1, K1, I(13) );
+ R( b, c, d, e, a, F1, K1, I(14) );
+ R( a, b, c, d, e, F1, K1, I(15) );
R( e, a, b, c, d, F1, K1, M(16) );
R( d, e, a, b, c, F1, K1, M(17) );
R( c, d, e, a, b, F1, K1, M(18) );
@@ -227,53 +229,29 @@ transform (SHA1_CONTEXT *hd, const unsigned char *data, size_t nblocks)
hd->h2 += c;
hd->h3 += d;
hd->h4 += e;
- }
+
+ return /* burn_stack */ 88+4*sizeof(void*);
}
-/* Update the message digest with the contents
- * of INBUF with length INLEN.
- */
-static void
-sha1_write( void *context, const void *inbuf_arg, size_t inlen)
-{
- const unsigned char *inbuf = inbuf_arg;
- SHA1_CONTEXT *hd = context;
- size_t nblocks;
+#ifdef USE_SSSE3
+unsigned int
+_gcry_sha1_transform_amd64_ssse3 (void *state, const unsigned char *data);
+#endif
- if (hd->count == 64) /* Flush the buffer. */
- {
- TRANSFORM( hd, hd->buf, 1 );
- _gcry_burn_stack (88+4*sizeof(void*));
- hd->count = 0;
- hd->nblocks++;
- }
- if (!inbuf)
- return;
- if (hd->count)
- {
- for (; inlen && hd->count < 64; inlen--)
- hd->buf[hd->count++] = *inbuf++;
- sha1_write (hd, NULL, 0);
- if (!inlen)
- return;
- }
+static unsigned int
+transform (void *ctx, const unsigned char *data)
+{
+ SHA1_CONTEXT *hd = ctx;
- nblocks = inlen / 64;
- if (nblocks)
- {
- TRANSFORM (hd, inbuf, nblocks);
- hd->count = 0;
- hd->nblocks += nblocks;
- inlen -= nblocks * 64;
- inbuf += nblocks * 64;
- }
- _gcry_burn_stack (88+4*sizeof(void*));
+#ifdef USE_SSSE3
+ if (hd->use_ssse3)
+ return _gcry_sha1_transform_amd64_ssse3 (&hd->h0, data)
+ + 4 * sizeof(void*);
+#endif
- /* Save remaining bytes. */
- for (; inlen && hd->count < 64; inlen--)
- hd->buf[hd->count++] = *inbuf++;
+ return _transform (hd, data);
}
@@ -288,19 +266,24 @@ static void
sha1_final(void *context)
{
SHA1_CONTEXT *hd = context;
-
- u32 t, msb, lsb;
+ u32 t, th, msb, lsb;
unsigned char *p;
+ unsigned int burn;
- sha1_write(hd, NULL, 0); /* flush */;
+ _gcry_md_block_write (hd, NULL, 0); /* flush */;
+
+ t = hd->bctx.nblocks;
+ if (sizeof t == sizeof hd->bctx.nblocks)
+ th = hd->bctx.nblocks_high;
+ else
+ th = hd->bctx.nblocks >> 32;
- t = hd->nblocks;
/* multiply by 64 to make a byte count */
lsb = t << 6;
- msb = t >> 26;
+ msb = (th << 6) | (t >> 26);
/* add the count */
t = lsb;
- if( (lsb += hd->count) < t )
+ if( (lsb += hd->bctx.count) < t )
msb++;
/* multiply by 8 to make a bit count */
t = lsb;
@@ -308,39 +291,28 @@ sha1_final(void *context)
msb <<= 3;
msb |= t >> 29;
- if( hd->count < 56 ) /* enough room */
+ if( hd->bctx.count < 56 ) /* enough room */
{
- hd->buf[hd->count++] = 0x80; /* pad */
- while( hd->count < 56 )
- hd->buf[hd->count++] = 0; /* pad */
+ hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
+ while( hd->bctx.count < 56 )
+ hd->bctx.buf[hd->bctx.count++] = 0; /* pad */
}
else /* need one extra block */
{
- hd->buf[hd->count++] = 0x80; /* pad character */
- while( hd->count < 64 )
- hd->buf[hd->count++] = 0;
- sha1_write(hd, NULL, 0); /* flush */;
- memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+ hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
+ while( hd->bctx.count < 64 )
+ hd->bctx.buf[hd->bctx.count++] = 0;
+ _gcry_md_block_write(hd, NULL, 0); /* flush */;
+ memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
}
/* append the 64 bit count */
- hd->buf[56] = msb >> 24;
- hd->buf[57] = msb >> 16;
- hd->buf[58] = msb >> 8;
- hd->buf[59] = msb ;
- hd->buf[60] = lsb >> 24;
- hd->buf[61] = lsb >> 16;
- hd->buf[62] = lsb >> 8;
- hd->buf[63] = lsb ;
- TRANSFORM( hd, hd->buf, 1 );
- _gcry_burn_stack (88+4*sizeof(void*));
-
- p = hd->buf;
-#ifdef WORDS_BIGENDIAN
-#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
-#else /* little endian */
-#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \
- *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0)
-#endif
+ buf_put_be32(hd->bctx.buf + 56, msb);
+ buf_put_be32(hd->bctx.buf + 60, lsb);
+ burn = transform( hd, hd->bctx.buf );
+ _gcry_burn_stack (burn);
+
+ p = hd->bctx.buf;
+#define X(a) do { *(u32*)p = be_bswap32(hd->h##a) ; p += 4; } while(0)
X(0);
X(1);
X(2);
@@ -355,7 +327,7 @@ sha1_read( void *context )
{
SHA1_CONTEXT *hd = context;
- return hd->buf;
+ return hd->bctx.buf;
}
/****************
@@ -367,15 +339,30 @@ _gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length)
{
SHA1_CONTEXT hd;
- mir_sha1_init (&hd);
- sha1_write (&hd, buffer, length);
+ sha1_init (&hd, 0);
+ _gcry_md_block_write (&hd, buffer, length);
+ sha1_final (&hd);
+ memcpy (outbuf, hd.bctx.buf, 20);
+}
+
+
+/* Variant of the above shortcut function using a multiple buffers. */
+void
+_gcry_sha1_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt)
+{
+ SHA1_CONTEXT hd;
+
+ sha1_init (&hd, 0);
+ for (;iovcnt > 0; iov++, iovcnt--)
+ _gcry_md_block_write (&hd,
+ (const char*)iov[0].data + iov[0].off, iov[0].len);
sha1_final (&hd);
- memcpy (outbuf, hd.buf, 20);
+ memcpy (outbuf, hd.bctx.buf, 20);
}
-/*
+/*
Self-test section.
*/
@@ -385,10 +372,10 @@ selftests_sha1 (int extended, selftest_report_func_t report)
{
const char *what;
const char *errtxt;
-
+
what = "short string";
errtxt = _gcry_hash_selftest_check_one
- (GCRY_MD_SHA1, 0,
+ (GCRY_MD_SHA1, 0,
"abc", 3,
"\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E"
"\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D", 20);
@@ -399,13 +386,13 @@ selftests_sha1 (int extended, selftest_report_func_t report)
{
what = "long string";
errtxt = _gcry_hash_selftest_check_one
- (GCRY_MD_SHA1, 0,
+ (GCRY_MD_SHA1, 0,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
"\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE"
"\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1", 20);
if (errtxt)
goto failed;
-
+
what = "one million \"a\"";
errtxt = _gcry_hash_selftest_check_one
(GCRY_MD_SHA1, 1,
@@ -439,7 +426,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
default:
ec = GPG_ERR_DIGEST_ALGO;
break;
-
+
}
return ec;
}
@@ -468,12 +455,9 @@ static gcry_md_oid_spec_t oid_spec_sha1[] =
gcry_md_spec_t _gcry_digest_spec_sha1 =
{
+ GCRY_MD_SHA1, {0, 1},
"SHA1", asn, DIM (asn), oid_spec_sha1, 20,
- mir_sha1_init, sha1_write, sha1_final, sha1_read,
- sizeof (SHA1_CONTEXT)
- };
-md_extra_spec_t _gcry_digest_extraspec_sha1 =
- {
+ sha1_init, _gcry_md_block_write, sha1_final, sha1_read,
+ sizeof (SHA1_CONTEXT),
run_selftests
};
-