|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H |
|
|
# include <config.h> |
|
|
#endif |
|
|
|
|
|
#include <stdio.h> |
|
|
#include <stdlib.h> |
|
|
|
|
|
#include "blake2.h" |
|
|
|
|
|
#if 0 |
|
|
|
|
|
int blake2s_stream( FILE *stream, void *resstream, size_t outbytes ) |
|
|
{ |
|
|
int ret = -1; |
|
|
size_t sum, n; |
|
|
blake2s_state S[1]; |
|
|
static const size_t buffer_length = 32768; |
|
|
uint8_t *buffer = ( uint8_t * )malloc( buffer_length ); |
|
|
|
|
|
if( !buffer ) return -1; |
|
|
|
|
|
blake2s_init( S, outbytes ); |
|
|
|
|
|
while( 1 ) |
|
|
{ |
|
|
sum = 0; |
|
|
|
|
|
while( 1 ) |
|
|
{ |
|
|
n = fread( buffer + sum, 1, buffer_length - sum, stream ); |
|
|
sum += n; |
|
|
|
|
|
if( buffer_length == sum ) |
|
|
break; |
|
|
|
|
|
if( 0 == n ) |
|
|
{ |
|
|
if( ferror( stream ) ) |
|
|
goto cleanup_buffer; |
|
|
|
|
|
goto final_process; |
|
|
} |
|
|
|
|
|
if( feof( stream ) ) |
|
|
goto final_process; |
|
|
} |
|
|
|
|
|
blake2s_update( S, buffer, buffer_length ); |
|
|
} |
|
|
|
|
|
final_process:; |
|
|
|
|
|
if( sum > 0 ) blake2s_update( S, buffer, sum ); |
|
|
|
|
|
blake2s_final( S, resstream, outbytes ); |
|
|
ret = 0; |
|
|
cleanup_buffer: |
|
|
free( buffer ); |
|
|
return ret; |
|
|
} |
|
|
#endif |
|
|
|
|
|
int blake2b_stream( FILE *stream, void *resstream, size_t outbytes ) |
|
|
{ |
|
|
int ret = -1; |
|
|
size_t sum, n; |
|
|
blake2b_state S[1]; |
|
|
static const size_t buffer_length = 32768; |
|
|
uint8_t *buffer = ( uint8_t * )malloc( buffer_length ); |
|
|
|
|
|
if( !buffer ) return -1; |
|
|
|
|
|
blake2b_init( S, outbytes ); |
|
|
|
|
|
while( 1 ) |
|
|
{ |
|
|
sum = 0; |
|
|
|
|
|
while( 1 ) |
|
|
{ |
|
|
n = fread( buffer + sum, 1, buffer_length - sum, stream ); |
|
|
sum += n; |
|
|
|
|
|
if( buffer_length == sum ) |
|
|
break; |
|
|
|
|
|
if( 0 == n ) |
|
|
{ |
|
|
if( ferror( stream ) ) |
|
|
goto cleanup_buffer; |
|
|
|
|
|
goto final_process; |
|
|
} |
|
|
|
|
|
if( feof( stream ) ) |
|
|
goto final_process; |
|
|
} |
|
|
|
|
|
blake2b_update( S, buffer, buffer_length ); |
|
|
} |
|
|
|
|
|
final_process:; |
|
|
|
|
|
if( sum > 0 ) blake2b_update( S, buffer, sum ); |
|
|
|
|
|
blake2b_final( S, resstream, outbytes ); |
|
|
ret = 0; |
|
|
cleanup_buffer: |
|
|
free( buffer ); |
|
|
return ret; |
|
|
} |
|
|
|
|
|
#if 0 |
|
|
|
|
|
#include <errno.h> |
|
|
#include <getopt.h> |
|
|
#include <string.h> |
|
|
#include <unistd.h> |
|
|
|
|
|
int blake2sp_stream( FILE *stream, void *resstream, size_t outbytes ) |
|
|
{ |
|
|
int ret = -1; |
|
|
size_t sum, n; |
|
|
blake2sp_state S[1]; |
|
|
static const size_t buffer_length = 16 * ( 1UL << 20 ); |
|
|
uint8_t *buffer = ( uint8_t * )malloc( buffer_length ); |
|
|
|
|
|
if( !buffer ) return -1; |
|
|
|
|
|
blake2sp_init( S, outbytes ); |
|
|
|
|
|
while( 1 ) |
|
|
{ |
|
|
sum = 0; |
|
|
|
|
|
while( 1 ) |
|
|
{ |
|
|
n = fread( buffer + sum, 1, buffer_length - sum, stream ); |
|
|
sum += n; |
|
|
|
|
|
if( buffer_length == sum ) |
|
|
break; |
|
|
|
|
|
if( 0 == n ) |
|
|
{ |
|
|
if( ferror( stream ) ) |
|
|
goto cleanup_buffer; |
|
|
|
|
|
goto final_process; |
|
|
} |
|
|
|
|
|
if( feof( stream ) ) |
|
|
goto final_process; |
|
|
} |
|
|
|
|
|
blake2sp_update( S, buffer, buffer_length ); |
|
|
} |
|
|
|
|
|
final_process:; |
|
|
|
|
|
if( sum > 0 ) blake2sp_update( S, buffer, sum ); |
|
|
|
|
|
blake2sp_final( S, resstream, outbytes ); |
|
|
ret = 0; |
|
|
cleanup_buffer: |
|
|
free( buffer ); |
|
|
return ret; |
|
|
} |
|
|
|
|
|
|
|
|
int blake2bp_stream( FILE *stream, void *resstream, size_t outbytes ) |
|
|
{ |
|
|
int ret = -1; |
|
|
size_t sum, n; |
|
|
blake2bp_state S[1]; |
|
|
static const size_t buffer_length = 16 * ( 1UL << 20 ); |
|
|
uint8_t *buffer = ( uint8_t * )malloc( buffer_length ); |
|
|
|
|
|
if( !buffer ) return -1; |
|
|
|
|
|
blake2bp_init( S, outbytes ); |
|
|
|
|
|
while( 1 ) |
|
|
{ |
|
|
sum = 0; |
|
|
|
|
|
while( 1 ) |
|
|
{ |
|
|
n = fread( buffer + sum, 1, buffer_length - sum, stream ); |
|
|
sum += n; |
|
|
|
|
|
if( buffer_length == sum ) |
|
|
break; |
|
|
|
|
|
if( 0 == n ) |
|
|
{ |
|
|
if( ferror( stream ) ) |
|
|
goto cleanup_buffer; |
|
|
|
|
|
goto final_process; |
|
|
} |
|
|
|
|
|
if( feof( stream ) ) |
|
|
goto final_process; |
|
|
} |
|
|
|
|
|
blake2bp_update( S, buffer, buffer_length ); |
|
|
} |
|
|
|
|
|
final_process:; |
|
|
|
|
|
if( sum > 0 ) blake2bp_update( S, buffer, sum ); |
|
|
|
|
|
blake2bp_final( S, resstream, outbytes ); |
|
|
ret = 0; |
|
|
cleanup_buffer: |
|
|
free( buffer ); |
|
|
return ret; |
|
|
} |
|
|
|
|
|
typedef int ( *blake2fn )( FILE *, void *, size_t ); |
|
|
|
|
|
|
|
|
static void usage( char **argv, int errcode ) |
|
|
{ |
|
|
FILE *out = errcode ? stderr : stdout; |
|
|
fprintf( out, "Usage: %s [OPTION]... [FILE]...\n", argv[0] ); |
|
|
fprintf( out, "\n" ); |
|
|
fprintf( out, "With no FILE, or when FILE is -, read standard input.\n" ); |
|
|
fprintf( out, "\n" ); |
|
|
fprintf( out, " -a <algo> hash algorithm (blake2b is default): \n" |
|
|
" [blake2b|blake2s|blake2bp|blake2sp]\n" ); |
|
|
fprintf( out, " -l <length> digest length in bits, must not exceed the maximum for\n" |
|
|
" the selected algorithm and must be a multiple of 8\n" ); |
|
|
fprintf( out, " --tag create a BSD-style checksum\n" ); |
|
|
fprintf( out, " --help display this help and exit\n" ); |
|
|
exit( errcode ); |
|
|
} |
|
|
|
|
|
|
|
|
int main( int argc, char **argv ) |
|
|
{ |
|
|
blake2fn blake2_stream = blake2b_stream; |
|
|
unsigned long maxbytes = BLAKE2B_OUTBYTES; |
|
|
const char *algorithm = "BLAKE2b"; |
|
|
unsigned long outbytes = 0; |
|
|
unsigned char hash[BLAKE2B_OUTBYTES] = {0}; |
|
|
bool bsdstyle = false; |
|
|
int c, i; |
|
|
opterr = 1; |
|
|
|
|
|
while( 1 ) |
|
|
{ |
|
|
int option_index = 0; |
|
|
char *end = nullptr; |
|
|
unsigned long outbits; |
|
|
static struct option long_options[] = { |
|
|
{ "help", no_argument, 0, 0 }, |
|
|
{ "tag", no_argument, 0, 0 }, |
|
|
{ nullptr, 0, nullptr, 0 } |
|
|
}; |
|
|
|
|
|
c = getopt_long( argc, argv, "a:l:", long_options, &option_index ); |
|
|
if( c == -1 ) break; |
|
|
switch( c ) |
|
|
{ |
|
|
case 'a': |
|
|
if( 0 == strcmp( optarg, "blake2b" ) ) |
|
|
{ |
|
|
blake2_stream = blake2b_stream; |
|
|
maxbytes = BLAKE2B_OUTBYTES; |
|
|
algorithm = "BLAKE2b"; |
|
|
} |
|
|
else if ( 0 == strcmp( optarg, "blake2s" ) ) |
|
|
{ |
|
|
blake2_stream = blake2s_stream; |
|
|
maxbytes = BLAKE2S_OUTBYTES; |
|
|
algorithm = "BLAKE2s"; |
|
|
} |
|
|
else if ( 0 == strcmp( optarg, "blake2bp" ) ) |
|
|
{ |
|
|
blake2_stream = blake2bp_stream; |
|
|
maxbytes = BLAKE2B_OUTBYTES; |
|
|
algorithm = "BLAKE2bp"; |
|
|
} |
|
|
else if ( 0 == strcmp( optarg, "blake2sp" ) ) |
|
|
{ |
|
|
blake2_stream = blake2sp_stream; |
|
|
maxbytes = BLAKE2S_OUTBYTES; |
|
|
algorithm = "BLAKE2sp"; |
|
|
} |
|
|
else |
|
|
{ |
|
|
printf( "Invalid function name: `%s'\n", optarg ); |
|
|
usage( argv, 111 ); |
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case 'l': |
|
|
outbits = strtoul(optarg, &end, 10); |
|
|
if( !end || *end != '\0' || outbits % 8 != 0) |
|
|
{ |
|
|
printf( "Invalid length argument: `%s'\n", optarg); |
|
|
usage( argv, 111 ); |
|
|
} |
|
|
outbytes = outbits / 8; |
|
|
break; |
|
|
|
|
|
case 0: |
|
|
if( 0 == strcmp( "help", long_options[option_index].name ) ) |
|
|
usage( argv, 0 ); |
|
|
else if( 0 == strcmp( "tag", long_options[option_index].name ) ) |
|
|
bsdstyle = true; |
|
|
break; |
|
|
|
|
|
case '?': |
|
|
usage( argv, 1 ); |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
if(outbytes > maxbytes) |
|
|
{ |
|
|
printf( "Invalid length argument: %lu\n", outbytes * 8 ); |
|
|
printf( "Maximum digest length for %s is %lu\n", algorithm, maxbytes * 8 ); |
|
|
usage( argv, 111 ); |
|
|
} |
|
|
else if( outbytes == 0 ) |
|
|
outbytes = maxbytes; |
|
|
|
|
|
if( optind == argc ) |
|
|
argv[argc++] = (char *) "-"; |
|
|
|
|
|
for( i = optind; i < argc; ++i ) |
|
|
{ |
|
|
FILE *f = nullptr; |
|
|
if( argv[i][0] == '-' && argv[i][1] == '\0' ) |
|
|
f = stdin; |
|
|
else |
|
|
f = fopen( argv[i], "rb" ); |
|
|
|
|
|
if( !f ) |
|
|
{ |
|
|
fprintf( stderr, "Could not open `%s': %s\n", argv[i], strerror( errno ) ); |
|
|
continue; |
|
|
} |
|
|
|
|
|
if( blake2_stream( f, hash, outbytes ) < 0 ) |
|
|
{ |
|
|
fprintf( stderr, "Failed to hash `%s'\n", argv[i] ); |
|
|
} |
|
|
else |
|
|
{ |
|
|
size_t j; |
|
|
if( bsdstyle ) |
|
|
{ |
|
|
if( outbytes < maxbytes ) |
|
|
printf( "%s-%lu (%s) = ", algorithm, outbytes * 8, argv[i] ); |
|
|
else |
|
|
printf( "%s (%s) = ", algorithm, argv[i] ); |
|
|
} |
|
|
|
|
|
for( j = 0; j < outbytes; ++j ) |
|
|
printf( "%02x", hash[j] ); |
|
|
|
|
|
if( bsdstyle ) |
|
|
printf( "\n" ); |
|
|
else |
|
|
printf( " %s\n", argv[i] ); |
|
|
} |
|
|
|
|
|
if( f == stdin ) |
|
|
clearerr( f ); |
|
|
else if( fclose( f ) != 0 ) |
|
|
fprintf( stderr, "Could not close `%s': %s\n", argv[i], strerror( errno ) ); |
|
|
} |
|
|
|
|
|
return 0; |
|
|
} |
|
|
#endif |
|
|
|