mirror of
https://github.com/BLAKE2/BLAKE2
synced 2024-11-07 14:49:17 +01:00
2407e7a40a
This falls afoul of various commit git commit hooks, so strip trailing whitespace at EOL and EOF.
388 lines
8.3 KiB
C
388 lines
8.3 KiB
C
/*
|
|
BLAKE2 reference source code package - b2sum tool
|
|
|
|
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
|
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
|
your option. The terms of these licenses can be found at:
|
|
|
|
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
|
- OpenSSL license : https://www.openssl.org/source/license.html
|
|
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
More information about the BLAKE2 hash function can be found at
|
|
https://blake2.net.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
|
|
#include <ctype.h>
|
|
#include <unistd.h>
|
|
#include <getopt.h>
|
|
#include <stdbool.h>
|
|
|
|
#include "blake2.h"
|
|
|
|
/* This will help compatibility with coreutils */
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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 = NULL;
|
|
unsigned long outbits;
|
|
static struct option long_options[] = {
|
|
{ "help", no_argument, 0, 0 },
|
|
{ "tag", no_argument, 0, 0 },
|
|
{ NULL, 0, NULL, 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 = NULL;
|
|
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 ) fclose( f );
|
|
}
|
|
|
|
return 0;
|
|
}
|