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