OLD | NEW |
(Empty) | |
| 1 /********************************************************************** |
| 2 * gostsum.c * |
| 3 * Copyright (c) 2005-2006 Cryptocom LTD * |
| 4 * This file is distributed under the same license as OpenSSL * |
| 5 * * |
| 6 * Almost drop-in replacement for md5sum and sha1sum * |
| 7 * which computes GOST R 34.11-94 hashsum instead * |
| 8 * * |
| 9 **********************************************************************/ |
| 10 #include <stdio.h> |
| 11 #include <stdlib.h> |
| 12 #include <unistd.h> |
| 13 #include <limits.h> |
| 14 #include <fcntl.h> |
| 15 #include <string.h> |
| 16 #include "gosthash.h" |
| 17 #define BUF_SIZE 262144 |
| 18 int hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode); |
| 19 int hash_stream(gost_hash_ctx *ctx,int fd, char *sum); |
| 20 int get_line(FILE *f,char *hash,char *filename); |
| 21 void help() |
| 22 { |
| 23 fprintf(stderr,"gostsum [-bvt] [-c [file]]| [files]\n" |
| 24 "\t-c check message digests (default is generate)\n" |
| 25 "\t-v verbose, print file names when checking\n" |
| 26 "\t-b read files in binary mode\n" |
| 27 "\t-t use test GOST paramset (default is CryptoPro paramset)\n" |
| 28 "The input for -c should be the list of message digests and file
names\n" |
| 29 "that is printed on stdout by this program when it generates dig
ests.\n"); |
| 30 exit(3); |
| 31 } |
| 32 |
| 33 #ifndef O_BINARY |
| 34 #define O_BINARY 0 |
| 35 #endif |
| 36 |
| 37 int main(int argc,char **argv) |
| 38 { |
| 39 int c,i; |
| 40 int verbose=0; |
| 41 int errors=0; |
| 42 int open_mode = O_RDONLY; |
| 43 gost_subst_block *b= &GostR3411_94_CryptoProParamSet; |
| 44 FILE *check_file = NULL; |
| 45 gost_hash_ctx ctx; |
| 46 |
| 47 while( (c=getopt(argc,argv,"bc::tv"))!=-1) |
| 48 { |
| 49 switch (c) |
| 50 { |
| 51 case 'v': verbose=1; break; |
| 52 case 't': b= &GostR3411_94_TestParamSet; break; |
| 53 case 'b': open_mode |= O_BINARY; break; |
| 54 case 'c': |
| 55 if (optarg) |
| 56 { |
| 57 check_file = fopen(optarg,"r"); |
| 58 if (!check_file) |
| 59 { |
| 60 perror(optarg); |
| 61 exit(2); |
| 62 } |
| 63 } |
| 64 else |
| 65 { |
| 66 check_file= stdin; |
| 67 } |
| 68 break; |
| 69 default: |
| 70 fprintf(stderr,"invalid option %c",optopt); |
| 71 help(); |
| 72 } |
| 73 } |
| 74 init_gost_hash_ctx(&ctx,b); |
| 75 if (check_file) |
| 76 { |
| 77 char inhash[65],calcsum[65],filename[PATH_MAX]; |
| 78 int failcount=0,count=0;; |
| 79 if (check_file==stdin && optind<argc) |
| 80 { |
| 81 check_file=fopen(argv[optind],"r"); |
| 82 if (!check_file) |
| 83 { |
| 84 perror(argv[optind]); |
| 85 exit(2); |
| 86 } |
| 87 } |
| 88 while (get_line(check_file,inhash,filename)) |
| 89 { |
| 90 if (!hash_file(&ctx,filename,calcsum,open_mode)) |
| 91 { |
| 92 exit (2); |
| 93 } |
| 94 count++; |
| 95 if (!strncmp(calcsum,inhash,65)) |
| 96 { |
| 97 if (verbose) |
| 98 { |
| 99 fprintf(stderr,"%s\tOK\n",filename); |
| 100 } |
| 101 } |
| 102 else |
| 103 { |
| 104 if (verbose) |
| 105 { |
| 106 fprintf(stderr,"%s\tFAILED\n",filename); |
| 107 } |
| 108 else |
| 109 { |
| 110 fprintf(stderr,"%s: GOST hash sum check
failed for '%s'\n", |
| 111 argv[0],filename); |
| 112 } |
| 113 failcount++; |
| 114 } |
| 115 } |
| 116 if (verbose && failcount) |
| 117 { |
| 118 fprintf(stderr,"%s: %d of %d file(f) failed GOST hash su
m check\n", |
| 119 argv[0],failcount,count); |
| 120 } |
| 121 exit (failcount?1:0); |
| 122 } |
| 123 if (optind==argc) |
| 124 { |
| 125 char sum[65]; |
| 126 if (!hash_stream(&ctx,fileno(stdin),sum)) |
| 127 { |
| 128 perror("stdin"); |
| 129 exit(1); |
| 130 } |
| 131 printf("%s -\n",sum); |
| 132 exit(0); |
| 133 } |
| 134 for (i=optind;i<argc;i++) |
| 135 { |
| 136 char sum[65]; |
| 137 if (!hash_file(&ctx,argv[i],sum,open_mode)) |
| 138 { |
| 139 errors++; |
| 140 } |
| 141 else |
| 142 { |
| 143 printf("%s %s\n",sum,argv[i]); |
| 144 } |
| 145 } |
| 146 exit(errors?1:0); |
| 147 } |
| 148 |
| 149 int hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode) |
| 150 { |
| 151 int fd; |
| 152 if ((fd=open(filename,mode))<0) |
| 153 { |
| 154 perror(filename); |
| 155 return 0; |
| 156 } |
| 157 if (!hash_stream(ctx,fd,sum)) |
| 158 { |
| 159 perror(filename); |
| 160 return 0; |
| 161 } |
| 162 close(fd); |
| 163 return 1; |
| 164 } |
| 165 |
| 166 int hash_stream(gost_hash_ctx *ctx,int fd, char *sum) |
| 167 { |
| 168 unsigned char buffer[BUF_SIZE]; |
| 169 ssize_t bytes; |
| 170 int i; |
| 171 start_hash(ctx); |
| 172 while ((bytes=read(fd,buffer,BUF_SIZE))>0) |
| 173 { |
| 174 hash_block(ctx,buffer,bytes); |
| 175 } |
| 176 if (bytes<0) |
| 177 { |
| 178 return 0; |
| 179 } |
| 180 finish_hash(ctx,buffer); |
| 181 for (i=0;i<32;i++) |
| 182 { |
| 183 sprintf(sum+2*i,"%02x",buffer[31-i]); |
| 184 } |
| 185 return 1; |
| 186 } |
| 187 |
| 188 int get_line(FILE *f,char *hash,char *filename) |
| 189 { |
| 190 int i; |
| 191 if (fread(hash,1,64,f)<64) return 0; |
| 192 hash[64]=0; |
| 193 for (i=0;i<64;i++) |
| 194 { |
| 195 if (hash[i]<'0' || (hash[i]>'9' && hash[i]<'A') || (hash[i]>'F' |
| 196 && hash[i]<'a')||hash[i]>'f') |
| 197 { |
| 198 fprintf(stderr,"Not a hash value '%s'\n",hash); |
| 199 return 0; |
| 200 } |
| 201 } |
| 202 if (fgetc(f)!=' ') |
| 203 { |
| 204 fprintf(stderr,"Malformed input line\n"); |
| 205 return 0; |
| 206 } |
| 207 i=strlen(fgets(filename,PATH_MAX,f)); |
| 208 while (filename[--i]=='\n'||filename[i]=='\r') filename[i]=0; |
| 209 return 1; |
| 210 } |
OLD | NEW |