Index: openssl/engines/ccgost/gostsum.c |
=================================================================== |
--- openssl/engines/ccgost/gostsum.c (revision 0) |
+++ openssl/engines/ccgost/gostsum.c (revision 0) |
@@ -0,0 +1,210 @@ |
+/********************************************************************** |
+ * gostsum.c * |
+ * Copyright (c) 2005-2006 Cryptocom LTD * |
+ * This file is distributed under the same license as OpenSSL * |
+ * * |
+ * Almost drop-in replacement for md5sum and sha1sum * |
+ * which computes GOST R 34.11-94 hashsum instead * |
+ * * |
+ **********************************************************************/ |
+#include <stdio.h> |
+#include <stdlib.h> |
+#include <unistd.h> |
+#include <limits.h> |
+#include <fcntl.h> |
+#include <string.h> |
+#include "gosthash.h" |
+#define BUF_SIZE 262144 |
+int hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode); |
+int hash_stream(gost_hash_ctx *ctx,int fd, char *sum); |
+int get_line(FILE *f,char *hash,char *filename); |
+void help() |
+ { |
+ fprintf(stderr,"gostsum [-bvt] [-c [file]]| [files]\n" |
+ "\t-c check message digests (default is generate)\n" |
+ "\t-v verbose, print file names when checking\n" |
+ "\t-b read files in binary mode\n" |
+ "\t-t use test GOST paramset (default is CryptoPro paramset)\n" |
+ "The input for -c should be the list of message digests and file names\n" |
+ "that is printed on stdout by this program when it generates digests.\n"); |
+ exit(3); |
+ } |
+ |
+#ifndef O_BINARY |
+#define O_BINARY 0 |
+#endif |
+ |
+int main(int argc,char **argv) |
+ { |
+ int c,i; |
+ int verbose=0; |
+ int errors=0; |
+ int open_mode = O_RDONLY; |
+ gost_subst_block *b= &GostR3411_94_CryptoProParamSet; |
+ FILE *check_file = NULL; |
+ gost_hash_ctx ctx; |
+ |
+ while( (c=getopt(argc,argv,"bc::tv"))!=-1) |
+ { |
+ switch (c) |
+ { |
+ case 'v': verbose=1; break; |
+ case 't': b= &GostR3411_94_TestParamSet; break; |
+ case 'b': open_mode |= O_BINARY; break; |
+ case 'c': |
+ if (optarg) |
+ { |
+ check_file = fopen(optarg,"r"); |
+ if (!check_file) |
+ { |
+ perror(optarg); |
+ exit(2); |
+ } |
+ } |
+ else |
+ { |
+ check_file= stdin; |
+ } |
+ break; |
+ default: |
+ fprintf(stderr,"invalid option %c",optopt); |
+ help(); |
+ } |
+ } |
+ init_gost_hash_ctx(&ctx,b); |
+ if (check_file) |
+ { |
+ char inhash[65],calcsum[65],filename[PATH_MAX]; |
+ int failcount=0,count=0;; |
+ if (check_file==stdin && optind<argc) |
+ { |
+ check_file=fopen(argv[optind],"r"); |
+ if (!check_file) |
+ { |
+ perror(argv[optind]); |
+ exit(2); |
+ } |
+ } |
+ while (get_line(check_file,inhash,filename)) |
+ { |
+ if (!hash_file(&ctx,filename,calcsum,open_mode)) |
+ { |
+ exit (2); |
+ } |
+ count++; |
+ if (!strncmp(calcsum,inhash,65)) |
+ { |
+ if (verbose) |
+ { |
+ fprintf(stderr,"%s\tOK\n",filename); |
+ } |
+ } |
+ else |
+ { |
+ if (verbose) |
+ { |
+ fprintf(stderr,"%s\tFAILED\n",filename); |
+ } |
+ else |
+ { |
+ fprintf(stderr,"%s: GOST hash sum check failed for '%s'\n", |
+ argv[0],filename); |
+ } |
+ failcount++; |
+ } |
+ } |
+ if (verbose && failcount) |
+ { |
+ fprintf(stderr,"%s: %d of %d file(f) failed GOST hash sum check\n", |
+ argv[0],failcount,count); |
+ } |
+ exit (failcount?1:0); |
+ } |
+ if (optind==argc) |
+ { |
+ char sum[65]; |
+ if (!hash_stream(&ctx,fileno(stdin),sum)) |
+ { |
+ perror("stdin"); |
+ exit(1); |
+ } |
+ printf("%s -\n",sum); |
+ exit(0); |
+ } |
+ for (i=optind;i<argc;i++) |
+ { |
+ char sum[65]; |
+ if (!hash_file(&ctx,argv[i],sum,open_mode)) |
+ { |
+ errors++; |
+ } |
+ else |
+ { |
+ printf("%s %s\n",sum,argv[i]); |
+ } |
+ } |
+ exit(errors?1:0); |
+ } |
+ |
+int hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode) |
+ { |
+ int fd; |
+ if ((fd=open(filename,mode))<0) |
+ { |
+ perror(filename); |
+ return 0; |
+ } |
+ if (!hash_stream(ctx,fd,sum)) |
+ { |
+ perror(filename); |
+ return 0; |
+ } |
+ close(fd); |
+ return 1; |
+ } |
+ |
+int hash_stream(gost_hash_ctx *ctx,int fd, char *sum) |
+ { |
+ unsigned char buffer[BUF_SIZE]; |
+ ssize_t bytes; |
+ int i; |
+ start_hash(ctx); |
+ while ((bytes=read(fd,buffer,BUF_SIZE))>0) |
+ { |
+ hash_block(ctx,buffer,bytes); |
+ } |
+ if (bytes<0) |
+ { |
+ return 0; |
+ } |
+ finish_hash(ctx,buffer); |
+ for (i=0;i<32;i++) |
+ { |
+ sprintf(sum+2*i,"%02x",buffer[31-i]); |
+ } |
+ return 1; |
+ } |
+ |
+int get_line(FILE *f,char *hash,char *filename) |
+ { |
+ int i; |
+ if (fread(hash,1,64,f)<64) return 0; |
+ hash[64]=0; |
+ for (i=0;i<64;i++) |
+ { |
+ if (hash[i]<'0' || (hash[i]>'9' && hash[i]<'A') || (hash[i]>'F' |
+ && hash[i]<'a')||hash[i]>'f') |
+ { |
+ fprintf(stderr,"Not a hash value '%s'\n",hash); |
+ return 0; |
+ } |
+ } |
+ if (fgetc(f)!=' ') |
+ { |
+ fprintf(stderr,"Malformed input line\n"); |
+ return 0; |
+ } |
+ i=strlen(fgets(filename,PATH_MAX,f)); |
+ while (filename[--i]=='\n'||filename[i]=='\r') filename[i]=0; |
+ return 1; |
+ } |