Skip to content

Commit adef5dc

Browse files
committed
Add optional openssl accelerated versions of hash functions, loosely based on
a patch from Elliott Hughes, who said: [PATCH] Add support for libcrypto for MD5/SHA. Orders of magnitude faster (for architectures where OpenSSL/BoringSSL has optimized assembler). Also adds sha224sum, sha256sum, sha384sum, and sha512sum for folks building with libcrypto. The fallback portable C implementations could easily be refactored to be API-compatible, but I don't know whether they'd stay here or move to lib/ so I've left that part alone for now.
1 parent fff20ab commit adef5dc

File tree

4 files changed

+121
-22
lines changed

4 files changed

+121
-22
lines changed

Config.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ config TOYBOX_SMACK
6262

6363
endchoice
6464

65+
config TOYBOX_LIBCRYPTO
66+
bool "Use libcrypto (OpenSSL/BoringSSL)"
67+
default n
68+
help
69+
Use faster hash functions out of exteral -lcrypto library.
70+
6571
config TOYBOX_FLOAT
6672
bool "Floating point support"
6773
default y

scripts/make.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ then
103103
# for it.
104104

105105
> generated/optlibs.dat
106-
for i in util crypt m resolv selinux smack attr rt
106+
for i in util crypt m resolv selinux smack attr rt crypto
107107
do
108108
echo "int main(int argc, char *argv[]) {return 0;}" | \
109109
${CROSS_COMPILE}${CC} $CFLAGS -xc - -o generated/libprobe -Wl,--as-needed -l$i > /dev/null 2>/dev/null &&

scripts/mkflags.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ int main(int argc, char *argv[])
122122

