A faster c implementation of SHA1 for most platforms. Bug 285932.

r=wtchang     Modified Files: prng_fips1861.c sha_fast.c sha_fast.h
This commit is contained in:
nelsonb%netscape.com 2005-08-11 01:01:08 +00:00
Родитель 4f66f6debc
Коммит 22fdd8ffba
3 изменённых файлов: 133 добавлений и 165 удалений

Просмотреть файл

@ -35,7 +35,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: prng_fips1861.c,v 1.18 2005-08-06 07:10:34 nelsonb%netscape.com Exp $ */
/* $Id: prng_fips1861.c,v 1.19 2005-08-11 01:01:08 nelsonb%netscape.com Exp $ */
#include "prerr.h"
#include "secerr.h"
@ -441,7 +441,7 @@ RNG_UpdateAndEnd_FIPS186_1(SHA1Context *ctx,
unsigned char *hashout, unsigned int *pDigestLen,
unsigned int maxDigestLen)
{
#if defined(IS_LITTLE_ENDIAN)
#if defined(SHA_NEED_TMP_VARIABLE)
register PRUint32 tmp;
#endif
static const unsigned char bulk_pad0[64] = { 0,0,0,0,0,0,0,0,0,0,
@ -465,20 +465,8 @@ RNG_UpdateAndEnd_FIPS186_1(SHA1Context *ctx,
/*
* Output hash
*/
#if defined(IS_LITTLE_ENDIAN)
SHA_BYTESWAP(ctx->H[0]);
SHA_BYTESWAP(ctx->H[1]);
SHA_BYTESWAP(ctx->H[2]);
SHA_BYTESWAP(ctx->H[3]);
SHA_BYTESWAP(ctx->H[4]);
#endif
memcpy(hashout, ctx->H, SHA1_LENGTH);
SHA_STORE_RESULT;
*pDigestLen = SHA1_LENGTH;
/*
* Re-initialize the context (also zeroizes contents)
*/
SHA1_Begin(ctx);
}
/*

Просмотреть файл

@ -37,85 +37,17 @@
#include "blapi.h"
#include "sha_fast.h"
#include "prerror.h"
#include "prlong.h"
#ifdef TRACING_SSL
#include "ssl.h"
#include "ssltrace.h"
#endif
#if defined(_MSC_VER) && defined(_X86_)
#if defined(IS_LITTLE_ENDIAN)
#undef SHA_HTONL
#ifndef FORCEINLINE
#if (MSC_VER >= 1200)
#define FORCEINLINE __forceinline
#else
#define FORCEINLINE __inline
#endif
#endif
#define FASTCALL __fastcall
static FORCEINLINE PRUint32 FASTCALL
swap4b(PRUint32 dwd)
{
__asm {
mov eax,dwd
bswap eax
}
}
#define SHA_HTONL(x) swap4b(x)
#endif /* IS_LITTLE_ENDIAN */
#pragma intrinsic (_lrotr, _lrotl)
#define SHA_ROTL(x,n) _lrotl(x,n)
#define SHA_ROTL_IS_DEFINED 1
#endif /* _MSC_VER */
static void shaCompress(volatile SHA_HW_t *X, const PRUint32 * datain);
#define W u.w
#define B u.b
#if defined(_X86_) || defined(_x86) || defined(__x86_64__) || defined(__x86_64)
#define SHA_ALLOW_UNALIGNED_ACCESS 1
#endif
#if defined(__GNUC__)
/* __x86_64__ and __x86_64 are defined on x86_64 CPUs */
#if SHA1_USING_64_bit
static __inline__ uint64 SHA_ROTL(uint64 x, uint32 n)
{
uint32 t = (uint32)x;
return ((t << n) | (t >> (32 - n)));
}
#else
static __inline__ uint32 SHA_ROTL(uint32 t, uint32 n)
{
return ((t << n) | (t >> (32 - n)));
}
#endif
#define SHA_ROTL_IS_DEFINED 1
#if defined(_X86_) || defined(_x86) || defined(__x86_64__) || defined(__x86_64)
static __inline__ uint32 swap4b(uint32 value)
{
__asm__("bswap %0" : "+r" (value));
return (value);
}
#undef SHA_HTONL
#define SHA_HTONL(x) swap4b(x)
#endif /* x86 family */
#endif /* __GNUC__ */
#if !defined(SHA_ROTL_IS_DEFINED)
/* calling function must define PRUint32 tmp; */
#define SHA_ROTL(X,n) (tmp = (X), ((tmp) << (n)) | ((tmp) >> (32-(n))))
#endif
#define SHA_F1(X,Y,Z) ((((Y)^(Z))&(X))^(Z))
#define SHA_F2(X,Y,Z) ((X)^(Y)^(Z))
@ -125,12 +57,12 @@ static __inline__ uint32 swap4b(uint32 value)
#define SHA_MIX(n,a,b,c) XW(n) = SHA_ROTL(XW(a)^XW(b)^XW(c)^XW(n), 1)
/*
* SHA: Zeroize and initialize context
* SHA: initialize context
*/
void
SHA1_Begin(SHA1Context *ctx)
{
LL_UI2L(ctx->size, 0);
ctx->size = 0;
/*
* Initialize H with constants from FIPS180-1.
*/
@ -177,7 +109,6 @@ SHA1_Begin(SHA1Context *ctx)
#define W2X 6 /* X[0] is W[6], and W[0] is X[-6] */
#else
#define H2X 0
#define W2X UNDEFINED
#endif
/*
@ -192,16 +123,10 @@ SHA1_Update(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len)
if (!len)
return;
#ifdef HAVE_LONG_LONG
/* accumulate the byte count. */
lenB = (unsigned int)(ctx->size) & 63U;
/* accumulate the byte count. */
ctx->size += len;
#else
ctx->size.lo += len;
if (ctx->size.lo < len)
ctx->size.hi++;
#endif
/*
* Read the data into W and process blocks as they get full
@ -218,13 +143,7 @@ SHA1_Update(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len)
shaCompress(&ctx->H[H2X], ctx->W);
}
}
#if defined(SHA_ALLOW_UNALIGNED_ACCESS)
while (len >= 64U) {
len -= 64U;
shaCompress(&ctx->H[H2X], (PRUint32 *)dataIn);
dataIn += 64U;
}
#else
#if !defined(SHA_ALLOW_UNALIGNED_ACCESS)
if ((ptrdiff_t)dataIn % sizeof(PRUint32)) {
while (len >= 64U) {
memcpy(ctx->B, dataIn, 64);
@ -232,14 +151,15 @@ SHA1_Update(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len)
shaCompress(&ctx->H[H2X], ctx->W);
dataIn += 64U;
}
} else {
} else
#endif
{
while (len >= 64U) {
len -= 64U;
shaCompress(&ctx->H[H2X], (PRUint32 *)dataIn);
dataIn += 64U;
}
}
#endif
if (len) {
memcpy(ctx->B, dataIn, len);
}
@ -253,13 +173,9 @@ void
SHA1_End(SHA1Context *ctx, unsigned char *hashout,
unsigned int *pDigestLen, unsigned int maxDigestLen)
{
#ifdef HAVE_LONG_LONG
register PRUint64 size;
register PRUint32 lenB;
#else
register PRUint32 lenB;
PRUint64 size;
#endif
static const unsigned char bulk_pad[64] = { 0x80,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
@ -272,69 +188,23 @@ SHA1_End(SHA1Context *ctx, unsigned char *hashout,
*/
size = ctx->size;
#ifdef HAVE_LONG_LONG
lenB = size & 63;
#else
lenB = size.lo & 63;
#endif
lenB = (PRUint32)size & 63;
SHA1_Update(ctx, bulk_pad, (((55+64) - lenB) & 63) + 1);
#ifdef HAVE_LONG_LONG
PORT_Assert((ctx->size & 63) == 56);
PORT_Assert(((PRUint32)ctx->size & 63) == 56);
/* Convert size from bytes to bits. */
size <<= 3;
ctx->W[14] = SHA_HTONL(size >> 32);
ctx->W[14] = SHA_HTONL((PRUint32)(size >> 32));
ctx->W[15] = SHA_HTONL((PRUint32)size);
#else
PORT_Assert((ctx->size.lo & 63) == 56);
/* Convert size from bytes to bits. */
ctx->W[14] = SHA_HTONL((size.lo >> 29) | (size.hi << 3));
ctx->W[15] = SHA_HTONL(size.lo << 3);
#endif
shaCompress(&ctx->H[H2X], ctx->W);
/*
* Output hash
*/
#define STORE(n) ((uint32*)hashout)[n] = SHA_HTONL(ctx->H[n])
#if defined(SHA_ALLOW_UNALIGNED_ACCESS)
STORE(0);
STORE(1);
STORE(2);
STORE(3);
STORE(4);
#else /* ! unaligned access */
if (!((ptrdiff_t)hashout % sizeof(PRUint32))) {
STORE(0);
STORE(1);
STORE(2);
STORE(3);
STORE(4);
} else {
#if defined(IS_LITTLE_ENDIAN) || SHA1_USING_64_bit
ctx->W[0] = SHA_HTONL(ctx->H[0]);
ctx->W[1] = SHA_HTONL(ctx->H[1]);
ctx->W[2] = SHA_HTONL(ctx->H[2]);
ctx->W[3] = SHA_HTONL(ctx->H[3]);
ctx->W[4] = SHA_HTONL(ctx->H[4]);
memcpy(hashout, ctx->W, SHA1_LENGTH);
#else /* 32-bit big-endian */
memcpy(hashout, ctx->H, SHA1_LENGTH);
#endif /* 32-bit big endian */
}
#endif /* ! unaligned access */
#undef STORE
SHA_STORE_RESULT;
*pDigestLen = SHA1_LENGTH;
/*
* Re-initialize the context (also zeroizes contents)
SHA1_Begin(ctx);
*/
}
#undef A
#undef B
#undef tmp
/*
@ -389,7 +259,7 @@ shaCompress(volatile SHA_HW_t *X, const PRUint32 *inbuf)
{
register SHA_HW_t A, B, C, D, E;
#if !defined(SHA_ROTL_IS_DEFINED)
#if defined(SHA_NEED_TMP_VARIABLE)
register PRUint32 tmp;
#endif
@ -534,10 +404,11 @@ SHA1_NewContext(void)
return cx;
}
/* Zero and free the context */
void
SHA1_DestroyContext(SHA1Context *cx, PRBool freeit)
{
/* memset(cx, 0, sizeof *cx); */
memset(cx, 0, sizeof *cx);
if (freeit) {
PORT_Free(cx);
}
@ -552,7 +423,6 @@ SHA1_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length)
SHA1_Begin(&ctx);
SHA1_Update(&ctx, src, src_length);
SHA1_End(&ctx, dest, &outLen, SHA1_LENGTH);
/* memset(&ctx, 0, sizeof ctx); */
return SECSuccess;
}
@ -592,7 +462,7 @@ SHA1_Resurrect(unsigned char *space,void *arg)
void SHA1_Clone(SHA1Context *dest, SHA1Context *src)
{
memcpy(dest, src, sizeof *dest);
memcpy(dest, src, sizeof *dest);
}
void

Просмотреть файл

@ -37,14 +37,15 @@
#ifndef _SHA_FAST_H_
#define _SHA_FAST_H_
#include "prlong.h"
#define SHA1_INPUT_LEN 64
#if defined(_LP64) && !defined(__sparc)
#if defined(IS_64) && !defined(__sparc)
typedef PRUint64 SHA_HW_t;
#define SHA1_USING_64_bit 1
#define SHA1_USING_64_BIT 1
#else
typedef PRUint32 SHA_HW_t;
#define SHA1_USING_64_bit 0
#endif
struct SHA1ContextStr {
@ -52,17 +53,126 @@ struct SHA1ContextStr {
PRUint32 w[16]; /* input buffer */
PRUint8 b[64];
} u;
PRUint64 size; /* 64-bit count of hashed bytes. */
PRUint64 size; /* count of hashed bytes. */
SHA_HW_t H[22]; /* 5 state variables, 16 tmp values, 1 extra */
};
#if defined(_MSC_VER) && defined(_X86_)
#if defined(IS_LITTLE_ENDIAN)
#ifndef FORCEINLINE
#if (_MSC_VER >= 1200)
#define FORCEINLINE __forceinline
#else
#define FORCEINLINE __inline
#endif /* _MSC_VER */
#endif /* !defined FORCEINLINE */
#define FASTCALL __fastcall
static FORCEINLINE PRUint32 FASTCALL
swap4b(PRUint32 dwd)
{
__asm {
mov eax,dwd
bswap eax
}
}
#define SHA_HTONL(x) swap4b(x)
#endif /* IS_LITTLE_ENDIAN */
#pragma intrinsic (_lrotr, _lrotl)
#define SHA_ROTL(x,n) _lrotl(x,n)
#define SHA_ROTL_IS_DEFINED 1
#endif /* _MSC_VER && _X86_ */
#if defined(__GNUC__)
/* __x86_64__ and __x86_64 are defined by GCC on x86_64 CPUs */
#if defined( SHA1_USING_64_BIT )
static __inline__ PRUint64 SHA_ROTL(PRUint64 x, PRUint32 n)
{
PRUint32 t = (PRUint32)x;
return ((t << n) | (t >> (32 - n)));
}
#else
static __inline__ PRUint32 SHA_ROTL(PRUint32 t, PRUint32 n)
{
return ((t << n) | (t >> (32 - n)));
}
#endif
#define SHA_ROTL_IS_DEFINED 1
#if defined(_X86_) || defined(__x86_64__) || defined(__x86_64)
static __inline__ PRUint32 swap4b(PRUint32 value)
{
__asm__("bswap %0" : "+r" (value));
return (value);
}
#define SHA_HTONL(x) swap4b(x)
#endif /* x86 family */
#endif /* __GNUC__ */
#if !defined(SHA_ROTL_IS_DEFINED)
#define SHA_NEED_TMP_VARIABLE 1
#define SHA_ROTL(X,n) (tmp = (X), ((tmp) << (n)) | ((tmp) >> (32-(n))))
#endif
#if defined(_X86_) || defined(__x86_64__) || defined(__x86_64)
#define SHA_ALLOW_UNALIGNED_ACCESS 1
#endif
#if !defined(SHA_HTONL)
#define SHA_MASK 0x00FF00FF
#if defined(IS_LITTLE_ENDIAN)
#undef SHA_NEED_TMP_VARIABLE
#define SHA_NEED_TMP_VARIABLE 1
#define SHA_HTONL(x) (tmp = (x), tmp = (tmp << 16) | (tmp >> 16), \
((tmp & SHA_MASK) << 8) | ((tmp >> 8) & SHA_MASK))
#else
#define SHA_HTONL(x) (x)
#endif
#endif
#define SHA_BYTESWAP(x) x = SHA_HTONL(x)
#define SHA_STORE(n) ((PRUint32*)hashout)[n] = SHA_HTONL(ctx->H[n])
#if defined(SHA_ALLOW_UNALIGNED_ACCESS)
#define SHA_STORE_RESULT \
SHA_STORE(0); \
SHA_STORE(1); \
SHA_STORE(2); \
SHA_STORE(3); \
SHA_STORE(4);
#elif defined(IS_LITTLE_ENDIAN) || defined( SHA1_USING_64_BIT )
#define SHA_STORE_RESULT \
if (!((ptrdiff_t)hashout % sizeof(PRUint32))) { \
SHA_STORE(0); \
SHA_STORE(1); \
SHA_STORE(2); \
SHA_STORE(3); \
SHA_STORE(4); \
} else { \
ctx->u.w[0] = SHA_HTONL(ctx->H[0]); \
ctx->u.w[1] = SHA_HTONL(ctx->H[1]); \
ctx->u.w[2] = SHA_HTONL(ctx->H[2]); \
ctx->u.w[3] = SHA_HTONL(ctx->H[3]); \
ctx->u.w[4] = SHA_HTONL(ctx->H[4]); \
memcpy(hashout, ctx->u.w, SHA1_LENGTH); \
}
#else
#define SHA_STORE_RESULT \
if (!((ptrdiff_t)hashout % sizeof(PRUint32))) { \
SHA_STORE(0); \
SHA_STORE(1); \
SHA_STORE(2); \
SHA_STORE(3); \
SHA_STORE(4); \
} else { \
memcpy(hashout, ctx->H, SHA1_LENGTH); \
}
#endif
#endif /* _SHA_FAST_H_ */