ts.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. /*
  2. * Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL project
  3. * 2002.
  4. */
  5. /* ====================================================================
  6. * Copyright (c) 2001 The OpenSSL Project. All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. All advertising materials mentioning features or use of this
  21. * software must display the following acknowledgment:
  22. * "This product includes software developed by the OpenSSL Project
  23. * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  24. *
  25. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  26. * endorse or promote products derived from this software without
  27. * prior written permission. For written permission, please contact
  28. * licensing@OpenSSL.org.
  29. *
  30. * 5. Products derived from this software may not be called "OpenSSL"
  31. * nor may "OpenSSL" appear in their names without prior written
  32. * permission of the OpenSSL Project.
  33. *
  34. * 6. Redistributions of any form whatsoever must retain the following
  35. * acknowledgment:
  36. * "This product includes software developed by the OpenSSL Project
  37. * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  38. *
  39. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  40. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  41. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  42. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  43. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  44. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  45. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  46. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  48. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  49. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  50. * OF THE POSSIBILITY OF SUCH DAMAGE.
  51. * ====================================================================
  52. *
  53. * This product includes cryptographic software written by Eric Young
  54. * (eay@cryptsoft.com). This product includes software written by Tim
  55. * Hudson (tjh@cryptsoft.com).
  56. *
  57. */
  58. #include <stdio.h>
  59. #include <stdlib.h>
  60. #include <string.h>
  61. #include "apps.h"
  62. #include <openssl/bio.h>
  63. #include <openssl/err.h>
  64. #include <openssl/pem.h>
  65. #include <openssl/rand.h>
  66. #include <openssl/ts.h>
  67. #include <openssl/bn.h>
  68. /* Request nonce length, in bits (must be a multiple of 8). */
  69. #define NONCE_LENGTH 64
  70. /* Name of config entry that defines the OID file. */
  71. #define ENV_OID_FILE "oid_file"
  72. /* Is |EXACTLY_ONE| of three pointers set? */
  73. #define EXACTLY_ONE(a, b, c) \
  74. (( a && !b && !c) || \
  75. ( b && !a && !c) || \
  76. ( c && !a && !b))
  77. static ASN1_OBJECT *txt2obj(const char *oid);
  78. static CONF *load_config_file(const char *configfile);
  79. /* Query related functions. */
  80. static int query_command(const char *data, char *digest,
  81. const EVP_MD *md, const char *policy, int no_nonce,
  82. int cert, const char *in, const char *out, int text);
  83. static TS_REQ *create_query(BIO *data_bio, char *digest, const EVP_MD *md,
  84. const char *policy, int no_nonce, int cert);
  85. static int create_digest(BIO *input, char *digest,
  86. const EVP_MD *md, unsigned char **md_value);
  87. static ASN1_INTEGER *create_nonce(int bits);
  88. /* Reply related functions. */
  89. static int reply_command(CONF *conf, char *section, char *engine,
  90. char *queryfile, char *passin, char *inkey,
  91. const EVP_MD *md, char *signer, char *chain,
  92. const char *policy, char *in, int token_in,
  93. char *out, int token_out, int text);
  94. static TS_RESP *read_PKCS7(BIO *in_bio);
  95. static TS_RESP *create_response(CONF *conf, const char *section, char *engine,
  96. char *queryfile, char *passin,
  97. char *inkey, const EVP_MD *md, char *signer,
  98. char *chain, const char *policy);
  99. static ASN1_INTEGER *serial_cb(TS_RESP_CTX *ctx, void *data);
  100. static ASN1_INTEGER *next_serial(const char *serialfile);
  101. static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial);
  102. /* Verify related functions. */
  103. static int verify_command(char *data, char *digest, char *queryfile,
  104. char *in, int token_in,
  105. char *CApath, char *CAfile, char *untrusted);
  106. static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest,
  107. char *queryfile,
  108. char *CApath, char *CAfile,
  109. char *untrusted);
  110. static X509_STORE *create_cert_store(char *CApath, char *CAfile);
  111. static int verify_cb(int ok, X509_STORE_CTX *ctx);
  112. typedef enum OPTION_choice {
  113. OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
  114. OPT_ENGINE, OPT_CONFIG, OPT_SECTION, OPT_QUERY, OPT_DATA,
  115. OPT_DIGEST, OPT_RAND, OPT_POLICY, OPT_NO_NONCE, OPT_CERT,
  116. OPT_IN, OPT_TOKEN_IN, OPT_OUT, OPT_TOKEN_OUT, OPT_TEXT,
  117. OPT_REPLY, OPT_QUERYFILE, OPT_PASSIN, OPT_INKEY, OPT_SIGNER,
  118. OPT_CHAIN, OPT_VERIFY, OPT_CAPATH, OPT_CAFILE, OPT_UNTRUSTED,
  119. OPT_MD
  120. } OPTION_CHOICE;
  121. OPTIONS ts_options[] = {
  122. {"help", OPT_HELP, '-', "Display this summary"},
  123. {"config", OPT_CONFIG, '<', "Configuration file"},
  124. {"section", OPT_SECTION, 's', "Section to use within config file"},
  125. {"query", OPT_QUERY, '-', "Generate a TS query"},
  126. {"data", OPT_DATA, '<', "File to hash"},
  127. {"digest", OPT_DIGEST, 's', "Digest (as a hex string)"},
  128. {"rand", OPT_RAND, 's',
  129. "Load the file(s) into the random number generator"},
  130. {"policy", OPT_POLICY, 's', "Policy OID to use"},
  131. {"no_nonce", OPT_NO_NONCE, '-', "Do not include a nonce"},
  132. {"cert", OPT_CERT, '-', "Put cert request into query"},
  133. {"in", OPT_IN, '<', "Input file"},
  134. {"token_in", OPT_TOKEN_IN, '-', "Input is a PKCS#7 file"},
  135. {"out", OPT_OUT, '>', "Output file"},
  136. {"token_out", OPT_TOKEN_OUT, '-', "Output is a PKCS#7 file"},
  137. {"text", OPT_TEXT, '-', "Output text (not DER)"},
  138. {"reply", OPT_REPLY, '-', "Generate a TS reply"},
  139. {"queryfile", OPT_QUERYFILE, '<', "File containing a TS query"},
  140. {"passin", OPT_PASSIN, 's'},
  141. {"inkey", OPT_INKEY, '<', "File with private key for reply"},
  142. {"signer", OPT_SIGNER, 's'},
  143. {"chain", OPT_CHAIN, '<', "File with signer CA chain"},
  144. {"verify", OPT_VERIFY, '-', "Verify a TS response"},
  145. {"CApath", OPT_CAPATH, '/', "Path to trusted CA files"},
  146. {"CAfile", OPT_CAFILE, '<', "File with trusted CA certs"},
  147. {"untrusted", OPT_UNTRUSTED, '<', "File with untrusted certs"},
  148. {"", OPT_MD, '-', "Any supported digest"},
  149. #ifndef OPENSSL_NO_ENGINE
  150. {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
  151. #endif
  152. {NULL}
  153. };
  154. /*
  155. * This comand is so complex, special help is needed.
  156. */
  157. static char* opt_helplist[] = {
  158. "Typical uses:",
  159. "ts -query [-rand file...] [-config file] [-data file]",
  160. " [-digest hexstring] [-policy oid] [-no_nonce] [-cert]",
  161. " [-in file] [-out file] [-text]",
  162. " or",
  163. "ts -reply [-config file] [-section tsa_section]",
  164. " [-queryfile file] [-passin password]",
  165. " [-signer tsa_cert.pem] [-inkey private_key.pem]",
  166. " [-chain certs_file.pem] [-policy oid]",
  167. " [-in file] [-token_in] [-out file] [-token_out]",
  168. #ifndef OPENSSL_NO_ENGINE
  169. " [-text]",
  170. #else
  171. " [-text] [-engine id]",
  172. #endif
  173. " or",
  174. "ts -verify -CApath dir -CAfile file.pem -untrusted file.pem",
  175. " [-data file] [-digest hexstring]",
  176. " [-queryfile file] -in file [-token_in]",
  177. NULL,
  178. };
  179. int ts_main(int argc, char **argv)
  180. {
  181. CONF *conf = NULL;
  182. char *CAfile = NULL, *untrusted = NULL, *engine = NULL, *prog, **helpp;
  183. char *configfile = default_config_file;
  184. char *section = NULL, *password = NULL;
  185. char *data = NULL, *digest = NULL, *rnd = NULL, *policy = NULL;
  186. char *in = NULL, *out = NULL, *queryfile = NULL, *passin = NULL;
  187. char *inkey = NULL, *signer = NULL, *chain = NULL, *CApath = NULL;
  188. const EVP_MD *md = NULL;
  189. OPTION_CHOICE o, mode = OPT_ERR;
  190. int ret = 1, no_nonce = 0, cert = 0, text = 0;
  191. /* Input is ContentInfo instead of TimeStampResp. */
  192. int token_in = 0;
  193. /* Output is ContentInfo instead of TimeStampResp. */
  194. int token_out = 0;
  195. prog = opt_init(argc, argv, ts_options);
  196. while ((o = opt_next()) != OPT_EOF) {
  197. switch (o) {
  198. case OPT_EOF:
  199. case OPT_ERR:
  200. opthelp:
  201. BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
  202. goto end;
  203. case OPT_HELP:
  204. opt_help(ts_options);
  205. for (helpp = opt_helplist; *helpp; ++helpp)
  206. BIO_printf(bio_err, "%s\n", *helpp);
  207. ret = 0;
  208. goto end;
  209. case OPT_CONFIG:
  210. configfile = opt_arg();
  211. break;
  212. case OPT_SECTION:
  213. section = opt_arg();
  214. break;
  215. case OPT_QUERY:
  216. case OPT_REPLY:
  217. case OPT_VERIFY:
  218. if (mode != OPT_ERR)
  219. goto opthelp;
  220. mode = o;
  221. break;
  222. case OPT_DATA:
  223. data = opt_arg();
  224. break;
  225. case OPT_DIGEST:
  226. digest = opt_arg();
  227. break;
  228. case OPT_RAND:
  229. rnd = opt_arg();
  230. break;
  231. case OPT_POLICY:
  232. policy = opt_arg();
  233. break;
  234. case OPT_NO_NONCE:
  235. no_nonce = 1;
  236. break;
  237. case OPT_CERT:
  238. cert = 1;
  239. break;
  240. case OPT_IN:
  241. in = opt_arg();
  242. break;
  243. case OPT_TOKEN_IN:
  244. token_in = 1;
  245. break;
  246. case OPT_OUT:
  247. out = opt_arg();
  248. break;
  249. case OPT_TOKEN_OUT:
  250. token_out = 1;
  251. break;
  252. case OPT_TEXT:
  253. text = 1;
  254. break;
  255. case OPT_QUERYFILE:
  256. queryfile = opt_arg();
  257. break;
  258. case OPT_PASSIN:
  259. passin = opt_arg();
  260. break;
  261. case OPT_INKEY:
  262. inkey = opt_arg();
  263. break;
  264. case OPT_SIGNER:
  265. signer = opt_arg();
  266. break;
  267. case OPT_CHAIN:
  268. chain = opt_arg();
  269. break;
  270. case OPT_CAPATH:
  271. CApath = opt_arg();
  272. break;
  273. case OPT_CAFILE:
  274. CAfile = opt_arg();
  275. break;
  276. case OPT_UNTRUSTED:
  277. untrusted = opt_arg();
  278. break;
  279. case OPT_ENGINE:
  280. engine = opt_arg();
  281. break;
  282. case OPT_MD:
  283. if (!opt_md(opt_unknown(), &md))
  284. goto opthelp;
  285. break;
  286. }
  287. }
  288. argc = opt_num_rest();
  289. argv = opt_rest();
  290. if (mode == OPT_ERR || argc != 0)
  291. goto opthelp;
  292. /* Seed the random number generator if it is going to be used. */
  293. if (mode == OPT_QUERY && !no_nonce) {
  294. if (!app_RAND_load_file(NULL, 1) && rnd == NULL)
  295. BIO_printf(bio_err, "warning, not much extra random "
  296. "data, consider using the -rand option\n");
  297. if (rnd != NULL)
  298. BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
  299. app_RAND_load_files(rnd));
  300. }
  301. if (mode == OPT_REPLY && passin &&
  302. !app_passwd(passin, NULL, &password, NULL)) {
  303. BIO_printf(bio_err, "Error getting password.\n");
  304. goto end;
  305. }
  306. conf = load_config_file(configfile);
  307. if (!app_load_modules(conf))
  308. goto end;
  309. /* Check parameter consistency and execute the appropriate function. */
  310. switch (mode) {
  311. default:
  312. case OPT_ERR:
  313. goto opthelp;
  314. case OPT_QUERY:
  315. if ((data != NULL) && (digest != NULL))
  316. goto opthelp;
  317. ret = !query_command(data, digest, md, policy, no_nonce, cert,
  318. in, out, text);
  319. break;
  320. case OPT_REPLY:
  321. if ((in != NULL) && (queryfile != NULL))
  322. goto opthelp;
  323. if (in == NULL) {
  324. if ((conf == NULL) || (token_in != 0))
  325. goto opthelp;
  326. }
  327. ret = !reply_command(conf, section, engine, queryfile,
  328. password, inkey, md, signer, chain, policy,
  329. in, token_in, out, token_out, text);
  330. break;
  331. case OPT_VERIFY:
  332. if ((in == NULL) || !EXACTLY_ONE(queryfile, data, digest))
  333. goto opthelp;
  334. ret = !verify_command(data, digest, queryfile, in, token_in,
  335. CApath, CAfile, untrusted);
  336. }
  337. end:
  338. app_RAND_write_file(NULL);
  339. NCONF_free(conf);
  340. OPENSSL_free(password);
  341. OBJ_cleanup();
  342. return (ret);
  343. }
  344. /*
  345. * Configuration file-related function definitions.
  346. */
  347. static ASN1_OBJECT *txt2obj(const char *oid)
  348. {
  349. ASN1_OBJECT *oid_obj = NULL;
  350. if ((oid_obj = OBJ_txt2obj(oid, 0)) == NULL)
  351. BIO_printf(bio_err, "cannot convert %s to OID\n", oid);
  352. return oid_obj;
  353. }
  354. static CONF *load_config_file(const char *configfile)
  355. {
  356. CONF *conf = app_load_config(configfile);
  357. if (conf != NULL) {
  358. const char *p;
  359. BIO_printf(bio_err, "Using configuration from %s\n", configfile);
  360. p = NCONF_get_string(conf, NULL, ENV_OID_FILE);
  361. if (p != NULL) {
  362. BIO *oid_bio = BIO_new_file(p, "r");
  363. if (!oid_bio)
  364. ERR_print_errors(bio_err);
  365. else {
  366. OBJ_create_objects(oid_bio);
  367. BIO_free_all(oid_bio);
  368. }
  369. } else
  370. ERR_clear_error();
  371. if (!add_oid_section(conf))
  372. ERR_print_errors(bio_err);
  373. }
  374. return conf;
  375. }
  376. /*
  377. * Query-related method definitions.
  378. */
  379. static int query_command(const char *data, char *digest, const EVP_MD *md,
  380. const char *policy, int no_nonce,
  381. int cert, const char *in, const char *out, int text)
  382. {
  383. int ret = 0;
  384. TS_REQ *query = NULL;
  385. BIO *in_bio = NULL;
  386. BIO *data_bio = NULL;
  387. BIO *out_bio = NULL;
  388. /* Build query object. */
  389. if (in != NULL) {
  390. if ((in_bio = bio_open_default(in, 'r', FORMAT_ASN1)) == NULL)
  391. goto end;
  392. query = d2i_TS_REQ_bio(in_bio, NULL);
  393. } else {
  394. if (digest == NULL
  395. && (data_bio = bio_open_default(data, 'r', FORMAT_ASN1)) == NULL)
  396. goto end;
  397. query = create_query(data_bio, digest, md, policy, no_nonce, cert);
  398. }
  399. if (query == NULL)
  400. goto end;
  401. if (text) {
  402. if ((out_bio = bio_open_default(out, 'w', FORMAT_TEXT)) == NULL)
  403. goto end;
  404. if (!TS_REQ_print_bio(out_bio, query))
  405. goto end;
  406. } else {
  407. if ((out_bio = bio_open_default(out, 'w', FORMAT_ASN1)) == NULL)
  408. goto end;
  409. if (!i2d_TS_REQ_bio(out_bio, query))
  410. goto end;
  411. }
  412. ret = 1;
  413. end:
  414. ERR_print_errors(bio_err);
  415. BIO_free_all(in_bio);
  416. BIO_free_all(data_bio);
  417. BIO_free_all(out_bio);
  418. TS_REQ_free(query);
  419. return ret;
  420. }
  421. static TS_REQ *create_query(BIO *data_bio, char *digest, const EVP_MD *md,
  422. const char *policy, int no_nonce, int cert)
  423. {
  424. int ret = 0;
  425. TS_REQ *ts_req = NULL;
  426. int len;
  427. TS_MSG_IMPRINT *msg_imprint = NULL;
  428. X509_ALGOR *algo = NULL;
  429. unsigned char *data = NULL;
  430. ASN1_OBJECT *policy_obj = NULL;
  431. ASN1_INTEGER *nonce_asn1 = NULL;
  432. if (md == NULL && (md = EVP_get_digestbyname("sha1")) == NULL)
  433. goto err;
  434. if ((ts_req = TS_REQ_new()) == NULL)
  435. goto err;
  436. if (!TS_REQ_set_version(ts_req, 1))
  437. goto err;
  438. if ((msg_imprint = TS_MSG_IMPRINT_new()) == NULL)
  439. goto err;
  440. if ((algo = X509_ALGOR_new()) == NULL)
  441. goto err;
  442. if ((algo->algorithm = OBJ_nid2obj(EVP_MD_type(md))) == NULL)
  443. goto err;
  444. if ((algo->parameter = ASN1_TYPE_new()) == NULL)
  445. goto err;
  446. algo->parameter->type = V_ASN1_NULL;
  447. if (!TS_MSG_IMPRINT_set_algo(msg_imprint, algo))
  448. goto err;
  449. if ((len = create_digest(data_bio, digest, md, &data)) == 0)
  450. goto err;
  451. if (!TS_MSG_IMPRINT_set_msg(msg_imprint, data, len))
  452. goto err;
  453. if (!TS_REQ_set_msg_imprint(ts_req, msg_imprint))
  454. goto err;
  455. if (policy && (policy_obj = txt2obj(policy)) == NULL)
  456. goto err;
  457. if (policy_obj && !TS_REQ_set_policy_id(ts_req, policy_obj))
  458. goto err;
  459. /* Setting nonce if requested. */
  460. if (!no_nonce && (nonce_asn1 = create_nonce(NONCE_LENGTH)) == NULL)
  461. goto err;
  462. if (nonce_asn1 && !TS_REQ_set_nonce(ts_req, nonce_asn1))
  463. goto err;
  464. if (!TS_REQ_set_cert_req(ts_req, cert))
  465. goto err;
  466. ret = 1;
  467. err:
  468. if (!ret) {
  469. TS_REQ_free(ts_req);
  470. ts_req = NULL;
  471. BIO_printf(bio_err, "could not create query\n");
  472. ERR_print_errors(bio_err);
  473. }
  474. TS_MSG_IMPRINT_free(msg_imprint);
  475. X509_ALGOR_free(algo);
  476. OPENSSL_free(data);
  477. ASN1_OBJECT_free(policy_obj);
  478. ASN1_INTEGER_free(nonce_asn1);
  479. return ts_req;
  480. }
  481. static int create_digest(BIO *input, char *digest, const EVP_MD *md,
  482. unsigned char **md_value)
  483. {
  484. int md_value_len;
  485. md_value_len = EVP_MD_size(md);
  486. if (md_value_len < 0)
  487. return 0;
  488. if (input) {
  489. EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
  490. unsigned char buffer[4096];
  491. int length;
  492. if (md_ctx == NULL)
  493. return 0;
  494. *md_value = app_malloc(md_value_len, "digest buffer");
  495. EVP_DigestInit(md_ctx, md);
  496. while ((length = BIO_read(input, buffer, sizeof(buffer))) > 0) {
  497. EVP_DigestUpdate(md_ctx, buffer, length);
  498. }
  499. if (!EVP_DigestFinal(md_ctx, *md_value, NULL)) {
  500. EVP_MD_CTX_free(md_ctx);
  501. return 0;
  502. }
  503. EVP_MD_CTX_free(md_ctx);
  504. } else {
  505. long digest_len;
  506. *md_value = string_to_hex(digest, &digest_len);
  507. if (!*md_value || md_value_len != digest_len) {
  508. OPENSSL_free(*md_value);
  509. *md_value = NULL;
  510. BIO_printf(bio_err, "bad digest, %d bytes "
  511. "must be specified\n", md_value_len);
  512. return 0;
  513. }
  514. }
  515. return md_value_len;
  516. }
  517. static ASN1_INTEGER *create_nonce(int bits)
  518. {
  519. unsigned char buf[20];
  520. ASN1_INTEGER *nonce = NULL;
  521. int len = (bits - 1) / 8 + 1;
  522. int i;
  523. if (len > (int)sizeof(buf))
  524. goto err;
  525. if (RAND_bytes(buf, len) <= 0)
  526. goto err;
  527. /* Find the first non-zero byte and creating ASN1_INTEGER object. */
  528. for (i = 0; i < len && !buf[i]; ++i)
  529. continue;
  530. if ((nonce = ASN1_INTEGER_new()) == NULL)
  531. goto err;
  532. OPENSSL_free(nonce->data);
  533. nonce->length = len - i;
  534. nonce->data = app_malloc(nonce->length + 1, "nonce buffer");
  535. memcpy(nonce->data, buf + i, nonce->length);
  536. return nonce;
  537. err:
  538. BIO_printf(bio_err, "could not create nonce\n");
  539. ASN1_INTEGER_free(nonce);
  540. return NULL;
  541. }
  542. /*
  543. * Reply-related method definitions.
  544. */
  545. static int reply_command(CONF *conf, char *section, char *engine,
  546. char *queryfile, char *passin, char *inkey,
  547. const EVP_MD *md, char *signer, char *chain,
  548. const char *policy, char *in, int token_in,
  549. char *out, int token_out, int text)
  550. {
  551. int ret = 0;
  552. TS_RESP *response = NULL;
  553. BIO *in_bio = NULL;
  554. BIO *query_bio = NULL;
  555. BIO *inkey_bio = NULL;
  556. BIO *signer_bio = NULL;
  557. BIO *out_bio = NULL;
  558. if (in != NULL) {
  559. if ((in_bio = BIO_new_file(in, "rb")) == NULL)
  560. goto end;
  561. if (token_in) {
  562. response = read_PKCS7(in_bio);
  563. } else {
  564. response = d2i_TS_RESP_bio(in_bio, NULL);
  565. }
  566. } else {
  567. response = create_response(conf, section, engine, queryfile,
  568. passin, inkey, md, signer, chain, policy);
  569. if (response)
  570. BIO_printf(bio_err, "Response has been generated.\n");
  571. else
  572. BIO_printf(bio_err, "Response is not generated.\n");
  573. }
  574. if (response == NULL)
  575. goto end;
  576. /* Write response. */
  577. if (text) {
  578. if ((out_bio = bio_open_default(out, 'w', FORMAT_TEXT)) == NULL)
  579. goto end;
  580. if (token_out) {
  581. TS_TST_INFO *tst_info = TS_RESP_get_tst_info(response);
  582. if (!TS_TST_INFO_print_bio(out_bio, tst_info))
  583. goto end;
  584. } else {
  585. if (!TS_RESP_print_bio(out_bio, response))
  586. goto end;
  587. }
  588. } else {
  589. if ((out_bio = bio_open_default(out, 'w', FORMAT_ASN1)) == NULL)
  590. goto end;
  591. if (token_out) {
  592. PKCS7 *token = TS_RESP_get_token(response);
  593. if (!i2d_PKCS7_bio(out_bio, token))
  594. goto end;
  595. } else {
  596. if (!i2d_TS_RESP_bio(out_bio, response))
  597. goto end;
  598. }
  599. }
  600. ret = 1;
  601. end:
  602. ERR_print_errors(bio_err);
  603. BIO_free_all(in_bio);
  604. BIO_free_all(query_bio);
  605. BIO_free_all(inkey_bio);
  606. BIO_free_all(signer_bio);
  607. BIO_free_all(out_bio);
  608. TS_RESP_free(response);
  609. return ret;
  610. }
  611. /* Reads a PKCS7 token and adds default 'granted' status info to it. */
  612. static TS_RESP *read_PKCS7(BIO *in_bio)
  613. {
  614. int ret = 0;
  615. PKCS7 *token = NULL;
  616. TS_TST_INFO *tst_info = NULL;
  617. TS_RESP *resp = NULL;
  618. TS_STATUS_INFO *si = NULL;
  619. if ((token = d2i_PKCS7_bio(in_bio, NULL)) == NULL)
  620. goto end;
  621. if ((tst_info = PKCS7_to_TS_TST_INFO(token)) == NULL)
  622. goto end;
  623. if ((resp = TS_RESP_new()) == NULL)
  624. goto end;
  625. if ((si = TS_STATUS_INFO_new()) == NULL)
  626. goto end;
  627. if (!TS_STATUS_INFO_set_status(si, TS_STATUS_GRANTED))
  628. goto end;
  629. if (!TS_RESP_set_status_info(resp, si))
  630. goto end;
  631. TS_RESP_set_tst_info(resp, token, tst_info);
  632. token = NULL; /* Ownership is lost. */
  633. tst_info = NULL; /* Ownership is lost. */
  634. ret = 1;
  635. end:
  636. PKCS7_free(token);
  637. TS_TST_INFO_free(tst_info);
  638. if (!ret) {
  639. TS_RESP_free(resp);
  640. resp = NULL;
  641. }
  642. TS_STATUS_INFO_free(si);
  643. return resp;
  644. }
  645. static TS_RESP *create_response(CONF *conf, const char *section, char *engine,
  646. char *queryfile, char *passin,
  647. char *inkey, const EVP_MD *md, char *signer,
  648. char *chain, const char *policy)
  649. {
  650. int ret = 0;
  651. TS_RESP *response = NULL;
  652. BIO *query_bio = NULL;
  653. TS_RESP_CTX *resp_ctx = NULL;
  654. if ((query_bio = BIO_new_file(queryfile, "rb")) == NULL)
  655. goto end;
  656. if ((section = TS_CONF_get_tsa_section(conf, section)) == NULL)
  657. goto end;
  658. if ((resp_ctx = TS_RESP_CTX_new()) == NULL)
  659. goto end;
  660. if (!TS_CONF_set_serial(conf, section, serial_cb, resp_ctx))
  661. goto end;
  662. #ifndef OPENSSL_NO_ENGINE
  663. if (!TS_CONF_set_crypto_device(conf, section, engine))
  664. goto end;
  665. #endif
  666. if (!TS_CONF_set_signer_cert(conf, section, signer, resp_ctx))
  667. goto end;
  668. if (!TS_CONF_set_certs(conf, section, chain, resp_ctx))
  669. goto end;
  670. if (!TS_CONF_set_signer_key(conf, section, inkey, passin, resp_ctx))
  671. goto end;
  672. if (md) {
  673. if (!TS_RESP_CTX_set_signer_digest(resp_ctx, md))
  674. goto end;
  675. } else if (!TS_CONF_set_signer_digest(conf, section, NULL, resp_ctx)) {
  676. goto end;
  677. }
  678. if (!TS_CONF_set_def_policy(conf, section, policy, resp_ctx))
  679. goto end;
  680. if (!TS_CONF_set_policies(conf, section, resp_ctx))
  681. goto end;
  682. if (!TS_CONF_set_digests(conf, section, resp_ctx))
  683. goto end;
  684. if (!TS_CONF_set_accuracy(conf, section, resp_ctx))
  685. goto end;
  686. if (!TS_CONF_set_clock_precision_digits(conf, section, resp_ctx))
  687. goto end;
  688. if (!TS_CONF_set_ordering(conf, section, resp_ctx))
  689. goto end;
  690. if (!TS_CONF_set_tsa_name(conf, section, resp_ctx))
  691. goto end;
  692. if (!TS_CONF_set_ess_cert_id_chain(conf, section, resp_ctx))
  693. goto end;
  694. if ((response = TS_RESP_create_response(resp_ctx, query_bio)) == NULL)
  695. goto end;
  696. ret = 1;
  697. end:
  698. if (!ret) {
  699. TS_RESP_free(response);
  700. response = NULL;
  701. }
  702. TS_RESP_CTX_free(resp_ctx);
  703. BIO_free_all(query_bio);
  704. return response;
  705. }
  706. static ASN1_INTEGER *serial_cb(TS_RESP_CTX *ctx, void *data)
  707. {
  708. const char *serial_file = (const char *)data;
  709. ASN1_INTEGER *serial = next_serial(serial_file);
  710. if (!serial) {
  711. TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
  712. "Error during serial number "
  713. "generation.");
  714. TS_RESP_CTX_add_failure_info(ctx, TS_INFO_ADD_INFO_NOT_AVAILABLE);
  715. } else
  716. save_ts_serial(serial_file, serial);
  717. return serial;
  718. }
  719. static ASN1_INTEGER *next_serial(const char *serialfile)
  720. {
  721. int ret = 0;
  722. BIO *in = NULL;
  723. ASN1_INTEGER *serial = NULL;
  724. BIGNUM *bn = NULL;
  725. if ((serial = ASN1_INTEGER_new()) == NULL)
  726. goto err;
  727. if ((in = BIO_new_file(serialfile, "r")) == NULL) {
  728. ERR_clear_error();
  729. BIO_printf(bio_err, "Warning: could not open file %s for "
  730. "reading, using serial number: 1\n", serialfile);
  731. if (!ASN1_INTEGER_set(serial, 1))
  732. goto err;
  733. } else {
  734. char buf[1024];
  735. if (!a2i_ASN1_INTEGER(in, serial, buf, sizeof(buf))) {
  736. BIO_printf(bio_err, "unable to load number from %s\n",
  737. serialfile);
  738. goto err;
  739. }
  740. if ((bn = ASN1_INTEGER_to_BN(serial, NULL)) == NULL)
  741. goto err;
  742. ASN1_INTEGER_free(serial);
  743. serial = NULL;
  744. if (!BN_add_word(bn, 1))
  745. goto err;
  746. if ((serial = BN_to_ASN1_INTEGER(bn, NULL)) == NULL)
  747. goto err;
  748. }
  749. ret = 1;
  750. err:
  751. if (!ret) {
  752. ASN1_INTEGER_free(serial);
  753. serial = NULL;
  754. }
  755. BIO_free_all(in);
  756. BN_free(bn);
  757. return serial;
  758. }
  759. static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial)
  760. {
  761. int ret = 0;
  762. BIO *out = NULL;
  763. if ((out = BIO_new_file(serialfile, "w")) == NULL)
  764. goto err;
  765. if (i2a_ASN1_INTEGER(out, serial) <= 0)
  766. goto err;
  767. if (BIO_puts(out, "\n") <= 0)
  768. goto err;
  769. ret = 1;
  770. err:
  771. if (!ret)
  772. BIO_printf(bio_err, "could not save serial number to %s\n",
  773. serialfile);
  774. BIO_free_all(out);
  775. return ret;
  776. }
  777. /*
  778. * Verify-related method definitions.
  779. */
  780. static int verify_command(char *data, char *digest, char *queryfile,
  781. char *in, int token_in,
  782. char *CApath, char *CAfile, char *untrusted)
  783. {
  784. BIO *in_bio = NULL;
  785. PKCS7 *token = NULL;
  786. TS_RESP *response = NULL;
  787. TS_VERIFY_CTX *verify_ctx = NULL;
  788. int ret = 0;
  789. if ((in_bio = BIO_new_file(in, "rb")) == NULL)
  790. goto end;
  791. if (token_in) {
  792. if ((token = d2i_PKCS7_bio(in_bio, NULL)) == NULL)
  793. goto end;
  794. } else {
  795. if ((response = d2i_TS_RESP_bio(in_bio, NULL)) == NULL)
  796. goto end;
  797. }
  798. if ((verify_ctx = create_verify_ctx(data, digest, queryfile,
  799. CApath, CAfile, untrusted)) == NULL)
  800. goto end;
  801. ret = token_in
  802. ? TS_RESP_verify_token(verify_ctx, token)
  803. : TS_RESP_verify_response(verify_ctx, response);
  804. end:
  805. printf("Verification: ");
  806. if (ret)
  807. printf("OK\n");
  808. else {
  809. printf("FAILED\n");
  810. ERR_print_errors(bio_err);
  811. }
  812. BIO_free_all(in_bio);
  813. PKCS7_free(token);
  814. TS_RESP_free(response);
  815. TS_VERIFY_CTX_free(verify_ctx);
  816. return ret;
  817. }
  818. static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest,
  819. char *queryfile,
  820. char *CApath, char *CAfile,
  821. char *untrusted)
  822. {
  823. TS_VERIFY_CTX *ctx = NULL;
  824. BIO *input = NULL;
  825. TS_REQ *request = NULL;
  826. int ret = 0;
  827. int f = 0;
  828. if (data != NULL || digest != NULL) {
  829. if ((ctx = TS_VERIFY_CTX_new()) == NULL)
  830. goto err;
  831. f = TS_VFY_VERSION | TS_VFY_SIGNER;
  832. if (data != NULL) {
  833. f |= TS_VFY_DATA;
  834. if (TS_VERIFY_CTX_set_data(ctx, BIO_new_file(data, "rb")) == NULL)
  835. goto err;
  836. } else if (digest != NULL) {
  837. long imprint_len;
  838. unsigned char *hexstr = string_to_hex(digest, &imprint_len);
  839. f |= TS_VFY_IMPRINT;
  840. if (TS_VERIFY_CTX_set_imprint(ctx, hexstr, imprint_len) == NULL) {
  841. BIO_printf(bio_err, "invalid digest string\n");
  842. goto err;
  843. }
  844. }
  845. } else if (queryfile != NULL) {
  846. if ((input = BIO_new_file(queryfile, "rb")) == NULL)
  847. goto err;
  848. if ((request = d2i_TS_REQ_bio(input, NULL)) == NULL)
  849. goto err;
  850. if ((ctx = TS_REQ_to_TS_VERIFY_CTX(request, NULL)) == NULL)
  851. goto err;
  852. } else
  853. return NULL;
  854. /* Add the signature verification flag and arguments. */
  855. TS_VERIFY_CTX_add_flags(ctx, f | TS_VFY_SIGNATURE);
  856. /* Initialising the X509_STORE object. */
  857. if (TS_VERIFY_CTX_set_store(ctx, create_cert_store(CApath, CAfile))
  858. == NULL)
  859. goto err;
  860. /* Loading untrusted certificates. */
  861. if (untrusted
  862. && TS_VERIFY_CTS_set_certs(ctx, TS_CONF_load_certs(untrusted)) == NULL)
  863. goto err;
  864. ret = 1;
  865. err:
  866. if (!ret) {
  867. TS_VERIFY_CTX_free(ctx);
  868. ctx = NULL;
  869. }
  870. BIO_free_all(input);
  871. TS_REQ_free(request);
  872. return ctx;
  873. }
  874. static X509_STORE *create_cert_store(char *CApath, char *CAfile)
  875. {
  876. X509_STORE *cert_ctx = NULL;
  877. X509_LOOKUP *lookup = NULL;
  878. int i;
  879. cert_ctx = X509_STORE_new();
  880. X509_STORE_set_verify_cb(cert_ctx, verify_cb);
  881. if (CApath != NULL) {
  882. lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());
  883. if (lookup == NULL) {
  884. BIO_printf(bio_err, "memory allocation failure\n");
  885. goto err;
  886. }
  887. i = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM);
  888. if (!i) {
  889. BIO_printf(bio_err, "Error loading directory %s\n", CApath);
  890. goto err;
  891. }
  892. }
  893. if (CAfile != NULL) {
  894. lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());
  895. if (lookup == NULL) {
  896. BIO_printf(bio_err, "memory allocation failure\n");
  897. goto err;
  898. }
  899. i = X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM);
  900. if (!i) {
  901. BIO_printf(bio_err, "Error loading file %s\n", CAfile);
  902. goto err;
  903. }
  904. }
  905. return cert_ctx;
  906. err:
  907. X509_STORE_free(cert_ctx);
  908. return NULL;
  909. }
  910. static int verify_cb(int ok, X509_STORE_CTX *ctx)
  911. {
  912. return ok;
  913. }