ts.c 31 KB

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