gostsum.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /**********************************************************************
  2. * gostsum.c *
  3. * Copyright (c) 2005-2006 Cryptocom LTD *
  4. * This file is distributed under the same license as OpenSSL *
  5. * *
  6. * Almost drop-in replacement for md5sum and sha1sum *
  7. * which computes GOST R 34.11-94 hashsum instead *
  8. * *
  9. **********************************************************************/
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #include <limits.h>
  14. #include <fcntl.h>
  15. #include <string.h>
  16. #include "gosthash.h"
  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);
  21. void help()
  22. {
  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");
  30. exit(3);
  31. }
  32. #ifndef O_BINARY
  33. #define O_BINARY 0
  34. #endif
  35. int main(int argc,char **argv)
  36. {
  37. int c,i;
  38. int verbose=0;
  39. int errors=0;
  40. int open_mode = O_RDONLY;
  41. gost_subst_block *b= &GostR3411_94_CryptoProParamSet;
  42. FILE *check_file = NULL;
  43. gost_hash_ctx ctx;
  44. while( (c=getopt(argc,argv,"bc::tv"))!=-1)
  45. {
  46. switch (c)
  47. {
  48. case 'v': verbose=1; break;
  49. case 't': b= &GostR3411_94_TestParamSet; break;
  50. case 'b': open_mode |= O_BINARY; break;
  51. case 'c':
  52. if (optarg)
  53. {
  54. check_file = fopen(optarg,"r");
  55. if (!check_file)
  56. {
  57. perror(optarg);
  58. exit(2);
  59. }
  60. }
  61. else
  62. {
  63. check_file= stdin;
  64. }
  65. break;
  66. default:
  67. fprintf(stderr,"invalid option %c",optopt);
  68. help();
  69. }
  70. }
  71. init_gost_hash_ctx(&ctx,b);
  72. if (check_file)
  73. {
  74. char inhash[65],calcsum[65],filename[PATH_MAX];
  75. int failcount=0,count=0;;
  76. if (check_file==stdin && optind<argc)
  77. {
  78. check_file=fopen(argv[optind],"r");
  79. if (!check_file)
  80. {
  81. perror(argv[optind]);
  82. exit(2);
  83. }
  84. }
  85. while (get_line(check_file,inhash,filename))
  86. {
  87. if (!hash_file(&ctx,filename,calcsum,open_mode))
  88. {
  89. exit (2);
  90. }
  91. count++;
  92. if (!strncmp(calcsum,inhash,65))
  93. {
  94. if (verbose)
  95. {
  96. fprintf(stderr,"%s\tOK\n",filename);
  97. }
  98. }
  99. else
  100. {
  101. if (verbose)
  102. {
  103. fprintf(stderr,"%s\tFAILED\n",filename);
  104. }
  105. else
  106. {
  107. fprintf(stderr,"%s: GOST hash sum check failed for '%s'\n",
  108. argv[0],filename);
  109. }
  110. failcount++;
  111. }
  112. }
  113. if (verbose && failcount)
  114. {
  115. fprintf(stderr,"%s: %d of %d file(f) failed GOST hash sum check\n",
  116. argv[0],failcount,count);
  117. }
  118. exit (failcount?1:0);
  119. }
  120. if (optind==argc)
  121. {
  122. char sum[65];
  123. if (!hash_stream(&ctx,fileno(stdin),sum))
  124. {
  125. perror("stdin");
  126. exit(1);
  127. }
  128. printf("%s -\n",sum);
  129. exit(0);
  130. }
  131. for (i=optind;i<argc;i++)
  132. {
  133. char sum[65];
  134. if (!hash_file(&ctx,argv[i],sum,open_mode))
  135. {
  136. errors++;
  137. }
  138. else
  139. {
  140. printf("%s %s\n",sum,argv[i]);
  141. }
  142. }
  143. exit(errors?1:0);
  144. }
  145. int hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode)
  146. {
  147. int fd;
  148. if ((fd=open(filename,mode))<0)
  149. {
  150. perror(filename);
  151. return 0;
  152. }
  153. if (!hash_stream(ctx,fd,sum))
  154. {
  155. perror(filename);
  156. return 0;
  157. }
  158. close(fd);
  159. return 1;
  160. }
  161. int hash_stream(gost_hash_ctx *ctx,int fd, char *sum)
  162. {
  163. unsigned char buffer[BUF_SIZE];
  164. ssize_t bytes;
  165. int i;
  166. start_hash(ctx);
  167. while ((bytes=read(fd,buffer,BUF_SIZE))>0)
  168. {
  169. hash_block(ctx,buffer,bytes);
  170. }
  171. if (bytes<0)
  172. {
  173. return 0;
  174. }
  175. finish_hash(ctx,buffer);
  176. for (i=0;i<32;i++)
  177. {
  178. sprintf(sum+2*i,"%02x",buffer[31-i]);
  179. }
  180. return 1;
  181. }
  182. int get_line(FILE *f,char *hash,char *filename)
  183. {
  184. int i;
  185. if (fread(hash,1,64,f)<64) return 0;
  186. hash[64]=0;
  187. for (i=0;i<64;i++)
  188. {
  189. if (hash[i]<'0' || (hash[i]>'9' && hash[i]<'A') || (hash[i]>'F'
  190. && hash[i]<'a')||hash[i]>'f')
  191. {
  192. fprintf(stderr,"Not a hash value '%s'\n",hash);
  193. return 0;
  194. }
  195. }
  196. if (fgetc(f)!=' ')
  197. {
  198. fprintf(stderr,"Malformed input line\n");
  199. return 0;
  200. }
  201. i=strlen(fgets(filename,PATH_MAX,f));
  202. while (filename[--i]=='\n'||filename[i]=='\r') filename[i]=0;
  203. return 1;
  204. }