Parent Directory
|
Revision Log
revert autotoolage fixes
/*
** Hash-A-Lot by Ben Slusky <sluskyb@paranoiacs.org>
**
** This program will read a passphrase from standard input and print a binary
** (not printable) hash to standard output. The output is suitable for use as
** an encryption key.
**
** USAGE:
** hashalot [ -x ] [ -s _salt_ ] [ -n _#bytes_ ] _hashtype_
** OR
** _hashtype_ [ -x ] [ -s _salt_ ] [ -n _#bytes_ ]
**
** Most of the code was cribbed from the kerneli.org patch to util-linux,
** by Marc Mutz <Marc@Mutz.com>. Most of what wasn't, was cribbed from GnuPG,
** v.1.0.3 (http://www.gnupg.org/).
*/
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/mman.h>
#include "rmd160.h"
#include "sha512.h"
typedef int (*phash_func_t)(char dest[], size_t dest_len, const char src[], size_t src_len);
static void *
xmalloc (size_t size);
static int
phash_rmd160(char dest[], size_t dest_len, const char src[], size_t src_len)
{
char key[RMD160_HASH_SIZE * 2] = { 0, };
char *tmp = xmalloc(src_len + 2);
tmp[0] = 'A';
tmp[1] = '\0';
strncpy(tmp + 1, src, src_len);
tmp[src_len + 1] = '\0';
rmd160_hash_buffer(key, src, src_len);
rmd160_hash_buffer(key + RMD160_HASH_SIZE, tmp, src_len + 1);
memcpy(dest, key, dest_len);
memset (tmp, 0, src_len + 2); /* paranoia */
memset (key, 0, RMD160_HASH_SIZE * 2); /* paranoia */
return dest_len;
}
static int
phash_sha256(char dest[], size_t dest_len, const char src[], size_t src_len)
{
memset(dest, 0, dest_len);
sha256_hash_buffer((char *) src, src_len, dest, dest_len);
return dest_len;
}
static int
phash_sha384(char dest[], size_t dest_len, const char src[], size_t src_len)
{
memset(dest, 0, dest_len);
sha384_hash_buffer((char *) src, src_len, dest, dest_len);
return dest_len;
}
static int
phash_sha512(char dest[], size_t dest_len, const char src[], size_t src_len)
{
memset(dest, 0, dest_len);
sha512_hash_buffer((char *) src, src_len, dest, dest_len);
return dest_len;
}
struct func_table_t {
const char *name;
phash_func_t func;
size_t def_length;
} static func_table[] = {
{ "ripemd160", phash_rmd160, 20 },
{ "rmd160", phash_rmd160, 20 },
{ "rmd160compat", phash_rmd160, 16 },
{ "sha256", phash_sha256, 32 },
{ "sha384", phash_sha384, 48 },
{ "sha512", phash_sha512, 64 },
{ 0, 0, 0 }
};
static int
show_usage(const char argv0[])
{
struct func_table_t *p = func_table;
fprintf (stderr,
"usage:\n"
" hashalot [ -x ] [ -s SALT ] [ -n _#bytes_ ] HASHTYPE\n"
" or\n"
" HASHTYPE [ -x ] [ -s SALT ] [ -n _#bytes_ ]\n"
"\n"
"supported values for HASHTYPE: ");
for (; p->name; ++p)
fprintf (stderr, "%s ", p->name);
fprintf (stderr, "\n");
return 1;
}
static phash_func_t
phash_lookup(const char phash_name[], size_t *length)
{
struct func_table_t *p = func_table;
if (!phash_name)
return 0;
for (; p->name && strcmp(phash_name, p->name); ++p);
if (length) *length = p->def_length;
return p->func;
}
/* A function to read the passphrase either from the terminal or from
* an open file descriptor */
static char *
xgetpass(const char *prompt)
{
if (isatty(STDIN_FILENO)) /* terminal */
return getpass(prompt); /* FIXME getpass(3) obsolete */
else { /* file descriptor */
char *pass = NULL;
int buflen, i;
buflen=0;
for (i=0; ; i++) {
if (i >= buflen - 1) {
/* we're running out of space in the buffer.
* Make it bigger: */
char *tmppass = pass;
buflen += 128;
pass = (char *) realloc(tmppass, buflen);
if (pass == NULL) {
/* realloc failed. Stop reading _now_. */
fprintf(stderr, "not enough memory while reading passphrase\n");
pass = tmppass; /* the old buffer hasn't changed */
break;
}
}
if (read(STDIN_FILENO, pass+i, 1) != 1 || pass[i] == '\n')
break;
}
if (pass == NULL)
return "";
else {
pass[i] = 0;
return pass;
}
}
}
static void *
xmalloc (size_t size) {
void *p;
if (size == 0)
return NULL;
p = malloc(size);
if (p == NULL) {
perror("malloc");
exit(1);
}
return p;
}
/* function to append a "salt" to the passphrase, to better resist
* dictionary attacks */
static char *
salt_passphrase(char *pass, const char *salt) {
char *buf = xmalloc(strlen(pass) + strlen(salt) + 1);
sprintf(buf, "%s%s", pass, salt);
memset (pass, 0, strlen (pass)); /* paranoia */
free(pass);
return buf;
}
static void
hexify(char *hash, size_t hashlen) {
int i;
char *h = xmalloc(hashlen);
memcpy(h, hash, hashlen);
for (i=0; i < hashlen; i++)
snprintf((hash + 2*i), 3, "%.2x", (unsigned char) h[i]);
strcat(hash, "\n");
memset(h, 0, hashlen); /* paranoia */
free(h);
}
int
main(int argc, char *argv[])
{
char *pass, *passhash, *salt = NULL, *p;
size_t hashlen = 0;
phash_func_t func;
int hex_output = 0, c;
int quiet = 0;
while ((c = getopt(argc, argv, "n:s:qx")) != -1) {
switch (c) {
case 'n':
hashlen = strtoul(optarg, &p, 0);
if (*p != '\0' || *optarg == '\0') {
fprintf (stderr,
"%s: argument to -n option must be numeric\n",
argv[0]);
show_usage(argv[0]);
exit(EXIT_FAILURE);
}
break;
case 's':
salt = optarg;
break;
case 'q':
quiet++;
break;
case 'x':
hex_output++;
break;
default:
show_usage(argv[0]);
exit(EXIT_FAILURE);
}
}
if (!(func = phash_lookup(basename(argv[0]), (hashlen ? NULL : &hashlen))))
/* lookup failed, so try next argv */
if (!(func = phash_lookup(argv[optind], (hashlen ? NULL : &hashlen)))) {
/* lookup failed again */
fprintf (stderr,
"%s: missing or unknown hash type requested\n",
argv[0]);
show_usage(argv[0]);
exit(EXIT_FAILURE);
}
assert (func != 0);
/* allocate memory for the password hash:
* enough for 2 hex digits per byte of the requested hash length,
* plus a newline, plus a null */
passhash = xmalloc(2*hashlen + 2);
/* try to lock memory so it doesn't get swapped out for sure */
if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1 && !quiet) {
perror("mlockall");
fputs("Warning: couldn't lock memory, are you root?\n", stderr);
}
/* here we acquire the precious passphrase... */
pass = xgetpass("Enter passphrase: ");
if (salt)
pass = salt_passphrase(pass, salt);
hashlen = func(passhash, hashlen, pass, strlen(pass));
memset (pass, 0, strlen (pass)); /* paranoia */
free(pass);
if (hex_output) {
hexify(passhash, hashlen);
hashlen = hashlen * 2 + 1;
}
if (write(STDOUT_FILENO, passhash, hashlen) != hashlen)
perror("write");
memset (passhash, 0, hashlen); /* paranoia again */
free(passhash);
exit(EXIT_SUCCESS);
}
| ViewVC Help | |
| Powered by ViewVC 1.0.5 |