sha3sum: new applet
No binary (build failed)
—
(log yok)
| @@ -514,6 +514,12 @@ config SHA512SUM | |
| help | |
| Compute and check SHA512 message digest | |
| + | config SHA3SUM |
| + | bool "sha3sum" |
| + | default y |
| + | help |
| + | Compute and check SHA3 (512-bit) message digest |
| + | |
| config SLEEP | |
| bool "sleep" | |
| default y | |
| @@ -766,13 +772,13 @@ config FEATURE_HUMAN_READABLE | |
| help | |
| Allow df, du, and ls to have human readable output. | |
| - | comment "Common options for md5sum, sha1sum, sha256sum, sha512sum" |
| - | depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM |
| + | comment "Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum" |
| + | depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM || SHA3SUM |
| config FEATURE_MD5_SHA1_SUM_CHECK | |
| bool "Enable -c, -s and -w options" | |
| default y | |
| - | depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM |
| + | depends on MD5SUM || SHA1SUM || SHA256SUM || SHA512SUM || SHA3SUM |
| help | |
| Enabling the -c options allows files to be checked | |
| against pre-calculated hash values. | |
| @@ -62,6 +62,7 @@ lib-$(CONFIG_SEQ) += seq.o | |
| lib-$(CONFIG_SHA1SUM) += md5_sha1_sum.o | |
| lib-$(CONFIG_SHA256SUM) += 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_SPLIT) += split.o | |
| lib-$(CONFIG_SORT) += sort.o | |
| @@ -55,6 +55,16 @@ | |
| //usage: "\n -s Don't output anything, status code shows success" | |
| //usage: "\n -w Warn about improperly formatted checksum lines" | |
| //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" | |
| @@ -65,6 +75,7 @@ enum { | |
| HASH_MD5 = 's', /* "md5>s<um" */ | |
| HASH_SHA1 = '1', | |
| HASH_SHA256 = '2', | |
| + | HASH_SHA3 = '3', |
| HASH_SHA512 = '5', | |
| }; | |
| @@ -86,6 +97,7 @@ static uint8_t *hash_file(const char *filename) | |
| { | |
| int src_fd, hash_len, count; | |
| union _ctx_ { | |
| + | sha3_ctx_t sha3; |
| sha512_ctx_t sha512; | |
| sha256_ctx_t sha256; | |
| sha1_ctx_t sha1; | |
| @@ -124,6 +136,11 @@ static uint8_t *hash_file(const char *filename) | |
| update = (void*)sha512_hash; | |
| final = (void*)sha512_end; | |
| 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 { | |
| xfunc_die(); /* can't reach this */ | |
| } | |
| @@ -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_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_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_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)) | |
| @@ -1636,6 +1636,10 @@ typedef struct sha512_ctx_t { | |
| uint64_t hash[8]; | |
| uint8_t wbuffer[128]; /* always correctly aligned for uint64_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_hash(md5_ctx_t *ctx, const void *data, size_t length) 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_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 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; | |
| uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; | |
| @@ -205,6 +205,7 @@ | |
| #include <stdint.h> | |
| typedef int bb__aliased_int FIX_ALIASING; | |
| + | typedef long bb__aliased_long FIX_ALIASING; |
| typedef uint16_t bb__aliased_uint16_t FIX_ALIASING; | |
| typedef uint32_t bb__aliased_uint32_t FIX_ALIASING; | |
| @@ -212,7 +213,8 @@ typedef uint32_t bb__aliased_uint32_t FIX_ALIASING; | |
| * a lvalue. This makes it more likely to not swap them by mistake | |
| */ | |
| #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_unaligned32(v, u32p) ((v) = *(bb__aliased_uint32_t*)(u32p)) | |
| # 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 | |
| /* performs reasonably well (gcc usually inlines memcpy here) */ | |
| # 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_unaligned32(v, u32p) (memcpy(&(v), (u32p), 4)) | |
| # define move_to_unaligned16(u16p, v) do { \ | |
| @@ -31,6 +31,11 @@ static ALWAYS_INLINE uint64_t rotr64(uint64_t x, unsigned 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. | |
| * 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)); | |
| } | |
| + | |
| + | |
| + | /* |
| + | * 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); |
| + | } |
| @@ -0,0 +1,3 @@ | |
| + | #!/bin/sh |
| + | |
| + | . ./md5sum.tests sha3sum c29d77bc548fa2b20a04c861400a5360879c52156e2a54a3415b99a9a3123e1d5f36714a24eca8c1f05a8e2d8ba859c930d41141f64a255c6794436fc99c486a |