]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost12sum.c
Fix MSVS2017 build errors.
[openssl-gost/engine.git] / gost12sum.c
1 /**********************************************************************
2  *                          gostsum12.c                               *
3  *             Copyright (c) 2005-2014 Cryptocom LTD                  *
4  *         This file is distributed under same license as OpenSSL     *
5  *                                                                    *
6  *    Implementation of GOST R 34.11-2012 hash function as            *
7  *    command line utility more or less interface                     *
8  *    compatible with md5sum and sha1sum                              *
9  *    Doesn't need OpenSSL                                            *
10  **********************************************************************/
11 #include <stdio.h>
12 #include <stdlib.h>
13 #ifdef _MSC_VER
14 #include "getopt.h"
15 # ifndef PATH_MAX
16 #  define PATH_MAX _MAX_PATH
17 # endif
18 #include <BaseTsd.h>
19 typedef SSIZE_T ssize_t;
20 #else
21 #include <unistd.h>
22 #endif
23 #include <limits.h>
24 #include <fcntl.h>
25 #ifdef _WIN32
26 # include <io.h>
27 #endif
28 #include <string.h>
29 #include "gosthash2012.h"
30
31 #define BUF_SIZE 262144
32 #define gost_hash_ctx gost2012_hash_ctx
33 #define GOST34112012Init init_gost2012_hash_ctx
34 #define GOST34112012Update gost2012_hash_block
35 #define GOST34112012Final gost2012_finish_hash
36
37 #define MAX_HASH_SIZE 128
38
39 typedef unsigned char byte;
40
41 int hashsize = 256;
42 int hash_file(gost_hash_ctx * ctx, char *filename, char *sum, int mode);
43 int hash_stream(gost_hash_ctx * ctx, int fd, char *sum);
44 int get_line(FILE *f, char *hash, char *filename, int verbose);
45
46 void help()
47 {
48     fprintf(stderr, "Calculates GOST R 34.11-2012 hash function\n\n");
49     fprintf(stderr, "gostsum12 [-bvl] [-c [file]]| [files]|-x\n"
50             "\t-c check message digests (default is generate)\n"
51             "\t-v verbose, print file names when checking\n"
52             "\t-b read files in binary mode\n"
53             "\t-l use 512 bit hash (default 256 bit)\n"
54             "\t-x read filenames from stdin rather than from arguments \n"
55             "The input for -c should be the list of message digests and file names\n"
56             "that is printed on stdout by this program when it generates digests.\n");
57     exit(3);
58 }
59
60 #ifndef O_BINARY
61 # define O_BINARY 0
62 #endif
63
64 int start_hash12(gost_hash_ctx * ctx)
65 {
66     GOST34112012Init(ctx, hashsize);
67     return 1;
68 }
69
70 int hash12_block(gost_hash_ctx * ctx, const byte * block, size_t length)
71 {
72     GOST34112012Update(ctx, block, length);
73     return 1;
74 }
75
76 int finish_hash12(gost_hash_ctx * ctx, byte * hashval)
77 {
78     GOST34112012Final(ctx, hashval);
79     return 1;
80 }
81
82 int main(int argc, char **argv)
83 {
84     int c, i;
85     int verbose = 0;
86     int errors = 0;
87     int open_mode = O_RDONLY;
88     FILE *check_file = NULL;
89     int filenames_from_stdin = 0;
90     gost_hash_ctx ctx;
91
92     while ((c = getopt(argc, argv, "bxlvc::")) != -1) {
93         switch (c) {
94         case 'b':
95             open_mode = open_mode | O_BINARY;
96             break;
97         case 'v':
98             verbose = 1;
99             break;
100         case 'l':
101             hashsize = 512;
102             break;
103         case 'x':
104             filenames_from_stdin = 1;
105             break;
106         case 'c':
107             if (optarg) {
108                 check_file = fopen(optarg, "r");
109                 if (!check_file) {
110                     perror(optarg);
111                     exit(2);
112                 }
113             } else {
114                 check_file = stdin;
115             }
116             break;
117         default:
118             fprintf(stderr, "invalid option %c", optopt);
119             help();
120         }
121     }
122     if (check_file) {
123         char inhash[MAX_HASH_SIZE + 1], calcsum[MAX_HASH_SIZE + 1],
124             filename[PATH_MAX];
125         int failcount = 0, count = 0;;
126         if (check_file == stdin && optind < argc) {
127             check_file = fopen(argv[optind], "r");
128             if (!check_file) {
129                 perror(argv[optind]);
130                 exit(2);
131             }
132         }
133         while (get_line(check_file, inhash, filename, verbose)) {
134             count++;
135             if (!hash_file(&ctx, filename, calcsum, open_mode)) {
136                 errors++;
137                 continue;
138             }
139             if (!strncmp(calcsum, inhash, hashsize / 4 + 1)) {
140                 if (verbose) {
141                     fprintf(stderr, "%s\tOK\n", filename);
142                 }
143             } else {
144                 if (verbose) {
145                     fprintf(stderr, "%s\tFAILED\n", filename);
146                 } else {
147                     fprintf(stderr,
148                             "%s: GOST hash sum check failed for '%s'\n",
149                             argv[0], filename);
150                 }
151                 failcount++;
152             }
153         }
154         if (errors) {
155             fprintf(stderr,
156                     "%s: WARNING %d of %d file(s) cannot be processed\n",
157                     argv[0], errors, count);
158
159         }
160         if (failcount) {
161             fprintf(stderr,
162                     "%s: WARNING %d of %d file(s) failed GOST hash sum check\n",
163                     argv[0], failcount, count - errors);
164         }
165         exit((failcount || errors) ? 1 : 0);
166     } else if (filenames_from_stdin) {
167         char sum[65];
168         char filename[PATH_MAX + 1], *end;
169         while (!feof(stdin)) {
170             if (!fgets(filename, PATH_MAX, stdin))
171                 break;
172             for (end = filename; *end; end++) ;
173             end--;
174             for (; *end == '\n' || *end == '\r'; end--)
175                 *end = 0;
176             if (!hash_file(&ctx, filename, sum, open_mode)) {
177                 errors++;
178             } else {
179                 printf("%s %s\n", sum, filename);
180             }
181         }
182     } else if (optind == argc) {
183         char sum[65];
184 #ifdef _WIN32
185         if (open_mode & O_BINARY) {
186             _setmode(fileno(stdin), O_BINARY);
187         }
188 #endif
189         if (!hash_stream(&ctx, fileno(stdin), sum)) {
190             perror("stdin");
191             exit(1);
192         }
193         printf("%s -\n", sum);
194         exit(0);
195     } else {
196         for (i = optind; i < argc; i++) {
197             char sum[65];
198             if (!hash_file(&ctx, argv[i], sum, open_mode)) {
199                 errors++;
200             } else {
201                 printf("%s %s\n", sum, argv[i]);
202             }
203         }
204     }
205     exit(errors ? 1 : 0);
206 }
207
208 int hash_file(gost_hash_ctx * ctx, char *filename, char *sum, int mode)
209 {
210     int fd;
211     if ((fd = open(filename, mode)) < 0) {
212         perror(filename);
213         return 0;
214     }
215     if (!hash_stream(ctx, fd, sum)) {
216         perror(filename);
217         return 0;
218     }
219     close(fd);
220     return 1;
221 }
222
223 int hash_stream(gost_hash_ctx * ctx, int fd, char *sum)
224 {
225     unsigned char buffer[BUF_SIZE];
226     ssize_t bytes;
227                 size_t i;
228
229     start_hash12(ctx);
230     while ((bytes = read(fd, buffer, BUF_SIZE)) > 0) {
231         hash12_block(ctx, buffer, bytes);
232     }
233     if (bytes < 0) {
234         return 0;
235     }
236     finish_hash12(ctx, buffer);
237     for (i = 0; i < (hashsize / 8); i++) {
238         sprintf(sum + 2 * i, "%02x", buffer[i]);
239     }
240     return 1;
241 }
242
243 int get_line(FILE *f, char *hash, char *filename, int verbose)
244 {
245     int i, len;
246     int hashstrlen = hashsize / 4;
247     while (!feof(f)) {
248         if (!fgets(filename, PATH_MAX, f))
249             return 0;
250         len = strlen(filename);
251         if (len < hashstrlen + 2) {
252             goto nextline;
253         }
254         if (filename[hashstrlen] != ' ') {
255             goto nextline;
256         }
257         for (i = 0; i < hashstrlen; i++) {
258             if (filename[i] < '0' || (filename[i] > '9' && filename[i] < 'A')
259                 || (filename[i] > 'F' && filename[i] < 'a')
260                 || filename[i] > 'f') {
261                 goto nextline;
262             }
263         }
264         memcpy(hash, filename, hashstrlen);
265         hash[hashstrlen] = 0;
266         while (filename[--len] == '\n' || filename[len] == '\r')
267             filename[len] = 0;
268         memmove(filename, filename + hashstrlen + 1, len - hashstrlen + 1);
269         return 1;
270  nextline:
271         if (verbose)
272             printf("%s\n", filename);
273     }
274     return 0;
275 }