diff options
Diffstat (limited to 'src/Crypto/Whirlpool.c')
-rw-r--r-- | src/Crypto/Whirlpool.c | 78 |
1 files changed, 49 insertions, 29 deletions
diff --git a/src/Crypto/Whirlpool.c b/src/Crypto/Whirlpool.c index 308f4812..140c7c6f 100644 --- a/src/Crypto/Whirlpool.c +++ b/src/Crypto/Whirlpool.c @@ -642,13 +642,27 @@ static const uint64 Whirlpool_C[8*256+R] = { // Whirlpool basic transformation. Transforms state based on block. void WhirlpoolTransform(uint64 *digest, const uint64 *block) { #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE +#if defined(__GNUC__) && (CRYPTOPP_GCC_VERSION <= 40407) + /* workaround for gcc 4.4.7 bug under CentOS which causes crash + * in inline assembly. + * This dummy check that is always false since "block" is aligned. + */ + uint64 lb = (uint64) block; + if (lb % 16) + { + TC_THROW_FATAL_EXCEPTION; + } +#endif +#endif + +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE if (HasISSE()) { #ifdef __GNUC__ #if CRYPTOPP_BOOL_X64 - uint64 workspace[16]; + CRYPTOPP_ALIGN_DATA(16) uint64 workspace[16]; #endif __asm__ __volatile__ ( INTEL_NOPREFIX @@ -879,9 +893,9 @@ static uint64 HashMultipleBlocks(WHIRLPOOL_CTX * const ctx, const uint64 *input, { #if BYTE_ORDER == BIG_ENDIAN WhirlpoolTransform(ctx->state, input); #else - CorrectEndianess(dataBuf, input, 64); + CorrectEndianness(dataBuf, input, 64); WhirlpoolTransform(ctx->state, dataBuf); #endif input += 8; length -= 64; @@ -921,9 +935,9 @@ void WHIRLPOOL_add(const unsigned char * input, return; else { uint64* dataBuf = ctx->data; - byte* data = (byte *)dataBuf; + uint8* data = (uint8 *)dataBuf; num = oldCountLo & 63; if (num != 0) // process left over data { @@ -932,9 +946,8 @@ void WHIRLPOOL_add(const unsigned char * input, memcpy(data+num, input, (size_t) (64-num)); HashMultipleBlocks(ctx, dataBuf, 64); input += (64-num); len -= (64-num); - num = 0; // drop through and do the rest } else { @@ -943,30 +956,37 @@ void WHIRLPOOL_add(const unsigned char * input, } } // now process the input data in blocks of 64 bytes and save the leftovers to ctx->data - if (len >= 64) - { - if (input == data) - { - HashMultipleBlocks(ctx, dataBuf, 64); - return; - } - else if (IsAligned16(input)) - { - uint64 leftOver = HashMultipleBlocks(ctx, (uint64 *)input, len); - input += (len - leftOver); - len = leftOver; - } - else - do - { // copy input first if it's not aligned correctly - memcpy(data, input, 64); - HashMultipleBlocks(ctx, dataBuf, 64); - input+=64; - len-=64; - } while (len >= 64); - } + if (len >= 64) + { + if (input == data) + { + HashMultipleBlocks(ctx, dataBuf, 64); + return; + } + else + { +#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS + if (IsAligned16(input)) +#endif + { + uint64 leftOver = HashMultipleBlocks(ctx, (uint64*)input, len); + input += (len - leftOver); + len = leftOver; + } +#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS + else + do + { // copy input first if it's not aligned correctly + memcpy(data, input, 64); + HashMultipleBlocks(ctx, dataBuf, 64); + input += 64; + len -= 64; + } while (len >= 64); +#endif + } + } if (len && data != input) memcpy(data, input, (size_t) len); } @@ -982,9 +1002,9 @@ void WHIRLPOOL_finalize(WHIRLPOOL_CTX * const ctx, { unsigned int num = ctx->countLo & 63; uint64* dataBuf = ctx->data; uint64* stateBuf = ctx->state; - byte* data = (byte *)dataBuf; + uint8* data = (uint8 *)dataBuf; data[num++] = 0x80; if (num <= 32) memset(data+num, 0, 32-num); @@ -994,9 +1014,9 @@ void WHIRLPOOL_finalize(WHIRLPOOL_CTX * const ctx, HashMultipleBlocks(ctx, dataBuf, 64); memset(data, 0, 32); } #if BYTE_ORDER == LITTLE_ENDIAN - CorrectEndianess(dataBuf, dataBuf, 32); + CorrectEndianness(dataBuf, dataBuf, 32); #endif dataBuf[4] = 0; dataBuf[5] = 0; @@ -1004,8 +1024,8 @@ void WHIRLPOOL_finalize(WHIRLPOOL_CTX * const ctx, dataBuf[7] = ctx->countLo << 3; WhirlpoolTransform(stateBuf, dataBuf); #if BYTE_ORDER == LITTLE_ENDIAN - CorrectEndianess(stateBuf, stateBuf, 64); + CorrectEndianness(stateBuf, stateBuf, 64); #endif memcpy(result, stateBuf, 64); } |