1 /**********************************************************************
3 * Copyright (c) 2005-2006 Cryptocom LTD *
4 * This file is distributed under the same license as OpenSSL *
6 * Almost drop-in replacement for md5sum and sha1sum *
7 * which computes GOST R 34.11-94 hashsum instead *
9 **********************************************************************/
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
);
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");
37 int main(int argc
, char **argv
)
42 int open_mode
= O_RDONLY
;
43 gost_subst_block
*b
= &GostR3411_94_CryptoProParamSet
;
44 FILE *check_file
= NULL
;
47 while ((c
= getopt(argc
, argv
, "bc::tv")) != -1) {
53 b
= &GostR3411_94_TestParamSet
;
56 open_mode
|= O_BINARY
;
60 check_file
= fopen(optarg
, "r");
70 fprintf(stderr
, "invalid option %c", optopt
);
74 init_gost_hash_ctx(&ctx
, b
);
76 char inhash
[65], calcsum
[65], filename
[PATH_MAX
];
77 int failcount
= 0, count
= 0;;
78 if (check_file
== stdin
&& optind
< argc
) {
79 check_file
= fopen(argv
[optind
], "r");
85 while (get_line(check_file
, inhash
, filename
)) {
86 if (!hash_file(&ctx
, filename
, calcsum
, open_mode
)) {
90 if (!strncmp(calcsum
, inhash
, 65)) {
92 fprintf(stderr
, "%s\tOK\n", filename
);
96 fprintf(stderr
, "%s\tFAILED\n", filename
);
99 "%s: GOST hash sum check failed for '%s'\n",
105 if (verbose
&& failcount
) {
107 "%s: %d of %d file(f) failed GOST hash sum check\n",
108 argv
[0], failcount
, count
);
110 exit(failcount
? 1 : 0);
112 if (optind
== argc
) {
114 if (!hash_stream(&ctx
, fileno(stdin
), sum
)) {
118 printf("%s -\n", sum
);
121 for (i
= optind
; i
< argc
; i
++) {
123 if (!hash_file(&ctx
, argv
[i
], sum
, open_mode
)) {
126 printf("%s %s\n", sum
, argv
[i
]);
129 exit(errors
? 1 : 0);
132 int hash_file(gost_hash_ctx
* ctx
, char *filename
, char *sum
, int mode
)
135 if ((fd
= open(filename
, mode
)) < 0) {
139 if (!hash_stream(ctx
, fd
, sum
)) {
147 int hash_stream(gost_hash_ctx
* ctx
, int fd
, char *sum
)
149 unsigned char buffer
[BUF_SIZE
];
153 while ((bytes
= read(fd
, buffer
, BUF_SIZE
)) > 0) {
154 hash_block(ctx
, buffer
, bytes
);
159 finish_hash(ctx
, buffer
);
160 for (i
= 0; i
< 32; i
++) {
161 sprintf(sum
+ 2 * i
, "%02x", buffer
[31 - i
]);
166 int get_line(FILE *f
, char *hash
, char *filename
)
169 if (fread(hash
, 1, 64, f
) < 64)
172 for (i
= 0; i
< 64; i
++) {
173 if (hash
[i
] < '0' || (hash
[i
] > '9' && hash
[i
] < 'A')
174 || (hash
[i
] > 'F' && hash
[i
] < 'a') || hash
[i
] > 'f') {
175 fprintf(stderr
, "Not a hash value '%s'\n", hash
);
179 if (fgetc(f
) != ' ') {
180 fprintf(stderr
, "Malformed input line\n");
183 i
= strlen(fgets(filename
, PATH_MAX
, f
));
184 while (filename
[--i
] == '\n' || filename
[i
] == '\r')