aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libbb.h46
-rw-r--r--libbb/hash_md5_sha.c163
2 files changed, 108 insertions, 101 deletions
diff --git a/include/libbb.h b/include/libbb.h
index c161ed7e2..3c8764b5c 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1515,35 +1515,14 @@ enum {
1515}; 1515};
1516void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags); 1516void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags);
1517 1517
1518typedef struct sha1_ctx_t {
1519 uint32_t hash[8]; /* 5, +3 elements for sha256 */
1520 uint64_t total64; /* must be directly after hash[] */
1521 uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */
1522 void (*process_block)(struct sha1_ctx_t*) FAST_FUNC;
1523} sha1_ctx_t;
1524void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC;
1525void sha1_hash(sha1_ctx_t *ctx, const void *data, size_t length) FAST_FUNC;
1526void sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC;
1527typedef struct sha1_ctx_t sha256_ctx_t;
1528void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC;
1529#define sha256_hash sha1_hash
1530#define sha256_end sha1_end
1531typedef struct sha512_ctx_t {
1532 uint64_t hash[8];
1533 uint64_t total64[2]; /* must be directly after hash[] */
1534 uint8_t wbuffer[128]; /* NB: always correctly aligned for uint64_t */
1535} sha512_ctx_t;
1536void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC;
1537void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
1538void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC;
1539#if 1 1518#if 1
1540typedef struct md5_ctx_t { 1519typedef struct md5_ctx_t {
1520 char wbuffer[64]; /* NB: always correctly aligned for uint64_t */
1521 uint64_t total64;
1541 uint32_t A; 1522 uint32_t A;
1542 uint32_t B; 1523 uint32_t B;
1543 uint32_t C; 1524 uint32_t C;
1544 uint32_t D; 1525 uint32_t D;
1545 uint64_t total64;
1546 char wbuffer[64]; /* NB: always correctly aligned for uint64_t */
1547} md5_ctx_t; 1526} md5_ctx_t;
1548#else 1527#else
1549/* libbb/md5prime.c uses a bit different one: */ 1528/* libbb/md5prime.c uses a bit different one: */
@@ -1556,6 +1535,27 @@ typedef struct md5_ctx_t {
1556void md5_begin(md5_ctx_t *ctx) FAST_FUNC; 1535void md5_begin(md5_ctx_t *ctx) FAST_FUNC;
1557void md5_hash(md5_ctx_t *ctx, const void *data, size_t length) FAST_FUNC; 1536void md5_hash(md5_ctx_t *ctx, const void *data, size_t length) FAST_FUNC;
1558void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC; 1537void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC;
1538typedef struct sha1_ctx_t {
1539 uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */
1540 uint64_t total64; /* must be directly before hash[] */
1541 uint32_t hash[8]; /* 5, +3 elements for sha256 */
1542 void (*process_block)(struct sha1_ctx_t*) FAST_FUNC;
1543} sha1_ctx_t;
1544void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC;
1545void sha1_hash(sha1_ctx_t *ctx, const void *data, size_t length) FAST_FUNC;
1546void sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC;
1547typedef struct sha1_ctx_t sha256_ctx_t;
1548void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC;
1549#define sha256_hash sha1_hash
1550#define sha256_end sha1_end
1551typedef struct sha512_ctx_t {
1552 uint64_t total64[2]; /* must be directly before hash[] */
1553 uint64_t hash[8];
1554 uint8_t wbuffer[128]; /* NB: always correctly aligned for uint64_t */
1555} sha512_ctx_t;
1556void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC;
1557void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
1558void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC;
1559 1559
1560 1560
1561uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; 1561uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC;
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c
index 3e708ef7e..b07ba55f7 100644
--- a/libbb/hash_md5_sha.c
+++ b/libbb/hash_md5_sha.c
@@ -1,31 +1,10 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Based on shasum from http://www.netsw.org/crypto/hash/ 3 * Utility routines.
4 * Majorly hacked up to use Dr Brian Gladman's sha1 code
5 * 4 *
6 * Copyright (C) 2002 Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK. 5 * Copyright (C) 2010 Denys Vlasenko
7 * Copyright (C) 2003 Glenn L. McGrath
8 * Copyright (C) 2003 Erik Andersen
9 * 6 *
10 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
11 *
12 * ---------------------------------------------------------------------------
13 * Issue Date: 10/11/2002
14 *
15 * This is a byte oriented version of SHA1 that operates on arrays of bytes
16 * stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor
17 *
18 * ---------------------------------------------------------------------------
19 *
20 * SHA256 and SHA512 parts are:
21 * Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>.
22 * Shrank by Denys Vlasenko.
23 *
24 * ---------------------------------------------------------------------------
25 *
26 * The best way to test random blocksizes is to go to coreutils/md5_sha1_sum.c
27 * and replace "4096" with something like "2000 + time(NULL) % 2097",
28 * then rebuild and compare "shaNNNsum bigfile" results.
29 */ 8 */
30 9
31#include "libbb.h" 10#include "libbb.h"
@@ -53,6 +32,70 @@ static ALWAYS_INLINE uint64_t rotr64(uint64_t x, unsigned n)
53} 32}
54 33
55 34
35typedef struct common64_ctx_t {
36 char wbuffer[64]; /* NB: always correctly aligned for uint64_t */
37 uint64_t total64;
38} common64_ctx_t;
39
40typedef void FAST_FUNC process_block64_func(void*);
41
42static void FAST_FUNC common64_end(void *vctx, process_block64_func process_block64, int swap_needed)
43{
44 common64_ctx_t *ctx = vctx;
45 unsigned bufpos = ctx->total64 & 63;
46 /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */
47 ctx->wbuffer[bufpos++] = 0x80;
48
49 /* This loop iterates either once or twice, no more, no less */
50 while (1) {
51 unsigned remaining = 64 - bufpos;
52 memset(ctx->wbuffer + bufpos, 0, remaining);
53 /* Do we have enough space for the length count? */
54 if (remaining >= 8) {
55 /* Store the 64-bit counter of bits in the buffer */
56 uint64_t t = ctx->total64 << 3;
57 if (swap_needed)
58 t = bb_bswap_64(t);
59 /* wbuffer is suitably aligned for this */
60 *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
61 }
62 process_block64(ctx);
63 if (remaining >= 8)
64 break;
65 bufpos = 0;
66 }
67}
68
69
70/*
71 * Based on shasum from http://www.netsw.org/crypto/hash/
72 * Majorly hacked up to use Dr Brian Gladman's sha1 code
73 *
74 * Copyright (C) 2002 Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
75 * Copyright (C) 2003 Glenn L. McGrath
76 * Copyright (C) 2003 Erik Andersen
77 *
78 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
79 *
80 * ---------------------------------------------------------------------------
81 * Issue Date: 10/11/2002
82 *
83 * This is a byte oriented version of SHA1 that operates on arrays of bytes
84 * stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor
85 *
86 * ---------------------------------------------------------------------------
87 *
88 * SHA256 and SHA512 parts are:
89 * Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>.
90 * Shrank by Denys Vlasenko.
91 *
92 * ---------------------------------------------------------------------------
93 *
94 * The best way to test random blocksizes is to go to coreutils/md5_sha1_sum.c
95 * and replace "4096" with something like "2000 + time(NULL) % 2097",
96 * then rebuild and compare "shaNNNsum bigfile" results.
97 */
98
56static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx) 99static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx)
57{ 100{
58 unsigned t; 101 unsigned t;
@@ -308,6 +351,8 @@ void FAST_FUNC sha1_begin(sha1_ctx_t *ctx)
308} 351}
309 352
310static const uint32_t init256[] = { 353static const uint32_t init256[] = {
354 0,
355 0,
311 0x6a09e667, 356 0x6a09e667,
312 0xbb67ae85, 357 0xbb67ae85,
313 0x3c6ef372, 358 0x3c6ef372,
@@ -316,10 +361,10 @@ static const uint32_t init256[] = {
316 0x9b05688c, 361 0x9b05688c,
317 0x1f83d9ab, 362 0x1f83d9ab,
318 0x5be0cd19, 363 0x5be0cd19,
319 0,
320 0,
321}; 364};
322static const uint32_t init512_lo[] = { 365static const uint32_t init512_lo[] = {
366 0,
367 0,
323 0xf3bcc908, 368 0xf3bcc908,
324 0x84caa73b, 369 0x84caa73b,
325 0xfe94f82b, 370 0xfe94f82b,
@@ -328,16 +373,14 @@ static const uint32_t init512_lo[] = {
328 0x2b3e6c1f, 373 0x2b3e6c1f,
329 0xfb41bd6b, 374 0xfb41bd6b,
330 0x137e2179, 375 0x137e2179,
331 0,
332 0,
333}; 376};
334 377
335/* Initialize structure containing state of computation. 378/* Initialize structure containing state of computation.
336 (FIPS 180-2:5.3.2) */ 379 (FIPS 180-2:5.3.2) */
337void FAST_FUNC sha256_begin(sha256_ctx_t *ctx) 380void FAST_FUNC sha256_begin(sha256_ctx_t *ctx)
338{ 381{
339 memcpy(ctx->hash, init256, sizeof(init256)); 382 memcpy(&ctx->total64, init256, sizeof(init256));
340 /*ctx->total64 = 0; - done by extending init256 with two 32-bit zeros */ 383 /*ctx->total64 = 0; - done by prepending two 32-bit zeros to init256 */
341 ctx->process_block = sha256_process_block64; 384 ctx->process_block = sha256_process_block64;
342} 385}
343 386
@@ -346,9 +389,10 @@ void FAST_FUNC sha256_begin(sha256_ctx_t *ctx)
346void FAST_FUNC sha512_begin(sha512_ctx_t *ctx) 389void FAST_FUNC sha512_begin(sha512_ctx_t *ctx)
347{ 390{
348 int i; 391 int i;
349 /* Two extra iterations zero out ctx->total64[] */ 392 /* Two extra iterations zero out ctx->total64[2] */
350 for (i = 0; i < 8+2; i++) 393 uint64_t *tp = ctx->total64;
351 ctx->hash[i] = ((uint64_t)(init256[i]) << 32) + init512_lo[i]; 394 for (i = 0; i < 2+8; i++)
395 tp[i] = ((uint64_t)(init256[i]) << 32) + init512_lo[i];
352 /*ctx->total64[0] = ctx->total64[1] = 0; - already done */ 396 /*ctx->total64[0] = ctx->total64[1] = 0; - already done */
353} 397}
354 398
@@ -448,37 +492,19 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len)
448/* Used also for sha256 */ 492/* Used also for sha256 */
449void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) 493void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf)
450{ 494{
451 unsigned bufpos = ctx->total64 & 63; 495 unsigned hash_size;
452 496
453 /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ 497 /* SHA stores total in BE, need to swap on LE arches: */
454 ctx->wbuffer[bufpos++] = 0x80; 498 common64_end(ctx, (process_block64_func*) ctx->process_block, /*swap_needed:*/ BB_LITTLE_ENDIAN);
455 499
456 /* This loop iterates either once or twice, no more, no less */ 500 hash_size = (ctx->process_block == sha1_process_block64) ? 5 : 8;
457 while (1) {
458 unsigned remaining = 64 - bufpos;
459 memset(ctx->wbuffer + bufpos, 0, remaining);
460 /* Do we have enough space for the length count? */
461 if (remaining >= 8) {
462 /* Store the 64-bit counter of bits in the buffer in BE format */
463 uint64_t t = ctx->total64 << 3;
464 t = SWAP_BE64(t);
465 /* wbuffer is suitably aligned for this */
466 *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
467 }
468 ctx->process_block(ctx);
469 if (remaining >= 8)
470 break;
471 bufpos = 0;
472 }
473
474 bufpos = (ctx->process_block == sha1_process_block64) ? 5 : 8;
475 /* This way we do not impose alignment constraints on resbuf: */ 501 /* This way we do not impose alignment constraints on resbuf: */
476 if (BB_LITTLE_ENDIAN) { 502 if (BB_LITTLE_ENDIAN) {
477 unsigned i; 503 unsigned i;
478 for (i = 0; i < bufpos; ++i) 504 for (i = 0; i < hash_size; ++i)
479 ctx->hash[i] = SWAP_BE32(ctx->hash[i]); 505 ctx->hash[i] = SWAP_BE32(ctx->hash[i]);
480 } 506 }
481 memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * bufpos); 507 memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * hash_size);
482} 508}
483 509
484void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) 510void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf)
@@ -566,7 +592,7 @@ void FAST_FUNC md5_begin(md5_ctx_t *ctx)
566#define FI(b, c, d) (c ^ (b | ~d)) 592#define FI(b, c, d) (c ^ (b | ~d))
567 593
568/* Hash a single block, 64 bytes long and 4-byte aligned */ 594/* Hash a single block, 64 bytes long and 4-byte aligned */
569static void md5_process_block64(md5_ctx_t *ctx) 595static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx)
570{ 596{
571#if MD5_SIZE_VS_SPEED > 0 597#if MD5_SIZE_VS_SPEED > 0
572 /* Before we start, one word to the strange constants. 598 /* 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)
927 */ 953 */
928void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) 954void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf)
929{ 955{
930 unsigned bufpos = ctx->total64 & 63; 956 /* MD5 stores total in LE, need to swap on BE arches: */
931 /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ 957 common64_end(ctx, (process_block64_func*) md5_process_block64, /*swap_needed:*/ BB_BIG_ENDIAN);
932 ctx->wbuffer[bufpos++] = 0x80;
933
934 /* This loop iterates either once or twice, no more, no less */
935 while (1) {
936 unsigned remaining = 64 - bufpos;
937 memset(ctx->wbuffer + bufpos, 0, remaining);
938 /* Do we have enough space for the length count? */
939 if (remaining >= 8) {
940 /* Store the 64-bit counter of bits in the buffer in LE format */
941 uint64_t t = ctx->total64 << 3;
942 t = SWAP_LE64(t);
943 /* wbuffer is suitably aligned for this */
944 *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
945 }
946 md5_process_block64(ctx);
947 if (remaining >= 8)
948 break;
949 bufpos = 0;
950 }
951 958
952 /* The MD5 result is in little endian byte order. 959 /* The MD5 result is in little endian byte order.
953 * We (ab)use the fact that A-D are consecutive in memory. 960 * We (ab)use the fact that A-D are consecutive in memory.