92bd5f9419f03a508b6aa19e7c13aca561be78fa
[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': if (optarg) {
55                                         check_file = fopen(optarg,"r");
56                                         if (!check_file) {
57                                                 perror(optarg);
58                                                 exit(2);
59                                         }
60                                   } else {
61                                         check_file= stdin;
62                                   }
63                                   break;
64                 default:
65                                 fprintf(stderr,"invalid option %c",optopt);
66                                 help();
67                 }
68         }       
69         init_gost_hash_ctx(&ctx,b);
70         if (check_file) 
71         {
72                 char inhash[65],calcsum[65],filename[PATH_MAX];
73                 int failcount=0,count=0;;
74                 if (check_file==stdin && optind<argc) 
75                 {
76                         check_file=fopen(argv[optind],"r");
77                         if (!check_file) 
78                         {       
79                                 perror(argv[optind]);
80                                 exit(2);
81                         }
82             }   
83                 while (get_line(check_file,inhash,filename)) 
84                 {
85                         if (!hash_file(&ctx,filename,calcsum,open_mode)) {
86                                 exit (2);
87                         }       
88                         count++;
89                         if (!strncmp(calcsum,inhash,65)) 
90                         {
91                                 if (verbose) {
92                                         fprintf(stderr,"%s\tOK\n",filename);
93                                 }
94                         } else {
95                                 if (verbose) {
96                                         fprintf(stderr,"%s\tFAILED\n",filename);
97                                 } else {
98                                         fprintf(stderr,"%s: GOST hash sum check failed for '%s'\n",
99                                                         argv[0],filename);
100                                 }
101                                 failcount++;
102                         }       
103                 }       
104                 if (verbose && failcount) {
105                         fprintf(stderr,"%s: %d of %d file(f) failed GOST hash sum check\n",
106                                         argv[0],failcount,count);
107                 }
108                 exit (failcount?1:0);
109         }
110         if (optind==argc) {
111                 char sum[65];
112                 if (!hash_stream(&ctx,fileno(stdin),sum)) {
113                         perror("stdin");
114                         exit(1);
115                 }       
116                 printf("%s -\n",sum);
117                 exit(0);
118         }       
119         for (i=optind;i<argc;i++) {
120                 char sum[65];
121                 if (!hash_file(&ctx,argv[i],sum,open_mode)) {
122                         errors++;
123                 } else {        
124                         printf("%s %s\n",sum,argv[i]);
125                 }
126         }       
127         exit(errors?1:0);       
128 }
129
130 int hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode) 
131 {
132         int fd;
133         if ((fd=open(filename,mode))<0) {
134                 perror(filename);
135                 return 0;
136         }
137         if (!hash_stream(ctx,fd,sum)) {
138                 perror(filename);
139                 return 0;
140         }       
141         close(fd);
142         return 1;
143 }
144
145 int hash_stream(gost_hash_ctx *ctx,int fd, char *sum) 
146 {
147         unsigned char buffer[BUF_SIZE];
148         ssize_t bytes;
149         int i;
150         start_hash(ctx);
151         while ((bytes=read(fd,buffer,BUF_SIZE))>0) {
152                 hash_block(ctx,buffer,bytes);
153         }
154         if (bytes<0) {
155                 return 0;
156         }       
157         finish_hash(ctx,buffer);
158         for (i=0;i<32;i++) {
159           sprintf(sum+2*i,"%02x",buffer[31-i]);
160         }
161         return 1;
162 }       
163         
164 int get_line(FILE *f,char *hash,char *filename) {
165         int i;
166         if (fread(hash,1,64,f)<64) return 0;
167         hash[64]=0;
168         for (i=0;i<64;i++) 
169         {
170                 if (hash[i]<'0' || (hash[i]>'9' && hash[i]<'A') || (hash[i]>'F'
171                     && hash[i]<'a')||hash[i]>'f') 
172                 { 
173                         fprintf(stderr,"Not a hash value '%s'\n",hash);
174                         return 0;
175                 }
176         }       
177         if (fgetc(f)!=' ') {
178                 fprintf(stderr,"Malformed input line\n");
179                 return 0;
180         }
181         i=strlen(fgets(filename,PATH_MAX,f));
182         while (filename[--i]=='\n'||filename[i]=='\r') filename[i]=0;
183         return 1;
184 }