| 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;
|
| + }
|
|
|