1109998Smarkm/* apps/engine.c -*- mode: C; c-file-style: "eay" -*- */ 2296341Sdelphij/* 3296341Sdelphij * Written by Richard Levitte <richard@levitte.org> for the OpenSSL project 4296341Sdelphij * 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 14296341Sdelphij * 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 64296341Sdelphij# define APPS_WIN16 65109998Smarkm#endif 66109998Smarkm#include "apps.h" 67109998Smarkm#include <openssl/err.h> 68194206Ssimon#ifndef OPENSSL_NO_ENGINE 69296341Sdelphij# include <openssl/engine.h> 70296341Sdelphij# include <openssl/ssl.h> 71109998Smarkm 72296341Sdelphij# undef PROG 73296341Sdelphij# define PROG engine_main 74109998Smarkm 75296341Sdelphijstatic const char *engine_usage[] = { 76296341Sdelphij "usage: engine opts [engine ...]\n", 77296341Sdelphij " -v[v[v[v]]] - verbose mode, for each engine, list its 'control commands'\n", 78296341Sdelphij " -vv will additionally display each command's description\n", 79296341Sdelphij " -vvv will also add the input flags for each command\n", 80296341Sdelphij " -vvvv will also show internal input flags\n", 81296341Sdelphij " -c - for each engine, also list the capabilities\n", 82296341Sdelphij " -t[t] - for each engine, check that they are really available\n", 83296341Sdelphij " -tt will display error trace for unavailable engines\n", 84296341Sdelphij " -pre <cmd> - runs command 'cmd' against the ENGINE before any attempts\n", 85296341Sdelphij " to load it (if -t is used)\n", 86296341Sdelphij " -post <cmd> - runs command 'cmd' against the ENGINE after loading it\n", 87296341Sdelphij " (only used if -t is also provided)\n", 88296341Sdelphij " NB: -pre and -post will be applied to all ENGINEs supplied on the command\n", 89296341Sdelphij " line, or all supported ENGINEs if none are specified.\n", 90296341Sdelphij " Eg. '-pre \"SO_PATH:/lib/libdriver.so\"' calls command \"SO_PATH\" with\n", 91296341Sdelphij " argument \"/lib/libdriver.so\".\n", 92296341Sdelphij NULL 93109998Smarkm}; 94109998Smarkm 95238405Sjkimstatic void identity(char *ptr) 96296341Sdelphij{ 97296341Sdelphij return; 98296341Sdelphij} 99109998Smarkm 100109998Smarkmstatic int append_buf(char **buf, const char *s, int *size, int step) 101296341Sdelphij{ 102296341Sdelphij int l = strlen(s); 103109998Smarkm 104296341Sdelphij if (*buf == NULL) { 105296341Sdelphij *size = step; 106296341Sdelphij *buf = OPENSSL_malloc(*size); 107296341Sdelphij if (*buf == NULL) 108296341Sdelphij return 0; 109296341Sdelphij **buf = '\0'; 110296341Sdelphij } 111109998Smarkm 112296341Sdelphij if (**buf != '\0') 113296341Sdelphij l += 2; /* ", " */ 114109998Smarkm 115296341Sdelphij if (strlen(*buf) + strlen(s) >= (unsigned int)*size) { 116296341Sdelphij *size += step; 117296341Sdelphij *buf = OPENSSL_realloc(*buf, *size); 118296341Sdelphij } 119109998Smarkm 120296341Sdelphij if (*buf == NULL) 121296341Sdelphij return 0; 122109998Smarkm 123296341Sdelphij if (**buf != '\0') 124296341Sdelphij BUF_strlcat(*buf, ", ", *size); 125296341Sdelphij BUF_strlcat(*buf, s, *size); 126109998Smarkm 127296341Sdelphij return 1; 128296341Sdelphij} 129109998Smarkm 130109998Smarkmstatic int util_flags(BIO *bio_out, unsigned int flags, const char *indent) 131296341Sdelphij{ 132296341Sdelphij int started = 0, err = 0; 133296341Sdelphij /* Indent before displaying input flags */ 134296341Sdelphij BIO_printf(bio_out, "%s%s(input flags): ", indent, indent); 135296341Sdelphij if (flags == 0) { 136296341Sdelphij BIO_printf(bio_out, "<no flags>\n"); 137296341Sdelphij return 1; 138296341Sdelphij } 139296341Sdelphij /* 140296341Sdelphij * If the object is internal, mark it in a way that shows instead of 141296341Sdelphij * having it part of all the other flags, even if it really is. 142296341Sdelphij */ 143296341Sdelphij if (flags & ENGINE_CMD_FLAG_INTERNAL) { 144296341Sdelphij BIO_printf(bio_out, "[Internal] "); 145296341Sdelphij } 146109998Smarkm 147296341Sdelphij if (flags & ENGINE_CMD_FLAG_NUMERIC) { 148296341Sdelphij BIO_printf(bio_out, "NUMERIC"); 149296341Sdelphij started = 1; 150296341Sdelphij } 151296341Sdelphij /* 152296341Sdelphij * Now we check that no combinations of the mutually exclusive NUMERIC, 153296341Sdelphij * STRING, and NO_INPUT flags have been used. Future flags that can be 154296341Sdelphij * OR'd together with these would need to added after these to preserve 155296341Sdelphij * the testing logic. 156296341Sdelphij */ 157296341Sdelphij if (flags & ENGINE_CMD_FLAG_STRING) { 158296341Sdelphij if (started) { 159296341Sdelphij BIO_printf(bio_out, "|"); 160296341Sdelphij err = 1; 161296341Sdelphij } 162296341Sdelphij BIO_printf(bio_out, "STRING"); 163296341Sdelphij started = 1; 164296341Sdelphij } 165296341Sdelphij if (flags & ENGINE_CMD_FLAG_NO_INPUT) { 166296341Sdelphij if (started) { 167296341Sdelphij BIO_printf(bio_out, "|"); 168296341Sdelphij err = 1; 169296341Sdelphij } 170296341Sdelphij BIO_printf(bio_out, "NO_INPUT"); 171296341Sdelphij started = 1; 172296341Sdelphij } 173296341Sdelphij /* Check for unknown flags */ 174296341Sdelphij flags = flags & ~ENGINE_CMD_FLAG_NUMERIC & 175296341Sdelphij ~ENGINE_CMD_FLAG_STRING & 176296341Sdelphij ~ENGINE_CMD_FLAG_NO_INPUT & ~ENGINE_CMD_FLAG_INTERNAL; 177296341Sdelphij if (flags) { 178296341Sdelphij if (started) 179296341Sdelphij BIO_printf(bio_out, "|"); 180296341Sdelphij BIO_printf(bio_out, "<0x%04X>", flags); 181296341Sdelphij } 182296341Sdelphij if (err) 183296341Sdelphij BIO_printf(bio_out, " <illegal flags!>"); 184296341Sdelphij BIO_printf(bio_out, "\n"); 185296341Sdelphij return 1; 186296341Sdelphij} 187109998Smarkm 188296341Sdelphijstatic int util_verbose(ENGINE *e, int verbose, BIO *bio_out, 189296341Sdelphij const char *indent) 190296341Sdelphij{ 191296341Sdelphij static const int line_wrap = 78; 192296341Sdelphij int num; 193296341Sdelphij int ret = 0; 194296341Sdelphij char *name = NULL; 195296341Sdelphij char *desc = NULL; 196296341Sdelphij int flags; 197296341Sdelphij int xpos = 0; 198296341Sdelphij STACK_OF(OPENSSL_STRING) *cmds = NULL; 199296341Sdelphij if (!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) || 200296341Sdelphij ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE, 201296341Sdelphij 0, NULL, NULL)) <= 0)) { 202296341Sdelphij# if 0 203296341Sdelphij BIO_printf(bio_out, "%s<no control commands>\n", indent); 204296341Sdelphij# endif 205296341Sdelphij return 1; 206296341Sdelphij } 207109998Smarkm 208296341Sdelphij cmds = sk_OPENSSL_STRING_new_null(); 209109998Smarkm 210296341Sdelphij if (!cmds) 211296341Sdelphij goto err; 212296341Sdelphij do { 213296341Sdelphij int len; 214296341Sdelphij /* Get the command input flags */ 215296341Sdelphij if ((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, 216296341Sdelphij NULL, NULL)) < 0) 217296341Sdelphij goto err; 218296341Sdelphij if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4) { 219296341Sdelphij /* Get the command name */ 220296341Sdelphij if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num, 221296341Sdelphij NULL, NULL)) <= 0) 222296341Sdelphij goto err; 223296341Sdelphij if ((name = OPENSSL_malloc(len + 1)) == NULL) 224296341Sdelphij goto err; 225296341Sdelphij if (ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name, 226296341Sdelphij NULL) <= 0) 227296341Sdelphij goto err; 228296341Sdelphij /* Get the command description */ 229296341Sdelphij if ((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num, 230296341Sdelphij NULL, NULL)) < 0) 231296341Sdelphij goto err; 232296341Sdelphij if (len > 0) { 233296341Sdelphij if ((desc = OPENSSL_malloc(len + 1)) == NULL) 234296341Sdelphij goto err; 235296341Sdelphij if (ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc, 236109998Smarkm NULL) <= 0) 237296341Sdelphij goto err; 238296341Sdelphij } 239296341Sdelphij /* Now decide on the output */ 240296341Sdelphij if (xpos == 0) 241296341Sdelphij /* Do an indent */ 242296341Sdelphij xpos = BIO_puts(bio_out, indent); 243296341Sdelphij else 244296341Sdelphij /* Otherwise prepend a ", " */ 245296341Sdelphij xpos += BIO_printf(bio_out, ", "); 246296341Sdelphij if (verbose == 1) { 247296341Sdelphij /* 248296341Sdelphij * We're just listing names, comma-delimited 249296341Sdelphij */ 250296341Sdelphij if ((xpos > (int)strlen(indent)) && 251296341Sdelphij (xpos + (int)strlen(name) > line_wrap)) { 252296341Sdelphij BIO_printf(bio_out, "\n"); 253296341Sdelphij xpos = BIO_puts(bio_out, indent); 254296341Sdelphij } 255296341Sdelphij xpos += BIO_printf(bio_out, "%s", name); 256296341Sdelphij } else { 257296341Sdelphij /* We're listing names plus descriptions */ 258296341Sdelphij BIO_printf(bio_out, "%s: %s\n", name, 259296341Sdelphij (desc == NULL) ? "<no description>" : desc); 260296341Sdelphij /* ... and sometimes input flags */ 261296341Sdelphij if ((verbose >= 3) && !util_flags(bio_out, flags, indent)) 262296341Sdelphij goto err; 263296341Sdelphij xpos = 0; 264296341Sdelphij } 265296341Sdelphij } 266296341Sdelphij OPENSSL_free(name); 267296341Sdelphij name = NULL; 268296341Sdelphij if (desc) { 269296341Sdelphij OPENSSL_free(desc); 270296341Sdelphij desc = NULL; 271296341Sdelphij } 272296341Sdelphij /* Move to the next command */ 273296341Sdelphij num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, num, NULL, NULL); 274296341Sdelphij } while (num > 0); 275296341Sdelphij if (xpos > 0) 276296341Sdelphij BIO_printf(bio_out, "\n"); 277296341Sdelphij ret = 1; 278296341Sdelphij err: 279296341Sdelphij if (cmds) 280296341Sdelphij sk_OPENSSL_STRING_pop_free(cmds, identity); 281296341Sdelphij if (name) 282296341Sdelphij OPENSSL_free(name); 283296341Sdelphij if (desc) 284296341Sdelphij OPENSSL_free(desc); 285296341Sdelphij return ret; 286296341Sdelphij} 287109998Smarkm 288238405Sjkimstatic void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds, 289296341Sdelphij BIO *bio_out, const char *indent) 290296341Sdelphij{ 291296341Sdelphij int loop, res, num = sk_OPENSSL_STRING_num(cmds); 292238405Sjkim 293296341Sdelphij if (num < 0) { 294296341Sdelphij BIO_printf(bio_out, "[Error]: internal stack error\n"); 295296341Sdelphij return; 296296341Sdelphij } 297296341Sdelphij for (loop = 0; loop < num; loop++) { 298296341Sdelphij char buf[256]; 299296341Sdelphij const char *cmd, *arg; 300296341Sdelphij cmd = sk_OPENSSL_STRING_value(cmds, loop); 301296341Sdelphij res = 1; /* assume success */ 302296341Sdelphij /* Check if this command has no ":arg" */ 303296341Sdelphij if ((arg = strstr(cmd, ":")) == NULL) { 304296341Sdelphij if (!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0)) 305296341Sdelphij res = 0; 306296341Sdelphij } else { 307296341Sdelphij if ((int)(arg - cmd) > 254) { 308296341Sdelphij BIO_printf(bio_out, "[Error]: command name too long\n"); 309296341Sdelphij return; 310296341Sdelphij } 311296341Sdelphij memcpy(buf, cmd, (int)(arg - cmd)); 312296341Sdelphij buf[arg - cmd] = '\0'; 313296341Sdelphij arg++; /* Move past the ":" */ 314296341Sdelphij /* Call the command with the argument */ 315296341Sdelphij if (!ENGINE_ctrl_cmd_string(e, buf, arg, 0)) 316296341Sdelphij res = 0; 317296341Sdelphij } 318296341Sdelphij if (res) 319296341Sdelphij BIO_printf(bio_out, "[Success]: %s\n", cmd); 320296341Sdelphij else { 321296341Sdelphij BIO_printf(bio_out, "[Failure]: %s\n", cmd); 322296341Sdelphij ERR_print_errors(bio_out); 323296341Sdelphij } 324296341Sdelphij } 325296341Sdelphij} 326109998Smarkm 327109998Smarkmint MAIN(int, char **); 328109998Smarkm 329109998Smarkmint MAIN(int argc, char **argv) 330296341Sdelphij{ 331296341Sdelphij int ret = 1, i; 332296341Sdelphij const char **pp; 333296341Sdelphij int verbose = 0, list_cap = 0, test_avail = 0, test_avail_noise = 0; 334296341Sdelphij ENGINE *e; 335296341Sdelphij STACK_OF(OPENSSL_STRING) *engines = sk_OPENSSL_STRING_new_null(); 336296341Sdelphij STACK_OF(OPENSSL_STRING) *pre_cmds = sk_OPENSSL_STRING_new_null(); 337296341Sdelphij STACK_OF(OPENSSL_STRING) *post_cmds = sk_OPENSSL_STRING_new_null(); 338296341Sdelphij int badops = 1; 339296341Sdelphij BIO *bio_out = NULL; 340296341Sdelphij const char *indent = " "; 341109998Smarkm 342296341Sdelphij apps_startup(); 343296341Sdelphij SSL_load_error_strings(); 344109998Smarkm 345296341Sdelphij if (bio_err == NULL) 346296341Sdelphij bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 347109998Smarkm 348296341Sdelphij if (!load_config(bio_err, NULL)) 349296341Sdelphij goto end; 350296341Sdelphij bio_out = BIO_new_fp(stdout, BIO_NOCLOSE); 351296341Sdelphij# ifdef OPENSSL_SYS_VMS 352296341Sdelphij { 353296341Sdelphij BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 354296341Sdelphij bio_out = BIO_push(tmpbio, bio_out); 355296341Sdelphij } 356296341Sdelphij# endif 357109998Smarkm 358296341Sdelphij argc--; 359296341Sdelphij argv++; 360296341Sdelphij while (argc >= 1) { 361296341Sdelphij if (strncmp(*argv, "-v", 2) == 0) { 362296341Sdelphij if (strspn(*argv + 1, "v") < strlen(*argv + 1)) 363296341Sdelphij goto skip_arg_loop; 364296341Sdelphij if ((verbose = strlen(*argv + 1)) > 4) 365296341Sdelphij goto skip_arg_loop; 366296341Sdelphij } else if (strcmp(*argv, "-c") == 0) 367296341Sdelphij list_cap = 1; 368296341Sdelphij else if (strncmp(*argv, "-t", 2) == 0) { 369296341Sdelphij test_avail = 1; 370296341Sdelphij if (strspn(*argv + 1, "t") < strlen(*argv + 1)) 371296341Sdelphij goto skip_arg_loop; 372296341Sdelphij if ((test_avail_noise = strlen(*argv + 1) - 1) > 1) 373296341Sdelphij goto skip_arg_loop; 374296341Sdelphij } else if (strcmp(*argv, "-pre") == 0) { 375296341Sdelphij argc--; 376296341Sdelphij argv++; 377296341Sdelphij if (argc == 0) 378296341Sdelphij goto skip_arg_loop; 379296341Sdelphij sk_OPENSSL_STRING_push(pre_cmds, *argv); 380296341Sdelphij } else if (strcmp(*argv, "-post") == 0) { 381296341Sdelphij argc--; 382296341Sdelphij argv++; 383296341Sdelphij if (argc == 0) 384296341Sdelphij goto skip_arg_loop; 385296341Sdelphij sk_OPENSSL_STRING_push(post_cmds, *argv); 386296341Sdelphij } else if ((strncmp(*argv, "-h", 2) == 0) || 387296341Sdelphij (strcmp(*argv, "-?") == 0)) 388296341Sdelphij goto skip_arg_loop; 389296341Sdelphij else 390296341Sdelphij sk_OPENSSL_STRING_push(engines, *argv); 391296341Sdelphij argc--; 392296341Sdelphij argv++; 393296341Sdelphij } 394296341Sdelphij /* Looks like everything went OK */ 395296341Sdelphij badops = 0; 396296341Sdelphij skip_arg_loop: 397109998Smarkm 398296341Sdelphij if (badops) { 399296341Sdelphij for (pp = engine_usage; (*pp != NULL); pp++) 400296341Sdelphij BIO_printf(bio_err, "%s", *pp); 401296341Sdelphij goto end; 402296341Sdelphij } 403109998Smarkm 404296341Sdelphij if (sk_OPENSSL_STRING_num(engines) == 0) { 405296341Sdelphij for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) { 406296341Sdelphij sk_OPENSSL_STRING_push(engines, (char *)ENGINE_get_id(e)); 407296341Sdelphij } 408296341Sdelphij } 409109998Smarkm 410296341Sdelphij for (i = 0; i < sk_OPENSSL_STRING_num(engines); i++) { 411296341Sdelphij const char *id = sk_OPENSSL_STRING_value(engines, i); 412296341Sdelphij if ((e = ENGINE_by_id(id)) != NULL) { 413296341Sdelphij const char *name = ENGINE_get_name(e); 414296341Sdelphij /* 415296341Sdelphij * Do "id" first, then "name". Easier to auto-parse. 416296341Sdelphij */ 417296341Sdelphij BIO_printf(bio_out, "(%s) %s\n", id, name); 418296341Sdelphij util_do_cmds(e, pre_cmds, bio_out, indent); 419296341Sdelphij if (strcmp(ENGINE_get_id(e), id) != 0) { 420296341Sdelphij BIO_printf(bio_out, "Loaded: (%s) %s\n", 421296341Sdelphij ENGINE_get_id(e), ENGINE_get_name(e)); 422296341Sdelphij } 423296341Sdelphij if (list_cap) { 424296341Sdelphij int cap_size = 256; 425296341Sdelphij char *cap_buf = NULL; 426296341Sdelphij int k, n; 427296341Sdelphij const int *nids; 428296341Sdelphij ENGINE_CIPHERS_PTR fn_c; 429296341Sdelphij ENGINE_DIGESTS_PTR fn_d; 430296341Sdelphij ENGINE_PKEY_METHS_PTR fn_pk; 431109998Smarkm 432296341Sdelphij if (ENGINE_get_RSA(e) != NULL 433296341Sdelphij && !append_buf(&cap_buf, "RSA", &cap_size, 256)) 434296341Sdelphij goto end; 435296341Sdelphij if (ENGINE_get_DSA(e) != NULL 436296341Sdelphij && !append_buf(&cap_buf, "DSA", &cap_size, 256)) 437296341Sdelphij goto end; 438296341Sdelphij if (ENGINE_get_DH(e) != NULL 439296341Sdelphij && !append_buf(&cap_buf, "DH", &cap_size, 256)) 440296341Sdelphij goto end; 441296341Sdelphij if (ENGINE_get_RAND(e) != NULL 442296341Sdelphij && !append_buf(&cap_buf, "RAND", &cap_size, 256)) 443296341Sdelphij goto end; 444109998Smarkm 445296341Sdelphij fn_c = ENGINE_get_ciphers(e); 446296341Sdelphij if (!fn_c) 447296341Sdelphij goto skip_ciphers; 448296341Sdelphij n = fn_c(e, NULL, &nids, 0); 449296341Sdelphij for (k = 0; k < n; ++k) 450296341Sdelphij if (!append_buf(&cap_buf, 451296341Sdelphij OBJ_nid2sn(nids[k]), &cap_size, 256)) 452296341Sdelphij goto end; 453109998Smarkm 454296341Sdelphij skip_ciphers: 455296341Sdelphij fn_d = ENGINE_get_digests(e); 456296341Sdelphij if (!fn_d) 457296341Sdelphij goto skip_digests; 458296341Sdelphij n = fn_d(e, NULL, &nids, 0); 459296341Sdelphij for (k = 0; k < n; ++k) 460296341Sdelphij if (!append_buf(&cap_buf, 461296341Sdelphij OBJ_nid2sn(nids[k]), &cap_size, 256)) 462296341Sdelphij goto end; 463109998Smarkm 464296341Sdelphij skip_digests: 465296341Sdelphij fn_pk = ENGINE_get_pkey_meths(e); 466296341Sdelphij if (!fn_pk) 467296341Sdelphij goto skip_pmeths; 468296341Sdelphij n = fn_pk(e, NULL, &nids, 0); 469296341Sdelphij for (k = 0; k < n; ++k) 470296341Sdelphij if (!append_buf(&cap_buf, 471296341Sdelphij OBJ_nid2sn(nids[k]), &cap_size, 256)) 472296341Sdelphij goto end; 473296341Sdelphij skip_pmeths: 474296341Sdelphij if (cap_buf && (*cap_buf != '\0')) 475296341Sdelphij BIO_printf(bio_out, " [%s]\n", cap_buf); 476109998Smarkm 477296341Sdelphij OPENSSL_free(cap_buf); 478296341Sdelphij } 479296341Sdelphij if (test_avail) { 480296341Sdelphij BIO_printf(bio_out, "%s", indent); 481296341Sdelphij if (ENGINE_init(e)) { 482296341Sdelphij BIO_printf(bio_out, "[ available ]\n"); 483296341Sdelphij util_do_cmds(e, post_cmds, bio_out, indent); 484296341Sdelphij ENGINE_finish(e); 485296341Sdelphij } else { 486296341Sdelphij BIO_printf(bio_out, "[ unavailable ]\n"); 487296341Sdelphij if (test_avail_noise) 488296341Sdelphij ERR_print_errors_fp(stdout); 489296341Sdelphij ERR_clear_error(); 490296341Sdelphij } 491296341Sdelphij } 492296341Sdelphij if ((verbose > 0) && !util_verbose(e, verbose, bio_out, indent)) 493296341Sdelphij goto end; 494296341Sdelphij ENGINE_free(e); 495296341Sdelphij } else 496296341Sdelphij ERR_print_errors(bio_err); 497296341Sdelphij } 498109998Smarkm 499296341Sdelphij ret = 0; 500296341Sdelphij end: 501160814Ssimon 502296341Sdelphij ERR_print_errors(bio_err); 503296341Sdelphij sk_OPENSSL_STRING_pop_free(engines, identity); 504296341Sdelphij sk_OPENSSL_STRING_pop_free(pre_cmds, identity); 505296341Sdelphij sk_OPENSSL_STRING_pop_free(post_cmds, identity); 506296341Sdelphij if (bio_out != NULL) 507296341Sdelphij BIO_free_all(bio_out); 508296341Sdelphij apps_shutdown(); 509296341Sdelphij OPENSSL_EXIT(ret); 510296341Sdelphij} 511120631Snectar#else 512120631Snectar 513120631Snectar# if PEDANTIC 514296341Sdelphijstatic void *dummy = &dummy; 515120631Snectar# endif 516120631Snectar 517111147Snectar#endif 518