| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #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 |
|
|