123123
for (;;) {
124124
struct flag *flist, *aflist, *offlist;
125-
char *gaps, *mgaps, c;
125+
char *mgaps;
126126
unsigned bit;
127127

128128
*command = *flags = *allflags = 0;
@@ -142,14 +142,9 @@ int main(int argc, char *argv[])
142142
bit = 0;
143143
printf("// %s %s %s\n", command, flags, allflags);
144144
mgaps = mark_gaps(flags, allflags);
145-
for (gaps = mgaps; *gaps == 1; gaps++);
146-
if (*gaps) c = '"';
147-
else {
148-
c = ' ';
149-
gaps = "0";
150-
}
151-
printf("#undef OPTSTR_%s\n#define OPTSTR_%s %c%s%c\n",
152-
command, command, c, gaps, c);
145+
// If command disabled, use allflags for OLDTOY()
146+
printf("#undef OPTSTR_%s\n#define OPTSTR_%s \"%s\"\n",
147+
command, command, strcmp(flags, " ") ? mgaps : allflags);
153148
free(mgaps);
154149

155150
flist = digest(flags);

toys/lsb/md5sum.c

Lines changed: 110 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,19 @@
66
* and http://www.ietf.org/rfc/rfc1321.txt
77
*
88
* They're combined this way to share infrastructure, and because md5sum is
9-
* and LSB standard command, sha1sum is just a good idea.
9+
* and LSB standard command (but sha1sum and newer hashes are a good idea,
10+
* see http://valerieaurora.org/hash.html).
11+
*
12+
* We optionally use openssl (or equivalent) to access assembly optimized
13+
* versions of these functions, but provide a built-in version to reduce
14+
* required dependencies.
1015
1116
USE_MD5SUM(NEWTOY(md5sum, "bc*[!bc]", TOYFLAG_USR|TOYFLAG_BIN))
1217
USE_SHA1SUM(NEWTOY(sha1sum, "bc*[!bc]", TOYFLAG_USR|TOYFLAG_BIN))
18+
USE_SHA224SUM(OLDTOY(sha224sum, sha1sum, TOYFLAG_USR|TOYFLAG_BIN))
19+
USE_SHA256SUM(OLDTOY(sha256sum, sha1sum, TOYFLAG_USR|TOYFLAG_BIN))
20+
USE_SHA384SUM(OLDTOY(sha384sum, sha1sum, TOYFLAG_USR|TOYFLAG_BIN))
21+
USE_SHA512SUM(OLDTOY(sha512sum, sha1sum, TOYFLAG_USR|TOYFLAG_BIN))
1322
1423
config MD5SUM
1524
bool "md5sum"
@@ -18,8 +27,7 @@ config MD5SUM
1827
usage: md5sum [-b] [-c FILE] [FILE]...
1928
2029
Calculate md5 hash for each input file, reading from stdin if none.
21-
Output one hash (16 hex digits) for each input file, followed by
22-
filename.
30+
Output one hash (32 hex digits) for each input file, followed by filename.
2331
2432
-b brief (hash only, no filename)
2533
-c Check each line of FILE is the same hash+filename we'd output.
@@ -28,19 +36,56 @@ config SHA1SUM
2836
bool "sha1sum"
2937
default y
3038
help
31-
usage: sha1sum [-b] [-c FILE] [FILE]...
39+
usage: sha?sum [-b] [-c FILE] [FILE]...
3240
33-
calculate sha1 hash for each input file, reading from stdin if none.
34-
Output one hash (20 hex digits) for each input file, followed by
35-
filename.
41+
calculate sha hash for each input file, reading from stdin if none. Output
42+
one hash (40 hex digits for sha1, 56 for sha224, 64 for sha256, 96 for sha384,
43+
and 128 for sha512) for each input file, followed by filename.
3644
3745
-b brief (hash only, no filename)
3846
-c Check each line of FILE is the same hash+filename we'd output.
47+
48+
config SHA224SUM
49+
bool "sha224sum"
50+
default y
51+
depends on TOYBOX_LIBCRYPTO
52+
help
53+
See sha1sum
54+
55+
config SHA256SUM
56+
bool "sha256sum"
57+
default y
58+
depends on TOYBOX_LIBCRYPTO
59+
help
60+
See sha1sum
61+
62+
config SHA384SUM
63+
bool "sha384sum"
64+
default y
65+
depends on TOYBOX_LIBCRYPTO
66+
help
67+
See sha1sum
68+
69+
config SHA512SUM
70+
bool "sha512sum"
71+
default y
72+
depends on TOYBOX_LIBCRYPTO
73+
help
74+
See sha1sum
3975
*/
4076

77+
#define FORCE_FLAGS
4178
#define FOR_md5sum
4279
#include "toys.h"
4380

81+
#if CFG_TOYBOX_LIBCRYPTO
82+
#include <openssl/md5.h>
83+
#include <openssl/sha.h>
84+
#else
85+
typedef int MD5_CTX;
86+
typedef int SHA_CTX;
87+
#endif
88+
4489
GLOBALS(
4590
struct arg_list *c;
4691

@@ -192,12 +237,58 @@ static void hash_update(char *data, unsigned int len, void (*transform)(void))
192237
}
193238
}
194239

240+
// Initialize array tersely
241+
#define HASH_INIT(name, prefix) { name, (void *)prefix##_Init, \
242+
(void *)prefix##_Update, (void *)prefix##_Final, \
243+
prefix##_DIGEST_LENGTH, }
244+
#define SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH
245+
246+
// Call the assembly optimized library code when CFG_TOYBOX_LIBCRYPTO
247+
static void do_lib_hash(int fd, char *name)
248+
{
249+
// Largest context
250+
SHA512_CTX ctx;
251+
struct hash {
252+
char *name;
253+
int (*init)(void *);
254+
int (*update)(void *, void *, size_t);
255+
int (*final)(void *, void *);
256+
int digest_length;
257+
} algorithms[] = {
258+
USE_TOYBOX_LIBCRYPTO(
259+
USE_MD5SUM(HASH_INIT("md5sum", MD5),)
260+
USE_SHA1SUM(HASH_INIT("sha1sum", SHA1),)
261+
USE_SHA224SUM(HASH_INIT("sha224sum", SHA224),)
262+
USE_SHA256SUM(HASH_INIT("sha256sum", SHA256),)
263+
USE_SHA384SUM(HASH_INIT("sha384sum", SHA384),)
264+
USE_SHA512SUM(HASH_INIT("sha512sum", SHA512),)
265+
)
266+
}, * hash;
267+
int i;
268+
269+
// This should never NOT match, so no need to check
270+
for (i = 0; i<ARRAY_LEN(algorithms); i++)
271+
if (!strcmp(toys.which->name, algorithms[i].name)) break;
272+
hash = algorithms+i;
273+
274+
hash->init(&ctx);
275+
for (;;) {
276+
i = read(fd, toybuf, sizeof(toybuf));
277+
if (i<1) break;
278+
hash->update(&ctx, toybuf, i);
279+
}
280+
hash->final(toybuf+128, &ctx);
281+
282+
for (i = 0; i<hash->digest_length; i++)
283+
sprintf(toybuf+2*i, "%02x", toybuf[i+128]);
284+
}
285+
195286
// Callback for loopfiles()
196287

197-
static void do_hash(int fd, char *name)
288+
static void do_builtin_hash(int fd, char *name)
198289
{
199290
uint64_t count;
200-
int i, sha1=toys.which->name[0]=='s';;
291+
int i, sha1=toys.which->name[0]=='s';
201292
char buf;
202293
void (*transform)(void);
203294

@@ -238,15 +329,22 @@ static void do_hash(int fd, char *name)
238329
sprintf(toybuf+2*i, "%02x", 255&(TT.state[i>>2] >> ((3-(i & 3)) * 8)));
239330
else for (i=0; i<4; i++) sprintf(toybuf+8*i, "%08x", bswap_32(TT.state[i]));
240331

241-
if (name)
242-
printf((toys.optflags & FLAG_b) ? "%s\n" : "%s %s\n", toybuf, name);
243-
244332
// Wipe variables. Cryptographer paranoia.
245333
memset(TT.state, 0, sizeof(TT)-((long)TT.state-(long)&TT));
246334
i = strlen(toybuf)+1;
247335
memset(toybuf+i, 0, sizeof(toybuf)-i);
248336
}
249337

338+
// Call builtin or lib hash function, then display output if necessary
339+
static void do_hash(int fd, char *name)
340+
{
341+
if (CFG_TOYBOX_LIBCRYPTO) do_lib_hash(fd, name);
342+
else do_builtin_hash(fd,name);
343+
344+
if (name)
345+
printf((toys.optflags & FLAG_b) ? "%s\n" : "%s %s\n", toybuf, name);
346+
}
347+
250348
static int do_c(char *line, size_t len)
251349
{
252350
int space = 0, fail = 0;

0 commit comments

Comments
 (0)