1109998Smarkm/* apps/engine.c -*- mode: C; c-file-style: "eay" -*- */ 2296465Sdelphij/* 3296465Sdelphij * Written by Richard Levitte <richard@levitte.org> for the OpenSSL project 4296465Sdelphij * 2000. 5109998Smarkm */ 6109998Smarkm/* ==================================================================== 7109998Smarkm * Copyright (c) 2000 The OpenSSL Project. All rights reserved. 8109998Smarkm * 9109998Smarkm * Redistribution and use in source and binary forms, with or without 10109998Smarkm * modification, are permitted provided that the following conditions 11109998Smarkm * are met: 12109998Smarkm * 13109998Smarkm * 1. Redistributions of source code must retain the above copyright 14296465Sdelphij * notice, this list of conditions and the following disclaimer. 15109998Smarkm * 16109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 17109998Smarkm * notice, this list of conditions and the following disclaimer in 18109998Smarkm * the documentation and/or other materials provided with the 19109998Smarkm * distribution. 20109998Smarkm * 21109998Smarkm * 3. All advertising materials mentioning features or use of this 22109998Smarkm * software must display the following acknowledgment: 23109998Smarkm * "This product includes software developed by the OpenSSL Project 24109998Smarkm * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25109998Smarkm * 26109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27109998Smarkm * endorse or promote products derived from this software without 28109998Smarkm * prior written permission. For written permission, please contact 29109998Smarkm * licensing@OpenSSL.org. 30109998Smarkm * 31109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 32109998Smarkm * nor may "OpenSSL" appear in their names without prior written 33109998Smarkm * permission of the OpenSSL Project. 34109998Smarkm * 35109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 36109998Smarkm * acknowledgment: 37109998Smarkm * "This product includes software developed by the OpenSSL Project 38109998Smarkm * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39109998Smarkm * 40109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 52109998Smarkm * ==================================================================== 53109998Smarkm * 54109998Smarkm * This product includes cryptographic software written by Eric Young 55109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 56109998Smarkm * Hudson (tjh@cryptsoft.com). 57109998Smarkm * 58109998Smarkm */ 59109998Smarkm 60109998Smarkm#include <stdio.h> 61109998Smarkm#include <stdlib.h> 62109998Smarkm#include <string.h> 63109998Smarkm#ifdef OPENSSL_NO_STDIO 64296465Sdelphij# define APPS_WIN16 65109998Smarkm#endif 66109998Smarkm#include "apps.h" 67109998Smarkm#include <openssl/err.h> 68194206Ssimon#ifndef OPENSSL_NO_ENGINE 69296465Sdelphij# include <openssl/engine.h> 70296465Sdelphij# include <openssl/ssl.h> 71109998Smarkm 72296465Sdelphij# undef PROG 73296465Sdelphij# define PROG engine_main 74109998Smarkm 75296465Sdelphijstatic const char *engine_usage[] = { 76296465Sdelphij "usage: engine opts [engine ...]\n", 77296465Sdelphij " -v[v[v[v]]] - verbose mode, for each engine, list its 'control commands'\n", 78296465Sdelphij " -vv will additionally display each command's description\n", 79296465Sdelphij " -vvv will also add the input flags for each command\n", 80296465Sdelphij " -vvvv will also show internal input flags\n", 81296465Sdelphij " -c - for each engine, also list the capabilities\n", 82296465Sdelphij " -t[t] - for each engine, check that they are really available\n", 83296465Sdelphij " -tt will display error trace for unavailable engines\n", 84296465Sdelphij " -pre <cmd> - runs command 'cmd' against the ENGINE before any attempts\n", 85296465Sdelphij " to load it (if -t is used)\n", 86296465Sdelphij " -post <cmd> - runs command 'cmd' against the ENGINE after loading it\n", 87296465Sdelphij " (only used if -t is also provided)\n", 88296465Sdelphij " NB: -pre and -post will be applied to all ENGINEs supplied on the command\n", 89296465Sdelphij " line, or all supported ENGINEs if none are specified.\n", 90296465Sdelphij " Eg. '-pre \"SO_PATH:/lib/libdriver.so\"' calls command \"SO_PATH\" with\n", 91296465Sdelphij " argument \"/lib/libdriver.so\".\n", 92296465Sdelphij NULL 93109998Smarkm}; 94109998Smarkm 95109998Smarkmstatic void identity(void *ptr) 96296465Sdelphij{ 97296465Sdelphij return; 98296465Sdelphij} 99109998Smarkm 100109998Smarkmstatic int append_buf(char **buf, const char *s, int *size, int step) 101296465Sdelphij{ 102296465Sdelphij int l = strlen(s); 103109998Smarkm 104296465Sdelphij if (*buf == NULL) { 105296465Sdelphij *size = step; 106296465Sdelphij *buf = OPENSSL_malloc(*size); 107296465Sdelphij if (*buf == NULL) 108296465Sdelphij return 0; 109296465Sdelphij **buf = '\0'; 110296465Sdelphij } 111109998Smarkm 112296465Sdelphij if (**buf != '\0') 113296465Sdelphij l += 2; /* ", " */ 114109998Smarkm 115296465Sdelphij if (strlen(*buf) + strlen(s) >= (unsigned int)*size) { 116296465Sdelphij *size += step; 117296465Sdelphij *buf = OPENSSL_realloc(*buf, *size); 118296465Sdelphij } 119109998Smarkm 120296465Sdelphij if (*buf == NULL) 121296465Sdelphij return 0; 122109998Smarkm 123296465Sdelphij if (**buf != '\0') 124296465Sdelphij BUF_strlcat(*buf, ", ", *size); 125296465Sdelphij BUF_strlcat(*buf, s, *size); 126109998Smarkm 127296465Sdelphij return 1; 128296465Sdelphij} 129109998Smarkm 130109998Smarkmstatic int util_flags(BIO *bio_out, unsigned int flags, const char *indent) 131296465Sdelphij{ 132296465Sdelphij int started = 0, err = 0; 133296465Sdelphij /* Indent before displaying input flags */ 134296465Sdelphij BIO_printf(bio_out, "%s%s(input flags): ", indent, indent); 135296465Sdelphij if (flags == 0) { 136296465Sdelphij BIO_printf(bio_out, "<no flags>\n"); 137296465Sdelphij return 1; 138296465Sdelphij } 139296465Sdelphij /* 140296465Sdelphij * If the object is internal, mark it in a way that shows instead of 141296465Sdelphij * having it part of all the other flags, even if it really is. 142296465Sdelphij */ 143296465Sdelphij if (flags & ENGINE_CMD_FLAG_INTERNAL) { 144296465Sdelphij BIO_printf(bio_out, "[Internal] "); 145296465Sdelphij } 146109998Smarkm 147296465Sdelphij if (flags & ENGINE_CMD_FLAG_NUMERIC) { 148296465Sdelphij if (started) { 149296465Sdelphij BIO_printf(bio_out, "|"); 150296465Sdelphij err = 1; 151296465Sdelphij } 152296465Sdelphij BIO_printf(bio_out, "NUMERIC"); 153296465Sdelphij started = 1; 154296465Sdelphij } 155296465Sdelphij /* 156296465Sdelphij * Now we check that no combinations of the mutually exclusive NUMERIC, 157296465Sdelphij * STRING, and NO_INPUT flags have been used. Future flags that can be 158296465Sdelphij * OR'd together with these would need to added after these to preserve 159296465Sdelphij * the testing logic. 160296465Sdelphij */ 161296465Sdelphij if (flags & ENGINE_CMD_FLAG_STRING) { 162296465Sdelphij if (started) { 163296465Sdelphij BIO_printf(bio_out, "|"); 164296465Sdelphij err = 1; 165296465Sdelphij } 166296465Sdelphij BIO_printf(bio_out, "STRING"); 167296465Sdelphij started = 1; 168296465Sdelphij } 169296465Sdelphij if (flags & ENGINE_CMD_FLAG_NO_INPUT) { 170296465Sdelphij if (started) { 171296465Sdelphij BIO_printf(bio_out, "|"); 172296465Sdelphij err = 1; 173296465Sdelphij } 174296465Sdelphij BIO_printf(bio_out, "NO_INPUT"); 175296465Sdelphij started = 1; 176296465Sdelphij } 177296465Sdelphij /* Check for unknown flags */ 178296465Sdelphij flags = flags & ~ENGINE_CMD_FLAG_NUMERIC & 179296465Sdelphij ~ENGINE_CMD_FLAG_STRING & 180296465Sdelphij ~ENGINE_CMD_FLAG_NO_INPUT & ~ENGINE_CMD_FLAG_INTERNAL; 181296465Sdelphij if (flags) { 182296465Sdelphij if (started) 183296465Sdelphij BIO_printf(bio_out, "|"); 184296465Sdelphij BIO_printf(bio_out, "<0x%04X>", flags); 185296465Sdelphij } 186296465Sdelphij if (err) 187296465Sdelphij BIO_printf(bio_out, " <illegal flags!>"); 188296465Sdelphij BIO_printf(bio_out, "\n"); 189296465Sdelphij return 1; 190296465Sdelphij} 191109998Smarkm 192296465Sdelphijstatic int util_verbose(ENGINE *e, int verbose, BIO *bio_out, 193296465Sdelphij const char *indent) 194296465Sdelphij{ 195296465Sdelphij static const int line_wrap = 78; 196296465Sdelphij int num; 197296465Sdelphij int ret = 0; 198296465Sdelphij char *name = NULL; 199296465Sdelphij char *desc = NULL; 200296465Sdelphij int flags; 201296465Sdelphij int xpos = 0; 202296465Sdelphij STACK *cmds = NULL; 203296465Sdelphij if (!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) || 204296465Sdelphij ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE, 205296465Sdelphij 0, NULL, NULL)) <= 0)) { 206296465Sdelphij# if 0 207296465Sdelphij BIO_printf(bio_out, "%s<no control commands>\n", indent); 208296465Sdelphij# endif 209296465Sdelphij return 1; 210296465Sdelphij } 211109998Smarkm 212296465Sdelphij cmds = sk_new_null(); 213109998Smarkm 214296465Sdelphij if (!cmds) 215296465Sdelphij goto err; 216296465Sdelphij do { 217296465Sdelphij int len; 218296465Sdelphij /* Get the command input flags */ 219296465Sdelphij if ((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, 220296465Sdelphij NULL, NULL)) < 0) 221296465Sdelphij goto err; 222296465Sdelphij if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4) { 223296465Sdelphij /* Get the command name */ 224296465Sdelphij if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num, 225296465Sdelphij NULL, NULL)) <= 0) 226296465Sdelphij goto err; 227296465Sdelphij if ((name = OPENSSL_malloc(len + 1)) == NULL) 228296465Sdelphij goto err; 229296465Sdelphij if (ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name, 230296465Sdelphij NULL) <= 0) 231296465Sdelphij goto err; 232296465Sdelphij /* Get the command description */ 233296465Sdelphij if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num, 234296465Sdelphij NULL, NULL)) < 0) 235296465Sdelphij goto err; 236296465Sdelphij if (len > 0) { 237296465Sdelphij if ((desc = OPENSSL_malloc(len + 1)) == NULL) 238296465Sdelphij goto err; 239296465Sdelphij if (ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc, 240109998Smarkm NULL) <= 0) 241296465Sdelphij goto err; 242296465Sdelphij } 243296465Sdelphij /* Now decide on the output */ 244296465Sdelphij if (xpos == 0) 245296465Sdelphij /* Do an indent */ 246296465Sdelphij xpos = BIO_puts(bio_out, indent); 247296465Sdelphij else 248296465Sdelphij /* Otherwise prepend a ", " */ 249296465Sdelphij xpos += BIO_printf(bio_out, ", "); 250296465Sdelphij if (verbose == 1) { 251296465Sdelphij /* 252296465Sdelphij * We're just listing names, comma-delimited 253296465Sdelphij */ 254296465Sdelphij if ((xpos > (int)strlen(indent)) && 255296465Sdelphij (xpos + (int)strlen(name) > line_wrap)) { 256296465Sdelphij BIO_printf(bio_out, "\n"); 257296465Sdelphij xpos = BIO_puts(bio_out, indent); 258296465Sdelphij } 259296465Sdelphij xpos += BIO_printf(bio_out, "%s", name); 260296465Sdelphij } else { 261296465Sdelphij /* We're listing names plus descriptions */ 262296465Sdelphij BIO_printf(bio_out, "%s: %s\n", name, 263296465Sdelphij (desc == NULL) ? "<no description>" : desc); 264296465Sdelphij /* ... and sometimes input flags */ 265296465Sdelphij if ((verbose >= 3) && !util_flags(bio_out, flags, indent)) 266296465Sdelphij goto err; 267296465Sdelphij xpos = 0; 268296465Sdelphij } 269296465Sdelphij } 270296465Sdelphij OPENSSL_free(name); 271296465Sdelphij name = NULL; 272296465Sdelphij if (desc) { 273296465Sdelphij OPENSSL_free(desc); 274296465Sdelphij desc = NULL; 275296465Sdelphij } 276296465Sdelphij /* Move to the next command */ 277296465Sdelphij num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, num, NULL, NULL); 278296465Sdelphij } while (num > 0); 279296465Sdelphij if (xpos > 0) 280296465Sdelphij BIO_printf(bio_out, "\n"); 281296465Sdelphij ret = 1; 282296465Sdelphij err: 283296465Sdelphij if (cmds) 284296465Sdelphij sk_pop_free(cmds, identity); 285296465Sdelphij if (name) 286296465Sdelphij OPENSSL_free(name); 287296465Sdelphij if (desc) 288296465Sdelphij OPENSSL_free(desc); 289296465Sdelphij return ret; 290296465Sdelphij} 291109998Smarkm 292296465Sdelphijstatic void util_do_cmds(ENGINE *e, STACK * cmds, BIO *bio_out, 293296465Sdelphij const char *indent) 294296465Sdelphij{ 295296465Sdelphij int loop, res, num = sk_num(cmds); 296296465Sdelphij if (num < 0) { 297296465Sdelphij BIO_printf(bio_out, "[Error]: internal stack error\n"); 298296465Sdelphij return; 299296465Sdelphij } 300296465Sdelphij for (loop = 0; loop < num; loop++) { 301296465Sdelphij char buf[256]; 302296465Sdelphij const char *cmd, *arg; 303296465Sdelphij cmd = sk_value(cmds, loop); 304296465Sdelphij res = 1; /* assume success */ 305296465Sdelphij /* Check if this command has no ":arg" */ 306296465Sdelphij if ((arg = strstr(cmd, ":")) == NULL) { 307296465Sdelphij if (!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0)) 308296465Sdelphij res = 0; 309296465Sdelphij } else { 310296465Sdelphij if ((int)(arg - cmd) > 254) { 311296465Sdelphij BIO_printf(bio_out, "[Error]: command name too long\n"); 312296465Sdelphij return; 313296465Sdelphij } 314296465Sdelphij memcpy(buf, cmd, (int)(arg - cmd)); 315296465Sdelphij buf[arg - cmd] = '\0'; 316296465Sdelphij arg++; /* Move past the ":" */ 317296465Sdelphij /* Call the command with the argument */ 318296465Sdelphij if (!ENGINE_ctrl_cmd_string(e, buf, arg, 0)) 319296465Sdelphij res = 0; 320296465Sdelphij } 321296465Sdelphij if (res) 322296465Sdelphij BIO_printf(bio_out, "[Success]: %s\n", cmd); 323296465Sdelphij else { 324296465Sdelphij BIO_printf(bio_out, "[Failure]: %s\n", cmd); 325296465Sdelphij ERR_print_errors(bio_out); 326296465Sdelphij } 327296465Sdelphij } 328296465Sdelphij} 329109998Smarkm 330109998Smarkmint MAIN(int, char **); 331109998Smarkm 332109998Smarkmint MAIN(int argc, char **argv) 333296465Sdelphij{ 334296465Sdelphij int ret = 1, i; 335296465Sdelphij const char **pp; 336296465Sdelphij int verbose = 0, list_cap = 0, test_avail = 0, test_avail_noise = 0; 337296465Sdelphij ENGINE *e; 338296465Sdelphij STACK *engines = sk_new_null(); 339296465Sdelphij STACK *pre_cmds = sk_new_null(); 340296465Sdelphij STACK *post_cmds = sk_new_null(); 341296465Sdelphij int badops = 1; 342296465Sdelphij BIO *bio_out = NULL; 343296465Sdelphij const char *indent = " "; 344109998Smarkm 345296465Sdelphij apps_startup(); 346296465Sdelphij SSL_load_error_strings(); 347109998Smarkm 348296465Sdelphij if (bio_err == NULL) 349296465Sdelphij bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 350109998Smarkm 351296465Sdelphij if (!load_config(bio_err, NULL)) 352296465Sdelphij goto end; 353296465Sdelphij bio_out = BIO_new_fp(stdout, BIO_NOCLOSE); 354296465Sdelphij# ifdef OPENSSL_SYS_VMS 355296465Sdelphij { 356296465Sdelphij BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 357296465Sdelphij bio_out = BIO_push(tmpbio, bio_out); 358296465Sdelphij } 359296465Sdelphij# endif 360109998Smarkm 361296465Sdelphij argc--; 362296465Sdelphij argv++; 363296465Sdelphij while (argc >= 1) { 364296465Sdelphij if (strncmp(*argv, "-v", 2) == 0) { 365296465Sdelphij if (strspn(*argv + 1, "v") < strlen(*argv + 1)) 366296465Sdelphij goto skip_arg_loop; 367296465Sdelphij if ((verbose = strlen(*argv + 1)) > 4) 368296465Sdelphij goto skip_arg_loop; 369296465Sdelphij } else if (strcmp(*argv, "-c") == 0) 370296465Sdelphij list_cap = 1; 371296465Sdelphij else if (strncmp(*argv, "-t", 2) == 0) { 372296465Sdelphij test_avail = 1; 373296465Sdelphij if (strspn(*argv + 1, "t") < strlen(*argv + 1)) 374296465Sdelphij goto skip_arg_loop; 375296465Sdelphij if ((test_avail_noise = strlen(*argv + 1) - 1) > 1) 376296465Sdelphij goto skip_arg_loop; 377296465Sdelphij } else if (strcmp(*argv, "-pre") == 0) { 378296465Sdelphij argc--; 379296465Sdelphij argv++; 380296465Sdelphij if (argc == 0) 381296465Sdelphij goto skip_arg_loop; 382296465Sdelphij sk_push(pre_cmds, *argv); 383296465Sdelphij } else if (strcmp(*argv, "-post") == 0) { 384296465Sdelphij argc--; 385296465Sdelphij argv++; 386296465Sdelphij if (argc == 0) 387296465Sdelphij goto skip_arg_loop; 388296465Sdelphij sk_push(post_cmds, *argv); 389296465Sdelphij } else if ((strncmp(*argv, "-h", 2) == 0) || 390296465Sdelphij (strcmp(*argv, "-?") == 0)) 391296465Sdelphij goto skip_arg_loop; 392296465Sdelphij else 393296465Sdelphij sk_push(engines, *argv); 394296465Sdelphij argc--; 395296465Sdelphij argv++; 396296465Sdelphij } 397296465Sdelphij /* Looks like everything went OK */ 398296465Sdelphij badops = 0; 399296465Sdelphij skip_arg_loop: 400109998Smarkm 401296465Sdelphij if (badops) { 402296465Sdelphij for (pp = engine_usage; (*pp != NULL); pp++) 403296465Sdelphij BIO_printf(bio_err, "%s", *pp); 404296465Sdelphij goto end; 405296465Sdelphij } 406109998Smarkm 407296465Sdelphij if (sk_num(engines) == 0) { 408296465Sdelphij for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) { 409296465Sdelphij sk_push(engines, (char *)ENGINE_get_id(e)); 410296465Sdelphij } 411296465Sdelphij } 412109998Smarkm 413296465Sdelphij for (i = 0; i < sk_num(engines); i++) { 414296465Sdelphij const char *id = sk_value(engines, i); 415296465Sdelphij if ((e = ENGINE_by_id(id)) != NULL) { 416296465Sdelphij const char *name = ENGINE_get_name(e); 417296465Sdelphij /* 418296465Sdelphij * Do "id" first, then "name". Easier to auto-parse. 419296465Sdelphij */ 420296465Sdelphij BIO_printf(bio_out, "(%s) %s\n", id, name); 421296465Sdelphij util_do_cmds(e, pre_cmds, bio_out, indent); 422296465Sdelphij if (strcmp(ENGINE_get_id(e), id) != 0) { 423296465Sdelphij BIO_printf(bio_out, "Loaded: (%s) %s\n", 424296465Sdelphij ENGINE_get_id(e), ENGINE_get_name(e)); 425296465Sdelphij } 426296465Sdelphij if (list_cap) { 427296465Sdelphij int cap_size = 256; 428296465Sdelphij char *cap_buf = NULL; 429296465Sdelphij int k, n; 430296465Sdelphij const int *nids; 431296465Sdelphij ENGINE_CIPHERS_PTR fn_c; 432296465Sdelphij ENGINE_DIGESTS_PTR fn_d; 433109998Smarkm 434296465Sdelphij if (ENGINE_get_RSA(e) != NULL 435296465Sdelphij && !append_buf(&cap_buf, "RSA", &cap_size, 256)) 436296465Sdelphij goto end; 437296465Sdelphij if (ENGINE_get_DSA(e) != NULL 438296465Sdelphij && !append_buf(&cap_buf, "DSA", &cap_size, 256)) 439296465Sdelphij goto end; 440296465Sdelphij if (ENGINE_get_DH(e) != NULL 441296465Sdelphij && !append_buf(&cap_buf, "DH", &cap_size, 256)) 442296465Sdelphij goto end; 443296465Sdelphij if (ENGINE_get_RAND(e) != NULL 444296465Sdelphij && !append_buf(&cap_buf, "RAND", &cap_size, 256)) 445296465Sdelphij goto end; 446109998Smarkm 447296465Sdelphij fn_c = ENGINE_get_ciphers(e); 448296465Sdelphij if (!fn_c) 449296465Sdelphij goto skip_ciphers; 450296465Sdelphij n = fn_c(e, NULL, &nids, 0); 451296465Sdelphij for (k = 0; k < n; ++k) 452296465Sdelphij if (!append_buf(&cap_buf, 453296465Sdelphij OBJ_nid2sn(nids[k]), &cap_size, 256)) 454296465Sdelphij goto end; 455109998Smarkm 456296465Sdelphij skip_ciphers: 457296465Sdelphij fn_d = ENGINE_get_digests(e); 458296465Sdelphij if (!fn_d) 459296465Sdelphij goto skip_digests; 460296465Sdelphij n = fn_d(e, NULL, &nids, 0); 461296465Sdelphij for (k = 0; k < n; ++k) 462296465Sdelphij if (!append_buf(&cap_buf, 463296465Sdelphij OBJ_nid2sn(nids[k]), &cap_size, 256)) 464296465Sdelphij goto end; 465109998Smarkm 466296465Sdelphij skip_digests: 467296465Sdelphij if (cap_buf && (*cap_buf != '\0')) 468296465Sdelphij BIO_printf(bio_out, " [%s]\n", cap_buf); 469109998Smarkm 470296465Sdelphij OPENSSL_free(cap_buf); 471296465Sdelphij } 472296465Sdelphij if (test_avail) { 473296465Sdelphij BIO_printf(bio_out, "%s", indent); 474296465Sdelphij if (ENGINE_init(e)) { 475296465Sdelphij BIO_printf(bio_out, "[ available ]\n"); 476296465Sdelphij util_do_cmds(e, post_cmds, bio_out, indent); 477296465Sdelphij ENGINE_finish(e); 478296465Sdelphij } else { 479296465Sdelphij BIO_printf(bio_out, "[ unavailable ]\n"); 480296465Sdelphij if (test_avail_noise) 481296465Sdelphij ERR_print_errors_fp(stdout); 482296465Sdelphij ERR_clear_error(); 483296465Sdelphij } 484296465Sdelphij } 485296465Sdelphij if ((verbose > 0) && !util_verbose(e, verbose, bio_out, indent)) 486296465Sdelphij goto end; 487296465Sdelphij ENGINE_free(e); 488296465Sdelphij } else 489296465Sdelphij ERR_print_errors(bio_err); 490296465Sdelphij } 491109998Smarkm 492296465Sdelphij ret = 0; 493296465Sdelphij end: 494160814Ssimon 495296465Sdelphij ERR_print_errors(bio_err); 496296465Sdelphij sk_pop_free(engines, identity); 497296465Sdelphij sk_pop_free(pre_cmds, identity); 498296465Sdelphij sk_pop_free(post_cmds, identity); 499296465Sdelphij if (bio_out != NULL) 500296465Sdelphij BIO_free_all(bio_out); 501296465Sdelphij apps_shutdown(); 502296465Sdelphij OPENSSL_EXIT(ret); 503296465Sdelphij} 504120631Snectar#else 505120631Snectar 506120631Snectar# if PEDANTIC 507296465Sdelphijstatic void *dummy = &dummy; 508120631Snectar# endif 509120631Snectar 510111147Snectar#endif 511