2
0

engine.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /*
  2. * Copyright 2000-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. /* We need to use some engine deprecated APIs */
  10. #define OPENSSL_SUPPRESS_DEPRECATED
  11. #include <openssl/opensslconf.h>
  12. #include "apps.h"
  13. #include "progs.h"
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <openssl/err.h>
  18. #include <openssl/engine.h>
  19. #include <openssl/ssl.h>
  20. #include <openssl/store.h>
  21. typedef enum OPTION_choice {
  22. OPT_COMMON,
  23. OPT_C, OPT_T, OPT_TT, OPT_PRE, OPT_POST,
  24. OPT_V = 100, OPT_VV, OPT_VVV, OPT_VVVV
  25. } OPTION_CHOICE;
  26. const OPTIONS engine_options[] = {
  27. {OPT_HELP_STR, 1, '-', "Usage: %s [options] engine...\n"},
  28. OPT_SECTION("General"),
  29. {"help", OPT_HELP, '-', "Display this summary"},
  30. {"t", OPT_T, '-', "Check that specified engine is available"},
  31. {"pre", OPT_PRE, 's', "Run command against the ENGINE before loading it"},
  32. {"post", OPT_POST, 's', "Run command against the ENGINE after loading it"},
  33. OPT_SECTION("Output"),
  34. {"v", OPT_V, '-', "List 'control commands' For each specified engine"},
  35. {"vv", OPT_VV, '-', "Also display each command's description"},
  36. {"vvv", OPT_VVV, '-', "Also add the input flags for each command"},
  37. {"vvvv", OPT_VVVV, '-', "Also show internal input flags"},
  38. {"c", OPT_C, '-', "List the capabilities of specified engine"},
  39. {"tt", OPT_TT, '-', "Display error trace for unavailable engines"},
  40. {OPT_MORE_STR, OPT_EOF, 1,
  41. "Commands are like \"SO_PATH:/lib/libdriver.so\""},
  42. OPT_PARAMETERS(),
  43. {"engine", 0, 0, "ID of engine(s) to load"},
  44. {NULL}
  45. };
  46. static int append_buf(char **buf, int *size, const char *s)
  47. {
  48. const int expand = 256;
  49. int len = strlen(s) + 1;
  50. char *p = *buf;
  51. if (p == NULL) {
  52. *size = ((len + expand - 1) / expand) * expand;
  53. p = *buf = app_malloc(*size, "engine buffer");
  54. } else {
  55. const int blen = strlen(p);
  56. if (blen > 0)
  57. len += 2 + blen;
  58. if (len > *size) {
  59. *size = ((len + expand - 1) / expand) * expand;
  60. p = OPENSSL_realloc(p, *size);
  61. if (p == NULL) {
  62. OPENSSL_free(*buf);
  63. *buf = NULL;
  64. return 0;
  65. }
  66. *buf = p;
  67. }
  68. if (blen > 0) {
  69. p += blen;
  70. *p++ = ',';
  71. *p++ = ' ';
  72. }
  73. }
  74. strcpy(p, s);
  75. return 1;
  76. }
  77. static int util_flags(BIO *out, unsigned int flags, const char *indent)
  78. {
  79. int started = 0, err = 0;
  80. /* Indent before displaying input flags */
  81. BIO_printf(out, "%s%s(input flags): ", indent, indent);
  82. if (flags == 0) {
  83. BIO_printf(out, "<no flags>\n");
  84. return 1;
  85. }
  86. /*
  87. * If the object is internal, mark it in a way that shows instead of
  88. * having it part of all the other flags, even if it really is.
  89. */
  90. if (flags & ENGINE_CMD_FLAG_INTERNAL) {
  91. BIO_printf(out, "[Internal] ");
  92. }
  93. if (flags & ENGINE_CMD_FLAG_NUMERIC) {
  94. BIO_printf(out, "NUMERIC");
  95. started = 1;
  96. }
  97. /*
  98. * Now we check that no combinations of the mutually exclusive NUMERIC,
  99. * STRING, and NO_INPUT flags have been used. Future flags that can be
  100. * OR'd together with these would need to added after these to preserve
  101. * the testing logic.
  102. */
  103. if (flags & ENGINE_CMD_FLAG_STRING) {
  104. if (started) {
  105. BIO_printf(out, "|");
  106. err = 1;
  107. }
  108. BIO_printf(out, "STRING");
  109. started = 1;
  110. }
  111. if (flags & ENGINE_CMD_FLAG_NO_INPUT) {
  112. if (started) {
  113. BIO_printf(out, "|");
  114. err = 1;
  115. }
  116. BIO_printf(out, "NO_INPUT");
  117. started = 1;
  118. }
  119. /* Check for unknown flags */
  120. flags = flags & ~ENGINE_CMD_FLAG_NUMERIC &
  121. ~ENGINE_CMD_FLAG_STRING &
  122. ~ENGINE_CMD_FLAG_NO_INPUT & ~ENGINE_CMD_FLAG_INTERNAL;
  123. if (flags) {
  124. if (started)
  125. BIO_printf(out, "|");
  126. BIO_printf(out, "<0x%04X>", flags);
  127. }
  128. if (err)
  129. BIO_printf(out, " <illegal flags!>");
  130. BIO_printf(out, "\n");
  131. return 1;
  132. }
  133. static int util_verbose(ENGINE *e, int verbose, BIO *out, const char *indent)
  134. {
  135. static const int line_wrap = 78;
  136. int num;
  137. int ret = 0;
  138. char *name = NULL;
  139. char *desc = NULL;
  140. int flags;
  141. int xpos = 0;
  142. STACK_OF(OPENSSL_STRING) *cmds = NULL;
  143. if (!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) ||
  144. ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE,
  145. 0, NULL, NULL)) <= 0)) {
  146. return 1;
  147. }
  148. cmds = sk_OPENSSL_STRING_new_null();
  149. if (cmds == NULL)
  150. goto err;
  151. do {
  152. int len;
  153. /* Get the command input flags */
  154. if ((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num,
  155. NULL, NULL)) < 0)
  156. goto err;
  157. if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4) {
  158. /* Get the command name */
  159. if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num,
  160. NULL, NULL)) <= 0)
  161. goto err;
  162. name = app_malloc(len + 1, "name buffer");
  163. if (ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name,
  164. NULL) <= 0)
  165. goto err;
  166. /* Get the command description */
  167. if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num,
  168. NULL, NULL)) < 0)
  169. goto err;
  170. if (len > 0) {
  171. desc = app_malloc(len + 1, "description buffer");
  172. if (ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc,
  173. NULL) <= 0)
  174. goto err;
  175. }
  176. /* Now decide on the output */
  177. if (xpos == 0)
  178. /* Do an indent */
  179. xpos = BIO_puts(out, indent);
  180. else
  181. /* Otherwise prepend a ", " */
  182. xpos += BIO_printf(out, ", ");
  183. if (verbose == 1) {
  184. /*
  185. * We're just listing names, comma-delimited
  186. */
  187. if ((xpos > (int)strlen(indent)) &&
  188. (xpos + (int)strlen(name) > line_wrap)) {
  189. BIO_printf(out, "\n");
  190. xpos = BIO_puts(out, indent);
  191. }
  192. xpos += BIO_printf(out, "%s", name);
  193. } else {
  194. /* We're listing names plus descriptions */
  195. BIO_printf(out, "%s: %s\n", name,
  196. (desc == NULL) ? "<no description>" : desc);
  197. /* ... and sometimes input flags */
  198. if ((verbose >= 3) && !util_flags(out, flags, indent))
  199. goto err;
  200. xpos = 0;
  201. }
  202. }
  203. OPENSSL_free(name);
  204. name = NULL;
  205. OPENSSL_free(desc);
  206. desc = NULL;
  207. /* Move to the next command */
  208. num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, num, NULL, NULL);
  209. } while (num > 0);
  210. if (xpos > 0)
  211. BIO_printf(out, "\n");
  212. ret = 1;
  213. err:
  214. sk_OPENSSL_STRING_free(cmds);
  215. OPENSSL_free(name);
  216. OPENSSL_free(desc);
  217. return ret;
  218. }
  219. static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds,
  220. BIO *out, const char *indent)
  221. {
  222. int loop, res, num = sk_OPENSSL_STRING_num(cmds);
  223. if (num < 0) {
  224. BIO_printf(out, "[Error]: internal stack error\n");
  225. return;
  226. }
  227. for (loop = 0; loop < num; loop++) {
  228. char buf[256];
  229. const char *cmd, *arg;
  230. cmd = sk_OPENSSL_STRING_value(cmds, loop);
  231. res = 1; /* assume success */
  232. /* Check if this command has no ":arg" */
  233. if ((arg = strstr(cmd, ":")) == NULL) {
  234. if (!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0))
  235. res = 0;
  236. } else {
  237. if ((int)(arg - cmd) > 254) {
  238. BIO_printf(out, "[Error]: command name too long\n");
  239. return;
  240. }
  241. memcpy(buf, cmd, (int)(arg - cmd));
  242. buf[arg - cmd] = '\0';
  243. arg++; /* Move past the ":" */
  244. /* Call the command with the argument */
  245. if (!ENGINE_ctrl_cmd_string(e, buf, arg, 0))
  246. res = 0;
  247. }
  248. if (res) {
  249. BIO_printf(out, "[Success]: %s\n", cmd);
  250. } else {
  251. BIO_printf(out, "[Failure]: %s\n", cmd);
  252. ERR_print_errors(out);
  253. }
  254. }
  255. }
  256. struct util_store_cap_data {
  257. ENGINE *engine;
  258. char **cap_buf;
  259. int *cap_size;
  260. int ok;
  261. };
  262. static void util_store_cap(const OSSL_STORE_LOADER *loader, void *arg)
  263. {
  264. struct util_store_cap_data *ctx = arg;
  265. if (OSSL_STORE_LOADER_get0_engine(loader) == ctx->engine) {
  266. char buf[256];
  267. BIO_snprintf(buf, sizeof(buf), "STORE(%s)",
  268. OSSL_STORE_LOADER_get0_scheme(loader));
  269. if (!append_buf(ctx->cap_buf, ctx->cap_size, buf))
  270. ctx->ok = 0;
  271. }
  272. }
  273. int engine_main(int argc, char **argv)
  274. {
  275. int ret = 1, i;
  276. int verbose = 0, list_cap = 0, test_avail = 0, test_avail_noise = 0;
  277. ENGINE *e;
  278. STACK_OF(OPENSSL_CSTRING) *engines = sk_OPENSSL_CSTRING_new_null();
  279. STACK_OF(OPENSSL_STRING) *pre_cmds = sk_OPENSSL_STRING_new_null();
  280. STACK_OF(OPENSSL_STRING) *post_cmds = sk_OPENSSL_STRING_new_null();
  281. BIO *out;
  282. const char *indent = " ";
  283. OPTION_CHOICE o;
  284. char *prog;
  285. char *argv1;
  286. out = dup_bio_out(FORMAT_TEXT);
  287. if (engines == NULL || pre_cmds == NULL || post_cmds == NULL)
  288. goto end;
  289. /* Remember the original command name, parse/skip any leading engine
  290. * names, and then setup to parse the rest of the line as flags. */
  291. prog = argv[0];
  292. while ((argv1 = argv[1]) != NULL && *argv1 != '-') {
  293. sk_OPENSSL_CSTRING_push(engines, argv1);
  294. argc--;
  295. argv++;
  296. }
  297. argv[0] = prog;
  298. opt_init(argc, argv, engine_options);
  299. while ((o = opt_next()) != OPT_EOF) {
  300. switch (o) {
  301. case OPT_EOF:
  302. case OPT_ERR:
  303. BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
  304. goto end;
  305. case OPT_HELP:
  306. opt_help(engine_options);
  307. ret = 0;
  308. goto end;
  309. case OPT_VVVV:
  310. case OPT_VVV:
  311. case OPT_VV:
  312. case OPT_V:
  313. /* Convert to an integer from one to four. */
  314. i = (int)(o - OPT_V) + 1;
  315. if (verbose < i)
  316. verbose = i;
  317. break;
  318. case OPT_C:
  319. list_cap = 1;
  320. break;
  321. case OPT_TT:
  322. test_avail_noise++;
  323. /* fall thru */
  324. case OPT_T:
  325. test_avail++;
  326. break;
  327. case OPT_PRE:
  328. sk_OPENSSL_STRING_push(pre_cmds, opt_arg());
  329. break;
  330. case OPT_POST:
  331. sk_OPENSSL_STRING_push(post_cmds, opt_arg());
  332. break;
  333. }
  334. }
  335. /* Any remaining arguments are engine names. */
  336. argc = opt_num_rest();
  337. argv = opt_rest();
  338. for ( ; *argv; argv++) {
  339. if (**argv == '-') {
  340. BIO_printf(bio_err, "%s: Cannot mix flags and engine names.\n",
  341. prog);
  342. BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
  343. goto end;
  344. }
  345. sk_OPENSSL_CSTRING_push(engines, *argv);
  346. }
  347. if (sk_OPENSSL_CSTRING_num(engines) == 0) {
  348. for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) {
  349. sk_OPENSSL_CSTRING_push(engines, ENGINE_get_id(e));
  350. }
  351. }
  352. ret = 0;
  353. for (i = 0; i < sk_OPENSSL_CSTRING_num(engines); i++) {
  354. const char *id = sk_OPENSSL_CSTRING_value(engines, i);
  355. if ((e = ENGINE_by_id(id)) != NULL) {
  356. const char *name = ENGINE_get_name(e);
  357. /*
  358. * Do "id" first, then "name". Easier to auto-parse.
  359. */
  360. BIO_printf(out, "(%s) %s\n", id, name);
  361. util_do_cmds(e, pre_cmds, out, indent);
  362. if (strcmp(ENGINE_get_id(e), id) != 0) {
  363. BIO_printf(out, "Loaded: (%s) %s\n",
  364. ENGINE_get_id(e), ENGINE_get_name(e));
  365. }
  366. if (list_cap) {
  367. int cap_size = 256;
  368. char *cap_buf = NULL;
  369. int k, n;
  370. const int *nids;
  371. ENGINE_CIPHERS_PTR fn_c;
  372. ENGINE_DIGESTS_PTR fn_d;
  373. ENGINE_PKEY_METHS_PTR fn_pk;
  374. if (ENGINE_get_RSA(e) != NULL
  375. && !append_buf(&cap_buf, &cap_size, "RSA"))
  376. goto end;
  377. if (ENGINE_get_DSA(e) != NULL
  378. && !append_buf(&cap_buf, &cap_size, "DSA"))
  379. goto end;
  380. if (ENGINE_get_DH(e) != NULL
  381. && !append_buf(&cap_buf, &cap_size, "DH"))
  382. goto end;
  383. if (ENGINE_get_RAND(e) != NULL
  384. && !append_buf(&cap_buf, &cap_size, "RAND"))
  385. goto end;
  386. fn_c = ENGINE_get_ciphers(e);
  387. if (fn_c == NULL)
  388. goto skip_ciphers;
  389. n = fn_c(e, NULL, &nids, 0);
  390. for (k = 0; k < n; ++k)
  391. if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k])))
  392. goto end;
  393. skip_ciphers:
  394. fn_d = ENGINE_get_digests(e);
  395. if (fn_d == NULL)
  396. goto skip_digests;
  397. n = fn_d(e, NULL, &nids, 0);
  398. for (k = 0; k < n; ++k)
  399. if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k])))
  400. goto end;
  401. skip_digests:
  402. fn_pk = ENGINE_get_pkey_meths(e);
  403. if (fn_pk == NULL)
  404. goto skip_pmeths;
  405. n = fn_pk(e, NULL, &nids, 0);
  406. for (k = 0; k < n; ++k)
  407. if (!append_buf(&cap_buf, &cap_size, OBJ_nid2sn(nids[k])))
  408. goto end;
  409. skip_pmeths:
  410. {
  411. struct util_store_cap_data store_ctx;
  412. store_ctx.engine = e;
  413. store_ctx.cap_buf = &cap_buf;
  414. store_ctx.cap_size = &cap_size;
  415. store_ctx.ok = 1;
  416. OSSL_STORE_do_all_loaders(util_store_cap, &store_ctx);
  417. if (!store_ctx.ok)
  418. goto end;
  419. }
  420. if (cap_buf != NULL && (*cap_buf != '\0'))
  421. BIO_printf(out, " [%s]\n", cap_buf);
  422. OPENSSL_free(cap_buf);
  423. }
  424. if (test_avail) {
  425. BIO_printf(out, "%s", indent);
  426. if (ENGINE_init(e)) {
  427. BIO_printf(out, "[ available ]\n");
  428. util_do_cmds(e, post_cmds, out, indent);
  429. ENGINE_finish(e);
  430. } else {
  431. BIO_printf(out, "[ unavailable ]\n");
  432. if (test_avail_noise)
  433. ERR_print_errors_fp(stdout);
  434. ERR_clear_error();
  435. }
  436. }
  437. if ((verbose > 0) && !util_verbose(e, verbose, out, indent))
  438. goto end;
  439. ENGINE_free(e);
  440. } else {
  441. ERR_print_errors(bio_err);
  442. /* because exit codes above 127 have special meaning on Unix */
  443. if (++ret > 127)
  444. ret = 127;
  445. }
  446. }
  447. end:
  448. ERR_print_errors(bio_err);
  449. sk_OPENSSL_CSTRING_free(engines);
  450. sk_OPENSSL_STRING_free(pre_cmds);
  451. sk_OPENSSL_STRING_free(post_cmds);
  452. BIO_free_all(out);
  453. return ret;
  454. }