gostsum.c revision 238405
116566Ssos/********************************************************************** 216566Ssos * gostsum.c * 316566Ssos * Copyright (c) 2005-2006 Cryptocom LTD * 416566Ssos * This file is distributed under the same license as OpenSSL * 516566Ssos * * 616566Ssos * Almost drop-in replacement for md5sum and sha1sum * 716566Ssos * which computes GOST R 34.11-94 hashsum instead * 816566Ssos * * 916566Ssos **********************************************************************/ 1016566Ssos#include <stdio.h> 1116566Ssos#include <stdlib.h> 1216566Ssos#include <unistd.h> 1316566Ssos#include <limits.h> 1416566Ssos#include <fcntl.h> 1516566Ssos#include <string.h> 1616566Ssos#include "gosthash.h" 1716566Ssos#define BUF_SIZE 262144 1816566Ssosint hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode); 1916566Ssosint hash_stream(gost_hash_ctx *ctx,int fd, char *sum); 2016566Ssosint get_line(FILE *f,char *hash,char *filename); 2116566Ssosvoid help() 2216566Ssos { 2316566Ssos fprintf(stderr,"gostsum [-bvt] [-c [file]]| [files]\n" 2416566Ssos "\t-c check message digests (default is generate)\n" 2516566Ssos "\t-v verbose, print file names when checking\n" 2616566Ssos "\t-b read files in binary mode\n" 2716566Ssos "\t-t use test GOST paramset (default is CryptoPro paramset)\n" 2816566Ssos "The input for -c should be the list of message digests and file names\n" 2916566Ssos "that is printed on stdout by this program when it generates digests.\n"); 3016566Ssos exit(3); 3116566Ssos } 3216566Ssos 3316566Ssos#ifndef O_BINARY 3416566Ssos#define O_BINARY 0 3516566Ssos#endif 3616566Ssos 3731604Syokotaint main(int argc,char **argv) 3831604Syokota { 3931604Syokota int c,i; 4016566Ssos int verbose=0; 4116566Ssos int errors=0; 4216566Ssos int open_mode = O_RDONLY; 4316566Ssos gost_subst_block *b= &GostR3411_94_CryptoProParamSet; 4416566Ssos FILE *check_file = NULL; 4516566Ssos gost_hash_ctx ctx; 4616566Ssos 4729849Scharnier while( (c=getopt(argc,argv,"bc::tv"))!=-1) 4829849Scharnier { 4931726Syokota switch (c) 5029849Scharnier { 5129849Scharnier case 'v': verbose=1; break; 5229849Scharnier case 't': b= &GostR3411_94_TestParamSet; break; 5329849Scharnier case 'b': open_mode |= O_BINARY; break; 5429849Scharnier case 'c': 5529849Scharnier if (optarg) 5616566Ssos { 5716566Ssos check_file = fopen(optarg,"r"); 5831604Syokota if (!check_file) 5916566Ssos { 6031604Syokota perror(optarg); 6131604Syokota exit(2); 6231604Syokota } 6316566Ssos } 6431604Syokota else 6531604Syokota { 6616566Ssos check_file= stdin; 6731604Syokota } 6831604Syokota break; 6921885Ssos default: 7021885Ssos fprintf(stderr,"invalid option %c",optopt); 7121885Ssos help(); 7216566Ssos } 7331604Syokota } 7431604Syokota init_gost_hash_ctx(&ctx,b); 7531604Syokota if (check_file) 7631604Syokota { 7731604Syokota char inhash[65],calcsum[65],filename[PATH_MAX]; 7831604Syokota int failcount=0,count=0;; 7931604Syokota if (check_file==stdin && optind<argc) 8031604Syokota { 8131604Syokota check_file=fopen(argv[optind],"r"); 8231604Syokota if (!check_file) 8331604Syokota { 8431604Syokota perror(argv[optind]); 8531604Syokota exit(2); 8631604Syokota } 8731604Syokota } 8831604Syokota while (get_line(check_file,inhash,filename)) 8931604Syokota { 9031604Syokota if (!hash_file(&ctx,filename,calcsum,open_mode)) 9131604Syokota { 9231604Syokota exit (2); 9331604Syokota } 9416566Ssos count++; 9529849Scharnier if (!strncmp(calcsum,inhash,65)) 9616566Ssos { 9731604Syokota if (verbose) 9831604Syokota { 9931604Syokota fprintf(stderr,"%s\tOK\n",filename); 10031604Syokota } 10131604Syokota } 10231604Syokota else 10331604Syokota { 10431604Syokota if (verbose) 10531604Syokota { 10631604Syokota fprintf(stderr,"%s\tFAILED\n",filename); 10731604Syokota } 10831604Syokota else 10931604Syokota { 11031604Syokota fprintf(stderr,"%s: GOST hash sum check failed for '%s'\n", 11131604Syokota argv[0],filename); 11231604Syokota } 11331604Syokota failcount++; 11431604Syokota } 11531604Syokota } 11631604Syokota if (verbose && failcount) 11731604Syokota { 11831604Syokota fprintf(stderr,"%s: %d of %d file(f) failed GOST hash sum check\n", 11931604Syokota argv[0],failcount,count); 12031604Syokota } 12131604Syokota exit (failcount?1:0); 12231604Syokota } 12331604Syokota if (optind==argc) 12431604Syokota { 12531604Syokota char sum[65]; 12631604Syokota if (!hash_stream(&ctx,fileno(stdin),sum)) 12731604Syokota { 12831604Syokota perror("stdin"); 12931604Syokota exit(1); 13031604Syokota } 13131604Syokota printf("%s -\n",sum); 13231604Syokota exit(0); 13331604Syokota } 13431604Syokota for (i=optind;i<argc;i++) 13531604Syokota { 13631604Syokota char sum[65]; 13731604Syokota if (!hash_file(&ctx,argv[i],sum,open_mode)) 13831604Syokota { 13931604Syokota errors++; 14031604Syokota } 14131604Syokota else 14231604Syokota { 14331604Syokota printf("%s %s\n",sum,argv[i]); 14431604Syokota } 14531604Syokota } 14631604Syokota exit(errors?1:0); 14731604Syokota } 14831604Syokota 14931604Syokotaint hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode) 15031604Syokota { 15131604Syokota int fd; 15231604Syokota if ((fd=open(filename,mode))<0) 15316566Ssos { 15431604Syokota perror(filename); 15531604Syokota return 0; 15631604Syokota } 15731604Syokota if (!hash_stream(ctx,fd,sum)) 15816566Ssos { 15931604Syokota perror(filename); 16016566Ssos return 0; 16131604Syokota } 16231604Syokota close(fd); 16331604Syokota return 1; 16431604Syokota } 16531604Syokota 16631604Syokotaint hash_stream(gost_hash_ctx *ctx,int fd, char *sum) 16731604Syokota { 16831604Syokota unsigned char buffer[BUF_SIZE]; 16931604Syokota ssize_t bytes; 17016566Ssos int i; 17131604Syokota start_hash(ctx); 17231604Syokota while ((bytes=read(fd,buffer,BUF_SIZE))>0) 17316566Ssos { 17416566Ssos hash_block(ctx,buffer,bytes); 17531604Syokota } 17616566Ssos if (bytes<0) 17731604Syokota { 17816566Ssos return 0; 17931604Syokota } 18016566Ssos finish_hash(ctx,buffer); 18118222Speter for (i=0;i<32;i++) 18231604Syokota { 18331604Syokota sprintf(sum+2*i,"%02x",buffer[31-i]); 18431604Syokota } 18531604Syokota return 1; 18631604Syokota } 18731604Syokota 18831604Syokotaint get_line(FILE *f,char *hash,char *filename) 18916566Ssos { 19016566Ssos int i; 19116566Ssos if (fread(hash,1,64,f)<64) return 0; 19231604Syokota hash[64]=0; 19331604Syokota for (i=0;i<64;i++) 19431604Syokota { 19531604Syokota if (hash[i]<'0' || (hash[i]>'9' && hash[i]<'A') || (hash[i]>'F' 19631604Syokota && hash[i]<'a')||hash[i]>'f') 19731604Syokota { 19831604Syokota fprintf(stderr,"Not a hash value '%s'\n",hash); 19931604Syokota return 0; 20031604Syokota } 20131604Syokota } 20231604Syokota if (fgetc(f)!=' ') 20331604Syokota { 20431604Syokota fprintf(stderr,"Malformed input line\n"); 20531604Syokota return 0; 20631604Syokota } 20731604Syokota i=strlen(fgets(filename,PATH_MAX,f)); 20831604Syokota while (filename[--i]=='\n'||filename[i]=='\r') filename[i]=0; 20931604Syokota return 1; 21031604Syokota } 21131604Syokota