mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-04-20 02:36:16 +02:00
Provide framework for computing sha-2 hashes.
This commit is contained in:
143
src/md5sum.c
143
src/md5sum.c
@@ -1,4 +1,4 @@
|
||||
/* Compute MD5 or SHA1 checksum of files or strings
|
||||
/* Compute MD5, SHA1, SHA224, SHA256, SHA384 or SHA512 checksum of files or strings
|
||||
Copyright (C) 1995-2005 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@@ -24,34 +24,85 @@
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#include "md5.h"
|
||||
#include "sha1.h"
|
||||
#include "checksum.h"
|
||||
#if HASH_ALGO_MD5
|
||||
# include "md5.h"
|
||||
#endif
|
||||
#if HASH_ALGO_SHA1
|
||||
# include "sha1.h"
|
||||
#endif
|
||||
#if HASH_ALGO_SHA256 || HASH_ALGO_SHA224
|
||||
# include "sha256.h"
|
||||
#endif
|
||||
#if HASH_ALGO_SHA512 || HASH_ALGO_SHA384
|
||||
# include "sha512.h"
|
||||
#endif
|
||||
#include "getline.h"
|
||||
#include "error.h"
|
||||
#include "quote.h"
|
||||
#include "stdio--.h"
|
||||
|
||||
/* The official name of this program (e.g., no `g' prefix). */
|
||||
#define PROGRAM_NAME (algorithm == ALG_MD5 ? "md5sum" : "sha1sum")
|
||||
#if HASH_ALGO_MD5
|
||||
# define PROGRAM_NAME "md5sum"
|
||||
# define DIGEST_TYPE_STRING "MD5"
|
||||
# define DIGEST_STREAM md5_stream
|
||||
# define DIGEST_BUFFER md5_buffer
|
||||
# define DIGEST_BITS 128
|
||||
# define DIGEST_REFERENCE "RFC 1321"
|
||||
# define DIGEST_ALIGN 4
|
||||
#elif HASH_ALGO_SHA1
|
||||
# define PROGRAM_NAME "sha1sum"
|
||||
# define DIGEST_TYPE_STRING "SHA1"
|
||||
# define DIGEST_STREAM sha1_stream
|
||||
# define DIGEST_BUFFER sha1_buffer
|
||||
# define DIGEST_BITS 160
|
||||
# define DIGEST_REFERENCE "FIPS-180-1"
|
||||
# define DIGEST_ALIGN 4
|
||||
#elif HASH_ALGO_SHA256
|
||||
# define PROGRAM_NAME "sha256sum"
|
||||
# define DIGEST_TYPE_STRING "SHA256"
|
||||
# define DIGEST_STREAM sha256_stream
|
||||
# define DIGEST_BUFFER sha256_buffer
|
||||
# define DIGEST_BITS 256
|
||||
# define DIGEST_REFERENCE "FIPS-180-2"
|
||||
# define DIGEST_ALIGN 4
|
||||
#elif HASH_ALGO_SHA224
|
||||
# define PROGRAM_NAME "sha224sum"
|
||||
# define DIGEST_TYPE_STRING "SHA224"
|
||||
# define DIGEST_STREAM sha224_stream
|
||||
# define DIGEST_BUFFER sha224_buffer
|
||||
# define DIGEST_BITS 224
|
||||
# define DIGEST_REFERENCE "RFC 3874"
|
||||
# define DIGEST_ALIGN 4
|
||||
#elif HASH_ALGO_SHA512
|
||||
# define PROGRAM_NAME "sha512sum"
|
||||
# define DIGEST_TYPE_STRING "SHA512"
|
||||
# define DIGEST_STREAM sha512_stream
|
||||
# define DIGEST_BUFFER sha512_buffer
|
||||
# define DIGEST_BITS 512
|
||||
# define DIGEST_REFERENCE "FIPS-180-2"
|
||||
# define DIGEST_ALIGN 8
|
||||
#elif HASH_ALGO_SHA384
|
||||
# define PROGRAM_NAME "sha384sum"
|
||||
# define DIGEST_TYPE_STRING "SHA384"
|
||||
# define DIGEST_STREAM sha384_stream
|
||||
# define DIGEST_BUFFER sha384_buffer
|
||||
# define DIGEST_BITS 384
|
||||
# define DIGEST_REFERENCE "FIPS-180-2"
|
||||
# define DIGEST_ALIGN 8
|
||||
#else
|
||||
# error "Can't decide which hash algorithm to compile."
|
||||
#endif
|
||||
|
||||
#define AUTHORS "Ulrich Drepper", "Scott Miller"
|
||||
#define DIGEST_HEX_BYTES (DIGEST_BITS / 4)
|
||||
#define DIGEST_BIN_BYTES (DIGEST_BITS / 8)
|
||||
|
||||
|
||||
#define DIGEST_TYPE_STRING(Alg) ((Alg) == ALG_MD5 ? "MD5" : "SHA1")
|
||||
#define DIGEST_STREAM(Alg) ((Alg) == ALG_MD5 ? md5_stream : sha1_stream)
|
||||
|
||||
#define DIGEST_BITS(Alg) ((Alg) == ALG_MD5 ? 128 : 160)
|
||||
#define DIGEST_HEX_BYTES(Alg) (DIGEST_BITS (Alg) / 4)
|
||||
#define DIGEST_BIN_BYTES(Alg) (DIGEST_BITS (Alg) / 8)
|
||||
|
||||
#define MAX_DIGEST_BIN_BYTES MAX (DIGEST_BIN_BYTES (ALG_MD5), \
|
||||
DIGEST_BIN_BYTES (ALG_SHA1))
|
||||
#define AUTHORS "Ulrich Drepper", "Scott Miller", "David Madore"
|
||||
|
||||
/* The minimum length of a valid digest line. This length does
|
||||
not include any newline character at the end of a line. */
|
||||
#define MIN_DIGEST_LINE_LENGTH(Alg) \
|
||||
(DIGEST_HEX_BYTES (Alg) /* length of hexadecimal message digest */ \
|
||||
#define MIN_DIGEST_LINE_LENGTH \
|
||||
(DIGEST_HEX_BYTES /* length of hexadecimal message digest */ \
|
||||
+ 2 /* blank and binary indicator */ \
|
||||
+ 1 /* minimum filename length */ )
|
||||
|
||||
@@ -72,9 +123,6 @@ static bool status_only = false;
|
||||
improperly formatted checksum line. */
|
||||
static bool warn = false;
|
||||
|
||||
/* Declared and set via one of the wrapper .c files. */
|
||||
/* int algorithm = ALG_UNSPECIFIED; */
|
||||
|
||||
/* The name this program was run with. */
|
||||
char *program_name;
|
||||
|
||||
@@ -112,8 +160,8 @@ With no FILE, or when FILE is -, read standard input.\n\
|
||||
\n\
|
||||
"),
|
||||
program_name,
|
||||
DIGEST_TYPE_STRING (algorithm),
|
||||
DIGEST_BITS (algorithm));
|
||||
DIGEST_TYPE_STRING,
|
||||
DIGEST_BITS);
|
||||
if (O_BINARY)
|
||||
fputs (_("\
|
||||
-b, --binary read in binary mode (default unless reading tty stdin)\n\
|
||||
@@ -124,7 +172,7 @@ With no FILE, or when FILE is -, read standard input.\n\
|
||||
"), stdout);
|
||||
printf (_("\
|
||||
-c, --check read %s sums from the FILEs and check them\n"),
|
||||
DIGEST_TYPE_STRING (algorithm));
|
||||
DIGEST_TYPE_STRING);
|
||||
if (O_BINARY)
|
||||
fputs (_("\
|
||||
-t, --text read in text mode (default if reading tty stdin)\n\
|
||||
@@ -148,7 +196,7 @@ The sums are computed as described in %s. When checking, the input\n\
|
||||
should be a former output of this program. The default mode is to print\n\
|
||||
a line with checksum, a character indicating type (`*' for binary, ` ' for\n\
|
||||
text), and name for each FILE.\n"),
|
||||
(algorithm == ALG_MD5 ? "RFC 1321" : "FIPS-180-1"));
|
||||
DIGEST_REFERENCE);
|
||||
printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
|
||||
}
|
||||
|
||||
@@ -211,8 +259,8 @@ split_3 (char *s, size_t s_len,
|
||||
++i;
|
||||
|
||||
/* Check for BSD-style checksum line. */
|
||||
algo_name_len = strlen (DIGEST_TYPE_STRING (algorithm));
|
||||
if (strncmp (s + i, DIGEST_TYPE_STRING (algorithm), algo_name_len) == 0)
|
||||
algo_name_len = strlen (DIGEST_TYPE_STRING);
|
||||
if (strncmp (s + i, DIGEST_TYPE_STRING, algo_name_len) == 0)
|
||||
{
|
||||
if (strncmp (s + i + algo_name_len, " (", 2) == 0)
|
||||
{
|
||||
@@ -313,8 +361,7 @@ hex_digits (unsigned char const *s)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* An interface to the function, DIGEST_STREAM,
|
||||
(either md5_stream or sha1_stream).
|
||||
/* An interface to the function, DIGEST_STREAM.
|
||||
Operate on FILENAME (it may be "-").
|
||||
|
||||
*BINARY indicates whether the file is binary. BINARY < 0 means it
|
||||
@@ -322,12 +369,11 @@ hex_digits (unsigned char const *s)
|
||||
a terminal; in that case, clear *BINARY if the file was treated as
|
||||
text because it was a terminal.
|
||||
|
||||
Put the checksum in *BIN_RESULT.
|
||||
Put the checksum in *BIN_RESULT, which must be properly aligned.
|
||||
Return true if successful. */
|
||||
|
||||
static bool
|
||||
digest_file (const char *filename, int *binary, unsigned char *bin_result,
|
||||
int (*digest_stream) (FILE *, void *))
|
||||
digest_file (const char *filename, int *binary, unsigned char *bin_result)
|
||||
{
|
||||
FILE *fp;
|
||||
int err;
|
||||
@@ -355,7 +401,7 @@ digest_file (const char *filename, int *binary, unsigned char *bin_result,
|
||||
}
|
||||
}
|
||||
|
||||
err = (*digest_stream) (fp, bin_result);
|
||||
err = DIGEST_STREAM (fp, bin_result);
|
||||
if (err)
|
||||
{
|
||||
error (0, errno, "%s", filename);
|
||||
@@ -374,18 +420,23 @@ digest_file (const char *filename, int *binary, unsigned char *bin_result,
|
||||
}
|
||||
|
||||
static bool
|
||||
digest_check (const char *checkfile_name, int (*digest_stream) (FILE *, void *))
|
||||
digest_check (const char *checkfile_name)
|
||||
{
|
||||
FILE *checkfile_stream;
|
||||
uintmax_t n_properly_formatted_lines = 0;
|
||||
uintmax_t n_mismatched_checksums = 0;
|
||||
uintmax_t n_open_or_read_failures = 0;
|
||||
unsigned char bin_buffer[MAX_DIGEST_BIN_BYTES];
|
||||
unsigned char bin_buffer_unaligned[DIGEST_BIN_BYTES+DIGEST_ALIGN];
|
||||
unsigned char *bin_buffer;
|
||||
uintmax_t line_number;
|
||||
char *line;
|
||||
size_t line_chars_allocated;
|
||||
bool is_stdin = STREQ (checkfile_name, "-");
|
||||
|
||||
/* Make sure bin_buffer is properly aligned. */
|
||||
bin_buffer = bin_buffer_unaligned
|
||||
+ ((unsigned)DIGEST_ALIGN - ((unsigned)bin_buffer_unaligned))%DIGEST_ALIGN;
|
||||
|
||||
if (is_stdin)
|
||||
{
|
||||
have_read_stdin = true;
|
||||
@@ -439,7 +490,7 @@ digest_check (const char *checkfile_name, int (*digest_stream) (FILE *, void *))
|
||||
_("%s: %" PRIuMAX
|
||||
": improperly formatted %s checksum line"),
|
||||
checkfile_name, line_number,
|
||||
DIGEST_TYPE_STRING (algorithm));
|
||||
DIGEST_TYPE_STRING);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -452,7 +503,7 @@ digest_check (const char *checkfile_name, int (*digest_stream) (FILE *, void *))
|
||||
|
||||
++n_properly_formatted_lines;
|
||||
|
||||
ok = digest_file (filename, &binary, bin_buffer, digest_stream);
|
||||
ok = digest_file (filename, &binary, bin_buffer);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
@@ -509,7 +560,7 @@ digest_check (const char *checkfile_name, int (*digest_stream) (FILE *, void *))
|
||||
{
|
||||
/* Warn if no tests are found. */
|
||||
error (0, 0, _("%s: no properly formatted %s checksum lines found"),
|
||||
checkfile_name, DIGEST_TYPE_STRING (algorithm));
|
||||
checkfile_name, DIGEST_TYPE_STRING);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -547,7 +598,8 @@ digest_check (const char *checkfile_name, int (*digest_stream) (FILE *, void *))
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
unsigned char bin_buffer[MAX_DIGEST_BIN_BYTES];
|
||||
unsigned char bin_buffer_unaligned[DIGEST_BIN_BYTES+DIGEST_ALIGN];
|
||||
unsigned char *bin_buffer;
|
||||
bool do_check = false;
|
||||
int opt;
|
||||
bool ok = true;
|
||||
@@ -588,8 +640,12 @@ main (int argc, char **argv)
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
min_digest_line_length = MIN_DIGEST_LINE_LENGTH (algorithm);
|
||||
digest_hex_bytes = DIGEST_HEX_BYTES (algorithm);
|
||||
min_digest_line_length = MIN_DIGEST_LINE_LENGTH;
|
||||
digest_hex_bytes = DIGEST_HEX_BYTES;
|
||||
|
||||
/* Make sure bin_buffer is properly aligned. */
|
||||
bin_buffer = bin_buffer_unaligned
|
||||
+ ((unsigned)DIGEST_ALIGN - ((unsigned)bin_buffer_unaligned))%DIGEST_ALIGN;
|
||||
|
||||
if (0 <= binary && do_check)
|
||||
{
|
||||
@@ -620,13 +676,12 @@ main (int argc, char **argv)
|
||||
char *file = argv[optind];
|
||||
|
||||
if (do_check)
|
||||
ok &= digest_check (file, DIGEST_STREAM (algorithm));
|
||||
ok &= digest_check (file);
|
||||
else
|
||||
{
|
||||
int file_is_binary = binary;
|
||||
|
||||
if (! digest_file (file, &file_is_binary, bin_buffer,
|
||||
DIGEST_STREAM (algorithm)))
|
||||
if (! digest_file (file, &file_is_binary, bin_buffer))
|
||||
ok = false;
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user