diff options
author | Cem Keylan <cem@ckyln.com> | 2020-10-16 17:47:01 +0300 |
---|---|---|
committer | Cem Keylan <cem@ckyln.com> | 2020-10-16 17:47:01 +0300 |
commit | 5d69c6a2661bba0a22f3ecfd517e2e9767a38346 (patch) | |
tree | 1f479b2714e127835db7f33a3bfed4c38c52f883 /bin/md5 | |
parent | e2abcdca396661cbe0ae2ddb13d5c2b85682c13a (diff) | |
download | otools-5d69c6a2661bba0a22f3ecfd517e2e9767a38346.tar.gz |
add tools
Diffstat (limited to 'bin/md5')
-rw-r--r-- | bin/md5/CVS/Entries | 7 | ||||
-rw-r--r-- | bin/md5/CVS/Repository | 1 | ||||
-rw-r--r-- | bin/md5/CVS/Root | 1 | ||||
-rw-r--r-- | bin/md5/Makefile | 14 | ||||
-rw-r--r-- | bin/md5/cksum.1 | 191 | ||||
-rw-r--r-- | bin/md5/crc.c | 137 | ||||
-rw-r--r-- | bin/md5/crc.h | 31 | ||||
-rw-r--r-- | bin/md5/md5.1 | 142 | ||||
-rw-r--r-- | bin/md5/md5.c | 852 |
9 files changed, 1376 insertions, 0 deletions
diff --git a/bin/md5/CVS/Entries b/bin/md5/CVS/Entries new file mode 100644 index 0000000..86ca07f --- /dev/null +++ b/bin/md5/CVS/Entries @@ -0,0 +1,7 @@ +/Makefile/1.15/Wed Mar 30 06:38:40 2016// +/cksum.1/1.39/Sat Sep 3 17:01:01 2016// +/crc.c/1.5/Fri Jan 25 00:19:25 2019// +/crc.h/1.4/Fri Jan 25 00:19:25 2019// +/md5.1/1.48/Fri Jan 25 00:19:25 2019// +/md5.c/1.95/Sat May 18 16:53:39 2019// +D diff --git a/bin/md5/CVS/Repository b/bin/md5/CVS/Repository new file mode 100644 index 0000000..0c71c98 --- /dev/null +++ b/bin/md5/CVS/Repository @@ -0,0 +1 @@ +src/bin/md5 diff --git a/bin/md5/CVS/Root b/bin/md5/CVS/Root new file mode 100644 index 0000000..3811072 --- /dev/null +++ b/bin/md5/CVS/Root @@ -0,0 +1 @@ +/cvs diff --git a/bin/md5/Makefile b/bin/md5/Makefile new file mode 100644 index 0000000..c094424 --- /dev/null +++ b/bin/md5/Makefile @@ -0,0 +1,14 @@ +# $OpenBSD: Makefile,v 1.15 2016/03/30 06:38:40 jmc Exp $ + +PROG= md5 +SRCS= crc.c md5.c +MAN= cksum.1 md5.1 +LINKS= ${BINDIR}/md5 ${BINDIR}/sha1 \ + ${BINDIR}/md5 ${BINDIR}/sha256 \ + ${BINDIR}/md5 ${BINDIR}/sha512 \ + ${BINDIR}/md5 ${BINDIR}/cksum + +CPPFLAGS+= -I${.CURDIR} +COPTS+= -Wall -Wconversion -Wmissing-prototypes + +.include <bsd.prog.mk> diff --git a/bin/md5/cksum.1 b/bin/md5/cksum.1 new file mode 100644 index 0000000..af52a4a --- /dev/null +++ b/bin/md5/cksum.1 @@ -0,0 +1,191 @@ +.\" $OpenBSD: cksum.1,v 1.39 2016/09/03 17:01:01 tedu Exp $ +.\" +.\" Copyright (c) 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the Institute of Electrical and Electronics Engineers, Inc. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)cksum.1 8.2 (Berkeley) 4/28/95 +.\" +.Dd $Mdocdate: September 3 2016 $ +.Dt CKSUM 1 +.Os +.Sh NAME +.Nm cksum +.Nd display file checksums and block counts +.Sh SYNOPSIS +.Nm cksum +.Bk -words +.Op Fl bcpqrtx +.Op Fl a Ar algorithms +.Op Fl C Ar checklist +.Op Fl h Ar hashfile +.Op Fl s Ar string +.Op Ar +.Ek +.Sh DESCRIPTION +The +.Nm cksum +utility writes to the standard output a single line for each input file. +The format of this line varies with the algorithm being used as follows: +.Bl -tag -width allxothers +.It cksum +The output line consists of three whitespace separated fields: +a CRC checksum, the number of octets in the input, +and name of the file or string. +If no file name is specified, the standard input is used and no file name +is written. +.It all others +The output line consists of four whitespace separated fields: +the name of the algorithm used, the name of the file or string in +parentheses, an equals sign, and the cryptographic hash of the input. +If no file name is specified, the standard input is used and only +the cryptographic hash is output. +.El +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl a Ar algorithms +Use the specified algorithm(s) instead of the default (cksum). +Supported algorithms include cksum, md5, rmd160, sha1, +sha224, sha256, sha384, sha512/256, and sha512. +Multiple algorithms may be specified, separated by a comma or whitespace. +Additionally, multiple +.Fl a +options may be specified on the command line. +Case is ignored when matching algorithms. +The output format may be specified on a per-algorithm basis +by using a single-character suffix, e.g.\& +.Dq sha256b . +If the algorithm has a +.Sq b +suffix, the checksum will be output in base64 format. +If the algorithm has an +.Sq x +suffix, the checksum will be output in hex format. +If an algorithm with the same output format is repeated, +only the first instance is used. +Note that output format suffixes are not supported +for the cksum algorithm. +.It Fl b +Output checksums in base64 notation, not hexadecimal by +default. +A +.Sq b +or +.Sq x +suffix on the algorithm will override this default. +This option is ignored for the cksum algorithm. +.It Fl C Ar checklist +Compare the checksum of each +.Ar file +against the checksums in the +.Ar checklist . +Any specified +.Ar file +that is not listed in the +.Ar checklist +will generate an error. +.It Fl c +If this option is specified, the +.Ar file +options become checklists. +Each checklist should contain hash results in the normal format, +which will be verified against the specified paths. +Output consists of the digest used, the file name, +and an OK, FAILED, or MISSING for the result of the comparison. +This will validate any of the supported checksums. +If no file is given, stdin is used. +The +.Fl c +option may not be used in conjunction with more than a single +.Fl a +option. +.It Fl h Ar hashfile +Place the checksum into +.Ar hashfile +instead of stdout. +.It Fl p +Echoes stdin to stdout and appends the +checksum to stdout. +.It Fl q +Only print the checksum (quiet mode) or if used in conjunction with the +.Fl c +flag, only print the failed cases. +.It Fl r +Reverse the format of the hash algorithm output, making +it match the checksum output format. +.It Fl s Ar string +Prints a checksum of the given +.Ar string . +.It Fl t +Runs a built-in time trial. +Specifying +.Fl t +multiple times results in the number of rounds being multiplied +by 10 for each additional flag. +.It Fl x +Runs a built-in test script. +.El +.Pp +The default CRC used is based on the polynomial used for CRC error checking +in the networking standard +ISO/IEC 8802-3:1996. +The other available algorithms are described in their respective +man pages in section 3 of the manual. +.Sh EXIT STATUS +.Ex -std cksum +.Sh SEE ALSO +.Xr md5 1 +.Pp +The default calculation is identical to that given in pseudo-code +in the following ACM article: +.Rs +.%T "Computation of Cyclic Redundancy Checks Via Table Lookup" +.%A Dilip V. Sarwate +.%J "Communications of the ACM" +.%D "August 1988" +.Re +.Sh STANDARDS +The +.Nm +utility is compliant with the +.St -p1003.1-2008 +specification. +.Pp +All the flags are extensions to that specification. +.Sh HISTORY +The +.Nm cksum +utility appeared in +.Bx 4.4 . +.Sh CAVEATS +Do not use the cksum or md5 algorithms to verify file integrity. +An attacker can trivially produce modified payload that +has the same checksum as the original version. +Use a cryptographic checksum instead. diff --git a/bin/md5/crc.c b/bin/md5/crc.c new file mode 100644 index 0000000..19ea317 --- /dev/null +++ b/bin/md5/crc.c @@ -0,0 +1,137 @@ +/* $OpenBSD: crc.c,v 1.5 2019/01/25 00:19:25 millert Exp $ */ + +/* + * Copyright (c) 2004 Todd C. Miller <millert@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "crc.h" + +/* + * Table-driven version of the following polynomial from POSIX 1003.2: + * G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + + * x^7 + x^5 + x^4 + x^2 + x + 1 + */ +static const u_int32_t crc32tab[] = { + 0x00000000U, + 0x04c11db7U, 0x09823b6eU, 0x0d4326d9U, 0x130476dcU, 0x17c56b6bU, + 0x1a864db2U, 0x1e475005U, 0x2608edb8U, 0x22c9f00fU, 0x2f8ad6d6U, + 0x2b4bcb61U, 0x350c9b64U, 0x31cd86d3U, 0x3c8ea00aU, 0x384fbdbdU, + 0x4c11db70U, 0x48d0c6c7U, 0x4593e01eU, 0x4152fda9U, 0x5f15adacU, + 0x5bd4b01bU, 0x569796c2U, 0x52568b75U, 0x6a1936c8U, 0x6ed82b7fU, + 0x639b0da6U, 0x675a1011U, 0x791d4014U, 0x7ddc5da3U, 0x709f7b7aU, + 0x745e66cdU, 0x9823b6e0U, 0x9ce2ab57U, 0x91a18d8eU, 0x95609039U, + 0x8b27c03cU, 0x8fe6dd8bU, 0x82a5fb52U, 0x8664e6e5U, 0xbe2b5b58U, + 0xbaea46efU, 0xb7a96036U, 0xb3687d81U, 0xad2f2d84U, 0xa9ee3033U, + 0xa4ad16eaU, 0xa06c0b5dU, 0xd4326d90U, 0xd0f37027U, 0xddb056feU, + 0xd9714b49U, 0xc7361b4cU, 0xc3f706fbU, 0xceb42022U, 0xca753d95U, + 0xf23a8028U, 0xf6fb9d9fU, 0xfbb8bb46U, 0xff79a6f1U, 0xe13ef6f4U, + 0xe5ffeb43U, 0xe8bccd9aU, 0xec7dd02dU, 0x34867077U, 0x30476dc0U, + 0x3d044b19U, 0x39c556aeU, 0x278206abU, 0x23431b1cU, 0x2e003dc5U, + 0x2ac12072U, 0x128e9dcfU, 0x164f8078U, 0x1b0ca6a1U, 0x1fcdbb16U, + 0x018aeb13U, 0x054bf6a4U, 0x0808d07dU, 0x0cc9cdcaU, 0x7897ab07U, + 0x7c56b6b0U, 0x71159069U, 0x75d48ddeU, 0x6b93dddbU, 0x6f52c06cU, + 0x6211e6b5U, 0x66d0fb02U, 0x5e9f46bfU, 0x5a5e5b08U, 0x571d7dd1U, + 0x53dc6066U, 0x4d9b3063U, 0x495a2dd4U, 0x44190b0dU, 0x40d816baU, + 0xaca5c697U, 0xa864db20U, 0xa527fdf9U, 0xa1e6e04eU, 0xbfa1b04bU, + 0xbb60adfcU, 0xb6238b25U, 0xb2e29692U, 0x8aad2b2fU, 0x8e6c3698U, + 0x832f1041U, 0x87ee0df6U, 0x99a95df3U, 0x9d684044U, 0x902b669dU, + 0x94ea7b2aU, 0xe0b41de7U, 0xe4750050U, 0xe9362689U, 0xedf73b3eU, + 0xf3b06b3bU, 0xf771768cU, 0xfa325055U, 0xfef34de2U, 0xc6bcf05fU, + 0xc27dede8U, 0xcf3ecb31U, 0xcbffd686U, 0xd5b88683U, 0xd1799b34U, + 0xdc3abdedU, 0xd8fba05aU, 0x690ce0eeU, 0x6dcdfd59U, 0x608edb80U, + 0x644fc637U, 0x7a089632U, 0x7ec98b85U, 0x738aad5cU, 0x774bb0ebU, + 0x4f040d56U, 0x4bc510e1U, 0x46863638U, 0x42472b8fU, 0x5c007b8aU, + 0x58c1663dU, 0x558240e4U, 0x51435d53U, 0x251d3b9eU, 0x21dc2629U, + 0x2c9f00f0U, 0x285e1d47U, 0x36194d42U, 0x32d850f5U, 0x3f9b762cU, + 0x3b5a6b9bU, 0x0315d626U, 0x07d4cb91U, 0x0a97ed48U, 0x0e56f0ffU, + 0x1011a0faU, 0x14d0bd4dU, 0x19939b94U, 0x1d528623U, 0xf12f560eU, + 0xf5ee4bb9U, 0xf8ad6d60U, 0xfc6c70d7U, 0xe22b20d2U, 0xe6ea3d65U, + 0xeba91bbcU, 0xef68060bU, 0xd727bbb6U, 0xd3e6a601U, 0xdea580d8U, + 0xda649d6fU, 0xc423cd6aU, 0xc0e2d0ddU, 0xcda1f604U, 0xc960ebb3U, + 0xbd3e8d7eU, 0xb9ff90c9U, 0xb4bcb610U, 0xb07daba7U, 0xae3afba2U, + 0xaafbe615U, 0xa7b8c0ccU, 0xa379dd7bU, 0x9b3660c6U, 0x9ff77d71U, + 0x92b45ba8U, 0x9675461fU, 0x8832161aU, 0x8cf30badU, 0x81b02d74U, + 0x857130c3U, 0x5d8a9099U, 0x594b8d2eU, 0x5408abf7U, 0x50c9b640U, + 0x4e8ee645U, 0x4a4ffbf2U, 0x470cdd2bU, 0x43cdc09cU, 0x7b827d21U, + 0x7f436096U, 0x7200464fU, 0x76c15bf8U, 0x68860bfdU, 0x6c47164aU, + 0x61043093U, 0x65c52d24U, 0x119b4be9U, 0x155a565eU, 0x18197087U, + 0x1cd86d30U, 0x029f3d35U, 0x065e2082U, 0x0b1d065bU, 0x0fdc1becU, + 0x3793a651U, 0x3352bbe6U, 0x3e119d3fU, 0x3ad08088U, 0x2497d08dU, + 0x2056cd3aU, 0x2d15ebe3U, 0x29d4f654U, 0xc5a92679U, 0xc1683bceU, + 0xcc2b1d17U, 0xc8ea00a0U, 0xd6ad50a5U, 0xd26c4d12U, 0xdf2f6bcbU, + 0xdbee767cU, 0xe3a1cbc1U, 0xe760d676U, 0xea23f0afU, 0xeee2ed18U, + 0xf0a5bd1dU, 0xf464a0aaU, 0xf9278673U, 0xfde69bc4U, 0x89b8fd09U, + 0x8d79e0beU, 0x803ac667U, 0x84fbdbd0U, 0x9abc8bd5U, 0x9e7d9662U, + 0x933eb0bbU, 0x97ffad0cU, 0xafb010b1U, 0xab710d06U, 0xa6322bdfU, + 0xa2f33668U, 0xbcb4666dU, 0xb8757bdaU, 0xb5365d03U, 0xb1f740b4U +}; + +void +CKSUM_Init(CKSUM_CTX *ctx) +{ + ctx->crc = 0; + ctx->len = 0; +} + +#define UPDATE(crc, byte) do \ + (crc) = ((crc) << 8) ^ crc32tab[((crc) >> 24) ^ (byte)]; \ +while(0) + +void +CKSUM_Update(CKSUM_CTX *ctx, const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) + UPDATE(ctx->crc, buf[i]); + ctx->len += len; +} + +void +CKSUM_Final(CKSUM_CTX *ctx) +{ + off_t len = ctx->len; + + /* add in number of bytes read and finish */ + while (len != 0) { + UPDATE(ctx->crc, len & 0xff); + len >>= 8; + } + ctx->crc = ~ctx->crc; +} + +char * +CKSUM_End(CKSUM_CTX *ctx, char *outstr) +{ + CKSUM_Final(ctx); + + if (outstr == NULL) { + if (asprintf(&outstr, "%u %lld", ctx->crc, ctx->len) == -1) + return (NULL); + } else { + (void)snprintf(outstr, (size_t)CKSUM_DIGEST_STRING_LENGTH, + "%u %lld", ctx->crc, ctx->len); + } + + return (outstr); +} diff --git a/bin/md5/crc.h b/bin/md5/crc.h new file mode 100644 index 0000000..2000c48 --- /dev/null +++ b/bin/md5/crc.h @@ -0,0 +1,31 @@ +/* $OpenBSD: crc.h,v 1.4 2019/01/25 00:19:25 millert Exp $ */ + +/* + * Copyright (c) 2004 Todd C. Miller <millert@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define CKSUM_DIGEST_LENGTH 4 +#define CKSUM_DIGEST_STRING_LENGTH (10 + 1 + 20 + 1) + +typedef struct CKSUMContext { + u_int32_t crc; + off_t len; +} CKSUM_CTX; + +void CKSUM_Init(CKSUM_CTX *); +void CKSUM_Update(CKSUM_CTX *, const u_int8_t *, size_t); +void CKSUM_Final(CKSUM_CTX *); +char *CKSUM_End(CKSUM_CTX *, char *); +char *CKSUM_Data(const u_int8_t *, size_t, char *); diff --git a/bin/md5/md5.1 b/bin/md5/md5.1 new file mode 100644 index 0000000..fa860eb --- /dev/null +++ b/bin/md5/md5.1 @@ -0,0 +1,142 @@ +.\" $OpenBSD: md5.1,v 1.48 2019/01/25 00:19:25 millert Exp $ +.\" +.\" Copyright (c) 2003, 2004, 2006 Todd C. Miller <millert@openbsd.org> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.\" Sponsored in part by the Defense Advanced Research Projects +.\" Agency (DARPA) and Air Force Research Laboratory, Air Force +.\" Materiel Command, USAF, under agreement number F39502-99-1-0512. +.\" +.Dd $Mdocdate: January 25 2019 $ +.Dt MD5 1 +.Os +.Sh NAME +.Nm md5 , +.Nm sha1 , +.Nm sha256 , +.Nm sha512 +.Nd calculate a message digest (checksum) for a file +.Sh SYNOPSIS +.Nm md5 +.Op Fl bcpqrtx +.Op Fl C Ar checklist +.Op Fl h Ar hashfile +.Op Fl s Ar string +.Op Ar +.Nm sha1 +.Op Fl bcpqrtx +.Op Fl C Ar checklist +.Op Fl h Ar hashfile +.Op Fl s Ar string +.Op Ar +.Nm sha256 +.Op Fl bcpqrtx +.Op Fl C Ar checklist +.Op Fl h Ar hashfile +.Op Fl s Ar string +.Op Ar +.Nm sha512 +.Op Fl bcpqrtx +.Op Fl C Ar checklist +.Op Fl h Ar hashfile +.Op Fl s Ar string +.Op Ar +.Sh DESCRIPTION +These utilities take as input a message of arbitrary length and produce +as output a message digest (checksum) of the input. +.Pp +Two messages having the same message digest (a collision) have been produced +for MD5 and for SHA-1, so their use is deprecated. +.Pp +The options for use with each command are as follows: +.Bl -tag -width Ds +.It Fl b +Output checksums in base64 notation, not hexadecimal. +.It Fl C Ar checklist +Compare the checksum of each +.Ar file +against the checksums in the +.Ar checklist . +Any specified +.Ar file +that is not listed in the +.Ar checklist +will generate an error. +.It Fl c +If this option is specified, the +.Ar file +options become checklists. +Each checklist should contain hash results in the normal format, +which will be verified against the specified paths. +Output consists of the digest used, the file name, +and an OK, FAILED, or MISSING for the result of the comparison. +This will validate any of the supported checksums (see +.Xr cksum 1 ) . +If no file is given, stdin is used. +.It Fl h Ar hashfile +Place the checksum into +.Ar hashfile +instead of stdout. +.It Fl p +Echoes stdin to stdout and appends the +checksum to stdout. +.It Fl q +Only print the checksum (quiet mode) or if used in conjunction with the +.Fl c +flag, only print the failed cases. +.It Fl r +Reverse the format of the hash algorithm output, making +it match the output format used by +.Xr cksum 1 . +.It Fl s Ar string +Prints a checksum of the given +.Ar string . +.It Fl t +Runs a built-in time trial. +Specifying +.Fl t +multiple times results in the number of rounds being multiplied +by 10 for each additional flag. +.It Fl x +Runs a built-in test script. +.El +.Sh EXIT STATUS +These utilities exit 0 on success, +and \*(Gt0 if an error occurs. +.Sh SEE ALSO +.Xr cksum 1 +.Sh STANDARDS +.Rs +.%A R. Rivest +.%D April 1992 +.%R RFC 1321 +.%T The MD5 Message-Digest Algorithm +.Re +.Rs +.%A J. Burrows +.%O FIPS PUB 180-1 +.%T The Secure Hash Standard +.Re +.Pp +.Rs +.%A D. Eastlake +.%A P. Jones +.%D September 2001 +.%R RFC 3174 +.%T US Secure Hash Algorithm 1 (SHA1) +.Re +.Rs +.%T Secure Hash Standard +.%O FIPS PUB 180-2 +.Re diff --git a/bin/md5/md5.c b/bin/md5/md5.c new file mode 100644 index 0000000..069b2f5 --- /dev/null +++ b/bin/md5/md5.c @@ -0,0 +1,852 @@ +/* $OpenBSD: md5.c,v 1.95 2019/05/18 16:53:39 otto Exp $ */ + +/* + * Copyright (c) 2001,2003,2005-2007,2010,2013,2014 + * Todd C. Miller <millert@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#include <sys/cdefs.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/queue.h> +#include <sys/resource.h> +#include <netinet/in.h> +#include <ctype.h> +#include <err.h> +#include <fcntl.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <time.h> +#include <unistd.h> +#include <errno.h> + +#include <md5.h> +#include <rmd160.h> +#include <sha1.h> +#include <sha2.h> +#include "crc.h" + +#define STYLE_MD5 0 +#define STYLE_CKSUM 1 +#define STYLE_TERSE 2 + +#define MAX_DIGEST_LEN 128 + +#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) +#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) + +union ANY_CTX { +#if !defined(SHA2_ONLY) + CKSUM_CTX cksum; + MD5_CTX md5; + RMD160_CTX rmd160; + SHA1_CTX sha1; +#endif /* !defined(SHA2_ONLY) */ + SHA2_CTX sha2; +}; + +struct hash_function { + const char *name; + size_t digestlen; + int style; + int base64; + void *ctx; /* XXX - only used by digest_file() */ + void (*init)(void *); + void (*update)(void *, const unsigned char *, size_t); + void (*final)(unsigned char *, void *); + char * (*end)(void *, char *); + TAILQ_ENTRY(hash_function) tailq; +} functions[] = { +#if !defined(SHA2_ONLY) + { + "CKSUM", + CKSUM_DIGEST_LENGTH, + STYLE_CKSUM, + -1, + NULL, + (void (*)(void *))CKSUM_Init, + (void (*)(void *, const unsigned char *, size_t))CKSUM_Update, + (void (*)(unsigned char *, void *))CKSUM_Final, + (char *(*)(void *, char *))CKSUM_End + }, + { + "MD5", + MD5_DIGEST_LENGTH, + STYLE_MD5, + 0, + NULL, + (void (*)(void *))MD5Init, + (void (*)(void *, const unsigned char *, size_t))MD5Update, + (void (*)(unsigned char *, void *))MD5Final, + (char *(*)(void *, char *))MD5End + }, + { + "RMD160", + RMD160_DIGEST_LENGTH, + STYLE_MD5, + 0, + NULL, + (void (*)(void *))RMD160Init, + (void (*)(void *, const unsigned char *, size_t))RMD160Update, + (void (*)(unsigned char *, void *))RMD160Final, + (char *(*)(void *, char *))RMD160End + }, + { + "SHA1", + SHA1_DIGEST_LENGTH, + STYLE_MD5, + 0, + NULL, + (void (*)(void *))SHA1Init, + (void (*)(void *, const unsigned char *, size_t))SHA1Update, + (void (*)(unsigned char *, void *))SHA1Final, + (char *(*)(void *, char *))SHA1End + }, + { + "SHA224", + SHA224_DIGEST_LENGTH, + STYLE_MD5, + 0, + NULL, + (void (*)(void *))SHA224Init, + (void (*)(void *, const unsigned char *, size_t))SHA224Update, + (void (*)(unsigned char *, void *))SHA224Final, + (char *(*)(void *, char *))SHA224End + }, +#endif /* !defined(SHA2_ONLY) */ + { + "SHA256", + SHA256_DIGEST_LENGTH, + STYLE_MD5, + 0, + NULL, + (void (*)(void *))SHA256Init, + (void (*)(void *, const unsigned char *, size_t))SHA256Update, + (void (*)(unsigned char *, void *))SHA256Final, + (char *(*)(void *, char *))SHA256End + }, +#if !defined(SHA2_ONLY) + { + "SHA384", + SHA384_DIGEST_LENGTH, + STYLE_MD5, + 0, + NULL, + (void (*)(void *))SHA384Init, + (void (*)(void *, const unsigned char *, size_t))SHA384Update, + (void (*)(unsigned char *, void *))SHA384Final, + (char *(*)(void *, char *))SHA384End + }, + { + "SHA512/256", + SHA512_256_DIGEST_LENGTH, + STYLE_MD5, + 0, + NULL, + (void (*)(void *))SHA512_256Init, + (void (*)(void *, const unsigned char *, size_t))SHA512_256Update, + (void (*)(unsigned char *, void *))SHA512_256Final, + (char *(*)(void *, char *))SHA512_256End + }, +#endif /* !defined(SHA2_ONLY) */ + { + "SHA512", + SHA512_DIGEST_LENGTH, + STYLE_MD5, + 0, + NULL, + (void (*)(void *))SHA512Init, + (void (*)(void *, const unsigned char *, size_t))SHA512Update, + (void (*)(unsigned char *, void *))SHA512Final, + (char *(*)(void *, char *))SHA512End + }, + { + NULL, + } +}; + +TAILQ_HEAD(hash_list, hash_function); + +void digest_end(const struct hash_function *, void *, char *, size_t, int); +int digest_file(const char *, struct hash_list *, int); +void digest_print(const struct hash_function *, const char *, const char *); +#if !defined(SHA2_ONLY) +int digest_filelist(const char *, struct hash_function *, int, char **); +void digest_printstr(const struct hash_function *, const char *, const char *); +void digest_string(char *, struct hash_list *); +void digest_test(struct hash_list *); +void digest_time(struct hash_list *, int); +#endif /* !defined(SHA2_ONLY) */ +void hash_insert(struct hash_list *, struct hash_function *, int); +void usage(void) __attribute__((__noreturn__)); + +extern char *__progname; +int qflag = 0; +FILE *ofile = NULL; + +int +main(int argc, char **argv) +{ + struct hash_function *hf, *hftmp; + struct hash_list hl; + size_t len; + char *cp, *input_string, *selective_checklist; + const char *optstr; + int fl, error, base64; + int bflag, cflag, pflag, rflag, tflag, xflag; + + if (pledge("stdio rpath wpath cpath", NULL) == -1) + err(1, "pledge"); + + TAILQ_INIT(&hl); + input_string = NULL; + selective_checklist = NULL; + error = bflag = cflag = pflag = qflag = rflag = tflag = xflag = 0; + +#if !defined(SHA2_ONLY) + if (strcmp(__progname, "cksum") == 0) + optstr = "a:bC:ch:pqrs:tx"; + else +#endif /* !defined(SHA2_ONLY) */ + optstr = "bC:ch:pqrs:tx"; + + /* Check for -b option early since it changes behavior. */ + while ((fl = getopt(argc, argv, optstr)) != -1) { + switch (fl) { + case 'b': + bflag = 1; + break; + case '?': + usage(); + } + } + optind = 1; + optreset = 1; + while ((fl = getopt(argc, argv, optstr)) != -1) { + switch (fl) { + case 'a': + while ((cp = strsep(&optarg, " \t,")) != NULL) { + if (*cp == '\0') + continue; + base64 = -1; + for (hf = functions; hf->name != NULL; hf++) { + len = strlen(hf->name); + if (strncasecmp(cp, hf->name, len) != 0) + continue; + if (cp[len] == '\0') { + if (hf->base64 != -1) + base64 = bflag; + break; /* exact match */ + } + if (cp[len + 1] == '\0' && + (cp[len] == 'b' || cp[len] == 'x')) { + base64 = + cp[len] == 'b' ? 1 : 0; + break; /* match w/ suffix */ + } + } + if (hf->name == NULL) { + warnx("unknown algorithm \"%s\"", cp); + usage(); + } + if (hf->base64 == -1 && base64 != -1) { + warnx("%s doesn't support %s", + hf->name, + base64 ? "base64" : "hex"); + usage(); + } + /* Check for dupes. */ + TAILQ_FOREACH(hftmp, &hl, tailq) { + if (hftmp->base64 == base64 && + strcmp(hf->name, hftmp->name) == 0) + break; + } + if (hftmp == NULL) + hash_insert(&hl, hf, base64); + } + break; + case 'b': + /* has already been parsed */ + break; + case 'h': + ofile = fopen(optarg, "w"); + if (ofile == NULL) + err(1, "%s", optarg); + break; +#if !defined(SHA2_ONLY) + case 'C': + selective_checklist = optarg; + break; + case 'c': + cflag = 1; + break; +#endif /* !defined(SHA2_ONLY) */ + case 'p': + pflag = 1; + break; + case 'q': + qflag = 1; + break; + case 'r': + rflag = 1; + break; + case 's': + input_string = optarg; + break; + case 't': + tflag++; + break; + case 'x': + xflag = 1; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (ofile == NULL) + ofile = stdout; + + if (pledge("stdio rpath", NULL) == -1) + err(1, "pledge"); + + /* Most arguments are mutually exclusive */ + fl = pflag + (tflag ? 1 : 0) + xflag + cflag + (input_string != NULL); + if (fl > 1 || (fl && argc && cflag == 0) || (rflag && qflag) || + (selective_checklist != NULL && argc == 0)) + usage(); + if (selective_checklist || cflag) { + if (TAILQ_FIRST(&hl) != TAILQ_LAST(&hl, hash_list)) + errx(1, "only a single algorithm may be specified " + "in -C or -c mode"); + } + + /* No algorithm specified, check the name we were called as. */ + if (TAILQ_EMPTY(&hl)) { + for (hf = functions; hf->name != NULL; hf++) { + if (strcasecmp(hf->name, __progname) == 0) + break; + } + if (hf->name == NULL) + hf = &functions[0]; /* default to cksum */ + hash_insert(&hl, hf, (hf->base64 == -1 ? 0 : bflag)); + } + + if (rflag || qflag) { + const int new_style = rflag ? STYLE_CKSUM : STYLE_TERSE; + TAILQ_FOREACH(hf, &hl, tailq) { + hf->style = new_style; + } + } + +#if !defined(SHA2_ONLY) + if (tflag) + digest_time(&hl, tflag); + else if (xflag) + digest_test(&hl); + else if (input_string) + digest_string(input_string, &hl); + else if (selective_checklist) { + int i; + + error = digest_filelist(selective_checklist, TAILQ_FIRST(&hl), + argc, argv); + for (i = 0; i < argc; i++) { + if (argv[i] != NULL) { + warnx("%s does not exist in %s", argv[i], + selective_checklist); + error++; + } + } + } else if (cflag) { + if (argc == 0) + error = digest_filelist("-", TAILQ_FIRST(&hl), 0, NULL); + else + while (argc--) + error += digest_filelist(*argv++, + TAILQ_FIRST(&hl), 0, NULL); + } else +#endif /* !defined(SHA2_ONLY) */ + if (pflag || argc == 0) + error = digest_file("-", &hl, pflag); + else + while (argc--) + error += digest_file(*argv++, &hl, 0); + + return(error ? EXIT_FAILURE : EXIT_SUCCESS); +} + +void +hash_insert(struct hash_list *hl, struct hash_function *hf, int base64) +{ + struct hash_function *hftmp; + + hftmp = malloc(sizeof(*hftmp)); + if (hftmp == NULL) + err(1, NULL); + *hftmp = *hf; + hftmp->base64 = base64; + TAILQ_INSERT_TAIL(hl, hftmp, tailq); +} + +void +digest_end(const struct hash_function *hf, void *ctx, char *buf, size_t bsize, + int base64) +{ + u_char *digest; + + if (base64 == 1) { + if ((digest = malloc(hf->digestlen)) == NULL) + err(1, NULL); + hf->final(digest, ctx); + if (b64_ntop(digest, hf->digestlen, buf, bsize) == -1) + errx(1, "error encoding base64"); + free(digest); + } else { + hf->end(ctx, buf); + } +} + +#if !defined(SHA2_ONLY) +void +digest_string(char *string, struct hash_list *hl) +{ + struct hash_function *hf; + char digest[MAX_DIGEST_LEN + 1]; + union ANY_CTX context; + + TAILQ_FOREACH(hf, hl, tailq) { + hf->init(&context); + hf->update(&context, string, strlen(string)); + digest_end(hf, &context, digest, sizeof(digest), + hf->base64); + digest_printstr(hf, string, digest); + } +} +#endif /* !defined(SHA2_ONLY) */ + +void +digest_print(const struct hash_function *hf, const char *what, + const char *digest) +{ + switch (hf->style) { + case STYLE_MD5: + (void)fprintf(ofile, "%s (%s) = %s\n", hf->name, what, digest); + break; + case STYLE_CKSUM: + (void)fprintf(ofile, "%s %s\n", digest, what); + break; + case STYLE_TERSE: + (void)fprintf(ofile, "%s\n", digest); + break; + } +} + +#if !defined(SHA2_ONLY) +void +digest_printstr(const struct hash_function *hf, const char *what, + const char *digest) +{ + switch (hf->style) { + case STYLE_MD5: + (void)fprintf(ofile, "%s (\"%s\") = %s\n", hf->name, what, digest); + break; + case STYLE_CKSUM: + (void)fprintf(ofile, "%s %s\n", digest, what); + break; + case STYLE_TERSE: + (void)fprintf(ofile, "%s\n", digest); + break; + } +} +#endif /* !defined(SHA2_ONLY) */ + +int +digest_file(const char *file, struct hash_list *hl, int echo) +{ + struct hash_function *hf; + FILE *fp; + size_t nread; + u_char data[32 * 1024]; + char digest[MAX_DIGEST_LEN + 1]; + + if (strcmp(file, "-") == 0) + fp = stdin; + else if ((fp = fopen(file, "r")) == NULL) { + warn("cannot open %s", file); + return(1); + } + + TAILQ_FOREACH(hf, hl, tailq) { + if ((hf->ctx = malloc(sizeof(union ANY_CTX))) == NULL) + err(1, NULL); + hf->init(hf->ctx); + } + while ((nread = fread(data, 1UL, sizeof(data), fp)) != 0) { + if (echo) { + (void)fwrite(data, nread, 1UL, stdout); + if (fflush(stdout) != 0) + err(1, "stdout: write error"); + } + TAILQ_FOREACH(hf, hl, tailq) + hf->update(hf->ctx, data, nread); + } + if (ferror(fp)) { + warn("%s: read error", file); + if (fp != stdin) + fclose(fp); + TAILQ_FOREACH(hf, hl, tailq) { + free(hf->ctx); + hf->ctx = NULL; + } + return(1); + } + if (fp != stdin) + fclose(fp); + TAILQ_FOREACH(hf, hl, tailq) { + digest_end(hf, hf->ctx, digest, sizeof(digest), hf->base64); + free(hf->ctx); + hf->ctx = NULL; + if (fp == stdin) + fprintf(ofile, "%s\n", digest); + else + digest_print(hf, file, digest); + } + return(0); +} + +#if !defined(SHA2_ONLY) +/* + * Parse through the input file looking for valid lines. + * If one is found, use this checksum and file as a reference and + * generate a new checksum against the file on the filesystem. + * Print out the result of each comparison. + */ +int +digest_filelist(const char *file, struct hash_function *defhash, int selcount, + char **sel) +{ + int found, base64, error, cmp, i; + size_t algorithm_max, algorithm_min; + const char *algorithm; + char *filename, *checksum, *line, *p, *tmpline; + char digest[MAX_DIGEST_LEN + 1]; + ssize_t linelen; + FILE *listfp, *fp; + size_t len, linesize, nread; + int *sel_found = NULL; + u_char data[32 * 1024]; + union ANY_CTX context; + struct hash_function *hf; + + if (strcmp(file, "-") == 0) { + listfp = stdin; + } else if ((listfp = fopen(file, "r")) == NULL) { + warn("cannot open %s", file); + return(1); + } + + if (sel != NULL) { + sel_found = calloc((size_t)selcount, sizeof(*sel_found)); + if (sel_found == NULL) + err(1, NULL); + } + + algorithm_max = algorithm_min = strlen(functions[0].name); + for (hf = &functions[1]; hf->name != NULL; hf++) { + len = strlen(hf->name); + algorithm_max = MAXIMUM(algorithm_max, len); + algorithm_min = MINIMUM(algorithm_min, len); + } + + error = found = 0; + line = NULL; + linesize = 0; + while ((linelen = getline(&line, &linesize, listfp)) != -1) { + tmpline = line; + base64 = 0; + if (line[linelen - 1] == '\n') + line[linelen - 1] = '\0'; + while (isspace((unsigned char)*tmpline)) + tmpline++; + + /* + * Crack the line into an algorithm, filename, and checksum. + * Lines are of the form: + * ALGORITHM (FILENAME) = CHECKSUM + * + * Fallback on GNU form: + * CHECKSUM FILENAME + */ + p = strchr(tmpline, ' '); + if (p != NULL && *(p + 1) == '(') { + /* BSD form */ + *p = '\0'; + algorithm = tmpline; + len = strlen(algorithm); + if (len > algorithm_max || len < algorithm_min) + continue; + + filename = p + 2; + p = strrchr(filename, ')'); + if (p == NULL || strncmp(p + 1, " = ", (size_t)3) != 0) + continue; + *p = '\0'; + + checksum = p + 4; + p = strpbrk(checksum, " \t\r"); + if (p != NULL) + *p = '\0'; + + /* + * Check that the algorithm is one we recognize. + */ + for (hf = functions; hf->name != NULL; hf++) { + if (strcasecmp(algorithm, hf->name) == 0) + break; + } + if (hf->name == NULL || *checksum == '\0') + continue; + /* + * Check the length to see if this could be + * a valid checksum. If hex, it will be 2x the + * size of the binary data. For base64, we have + * to check both with and without the '=' padding. + */ + len = strlen(checksum); + if (len != hf->digestlen * 2) { + size_t len2; + + if (checksum[len - 1] == '=') { + /* use padding */ + len2 = 4 * ((hf->digestlen + 2) / 3); + } else { + /* no padding */ + len2 = (4 * hf->digestlen + 2) / 3; + } + if (len != len2) + continue; + base64 = 1; + } + } else { + /* could be GNU form */ + if ((hf = defhash) == NULL) + continue; + algorithm = hf->name; + checksum = tmpline; + if ((p = strchr(checksum, ' ')) == NULL) + continue; + if (hf->style == STYLE_CKSUM) { + if ((p = strchr(p + 1, ' ')) == NULL) + continue; + } + *p++ = '\0'; + while (isspace((unsigned char)*p)) + p++; + if (*p == '\0') + continue; + filename = p; + p = strpbrk(filename, "\t\r"); + if (p != NULL) + *p = '\0'; + } + found = 1; + + /* + * If only a selection of files is wanted, proceed only + * if the filename matches one of those in the selection. + */ + if (sel != NULL) { + for (i = 0; i < selcount; i++) { + if (strcmp(sel[i], filename) == 0) { + sel_found[i] = 1; + break; + } + } + if (i == selcount) + continue; + } + + if ((fp = fopen(filename, "r")) == NULL) { + warn("cannot open %s", filename); + (void)printf("(%s) %s: %s\n", algorithm, filename, + (errno == ENOENT ? "MISSING" : "FAILED")); + error = 1; + continue; + } + + hf->init(&context); + while ((nread = fread(data, 1UL, sizeof(data), fp)) > 0) + hf->update(&context, data, nread); + if (ferror(fp)) { + warn("%s: read error", file); + error = 1; + fclose(fp); + continue; + } + fclose(fp); + digest_end(hf, &context, digest, sizeof(digest), base64); + + if (base64) + cmp = strncmp(checksum, digest, len); + else + cmp = strcasecmp(checksum, digest); + if (cmp == 0) { + if (qflag == 0) + (void)printf("(%s) %s: OK\n", algorithm, + filename); + } else { + (void)printf("(%s) %s: FAILED\n", algorithm, filename); + error = 1; + } + } + free(line); + if (ferror(listfp)) { + warn("%s: getline", file); + error = 1; + } + if (listfp != stdin) + fclose(listfp); + if (!found) + warnx("%s: no properly formatted checksum lines found", file); + if (sel_found != NULL) { + /* + * Mark found files by setting them to NULL so that we can + * detect files that are missing from the checklist later. + */ + for (i = 0; i < selcount; i++) { + if (sel_found[i]) + sel[i] = NULL; + } + free(sel_found); + } + return(error || !found); +} + +#define TEST_BLOCK_LEN 10000 +#define TEST_BLOCK_COUNT 10000 + +void +digest_time(struct hash_list *hl, int times) +{ + struct hash_function *hf; + struct rusage start, stop; + struct timeval res; + union ANY_CTX context; + u_int i; + u_char data[TEST_BLOCK_LEN]; + char digest[MAX_DIGEST_LEN + 1]; + double elapsed; + int count = TEST_BLOCK_COUNT; + while (--times > 0 && count < INT_MAX / 10) + count *= 10; + + TAILQ_FOREACH(hf, hl, tailq) { + (void)printf("%s time trial. Processing %d %d-byte blocks...", + hf->name, count, TEST_BLOCK_LEN); + fflush(stdout); + + /* Initialize data based on block number. */ + for (i = 0; i < TEST_BLOCK_LEN; i++) + data[i] = (u_char)(i & 0xff); + + getrusage(RUSAGE_SELF, &start); + hf->init(&context); + for (i = 0; i < count; i++) + hf->update(&context, data, (size_t)TEST_BLOCK_LEN); + digest_end(hf, &context, digest, sizeof(digest), hf->base64); + getrusage(RUSAGE_SELF, &stop); + timersub(&stop.ru_utime, &start.ru_utime, &res); + elapsed = res.tv_sec + res.tv_usec / 1000000.0; + + (void)printf("\nDigest = %s\n", digest); + (void)printf("Time = %f seconds\n", elapsed); + (void)printf("Speed = %f bytes/second\n", + (double)TEST_BLOCK_LEN * count / elapsed); + } +} + +void +digest_test(struct hash_list *hl) +{ + struct hash_function *hf; + union ANY_CTX context; + int i; + char digest[MAX_DIGEST_LEN + 1]; + unsigned char buf[1000]; + unsigned const char *test_strings[] = { + "", + "a", + "abc", + "message digest", + "abcdefghijklmnopqrstuvwxyz", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789", + "12345678901234567890123456789012345678901234567890123456789" + "012345678901234567890", + }; + + TAILQ_FOREACH(hf, hl, tailq) { + (void)printf("%s test suite:\n", hf->name); + + for (i = 0; i < 8; i++) { + hf->init(&context); + hf->update(&context, test_strings[i], + strlen(test_strings[i])); + digest_end(hf, &context, digest, sizeof(digest), + hf->base64); + digest_printstr(hf, test_strings[i], digest); + } + + /* Now simulate a string of a million 'a' characters. */ + memset(buf, 'a', sizeof(buf)); + hf->init(&context); + for (i = 0; i < 1000; i++) + hf->update(&context, buf, sizeof(buf)); + digest_end(hf, &context, digest, sizeof(digest), hf->base64); + digest_print(hf, "one million 'a' characters", + digest); + } +} +#endif /* !defined(SHA2_ONLY) */ + +void +usage(void) +{ +#if !defined(SHA2_ONLY) + if (strcmp(__progname, "cksum") == 0) + fprintf(stderr, "usage: %s [-bcpqrtx] [-a algorithms] [-C checklist] " + "[-h hashfile]\n" + " [-s string] [file ...]\n", + __progname); + else +#endif /* !defined(SHA2_ONLY) */ + fprintf(stderr, "usage:" + "\t%s [-bcpqrtx] [-C checklist] [-h hashfile] [-s string] " + "[file ...]\n", + __progname); + + exit(EXIT_FAILURE); +} |