dgst.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /* apps/dgst.c */
  2. /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  3. * All rights reserved.
  4. *
  5. * This package is an SSL implementation written
  6. * by Eric Young (eay@cryptsoft.com).
  7. * The implementation was written so as to conform with Netscapes SSL.
  8. *
  9. * This library is free for commercial and non-commercial use as long as
  10. * the following conditions are aheared to. The following conditions
  11. * apply to all code found in this distribution, be it the RC4, RSA,
  12. * lhash, DES, etc., code; not just the SSL code. The SSL documentation
  13. * included with this distribution is covered by the same copyright terms
  14. * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  15. *
  16. * Copyright remains Eric Young's, and as such any Copyright notices in
  17. * the code are not to be removed.
  18. * If this package is used in a product, Eric Young should be given attribution
  19. * as the author of the parts of the library used.
  20. * This can be in the form of a textual message at program startup or
  21. * in documentation (online or textual) provided with the package.
  22. *
  23. * Redistribution and use in source and binary forms, with or without
  24. * modification, are permitted provided that the following conditions
  25. * are met:
  26. * 1. Redistributions of source code must retain the copyright
  27. * notice, this list of conditions and the following disclaimer.
  28. * 2. Redistributions in binary form must reproduce the above copyright
  29. * notice, this list of conditions and the following disclaimer in the
  30. * documentation and/or other materials provided with the distribution.
  31. * 3. All advertising materials mentioning features or use of this software
  32. * must display the following acknowledgement:
  33. * "This product includes cryptographic software written by
  34. * Eric Young (eay@cryptsoft.com)"
  35. * The word 'cryptographic' can be left out if the rouines from the library
  36. * being used are not cryptographic related :-).
  37. * 4. If you include any Windows specific code (or a derivative thereof) from
  38. * the apps directory (application code) you must include an acknowledgement:
  39. * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  40. *
  41. * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  42. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  43. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  44. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  45. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  46. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  47. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  49. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  50. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  51. * SUCH DAMAGE.
  52. *
  53. * The licence and distribution terms for any publically available version or
  54. * derivative of this code cannot be changed. i.e. this code cannot simply be
  55. * copied and put under another distribution licence
  56. * [including the GNU Public Licence.]
  57. */
  58. #include <stdio.h>
  59. #include <string.h>
  60. #include <stdlib.h>
  61. #include "apps.h"
  62. #include <openssl/bio.h>
  63. #include <openssl/err.h>
  64. #include <openssl/evp.h>
  65. #include <openssl/objects.h>
  66. #include <openssl/x509.h>
  67. #include <openssl/pem.h>
  68. #undef BUFSIZE
  69. #define BUFSIZE 1024*8
  70. #undef PROG
  71. #define PROG dgst_main
  72. int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
  73. EVP_PKEY *key, unsigned char *sigin, int siglen, const char *title,
  74. const char *file);
  75. int MAIN(int, char **);
  76. int MAIN(int argc, char **argv)
  77. {
  78. ENGINE *e = NULL;
  79. unsigned char *buf=NULL;
  80. int i,err=0;
  81. const EVP_MD *md=NULL,*m;
  82. BIO *in=NULL,*inp;
  83. BIO *bmd=NULL;
  84. BIO *out = NULL;
  85. const char *name;
  86. #define PROG_NAME_SIZE 39
  87. char pname[PROG_NAME_SIZE+1];
  88. int separator=0;
  89. int debug=0;
  90. int keyform=FORMAT_PEM;
  91. const char *outfile = NULL, *keyfile = NULL;
  92. const char *sigfile = NULL, *randfile = NULL;
  93. int out_bin = -1, want_pub = 0, do_verify = 0;
  94. EVP_PKEY *sigkey = NULL;
  95. unsigned char *sigbuf = NULL;
  96. int siglen = 0;
  97. char *passargin = NULL, *passin = NULL;
  98. #ifndef OPENSSL_NO_ENGINE
  99. char *engine=NULL;
  100. #endif
  101. apps_startup();
  102. if ((buf=(unsigned char *)OPENSSL_malloc(BUFSIZE)) == NULL)
  103. {
  104. BIO_printf(bio_err,"out of memory\n");
  105. goto end;
  106. }
  107. if (bio_err == NULL)
  108. if ((bio_err=BIO_new(BIO_s_file())) != NULL)
  109. BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
  110. if (!load_config(bio_err, NULL))
  111. goto end;
  112. /* first check the program name */
  113. program_name(argv[0],pname,sizeof pname);
  114. md=EVP_get_digestbyname(pname);
  115. argc--;
  116. argv++;
  117. while (argc > 0)
  118. {
  119. if ((*argv)[0] != '-') break;
  120. if (strcmp(*argv,"-c") == 0)
  121. separator=1;
  122. else if (strcmp(*argv,"-rand") == 0)
  123. {
  124. if (--argc < 1) break;
  125. randfile=*(++argv);
  126. }
  127. else if (strcmp(*argv,"-out") == 0)
  128. {
  129. if (--argc < 1) break;
  130. outfile=*(++argv);
  131. }
  132. else if (strcmp(*argv,"-sign") == 0)
  133. {
  134. if (--argc < 1) break;
  135. keyfile=*(++argv);
  136. }
  137. else if (!strcmp(*argv,"-passin"))
  138. {
  139. if (--argc < 1)
  140. break;
  141. passargin=*++argv;
  142. }
  143. else if (strcmp(*argv,"-verify") == 0)
  144. {
  145. if (--argc < 1) break;
  146. keyfile=*(++argv);
  147. want_pub = 1;
  148. do_verify = 1;
  149. }
  150. else if (strcmp(*argv,"-prverify") == 0)
  151. {
  152. if (--argc < 1) break;
  153. keyfile=*(++argv);
  154. do_verify = 1;
  155. }
  156. else if (strcmp(*argv,"-signature") == 0)
  157. {
  158. if (--argc < 1) break;
  159. sigfile=*(++argv);
  160. }
  161. else if (strcmp(*argv,"-keyform") == 0)
  162. {
  163. if (--argc < 1) break;
  164. keyform=str2fmt(*(++argv));
  165. }
  166. #ifndef OPENSSL_NO_ENGINE
  167. else if (strcmp(*argv,"-engine") == 0)
  168. {
  169. if (--argc < 1) break;
  170. engine= *(++argv);
  171. e = setup_engine(bio_err, engine, 0);
  172. }
  173. #endif
  174. else if (strcmp(*argv,"-hex") == 0)
  175. out_bin = 0;
  176. else if (strcmp(*argv,"-binary") == 0)
  177. out_bin = 1;
  178. else if (strcmp(*argv,"-d") == 0)
  179. debug=1;
  180. else if ((m=EVP_get_digestbyname(&((*argv)[1]))) != NULL)
  181. md=m;
  182. else
  183. break;
  184. argc--;
  185. argv++;
  186. }
  187. if (md == NULL)
  188. md=EVP_md5();
  189. if(do_verify && !sigfile) {
  190. BIO_printf(bio_err, "No signature to verify: use the -signature option\n");
  191. err = 1;
  192. goto end;
  193. }
  194. if ((argc > 0) && (argv[0][0] == '-')) /* bad option */
  195. {
  196. BIO_printf(bio_err,"unknown option '%s'\n",*argv);
  197. BIO_printf(bio_err,"options are\n");
  198. BIO_printf(bio_err,"-c to output the digest with separating colons\n");
  199. BIO_printf(bio_err,"-d to output debug info\n");
  200. BIO_printf(bio_err,"-hex output as hex dump\n");
  201. BIO_printf(bio_err,"-binary output in binary form\n");
  202. BIO_printf(bio_err,"-sign file sign digest using private key in file\n");
  203. BIO_printf(bio_err,"-verify file verify a signature using public key in file\n");
  204. BIO_printf(bio_err,"-prverify file verify a signature using private key in file\n");
  205. BIO_printf(bio_err,"-keyform arg key file format (PEM or ENGINE)\n");
  206. BIO_printf(bio_err,"-signature file signature to verify\n");
  207. BIO_printf(bio_err,"-binary output in binary form\n");
  208. #ifndef OPENSSL_NO_ENGINE
  209. BIO_printf(bio_err,"-engine e use engine e, possibly a hardware device.\n");
  210. #endif
  211. BIO_printf(bio_err,"-%-14s to use the %s message digest algorithm (default)\n",
  212. LN_md5,LN_md5);
  213. BIO_printf(bio_err,"-%-14s to use the %s message digest algorithm\n",
  214. LN_md4,LN_md4);
  215. BIO_printf(bio_err,"-%-14s to use the %s message digest algorithm\n",
  216. LN_md2,LN_md2);
  217. #ifndef OPENSSL_NO_SHA
  218. BIO_printf(bio_err,"-%-14s to use the %s message digest algorithm\n",
  219. LN_sha1,LN_sha1);
  220. #ifndef OPENSSL_NO_SHA256
  221. BIO_printf(bio_err,"-%-14s to use the %s message digest algorithm\n",
  222. LN_sha224,LN_sha224);
  223. BIO_printf(bio_err,"-%-14s to use the %s message digest algorithm\n",
  224. LN_sha256,LN_sha256);
  225. #endif
  226. #ifndef OPENSSL_NO_SHA512
  227. BIO_printf(bio_err,"-%-14s to use the %s message digest algorithm\n",
  228. LN_sha384,LN_sha384);
  229. BIO_printf(bio_err,"-%-14s to use the %s message digest algorithm\n",
  230. LN_sha512,LN_sha512);
  231. #endif
  232. #endif
  233. BIO_printf(bio_err,"-%-14s to use the %s message digest algorithm\n",
  234. LN_mdc2,LN_mdc2);
  235. BIO_printf(bio_err,"-%-14s to use the %s message digest algorithm\n",
  236. LN_ripemd160,LN_ripemd160);
  237. #ifndef OPENSSL_NO_WHIRLPOOL
  238. BIO_printf(bio_err,"-%-14s to use the %s message digest algorithm\n",
  239. SN_whirlpool,SN_whirlpool);
  240. #endif
  241. err=1;
  242. goto end;
  243. }
  244. in=BIO_new(BIO_s_file());
  245. bmd=BIO_new(BIO_f_md());
  246. if (debug)
  247. {
  248. BIO_set_callback(in,BIO_debug_callback);
  249. /* needed for windows 3.1 */
  250. BIO_set_callback_arg(in,bio_err);
  251. }
  252. if(!app_passwd(bio_err, passargin, NULL, &passin, NULL))
  253. {
  254. BIO_printf(bio_err, "Error getting password\n");
  255. goto end;
  256. }
  257. if ((in == NULL) || (bmd == NULL))
  258. {
  259. ERR_print_errors(bio_err);
  260. goto end;
  261. }
  262. if(out_bin == -1) {
  263. if(keyfile) out_bin = 1;
  264. else out_bin = 0;
  265. }
  266. if(randfile)
  267. app_RAND_load_file(randfile, bio_err, 0);
  268. if(outfile) {
  269. if(out_bin)
  270. out = BIO_new_file(outfile, "wb");
  271. else out = BIO_new_file(outfile, "w");
  272. } else {
  273. out = BIO_new_fp(stdout, BIO_NOCLOSE);
  274. #ifdef OPENSSL_SYS_VMS
  275. {
  276. BIO *tmpbio = BIO_new(BIO_f_linebuffer());
  277. out = BIO_push(tmpbio, out);
  278. }
  279. #endif
  280. }
  281. if(!out) {
  282. BIO_printf(bio_err, "Error opening output file %s\n",
  283. outfile ? outfile : "(stdout)");
  284. ERR_print_errors(bio_err);
  285. goto end;
  286. }
  287. if(keyfile)
  288. {
  289. if (want_pub)
  290. sigkey = load_pubkey(bio_err, keyfile, keyform, 0, NULL,
  291. e, "key file");
  292. else
  293. sigkey = load_key(bio_err, keyfile, keyform, 0, passin,
  294. e, "key file");
  295. if (!sigkey)
  296. {
  297. /* load_[pub]key() has already printed an appropriate
  298. message */
  299. goto end;
  300. }
  301. }
  302. if(sigfile && sigkey) {
  303. BIO *sigbio;
  304. sigbio = BIO_new_file(sigfile, "rb");
  305. siglen = EVP_PKEY_size(sigkey);
  306. sigbuf = OPENSSL_malloc(siglen);
  307. if(!sigbio) {
  308. BIO_printf(bio_err, "Error opening signature file %s\n",
  309. sigfile);
  310. ERR_print_errors(bio_err);
  311. goto end;
  312. }
  313. siglen = BIO_read(sigbio, sigbuf, siglen);
  314. BIO_free(sigbio);
  315. if(siglen <= 0) {
  316. BIO_printf(bio_err, "Error reading signature file %s\n",
  317. sigfile);
  318. ERR_print_errors(bio_err);
  319. goto end;
  320. }
  321. }
  322. /* we use md as a filter, reading from 'in' */
  323. if (!BIO_set_md(bmd,md))
  324. {
  325. BIO_printf(bio_err, "Error setting digest %s\n", pname);
  326. ERR_print_errors(bio_err);
  327. goto end;
  328. }
  329. inp=BIO_push(bmd,in);
  330. if (argc == 0)
  331. {
  332. BIO_set_fp(in,stdin,BIO_NOCLOSE);
  333. err=do_fp(out, buf,inp,separator, out_bin, sigkey, sigbuf,
  334. siglen,"","(stdin)");
  335. }
  336. else
  337. {
  338. name=OBJ_nid2sn(md->type);
  339. for (i=0; i<argc; i++)
  340. {
  341. char *tmp,*tofree=NULL;
  342. int r;
  343. if (BIO_read_filename(in,argv[i]) <= 0)
  344. {
  345. perror(argv[i]);
  346. err++;
  347. continue;
  348. }
  349. if(!out_bin)
  350. {
  351. size_t len = strlen(name)+strlen(argv[i])+5;
  352. tmp=tofree=OPENSSL_malloc(len);
  353. BIO_snprintf(tmp,len,"%s(%s)= ",name,argv[i]);
  354. }
  355. else
  356. tmp="";
  357. r=do_fp(out,buf,inp,separator,out_bin,sigkey,sigbuf,
  358. siglen,tmp,argv[i]);
  359. if(r)
  360. err=r;
  361. if(tofree)
  362. OPENSSL_free(tofree);
  363. (void)BIO_reset(bmd);
  364. }
  365. }
  366. end:
  367. if (buf != NULL)
  368. {
  369. OPENSSL_cleanse(buf,BUFSIZE);
  370. OPENSSL_free(buf);
  371. }
  372. if (in != NULL) BIO_free(in);
  373. if (passin)
  374. OPENSSL_free(passin);
  375. BIO_free_all(out);
  376. EVP_PKEY_free(sigkey);
  377. if(sigbuf) OPENSSL_free(sigbuf);
  378. if (bmd != NULL) BIO_free(bmd);
  379. apps_shutdown();
  380. OPENSSL_EXIT(err);
  381. }
  382. int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
  383. EVP_PKEY *key, unsigned char *sigin, int siglen, const char *title,
  384. const char *file)
  385. {
  386. int len;
  387. int i;
  388. for (;;)
  389. {
  390. i=BIO_read(bp,(char *)buf,BUFSIZE);
  391. if(i < 0)
  392. {
  393. BIO_printf(bio_err, "Read Error in %s\n",file);
  394. ERR_print_errors(bio_err);
  395. return 1;
  396. }
  397. if (i == 0) break;
  398. }
  399. if(sigin)
  400. {
  401. EVP_MD_CTX *ctx;
  402. BIO_get_md_ctx(bp, &ctx);
  403. i = EVP_VerifyFinal(ctx, sigin, (unsigned int)siglen, key);
  404. if(i > 0)
  405. BIO_printf(out, "Verified OK\n");
  406. else if(i == 0)
  407. {
  408. BIO_printf(out, "Verification Failure\n");
  409. return 1;
  410. }
  411. else
  412. {
  413. BIO_printf(bio_err, "Error Verifying Data\n");
  414. ERR_print_errors(bio_err);
  415. return 1;
  416. }
  417. return 0;
  418. }
  419. if(key)
  420. {
  421. EVP_MD_CTX *ctx;
  422. BIO_get_md_ctx(bp, &ctx);
  423. if(!EVP_SignFinal(ctx, buf, (unsigned int *)&len, key))
  424. {
  425. BIO_printf(bio_err, "Error Signing Data\n");
  426. ERR_print_errors(bio_err);
  427. return 1;
  428. }
  429. }
  430. else
  431. len=BIO_gets(bp,(char *)buf,BUFSIZE);
  432. if(binout) BIO_write(out, buf, len);
  433. else
  434. {
  435. BIO_write(out,title,strlen(title));
  436. for (i=0; i<len; i++)
  437. {
  438. if (sep && (i != 0))
  439. BIO_printf(out, ":");
  440. BIO_printf(out, "%02x",buf[i]);
  441. }
  442. BIO_printf(out, "\n");
  443. }
  444. return 0;
  445. }