ts.c 30 KB

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