diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2010-10-18 14:48:30 +0200 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2010-10-18 14:48:30 +0200 |
commit | c48a5c607d8bdb422224a9767925a30d486a1109 (patch) | |
tree | 3d06212aaa3096fc0f5c6e36dffb3dd8ddd8fe40 | |
parent | b5aa1d95a158683d936ea41eed0513aa20ed2e74 (diff) | |
download | busybox-w32-c48a5c607d8bdb422224a9767925a30d486a1109.tar.gz busybox-w32-c48a5c607d8bdb422224a9767925a30d486a1109.tar.bz2 busybox-w32-c48a5c607d8bdb422224a9767925a30d486a1109.zip |
hash_md5_sha: use common finalization routine for MD5 and sha1/256. -15 bytes
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rw-r--r-- | include/libbb.h | 46 | ||||
-rw-r--r-- | libbb/hash_md5_sha.c | 163 |
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 | }; |
1516 | void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags); | 1516 | void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags); |
1517 | 1517 | ||
1518 | typedef 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; | ||
1524 | void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC; | ||
1525 | void sha1_hash(sha1_ctx_t *ctx, const void *data, size_t length) FAST_FUNC; | ||
1526 | void sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC; | ||
1527 | typedef struct sha1_ctx_t sha256_ctx_t; | ||
1528 | void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC; | ||
1529 | #define sha256_hash sha1_hash | ||
1530 | #define sha256_end sha1_end | ||
1531 | typedef 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; | ||
1536 | void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC; | ||
1537 | void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; | ||
1538 | void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC; | ||
1539 | #if 1 | 1518 | #if 1 |
1540 | typedef struct md5_ctx_t { | 1519 | typedef 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 { | |||
1556 | void md5_begin(md5_ctx_t *ctx) FAST_FUNC; | 1535 | void md5_begin(md5_ctx_t *ctx) FAST_FUNC; |
1557 | void md5_hash(md5_ctx_t *ctx, const void *data, size_t length) FAST_FUNC; | 1536 | void md5_hash(md5_ctx_t *ctx, const void *data, size_t length) FAST_FUNC; |
1558 | void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC; | 1537 | void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC; |
1538 | typedef 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; | ||
1544 | void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC; | ||
1545 | void sha1_hash(sha1_ctx_t *ctx, const void *data, size_t length) FAST_FUNC; | ||
1546 | void sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC; | ||
1547 | typedef struct sha1_ctx_t sha256_ctx_t; | ||
1548 | void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC; | ||
1549 | #define sha256_hash sha1_hash | ||
1550 | #define sha256_end sha1_end | ||
1551 | typedef 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; | ||
1556 | void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC; | ||
1557 | void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; | ||
1558 | void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC; | ||
1559 | 1559 | ||
1560 | 1560 | ||
1561 | uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; | 1561 | uint32_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 | ||
35 | typedef struct common64_ctx_t { | ||
36 | char wbuffer[64]; /* NB: always correctly aligned for uint64_t */ | ||
37 | uint64_t total64; | ||
38 | } common64_ctx_t; | ||
39 | |||
40 | typedef void FAST_FUNC process_block64_func(void*); | ||
41 | |||
42 | static 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 | |||
56 | static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx) | 99 | static 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 | ||
310 | static const uint32_t init256[] = { | 353 | static 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 | }; |
322 | static const uint32_t init512_lo[] = { | 365 | static 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) */ |
337 | void FAST_FUNC sha256_begin(sha256_ctx_t *ctx) | 380 | void 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) | |||
346 | void FAST_FUNC sha512_begin(sha512_ctx_t *ctx) | 389 | void 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 */ |
449 | void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) | 493 | void 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 | ||
484 | void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) | 510 | void 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 */ |
569 | static void md5_process_block64(md5_ctx_t *ctx) | 595 | static 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 | */ |
928 | void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) | 954 | void 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. |