(root)/
coreutils-9.4/
src/
blake2/
b2sum.c
       1  /*
       2     BLAKE2 reference source code package - b2sum tool
       3  
       4     Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the
       5     terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
       6     your option.  The terms of these licenses can be found at:
       7  
       8     - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
       9     - OpenSSL license   : https://www.openssl.org/source/license.html
      10     - Apache 2.0        : https://www.apache.org/licenses/LICENSE-2.0
      11  
      12     More information about the BLAKE2 hash function can be found at
      13     https://blake2.net.
      14  */
      15  
      16  #ifdef HAVE_CONFIG_H
      17  # include <config.h>
      18  #endif
      19  
      20  #include <stdio.h>
      21  #include <stdlib.h>
      22  #include <string.h>
      23  #include <errno.h>
      24  
      25  #include <ctype.h>
      26  #include <unistd.h>
      27  #include <getopt.h>
      28  
      29  #include "blake2.h"
      30  
      31  #if 0
      32  /* This will help compatibility with coreutils */
      33  int blake2s_stream( FILE *stream, void *resstream, size_t outbytes )
      34  {
      35    int ret = -1;
      36    size_t sum, n;
      37    blake2s_state S[1];
      38    static const size_t buffer_length = 32768;
      39    uint8_t *buffer = ( uint8_t * )malloc( buffer_length );
      40  
      41    if( !buffer ) return -1;
      42  
      43    blake2s_init( S, outbytes );
      44  
      45    while( 1 )
      46    {
      47      sum = 0;
      48  
      49      while( 1 )
      50      {
      51        n = fread( buffer + sum, 1, buffer_length - sum, stream );
      52        sum += n;
      53  
      54        if( buffer_length == sum )
      55          break;
      56  
      57        if( 0 == n )
      58        {
      59          if( ferror( stream ) )
      60            goto cleanup_buffer;
      61  
      62          goto final_process;
      63        }
      64  
      65        if( feof( stream ) )
      66          goto final_process;
      67      }
      68  
      69      blake2s_update( S, buffer, buffer_length );
      70    }
      71  
      72  final_process:;
      73  
      74    if( sum > 0 ) blake2s_update( S, buffer, sum );
      75  
      76    blake2s_final( S, resstream, outbytes );
      77    ret = 0;
      78  cleanup_buffer:
      79    free( buffer );
      80    return ret;
      81  }
      82  #endif
      83  
      84  int blake2b_stream( FILE *stream, void *resstream, size_t outbytes )
      85  {
      86    int ret = -1;
      87    size_t sum, n;
      88    blake2b_state S[1];
      89    static const size_t buffer_length = 32768;
      90    uint8_t *buffer = ( uint8_t * )malloc( buffer_length );
      91  
      92    if( !buffer ) return -1;
      93  
      94    blake2b_init( S, outbytes );
      95  
      96    while( 1 )
      97    {
      98      sum = 0;
      99  
     100      while( 1 )
     101      {
     102        n = fread( buffer + sum, 1, buffer_length - sum, stream );
     103        sum += n;
     104  
     105        if( buffer_length == sum )
     106          break;
     107  
     108        if( 0 == n )
     109        {
     110          if( ferror( stream ) )
     111            goto cleanup_buffer;
     112  
     113          goto final_process;
     114        }
     115  
     116        if( feof( stream ) )
     117          goto final_process;
     118      }
     119  
     120      blake2b_update( S, buffer, buffer_length );
     121    }
     122  
     123  final_process:;
     124  
     125    if( sum > 0 ) blake2b_update( S, buffer, sum );
     126  
     127    blake2b_final( S, resstream, outbytes );
     128    ret = 0;
     129  cleanup_buffer:
     130    free( buffer );
     131    return ret;
     132  }
     133  
     134  #if 0
     135  
     136  int blake2sp_stream( FILE *stream, void *resstream, size_t outbytes )
     137  {
     138    int ret = -1;
     139    size_t sum, n;
     140    blake2sp_state S[1];
     141    static const size_t buffer_length = 16 * ( 1UL << 20 );
     142    uint8_t *buffer = ( uint8_t * )malloc( buffer_length );
     143  
     144    if( !buffer ) return -1;
     145  
     146    blake2sp_init( S, outbytes );
     147  
     148    while( 1 )
     149    {
     150      sum = 0;
     151  
     152      while( 1 )
     153      {
     154        n = fread( buffer + sum, 1, buffer_length - sum, stream );
     155        sum += n;
     156  
     157        if( buffer_length == sum )
     158          break;
     159  
     160        if( 0 == n )
     161        {
     162          if( ferror( stream ) )
     163            goto cleanup_buffer;
     164  
     165          goto final_process;
     166        }
     167  
     168        if( feof( stream ) )
     169          goto final_process;
     170      }
     171  
     172      blake2sp_update( S, buffer, buffer_length );
     173    }
     174  
     175  final_process:;
     176  
     177    if( sum > 0 ) blake2sp_update( S, buffer, sum );
     178  
     179    blake2sp_final( S, resstream, outbytes );
     180    ret = 0;
     181  cleanup_buffer:
     182    free( buffer );
     183    return ret;
     184  }
     185  
     186  
     187  int blake2bp_stream( FILE *stream, void *resstream, size_t outbytes )
     188  {
     189    int ret = -1;
     190    size_t sum, n;
     191    blake2bp_state S[1];
     192    static const size_t buffer_length = 16 * ( 1UL << 20 );
     193    uint8_t *buffer = ( uint8_t * )malloc( buffer_length );
     194  
     195    if( !buffer ) return -1;
     196  
     197    blake2bp_init( S, outbytes );
     198  
     199    while( 1 )
     200    {
     201      sum = 0;
     202  
     203      while( 1 )
     204      {
     205        n = fread( buffer + sum, 1, buffer_length - sum, stream );
     206        sum += n;
     207  
     208        if( buffer_length == sum )
     209          break;
     210  
     211        if( 0 == n )
     212        {
     213          if( ferror( stream ) )
     214            goto cleanup_buffer;
     215  
     216          goto final_process;
     217        }
     218  
     219        if( feof( stream ) )
     220          goto final_process;
     221      }
     222  
     223      blake2bp_update( S, buffer, buffer_length );
     224    }
     225  
     226  final_process:;
     227  
     228    if( sum > 0 ) blake2bp_update( S, buffer, sum );
     229  
     230    blake2bp_final( S, resstream, outbytes );
     231    ret = 0;
     232  cleanup_buffer:
     233    free( buffer );
     234    return ret;
     235  }
     236  
     237  typedef int ( *blake2fn )( FILE *, void *, size_t );
     238  
     239  
     240  static void usage( char **argv, int errcode )
     241  {
     242    FILE *out = errcode ? stderr : stdout;
     243    fprintf( out, "Usage: %s [OPTION]... [FILE]...\n", argv[0] );
     244    fprintf( out, "\n" );
     245    fprintf( out, "With no FILE, or when FILE is -, read standard input.\n" );
     246    fprintf( out, "\n" );
     247    fprintf( out, "  -a <algo>    hash algorithm (blake2b is default): \n"
     248                  "               [blake2b|blake2s|blake2bp|blake2sp]\n" );
     249    fprintf( out, "  -l <length>  digest length in bits, must not exceed the maximum for\n"
     250                  "               the selected algorithm and must be a multiple of 8\n" );
     251    fprintf( out, "  --tag        create a BSD-style checksum\n" );
     252    fprintf( out, "  --help       display this help and exit\n" );
     253    exit( errcode );
     254  }
     255  
     256  
     257  int main( int argc, char **argv )
     258  {
     259    blake2fn blake2_stream = blake2b_stream;
     260    unsigned long maxbytes = BLAKE2B_OUTBYTES;
     261    const char *algorithm = "BLAKE2b";
     262    unsigned long outbytes = 0;
     263    unsigned char hash[BLAKE2B_OUTBYTES] = {0};
     264    bool bsdstyle = false;
     265    int c, i;
     266    opterr = 1;
     267  
     268    while( 1 )
     269    {
     270      int option_index = 0;
     271      char *end = nullptr;
     272      unsigned long outbits;
     273      static struct option long_options[] = {
     274        { "help",  no_argument, 0,  0  },
     275        { "tag",   no_argument, 0,  0  },
     276        { nullptr, 0, nullptr, 0 }
     277      };
     278  
     279      c = getopt_long( argc, argv, "a:l:", long_options, &option_index );
     280      if( c == -1 ) break;
     281      switch( c )
     282      {
     283      case 'a':
     284        if( 0 == strcmp( optarg, "blake2b" ) )
     285        {
     286          blake2_stream = blake2b_stream;
     287          maxbytes = BLAKE2B_OUTBYTES;
     288          algorithm = "BLAKE2b";
     289        }
     290        else if ( 0 == strcmp( optarg, "blake2s" ) )
     291        {
     292          blake2_stream = blake2s_stream;
     293          maxbytes = BLAKE2S_OUTBYTES;
     294          algorithm = "BLAKE2s";
     295        }
     296        else if ( 0 == strcmp( optarg, "blake2bp" ) )
     297        {
     298          blake2_stream = blake2bp_stream;
     299          maxbytes = BLAKE2B_OUTBYTES;
     300          algorithm = "BLAKE2bp";
     301        }
     302        else if ( 0 == strcmp( optarg, "blake2sp" ) )
     303        {
     304          blake2_stream = blake2sp_stream;
     305          maxbytes = BLAKE2S_OUTBYTES;
     306          algorithm = "BLAKE2sp";
     307        }
     308        else
     309        {
     310          printf( "Invalid function name: `%s'\n", optarg );
     311          usage( argv, 111 );
     312        }
     313  
     314        break;
     315  
     316      case 'l':
     317        outbits = strtoul(optarg, &end, 10);
     318        if( !end || *end != '\0' || outbits % 8 != 0)
     319        {
     320          printf( "Invalid length argument: `%s'\n", optarg);
     321          usage( argv, 111 );
     322        }
     323        outbytes = outbits / 8;
     324        break;
     325  
     326      case 0:
     327        if( 0 == strcmp( "help", long_options[option_index].name ) )
     328          usage( argv, 0 );
     329        else if( 0 == strcmp( "tag", long_options[option_index].name ) )
     330          bsdstyle = true;
     331        break;
     332  
     333      case '?':
     334        usage( argv, 1 );
     335        break;
     336      }
     337    }
     338  
     339    if(outbytes > maxbytes)
     340    {
     341      printf( "Invalid length argument: %lu\n", outbytes * 8 );
     342      printf( "Maximum digest length for %s is %lu\n", algorithm, maxbytes * 8 );
     343      usage( argv, 111 );
     344    }
     345    else if( outbytes == 0 )
     346      outbytes = maxbytes;
     347  
     348    if( optind == argc )
     349      argv[argc++] = (char *) "-";
     350  
     351    for( i = optind; i < argc; ++i )
     352    {
     353      FILE *f = nullptr;
     354      if( argv[i][0] == '-' && argv[i][1] == '\0' )
     355        f = stdin;
     356      else
     357        f = fopen( argv[i], "rb" );
     358  
     359      if( !f )
     360      {
     361        fprintf( stderr, "Could not open `%s': %s\n", argv[i], strerror( errno ) );
     362        continue;
     363      }
     364  
     365      if( blake2_stream( f, hash, outbytes ) < 0 )
     366      {
     367        fprintf( stderr, "Failed to hash `%s'\n", argv[i] );
     368      }
     369      else
     370      {
     371        size_t j;
     372        if( bsdstyle )
     373        {
     374          if( outbytes < maxbytes )
     375            printf( "%s-%lu (%s) = ", algorithm, outbytes * 8, argv[i] );
     376          else
     377            printf( "%s (%s) = ", algorithm, argv[i] );
     378        }
     379  
     380        for( j = 0; j < outbytes; ++j )
     381          printf( "%02x", hash[j] );
     382  
     383        if( bsdstyle )
     384          printf( "\n" );
     385        else
     386          printf( "  %s\n", argv[i] );
     387      }
     388  
     389      if( f == stdin )
     390        clearerr( f );
     391      else if( fclose( f ) != 0 )
     392        fprintf( stderr, "Could not close `%s': %s\n", argv[i], strerror( errno ) );
     393    }
     394  
     395    return 0;
     396  }
     397  #endif