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