Use properly local variables for thread-safety.
[openssl.git] / engines / ccgost / gostsum.c
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;
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 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         }