OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
gostsum.c
Go to the documentation of this file.
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 digests.\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;
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 sum 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  }