sha3sum: new applet

function                                             old     new   delta
KeccakF                                                -     496    +496
KeccakF_RoundConstants                                 -     192    +192
sha3_hash                                              -     171    +171
sha3_end                                               -      40     +40
hash_file                                            274     299     +25
KeccakF_RotationConstants                              -      25     +25
KeccakF_PiLane                                         -      25     +25
packed_usage                                       29213   29232     +19
sha3_begin                                             -      18     +18
KeccakF_Mod5                                           -      10     +10
applet_names                                        2445    2453      +8
applet_main                                         1420    1424      +4
applet_nameofs                                       710     712      +2
------------------------------------------------------------------------------
(add/remove: 8/0 grow/shrink: 9/7 up/down: 1049/-54)         Total: ~995 bytes

Signed-off-by: Lauri Kasanen <curaga@operamail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Lauri Kasanen 2013-01-14 05:20:50 +01:00 committed by Denys Vlasenko
parent b7841cf7b9
commit b8173b603f
8 changed files with 236 additions and 4 deletions

View File

@ -514,6 +514,12 @@ config SHA512SUM
help help
Compute and check SHA512 message digest Compute and check SHA512 message digest
config SHA3SUM
bool "sha3sum"
default y
help
Compute and check SHA3 (512-bit) message digest
config SLEEP config SLEEP
bool "sleep" bool "sleep"
default y default y
@ -766,13 +772,13 @@ config FEATURE_HUMAN_READABLE
help help
Allow df, du, and ls to have human readable output. Allow df, du, and ls to have human readable output.
comment "Common options for md5sum, sha1sum, sha256sum, sha512sum" comment "Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum"
depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM || SHA3SUM
config FEATURE_MD5_SHA1_SUM_CHECK config FEATURE_MD5_SHA1_SUM_CHECK
bool "Enable -c, -s and -w options" bool "Enable -c, -s and -w options"
default y default y
depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM || SHA3SUM
help help
Enabling the -c options allows files to be checked Enabling the -c options allows files to be checked
against pre-calculated hash values. against pre-calculated hash values.

View File

@ -62,6 +62,7 @@ lib-$(CONFIG_SEQ) += seq.o
lib-$(CONFIG_SHA1SUM) += md5_sha1_sum.o lib-$(CONFIG_SHA1SUM) += md5_sha1_sum.o
lib-$(CONFIG_SHA256SUM) += md5_sha1_sum.o lib-$(CONFIG_SHA256SUM) += md5_sha1_sum.o
lib-$(CONFIG_SHA512SUM) += md5_sha1_sum.o lib-$(CONFIG_SHA512SUM) += md5_sha1_sum.o
lib-$(CONFIG_SHA3SUM) += md5_sha1_sum.o
lib-$(CONFIG_SLEEP) += sleep.o lib-$(CONFIG_SLEEP) += sleep.o
lib-$(CONFIG_SPLIT) += split.o lib-$(CONFIG_SPLIT) += split.o
lib-$(CONFIG_SORT) += sort.o lib-$(CONFIG_SORT) += sort.o

View File

