diff options
Diffstat (limited to '')
-rw-r--r-- | src/blake2/b2sum.c | 396 |
1 files changed, 396 insertions, 0 deletions
diff --git a/src/blake2/b2sum.c b/src/blake2/b2sum.c new file mode 100644 index 0000000..9f11081 --- /dev/null +++ b/src/blake2/b2sum.c @@ -0,0 +1,396 @@ +/* + 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 : https://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#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" + +#if 0 +/* 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; +} +#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 + +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; +} +#endif |