hash_md5_sha: use common finalization routine for MD5 and sha1/256. -15 bytes
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
This commit is contained in:
parent
b5aa1d95a1
commit
c48a5c607d
@ -1515,35 +1515,14 @@ enum {
|
|||||||
};
|
};
|
||||||
void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags);
|
void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags);
|
||||||
|
|
||||||
typedef struct sha1_ctx_t {
|
|
||||||
uint32_t hash[8]; /* 5, +3 elements for sha256 */
|
|
||||||
uint64_t total64; /* must be directly after hash[] */
|
|
||||||
uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */
|
|
||||||
void (*process_block)(struct sha1_ctx_t*) FAST_FUNC;
|
|
||||||
} sha1_ctx_t;
|
|
||||||
void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC;
|
|
||||||
void sha1_hash(sha1_ctx_t *ctx, const void *data, size_t length) FAST_FUNC;
|
|
||||||
void sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC;
|
|
||||||
typedef struct sha1_ctx_t sha256_ctx_t;
|
|
||||||
void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC;
|
|
||||||
#define sha256_hash sha1_hash
|
|
||||||
#define sha256_end sha1_end
|
|
||||||
typedef struct sha512_ctx_t {
|
|
||||||
uint64_t hash[8];
|
|
||||||
uint64_t total64[2]; /* must be directly after hash[] */
|
|
||||||
uint8_t wbuffer[128]; /* NB: always correctly aligned for uint64_t */
|
|
||||||
} sha512_ctx_t;
|
|
||||||
void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC;
|
|
||||||
void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
|
|
||||||
void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC;
|
|
||||||
#if 1
|
#if 1
|
||||||
typedef struct md5_ctx_t {
|
typedef struct md5_ctx_t {
|
||||||
|
char wbuffer[64]; /* NB: always correctly aligned for uint64_t */
|
||||||
|
uint64_t total64;
|
||||||
uint32_t A;
|
uint32_t A;
|
||||||
uint32_t B;
|
uint32_t B;
|
||||||
uint32_t C;
|
uint32_t C;
|
||||||
uint32_t D;
|
uint32_t D;
|
||||||
uint64_t total64;
|
|
||||||
char wbuffer[64]; /* NB: always correctly aligned for uint64_t */
|
|
||||||
} md5_ctx_t;
|
} md5_ctx_t;
|
||||||
#else
|
#else
|
||||||
/* libbb/md5prime.c uses a bit different one: */
|
/* libbb/md5prime.c uses a bit different one: */
|
||||||
@ -1556,6 +1535,27 @@ typedef struct md5_ctx_t {
|
|||||||
void md5_begin(md5_ctx_t *ctx) FAST_FUNC;
|
void md5_begin(md5_ctx_t *ctx) FAST_FUNC;
|
||||||
void md5_hash(md5_ctx_t *ctx, const void *data, size_t length) FAST_FUNC;
|
void md5_hash(md5_ctx_t *ctx, const void *data, size_t length) FAST_FUNC;
|
||||||
void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC;
|
void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC;
|
||||||
|
typedef struct sha1_ctx_t {
|
||||||
|
uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */
|
||||||
|
uint64_t total64; /* must be directly before hash[] */
|
||||||
|
uint32_t hash[8]; /* 5, +3 elements for sha256 */
|
||||||
|
void (*process_block)(struct sha1_ctx_t*) FAST_FUNC;
|
||||||
|
} sha1_ctx_t;
|
||||||
|
void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC;
|
||||||
|
void sha1_hash(sha1_ctx_t *ctx, const void *data, size_t length) FAST_FUNC;
|
||||||
|
void sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC;
|
||||||
|
typedef struct sha1_ctx_t sha256_ctx_t;
|
||||||
|
void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC;
|
||||||
|
#define sha256_hash sha1_hash
|
||||||
|
#define sha256_end sha1_end
|
||||||
|
typedef struct sha512_ctx_t {
|
||||||
|
uint64_t total64[2]; /* must be directly before hash[] */
|
||||||
|
uint64_t hash[8];
|
||||||
|
uint8_t wbuffer[128]; /* NB: always correctly aligned for uint64_t */
|
||||||
|
} sha512_ctx_t;
|
||||||
|
void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC;
|
||||||
|
void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
|
||||||
|
void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC;
|
||||||
|
|
||||||
|
|
||||||
uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC;
|
uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC;
|
||||||
|
@ -1,4 +1,72 @@
|
|||||||
/* vi: set sw=4 ts=4: */
|
/* vi: set sw=4 ts=4: */
|
||||||
|
/*
|
||||||
|
* Utility routines.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Denys Vlasenko
|
||||||
|
*
|
||||||
|
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libbb.h"
|
||||||
|
|
||||||
|
/* gcc 4.2.1 optimizes rotr64 better with inline than with macro
|
||||||
|
* (for rotX32, there is no difference). Why? My guess is that
|
||||||
|
* macro requires clever common subexpression elimination heuristics
|
||||||
|
* in gcc, while inline basically forces it to happen.
|
||||||
|
*/
|
||||||
|
//#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||||
|
static ALWAYS_INLINE uint32_t rotl32(uint32_t x, unsigned n)
|
||||||
|
{
|
||||||
|
return (x << n) | (x >> (32 - n));
|
||||||
|
}
|
||||||
|
//#define rotr32(x,n) (((x) >> (n)) | ((x) << (32 - (n))))
|
||||||
|
static ALWAYS_INLINE uint32_t rotr32(uint32_t x, unsigned n)
|
||||||
|
{
|
||||||
|
return (x >> n) | (x << (32 - n));
|
||||||
|
}
|
||||||
|
/* rotr64 in needed for sha512 only: */
|
||||||
|
//#define rotr64(x,n) (((x) >> (n)) | ((x) << (64 - (n))))
|
||||||
|
static ALWAYS_INLINE uint64_t rotr64(uint64_t x, unsigned n)
|
||||||
|
{
|
||||||
|
return (x >> n) | (x << (64 - n));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct common64_ctx_t {
|
||||||
|
char wbuffer[64]; /* NB: always correctly aligned for uint64_t */
|
||||||
|
uint64_t total64;
|
||||||
|
} common64_ctx_t;
|
||||||
|
|
||||||
|
typedef void FAST_FUNC process_block64_func(void*);
|
||||||
|
|
||||||
|
static void FAST_FUNC common64_end(void *vctx, process_block64_func process_block64, int swap_needed)
|
||||||
|
{
|
||||||
|
common64_ctx_t *ctx = vctx;
|
||||||
|
unsigned bufpos = ctx->total64 & 63;
|
||||||
|
/* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */
|
||||||
|
ctx->wbuffer[bufpos++] = 0x80;
|
||||||
|
|
||||||
|
/* This loop iterates either once or twice, no more, no less */
|
||||||
|
while (1) {
|
||||||
|
unsigned remaining = 64 - bufpos;
|
||||||
|
memset(ctx->wbuffer + bufpos, 0, remaining);
|
||||||
|
/* Do we have enough space for the length count? */
|
||||||
|
if (remaining >= 8) {
|
||||||
|
/* Store the 64-bit counter of bits in the buffer */
|
||||||
|
uint64_t t = ctx->total64 << 3;
|
||||||
|
if (swap_needed)
|
||||||
|
t = bb_bswap_64(t);
|
||||||
|
/* wbuffer is suitably aligned for this */
|
||||||
|
*(uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
|
||||||
|
}
|
||||||
|
process_block64(ctx);
|
||||||
|
if (remaining >= 8)
|
||||||
|
break;
|
||||||
|
bufpos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Based on shasum from http://www.netsw.org/crypto/hash/
|
* Based on shasum from http://www.netsw.org/crypto/hash/
|
||||||
* Majorly hacked up to use Dr Brian Gladman's sha1 code
|
* Majorly hacked up to use Dr Brian Gladman's sha1 code
|
||||||
@ -28,31 +96,6 @@
|
|||||||
* then rebuild and compare "shaNNNsum bigfile" results.
|
* then rebuild and compare "shaNNNsum bigfile" results.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libbb.h"
|
|
||||||
|
|
||||||
/* gcc 4.2.1 optimizes rotr64 better with inline than with macro
|
|
||||||
* (for rotX32, there is no difference). Why? My guess is that
|
|
||||||
* macro requires clever common subexpression elimination heuristics
|
|
||||||
* in gcc, while inline basically forces it to happen.
|
|
||||||
*/
|
|
||||||
//#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n))))
|
|
||||||
static ALWAYS_INLINE uint32_t rotl32(uint32_t x, unsigned n)
|
|
||||||
{
|
|
||||||
return (x << n) | (x >> (32 - n));
|
|
||||||
}
|
|
||||||
//#define rotr32(x,n) (((x) >> (n)) | ((x) << (32 - (n))))
|
|
||||||
static ALWAYS_INLINE uint32_t rotr32(uint32_t x, unsigned n)
|
|
||||||
{
|
|
||||||
return (x >> n) | (x << (32 - n));
|
|
||||||
}
|
|
||||||
/* rotr64 in needed for sha512 only: */
|
|
||||||
//#define rotr64(x,n) (((x) >> (n)) | ((x) << (64 - (n))))
|
|
||||||
static ALWAYS_INLINE uint64_t rotr64(uint64_t x, unsigned n)
|
|
||||||
{
|
|
||||||
return (x >> n) | (x << (64 - n));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx)
|
static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
unsigned t;
|
unsigned t;
|
||||||
@ -308,6 +351,8 @@ void FAST_FUNC sha1_begin(sha1_ctx_t *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const uint32_t init256[] = {
|
static const uint32_t init256[] = {
|
||||||
|
0,
|
||||||
|
0,
|
||||||
0x6a09e667,
|
0x6a09e667,
|
||||||
0xbb67ae85,
|
0xbb67ae85,
|
||||||
0x3c6ef372,
|
0x3c6ef372,
|
||||||
@ -316,10 +361,10 @@ static const uint32_t init256[] = {
|
|||||||
0x9b05688c,
|
0x9b05688c,
|
||||||
0x1f83d9ab,
|
0x1f83d9ab,
|
||||||
0x5be0cd19,
|
0x5be0cd19,
|
||||||
0,
|
|
||||||
0,
|
|
||||||
};
|
};
|
||||||
static const uint32_t init512_lo[] = {
|
static const uint32_t init512_lo[] = {
|
||||||
|
0,
|
||||||
|
0,
|
||||||
0xf3bcc908,
|
0xf3bcc908,
|
||||||
0x84caa73b,
|
0x84caa73b,
|
||||||
0xfe94f82b,
|
0xfe94f82b,
|
||||||
@ -328,16 +373,14 @@ static const uint32_t init512_lo[] = {
|
|||||||
0x2b3e6c1f,
|
0x2b3e6c1f,
|
||||||
0xfb41bd6b,
|
0xfb41bd6b,
|
||||||
0x137e2179,
|
0x137e2179,
|
||||||
0,
|
|
||||||
0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Initialize structure containing state of computation.
|
/* Initialize structure containing state of computation.
|
||||||
(FIPS 180-2:5.3.2) */
|
(FIPS 180-2:5.3.2) */
|
||||||
void FAST_FUNC sha256_begin(sha256_ctx_t *ctx)
|
void FAST_FUNC sha256_begin(sha256_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
memcpy(ctx->hash, init256, sizeof(init256));
|
memcpy(&ctx->total64, init256, sizeof(init256));
|
||||||
/*ctx->total64 = 0; - done by extending init256 with two 32-bit zeros */
|
/*ctx->total64 = 0; - done by prepending two 32-bit zeros to init256 */
|
||||||
ctx->process_block = sha256_process_block64;
|
ctx->process_block = sha256_process_block64;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,9 +389,10 @@ void FAST_FUNC sha256_begin(sha256_ctx_t *ctx)
|
|||||||
void FAST_FUNC sha512_begin(sha512_ctx_t *ctx)
|
void FAST_FUNC sha512_begin(sha512_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
/* Two extra iterations zero out ctx->total64[] */
|
/* Two extra iterations zero out ctx->total64[2] */
|
||||||
for (i = 0; i < 8+2; i++)
|
uint64_t *tp = ctx->total64;
|
||||||
ctx->hash[i] = ((uint64_t)(init256[i]) << 32) + init512_lo[i];
|
for (i = 0; i < 2+8; i++)
|
||||||
|
tp[i] = ((uint64_t)(init256[i]) << 32) + init512_lo[i];
|
||||||
/*ctx->total64[0] = ctx->total64[1] = 0; - already done */
|
/*ctx->total64[0] = ctx->total64[1] = 0; - already done */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,37 +492,19 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len)
|
|||||||
/* Used also for sha256 */
|
/* Used also for sha256 */
|
||||||
void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf)
|
void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf)
|
||||||
{
|
{
|
||||||
unsigned bufpos = ctx->total64 & 63;
|
unsigned hash_size;
|
||||||
|
|
||||||
/* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */
|
/* SHA stores total in BE, need to swap on LE arches: */
|
||||||
ctx->wbuffer[bufpos++] = 0x80;
|
common64_end(ctx, (process_block64_func*) ctx->process_block, /*swap_needed:*/ BB_LITTLE_ENDIAN);
|
||||||
|
|
||||||
/* This loop iterates either once or twice, no more, no less */
|
hash_size = (ctx->process_block == sha1_process_block64) ? 5 : 8;
|
||||||
while (1) {
|
|
||||||
unsigned remaining = 64 - bufpos;
|
|
||||||
memset(ctx->wbuffer + bufpos, 0, remaining);
|
|
||||||
/* Do we have enough space for the length count? */
|
|
||||||
if (remaining >= 8) {
|
|
||||||
/* Store the 64-bit counter of bits in the buffer in BE format */
|
|
||||||
uint64_t t = ctx->total64 << 3;
|
|
||||||
t = SWAP_BE64(t);
|
|
||||||
/* wbuffer is suitably aligned for this */
|
|
||||||
*(uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
|
|
||||||
}
|
|
||||||
ctx->process_block(ctx);
|
|
||||||
if (remaining >= 8)
|
|
||||||
break;
|
|
||||||
bufpos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bufpos = (ctx->process_block == sha1_process_block64) ? 5 : 8;
|
|
||||||
/* This way we do not impose alignment constraints on resbuf: */
|
/* This way we do not impose alignment constraints on resbuf: */
|
||||||
if (BB_LITTLE_ENDIAN) {
|
if (BB_LITTLE_ENDIAN) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i < bufpos; ++i)
|
for (i = 0; i < hash_size; ++i)
|
||||||
ctx->hash[i] = SWAP_BE32(ctx->hash[i]);
|
ctx->hash[i] = SWAP_BE32(ctx->hash[i]);
|
||||||
}
|
}
|
||||||
memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * bufpos);
|
memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * hash_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf)
|
void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf)
|
||||||
@ -566,7 +592,7 @@ void FAST_FUNC md5_begin(md5_ctx_t *ctx)
|
|||||||
#define FI(b, c, d) (c ^ (b | ~d))
|
#define FI(b, c, d) (c ^ (b | ~d))
|
||||||
|
|
||||||
/* Hash a single block, 64 bytes long and 4-byte aligned */
|
/* Hash a single block, 64 bytes long and 4-byte aligned */
|
||||||
static void md5_process_block64(md5_ctx_t *ctx)
|
static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
#if MD5_SIZE_VS_SPEED > 0
|
#if MD5_SIZE_VS_SPEED > 0
|
||||||
/* Before we start, one word to the strange constants.
|
/* Before we start, one word to the strange constants.
|
||||||
@ -927,27 +953,8 @@ void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len)
|
|||||||
*/
|
*/
|
||||||
void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf)
|
void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf)
|
||||||
{
|
{
|
||||||
unsigned bufpos = ctx->total64 & 63;
|
/* MD5 stores total in LE, need to swap on BE arches: */
|
||||||
/* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */
|
common64_end(ctx, (process_block64_func*) md5_process_block64, /*swap_needed:*/ BB_BIG_ENDIAN);
|
||||||
ctx->wbuffer[bufpos++] = 0x80;
|
|
||||||
|
|
||||||
/* This loop iterates either once or twice, no more, no less */
|
|
||||||
while (1) {
|
|
||||||
unsigned remaining = 64 - bufpos;
|
|
||||||
memset(ctx->wbuffer + bufpos, 0, remaining);
|
|
||||||
/* Do we have enough space for the length count? */
|
|
||||||
if (remaining >= 8) {
|
|
||||||
/* Store the 64-bit counter of bits in the buffer in LE format */
|
|
||||||
uint64_t t = ctx->total64 << 3;
|
|
||||||
t = SWAP_LE64(t);
|
|
||||||
/* wbuffer is suitably aligned for this */
|
|
||||||
*(uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
|
|
||||||
}
|
|
||||||
md5_process_block64(ctx);
|
|
||||||
if (remaining >= 8)
|
|
||||||
break;
|
|
||||||
bufpos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The MD5 result is in little endian byte order.
|
/* The MD5 result is in little endian byte order.
|
||||||
* We (ab)use the fact that A-D are consecutive in memory.
|
* We (ab)use the fact that A-D are consecutive in memory.
|
||||||
|
Loading…
Reference in New Issue
Block a user