@ -55,6 +55,16 @@
//usage: "\n -s Don't output anything, status code shows success" //usage: "\n -s Don't output anything, status code shows success"
//usage: "\n -w Warn about improperly formatted checksum lines" //usage: "\n -w Warn about improperly formatted checksum lines"
//usage: ) //usage: )
//usage:
//usage:#define sha3sum_trivial_usage
//usage: IF_FEATURE_MD5_SHA1_SUM_CHECK("[-c[sw]] ")"[FILE]..."
//usage:#define sha3sum_full_usage "\n\n"
//usage: "Print" IF_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA3-512 checksums"
//usage: IF_FEATURE_MD5_SHA1_SUM_CHECK( "\n"
//usage: "\n -c Check sums against list in FILEs"
//usage: "\n -s Don't output anything, status code shows success"
//usage: "\n -w Warn about improperly formatted checksum lines"
//usage: )
#include "libbb.h" #include "libbb.h"
@ -65,6 +75,7 @@ enum {
HASH_MD5 = 's', /* "md5>s<um" */ HASH_MD5 = 's', /* "md5>s<um" */
HASH_SHA1 = '1', HASH_SHA1 = '1',
HASH_SHA256 = '2', HASH_SHA256 = '2',
HASH_SHA3 = '3',
HASH_SHA512 = '5', HASH_SHA512 = '5',
}; };
@ -86,6 +97,7 @@ static uint8_t *hash_file(const char *filename)
{ {
int src_fd, hash_len, count; int src_fd, hash_len, count;
union _ctx_ { union _ctx_ {
sha3_ctx_t sha3;
sha512_ctx_t sha512; sha512_ctx_t sha512;
sha256_ctx_t sha256; sha256_ctx_t sha256;
sha1_ctx_t sha1; sha1_ctx_t sha1;
@ -124,6 +136,11 @@ static uint8_t *hash_file(const char *filename)
update = (void*)sha512_hash; update = (void*)sha512_hash;
final = (void*)sha512_end; final = (void*)sha512_end;
hash_len = 64; hash_len = 64;
} else if (ENABLE_SHA3SUM && hash_algo == HASH_SHA3) {
sha3_begin(&context.sha3);
update = (void*)sha3_hash;
final = (void*)sha3_end;
hash_len = 64;
} else { } else {
xfunc_die(); /* can't reach this */ xfunc_die(); /* can't reach this */
} }

View File

@ -328,6 +328,7 @@ IF_SETSEBOOL(APPLET(setsebool, BB_DIR_USR_SBIN, BB_SUID_DROP))
IF_SETSID(APPLET(setsid, BB_DIR_USR_BIN, BB_SUID_DROP)) IF_SETSID(APPLET(setsid, BB_DIR_USR_BIN, BB_SUID_DROP))
IF_SETUIDGID(APPLET_ODDNAME(setuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, setuidgid)) IF_SETUIDGID(APPLET_ODDNAME(setuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, setuidgid))
IF_SHA1SUM(APPLET_NOEXEC(sha1sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha1sum)) IF_SHA1SUM(APPLET_NOEXEC(sha1sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha1sum))
IF_SHA3SUM(APPLET_NOEXEC(sha3sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha3sum))
IF_SHA256SUM(APPLET_NOEXEC(sha256sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha256sum)) IF_SHA256SUM(APPLET_NOEXEC(sha256sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha256sum))
IF_SHA512SUM(APPLET_NOEXEC(sha512sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha512sum)) IF_SHA512SUM(APPLET_NOEXEC(sha512sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, sha512sum))
IF_SHOWKEY(APPLET(showkey, BB_DIR_USR_BIN, BB_SUID_DROP)) IF_SHOWKEY(APPLET(showkey, BB_DIR_USR_BIN, BB_SUID_DROP))

View File

@ -1636,6 +1636,10 @@ typedef struct sha512_ctx_t {
uint64_t hash[8]; uint64_t hash[8];
uint8_t wbuffer[128]; /* always correctly aligned for uint64_t */ uint8_t wbuffer[128]; /* always correctly aligned for uint64_t */
} sha512_ctx_t; } sha512_ctx_t;
typedef struct sha3_ctx_t {
uint64_t state[25];
unsigned bytes_queued;
} sha3_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;
@ -1648,6 +1652,9 @@ void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC;
void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC; 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_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC; void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC;
void sha3_begin(sha3_ctx_t *ctx) FAST_FUNC;
void sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
void sha3_end(sha3_ctx_t *ctx, uint8_t *resbuf) FAST_FUNC;
extern uint32_t *global_crc32_table; extern uint32_t *global_crc32_table;
uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC;

View File

@ -205,6 +205,7 @@
#include <stdint.h> #include <stdint.h>
typedef int bb__aliased_int FIX_ALIASING; typedef int bb__aliased_int FIX_ALIASING;
typedef long bb__aliased_long FIX_ALIASING;
typedef uint16_t bb__aliased_uint16_t FIX_ALIASING; typedef uint16_t bb__aliased_uint16_t FIX_ALIASING;
typedef uint32_t bb__aliased_uint32_t FIX_ALIASING; typedef uint32_t bb__aliased_uint32_t FIX_ALIASING;
@ -213,6 +214,7 @@ typedef uint32_t bb__aliased_uint32_t FIX_ALIASING;
*/ */
#if defined(i386) || defined(__x86_64__) || defined(__powerpc__) #if defined(i386) || defined(__x86_64__) || defined(__powerpc__)
# define move_from_unaligned_int(v, intp) ((v) = *(bb__aliased_int*)(intp)) # define move_from_unaligned_int(v, intp) ((v) = *(bb__aliased_int*)(intp))
# define move_from_unaligned_long(v, longp) ((v) = *(bb__aliased_long*)(longp))
# define move_from_unaligned16(v, u16p) ((v) = *(bb__aliased_uint16_t*)(u16p)) # define move_from_unaligned16(v, u16p) ((v) = *(bb__aliased_uint16_t*)(u16p))
# define move_from_unaligned32(v, u32p) ((v) = *(bb__aliased_uint32_t*)(u32p)) # define move_from_unaligned32(v, u32p) ((v) = *(bb__aliased_uint32_t*)(u32p))
# define move_to_unaligned16(u16p, v) (*(bb__aliased_uint16_t*)(u16p) = (v)) # define move_to_unaligned16(u16p, v) (*(bb__aliased_uint16_t*)(u16p) = (v))
@ -221,6 +223,7 @@ typedef uint32_t bb__aliased_uint32_t FIX_ALIASING;
#else #else
/* performs reasonably well (gcc usually inlines memcpy here) */ /* performs reasonably well (gcc usually inlines memcpy here) */
# define move_from_unaligned_int(v, intp) (memcpy(&(v), (intp), sizeof(int))) # define move_from_unaligned_int(v, intp) (memcpy(&(v), (intp), sizeof(int)))
# define move_from_unaligned_long(v, longp) (memcpy(&(v), (longp), sizeof(long)))
# define move_from_unaligned16(v, u16p) (memcpy(&(v), (u16p), 2)) # define move_from_unaligned16(v, u16p) (memcpy(&(v), (u16p), 2))
# define move_from_unaligned32(v, u32p) (memcpy(&(v), (u32p), 4)) # define move_from_unaligned32(v, u32p) (memcpy(&(v), (u32p), 4))
# define move_to_unaligned16(u16p, v) do { \ # define move_to_unaligned16(u16p, v) do { \

View File

@ -31,6 +31,11 @@ static ALWAYS_INLINE uint64_t rotr64(uint64_t x, unsigned n)
return (x >> n) | (x << (64 - n)); return (x >> n) | (x << (64 - n));
} }
/* rotl64 only used for sha3 currently */
static ALWAYS_INLINE uint64_t rotl64(uint64_t x, unsigned n)
{
return (x << n) | (x >> (64 - n));
}
/* Feed data through a temporary buffer. /* Feed data through a temporary buffer.
* The internal buffer remembers previous data until it has 64 * The internal buffer remembers previous data until it has 64
@ -896,3 +901,192 @@ void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf)
} }
memcpy(resbuf, ctx->hash, sizeof(ctx->hash)); memcpy(resbuf, ctx->hash, sizeof(ctx->hash));
} }
/*
* The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
* Michael Peeters and Gilles Van Assche. For more information, feedback or
* questions, please refer to our website: http://keccak.noekeon.org/
*
* Implementation by Ronny Van Keer,
* hereby denoted as "the implementer".
*
* To the extent possible under law, the implementer has waived all copyright
* and related or neighboring rights to the source code in this file.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* Busybox modifications (C) Lauri Kasanen, under the GPLv2.
*/
enum {
cKeccakR_SizeInBytes = 576 / 8,
cKeccakNumberOfRounds = 24,
};
static const uint64_t KeccakF_RoundConstants[cKeccakNumberOfRounds] = {
0x0000000000000001ULL,
0x0000000000008082ULL,
0x800000000000808aULL,
0x8000000080008000ULL,
0x000000000000808bULL,
0x0000000080000001ULL,
0x8000000080008081ULL,
0x8000000000008009ULL,
0x000000000000008aULL,
0x0000000000000088ULL,
0x0000000080008009ULL,
0x000000008000000aULL,
0x000000008000808bULL,
0x800000000000008bULL,
0x8000000000008089ULL,
0x8000000000008003ULL,
0x8000000000008002ULL,
0x8000000000000080ULL,
0x000000000000800aULL,
0x800000008000000aULL,
0x8000000080008081ULL,
0x8000000000008080ULL,
0x0000000080000001ULL,
0x8000000080008008ULL
};
static const uint8_t KeccakF_RotationConstants[25] = {
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62,
18, 39, 61, 20, 44
};
static const uint8_t KeccakF_PiLane[25] = {
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20,
14, 22, 9, 6, 1
};
static const uint8_t KeccakF_Mod5[10] = {
0, 1, 2, 3, 4, 0, 1, 2, 3, 4
};
static void KeccakF(uint64_t *state)
{
uint8_t x, y;
uint64_t temp;
uint64_t BC[5];
int round;
if (BB_BIG_ENDIAN) {
for (x = 0; x < 25; x++) {
state[x] = SWAP_LE64(state[x]);
}
}
for (round = 0; round < cKeccakNumberOfRounds; ++round) {
/* Theta */
for (x = 0; x < 5; ++x) {
BC[x] = state[x] ^ state[5 + x] ^ state[10 + x] ^
state[15 + x] ^ state[20 + x];
}
for (x = 0; x < 5; ++x) {
temp = BC[KeccakF_Mod5[x + 4]] ^
rotl64(BC[KeccakF_Mod5[x + 1]], 1);
for (y = 0; y <= 20; y += 5) {
state[y + x] ^= temp;
}
}
/* Rho Pi */
temp = state[1];
for (x = 0; x < 24; ++x) {
BC[0] = state[KeccakF_PiLane[x]];
state[KeccakF_PiLane[x]] =
rotl64(temp, KeccakF_RotationConstants[x]);
temp = BC[0];
}
/* Chi */
for (y = 0; y < 25; y += 5) {
BC[0] = state[y + 0];
BC[1] = state[y + 1];
BC[2] = state[y + 2];
BC[3] = state[y + 3];
BC[4] = state[y + 4];
for (x = 0; x < 5; ++x) {
state[y + x] =
BC[x] ^ ((~BC[KeccakF_Mod5[x + 1]]) &
BC[KeccakF_Mod5[x + 2]]);
}
}
/* Iota */
state[0] ^= KeccakF_RoundConstants[round];
}
if (BB_BIG_ENDIAN) {
for (x = 0; x < 25; x++) {
state[x] = SWAP_LE64(state[x]);
}
}
}
void FAST_FUNC sha3_begin(sha3_ctx_t *ctx)
{
memset(ctx, 0, sizeof(*ctx));
}
void FAST_FUNC sha3_hash(sha3_ctx_t *ctx, const void *buf, size_t bytes)
{
const uint8_t *data = buf;
/* If already data in queue, continue queuing first */
while (bytes != 0 && ctx->bytes_queued != 0) {
uint8_t *buffer = (uint8_t*)ctx->state;
buffer[ctx->bytes_queued] ^= *data++;
bytes--;
ctx->bytes_queued++;
if (ctx->bytes_queued == cKeccakR_SizeInBytes) {
KeccakF(ctx->state);
ctx->bytes_queued = 0;
}
}
/* Absorb complete blocks */
while (bytes >= cKeccakR_SizeInBytes) {
/* XOR data onto beginning of state[].
* We try to be efficient - operate on word at a time, not byte.
* Yet safe wrt unaligned access: can't just use "*(long*)data"...
*/
unsigned count = cKeccakR_SizeInBytes / sizeof(long);
long *buffer = (long*)ctx->state;
do {
long v;
move_from_unaligned_long(v, (long*)data);
*buffer++ ^= v;
data += sizeof(long);
} while (--count);
KeccakF(ctx->state);
bytes -= cKeccakR_SizeInBytes;
}
/* Queue remaining data bytes */
while (bytes != 0) {
uint8_t *buffer = (uint8_t*)ctx->state;
buffer[ctx->bytes_queued] ^= *data++;
ctx->bytes_queued++;
bytes--;
}
}
void FAST_FUNC sha3_end(sha3_ctx_t *ctx, uint8_t *hashval)
{
/* Padding */
uint8_t *buffer = (uint8_t*)ctx->state;
/* 0 is the number of bits in last, incomplete byte
* (that is, zero: we never have incomplete bytes):
*/
buffer[ctx->bytes_queued] ^= 1 << 0;
buffer[cKeccakR_SizeInBytes - 1] ^= 0x80;
KeccakF(ctx->state);
/* Output */
memcpy(hashval, ctx->state, 64);
}

3
testsuite/sha3sum.tests Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
. ./md5sum.tests sha3sum c29d77bc548fa2b20a04c861400a5360879c52156e2a54a3415b99a9a3123e1d5f36714a24eca8c1f05a8e2d8ba859c930d41141f64a255c6794436fc99c486a