diff options
Diffstat (limited to 'openssl/engines/ccgost/gostsum.c')
-rw-r--r-- | openssl/engines/ccgost/gostsum.c | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/openssl/engines/ccgost/gostsum.c b/openssl/engines/ccgost/gostsum.c new file mode 100644 index 000000000..d57112eb5 --- /dev/null +++ b/openssl/engines/ccgost/gostsum.c @@ -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; + } |