engine.c revision 160814
1106266Sjulian/* apps/engine.c -*- mode: C; c-file-style: "eay" -*- */ 2106266Sjulian/* Written by Richard Levitte <richard@levitte.org> for the OpenSSL 3106266Sjulian * project 2000. 4106266Sjulian */ 5106266Sjulian/* ==================================================================== 6106266Sjulian * Copyright (c) 2000 The OpenSSL Project. All rights reserved. 7106266Sjulian * 8106266Sjulian * Redistribution and use in source and binary forms, with or without 9106319Sjulian * modification, are permitted provided that the following conditions 10106266Sjulian * are met: 11106319Sjulian * 12106319Sjulian * 1. Redistributions of source code must retain the above copyright 13106266Sjulian * notice, this list of conditions and the following disclaimer. 14106319Sjulian * 15106319Sjulian * 2. Redistributions in binary form must reproduce the above copyright 16106266Sjulian * notice, this list of conditions and the following disclaimer in 17106266Sjulian * the documentation and/or other materials provided with the 18106266Sjulian * distribution. 19106319Sjulian * 20106319Sjulian * 3. All advertising materials mentioning features or use of this 21106319Sjulian * software must display the following acknowledgment: 22106266Sjulian * "This product includes software developed by the OpenSSL Project 23106266Sjulian * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24106266Sjulian * 25106266Sjulian * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26106266Sjulian * endorse or promote products derived from this software without 27106319Sjulian * prior written permission. For written permission, please contact 28106266Sjulian * licensing@OpenSSL.org. 29106266Sjulian * 30106266Sjulian * 5. Products derived from this software may not be called "OpenSSL" 31106266Sjulian * nor may "OpenSSL" appear in their names without prior written 32106266Sjulian * permission of the OpenSSL Project. 33106266Sjulian * 34106266Sjulian * 6. Redistributions of any form whatsoever must retain the following 35106266Sjulian * acknowledgment: 36106266Sjulian * "This product includes software developed by the OpenSSL Project 37106266Sjulian * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38125077Sharti * 39125077Sharti * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40125077Sharti * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41106266Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42106266Sjulian * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43106266Sjulian * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44106266Sjulian * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45106266Sjulian * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46106266Sjulian * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47106266Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48106266Sjulian * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49106266Sjulian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50106266Sjulian * OF THE POSSIBILITY OF SUCH DAMAGE. 51106266Sjulian * ==================================================================== 52106266Sjulian * 53106266Sjulian * This product includes cryptographic software written by Eric Young 54106266Sjulian * (eay@cryptsoft.com). This product includes software written by Tim 55106266Sjulian * Hudson (tjh@cryptsoft.com). 56106266Sjulian * 57106266Sjulian */ 58106266Sjulian 59106266Sjulian#ifndef OPENSSL_NO_ENGINE 60106266Sjulian 61106266Sjulian#include <stdio.h> 62106266Sjulian#include <stdlib.h> 63106266Sjulian#include <string.h> 64106266Sjulian#ifdef OPENSSL_NO_STDIO 65106266Sjulian#define APPS_WIN16 66106266Sjulian#endif 67106266Sjulian#include "apps.h" 68106266Sjulian#include <openssl/err.h> 69106266Sjulian#include <openssl/engine.h> 70106266Sjulian#include <openssl/ssl.h> 71106266Sjulian 72106266Sjulian#undef PROG 73106266Sjulian#define PROG engine_main 74106266Sjulian 75106266Sjulianstatic const char *engine_usage[]={ 76106266Sjulian"usage: engine opts [engine ...]\n", 77106266Sjulian" -v[v[v[v]]] - verbose mode, for each engine, list its 'control commands'\n", 78106266Sjulian" -vv will additionally display each command's description\n", 79106266Sjulian" -vvv will also add the input flags for each command\n", 80106266Sjulian" -vvvv will also show internal input flags\n", 81106266Sjulian" -c - for each engine, also list the capabilities\n", 82106266Sjulian" -t[t] - for each engine, check that they are really available\n", 83106266Sjulian" -tt will display error trace for unavailable engines\n", 84106266Sjulian" -pre <cmd> - runs command 'cmd' against the ENGINE before any attempts\n", 85106266Sjulian" to load it (if -t is used)\n", 86106266Sjulian" -post <cmd> - runs command 'cmd' against the ENGINE after loading it\n", 87106266Sjulian" (only used if -t is also provided)\n", 88106319Sjulian" NB: -pre and -post will be applied to all ENGINEs supplied on the command\n", 89106266Sjulian" line, or all supported ENGINEs if none are specified.\n", 90106266Sjulian" Eg. '-pre \"SO_PATH:/lib/libdriver.so\"' calls command \"SO_PATH\" with\n", 91106319Sjulian" argument \"/lib/libdriver.so\".\n", 92106266SjulianNULL 93106266Sjulian}; 94106266Sjulian 95106266Sjulianstatic void identity(void *ptr) 96106266Sjulian { 97106266Sjulian return; 98106266Sjulian } 99106266Sjulian 100106266Sjulianstatic int append_buf(char **buf, const char *s, int *size, int step) 101106266Sjulian { 102106266Sjulian int l = strlen(s); 103106266Sjulian 104106266Sjulian if (*buf == NULL) 105106266Sjulian { 106106266Sjulian *size = step; 107106266Sjulian *buf = OPENSSL_malloc(*size); 108125243Sharti if (*buf == NULL) 109125029Sharti return 0; 110106266Sjulian **buf = '\0'; 111106266Sjulian } 112106266Sjulian 113106266Sjulian if (**buf != '\0') 114106435Sjulian l += 2; /* ", " */ 115106435Sjulian 116106266Sjulian if (strlen(*buf) + strlen(s) >= (unsigned int)*size) 117106266Sjulian { 118106266Sjulian *size += step; 119125077Sharti *buf = OPENSSL_realloc(*buf, *size); 120106266Sjulian } 121106266Sjulian 122106266Sjulian if (*buf == NULL) 123106266Sjulian return 0; 124106266Sjulian 125106266Sjulian if (**buf != '\0') 126106266Sjulian BUF_strlcat(*buf, ", ", *size); 127106266Sjulian BUF_strlcat(*buf, s, *size); 128106266Sjulian 129106266Sjulian return 1; 130106266Sjulian } 131106266Sjulian 132106266Sjulianstatic int util_flags(BIO *bio_out, unsigned int flags, const char *indent) 133106266Sjulian { 134106266Sjulian int started = 0, err = 0; 135106266Sjulian /* Indent before displaying input flags */ 136106266Sjulian BIO_printf(bio_out, "%s%s(input flags): ", indent, indent); 137106266Sjulian if(flags == 0) 138106266Sjulian { 139106266Sjulian BIO_printf(bio_out, "<no flags>\n"); 140106266Sjulian return 1; 141106266Sjulian } 142106266Sjulian /* If the object is internal, mark it in a way that shows instead of 143106266Sjulian * having it part of all the other flags, even if it really is. */ 144106266Sjulian if(flags & ENGINE_CMD_FLAG_INTERNAL) 145106266Sjulian { 146106266Sjulian BIO_printf(bio_out, "[Internal] "); 147106266Sjulian } 148106266Sjulian 149106266Sjulian if(flags & ENGINE_CMD_FLAG_NUMERIC) 150106266Sjulian { 151106266Sjulian if(started) 152106266Sjulian { 153106266Sjulian BIO_printf(bio_out, "|"); 154106266Sjulian err = 1; 155106266Sjulian } 156106266Sjulian BIO_printf(bio_out, "NUMERIC"); 157106266Sjulian started = 1; 158106266Sjulian } 159106266Sjulian /* Now we check that no combinations of the mutually exclusive NUMERIC, 160106266Sjulian * STRING, and NO_INPUT flags have been used. Future flags that can be 161106266Sjulian * OR'd together with these would need to added after these to preserve 162106266Sjulian * the testing logic. */ 163106266Sjulian if(flags & ENGINE_CMD_FLAG_STRING) 164106266Sjulian { 165106266Sjulian if(started) 166106266Sjulian { 167106266Sjulian BIO_printf(bio_out, "|"); 168106266Sjulian err = 1; 169106266Sjulian } 170106266Sjulian BIO_printf(bio_out, "STRING"); 171106266Sjulian started = 1; 172106266Sjulian } 173106266Sjulian if(flags & ENGINE_CMD_FLAG_NO_INPUT) 174106266Sjulian { 175106266Sjulian if(started) 176106266Sjulian { 177106266Sjulian BIO_printf(bio_out, "|"); 178106266Sjulian err = 1; 179106266Sjulian } 180106266Sjulian BIO_printf(bio_out, "NO_INPUT"); 181125033Sharti started = 1; 182125033Sharti } 183125033Sharti /* Check for unknown flags */ 184125033Sharti flags = flags & ~ENGINE_CMD_FLAG_NUMERIC & 185125033Sharti ~ENGINE_CMD_FLAG_STRING & 186125033Sharti ~ENGINE_CMD_FLAG_NO_INPUT & 187125033Sharti ~ENGINE_CMD_FLAG_INTERNAL; 188106266Sjulian if(flags) 189106266Sjulian { 190106266Sjulian if(started) BIO_printf(bio_out, "|"); 191106266Sjulian BIO_printf(bio_out, "<0x%04X>", flags); 192106266Sjulian } 193125029Sharti if(err) 194106266Sjulian BIO_printf(bio_out, " <illegal flags!>"); 195106266Sjulian BIO_printf(bio_out, "\n"); 196106266Sjulian return 1; 197106266Sjulian } 198106266Sjulian 199106266Sjulianstatic int util_verbose(ENGINE *e, int verbose, BIO *bio_out, const char *indent) 200106266Sjulian { 201125077Sharti static const int line_wrap = 78; 202106266Sjulian int num; 203106266Sjulian int ret = 0; 204106266Sjulian char *name = NULL; 205106266Sjulian char *desc = NULL; 206106266Sjulian int flags; 207106266Sjulian int xpos = 0; 208125032Sharti STACK *cmds = NULL; 209125032Sharti if(!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) || 210106266Sjulian ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE, 211106266Sjulian 0, NULL, NULL)) <= 0)) 212106266Sjulian { 213106266Sjulian#if 0 214106321Sjulian BIO_printf(bio_out, "%s<no control commands>\n", indent); 215106266Sjulian#endif 216106266Sjulian return 1; 217106266Sjulian } 218125030Sharti 219106266Sjulian cmds = sk_new_null(); 220106266Sjulian 221106266Sjulian if(!cmds) 222106321Sjulian goto err; 223106321Sjulian do { 224106266Sjulian int len; 225106321Sjulian /* Get the command input flags */ 226106321Sjulian if((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, 227106266Sjulian NULL, NULL)) < 0) 228106266Sjulian goto err; 229106266Sjulian if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4) 230106266Sjulian { 231106266Sjulian /* Get the command name */ 232106266Sjulian if((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num, 233106266Sjulian NULL, NULL)) <= 0) 234106266Sjulian goto err; 235106266Sjulian if((name = OPENSSL_malloc(len + 1)) == NULL) 236106321Sjulian goto err; 237106266Sjulian if(ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name, 238106321Sjulian NULL) <= 0) 239125077Sharti goto err; 240106266Sjulian /* Get the command description */ 241106266Sjulian if((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num, 242106321Sjulian NULL, NULL)) < 0) 243106266Sjulian goto err; 244106266Sjulian if(len > 0) 245106321Sjulian { 246106266Sjulian if((desc = OPENSSL_malloc(len + 1)) == NULL) 247106266Sjulian goto err; 248106266Sjulian if(ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc, 249106266Sjulian NULL) <= 0) 250106266Sjulian goto err; 251106266Sjulian } 252106266Sjulian /* Now decide on the output */ 253106266Sjulian if(xpos == 0) 254106266Sjulian /* Do an indent */ 255106266Sjulian xpos = BIO_printf(bio_out, indent); 256106266Sjulian else 257106321Sjulian /* Otherwise prepend a ", " */ 258106266Sjulian xpos += BIO_printf(bio_out, ", "); 259106321Sjulian if(verbose == 1) 260106266Sjulian { 261106266Sjulian /* We're just listing names, comma-delimited */ 262106321Sjulian if((xpos > (int)strlen(indent)) && 263106266Sjulian (xpos + (int)strlen(name) > line_wrap)) 264106321Sjulian { 265106321Sjulian BIO_printf(bio_out, "\n"); 266125077Sharti xpos = BIO_printf(bio_out, indent); 267106266Sjulian } 268106266Sjulian xpos += BIO_printf(bio_out, "%s", name); 269106435Sjulian } 270106435Sjulian else 271106435Sjulian { 272106435Sjulian /* We're listing names plus descriptions */ 273106266Sjulian BIO_printf(bio_out, "%s: %s\n", name, 274106266Sjulian (desc == NULL) ? "<no description>" : desc); 275106266Sjulian /* ... and sometimes input flags */ 276106266Sjulian if((verbose >= 3) && !util_flags(bio_out, flags, 277106266Sjulian indent)) 278106266Sjulian goto err; 279106266Sjulian xpos = 0; 280106266Sjulian } 281106266Sjulian } 282106266Sjulian OPENSSL_free(name); name = NULL; 283106266Sjulian if(desc) { OPENSSL_free(desc); desc = NULL; } 284106266Sjulian /* Move to the next command */ 285106266Sjulian num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, 286106266Sjulian num, NULL, NULL); 287106266Sjulian } while(num > 0); 288106319Sjulian if(xpos > 0) 289106321Sjulian BIO_printf(bio_out, "\n"); 290106266Sjulian ret = 1; 291106319Sjulianerr: 292106266Sjulian if(cmds) sk_pop_free(cmds, identity); 293106319Sjulian if(name) OPENSSL_free(name); 294106266Sjulian if(desc) OPENSSL_free(desc); 295106319Sjulian return ret; 296106266Sjulian } 297106266Sjulian 298106266Sjulianstatic void util_do_cmds(ENGINE *e, STACK *cmds, BIO *bio_out, const char *indent) 299106266Sjulian { 300106266Sjulian int loop, res, num = sk_num(cmds); 301106266Sjulian if(num < 0) 302106266Sjulian { 303106266Sjulian BIO_printf(bio_out, "[Error]: internal stack error\n"); 304106266Sjulian return; 305106266Sjulian } 306106319Sjulian for(loop = 0; loop < num; loop++) 307125077Sharti { 308106266Sjulian char buf[256]; 309106266Sjulian const char *cmd, *arg; 310106266Sjulian cmd = sk_value(cmds, loop); 311106266Sjulian res = 1; /* assume success */ 312106266Sjulian /* Check if this command has no ":arg" */ 313106266Sjulian if((arg = strstr(cmd, ":")) == NULL) 314106266Sjulian { 315106266Sjulian if(!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0)) 316125033Sharti res = 0; 317125033Sharti } 318125033Sharti else 319125033Sharti { 320125033Sharti if((int)(arg - cmd) > 254) 321125077Sharti { 322125033Sharti BIO_printf(bio_out,"[Error]: command name too long\n"); 323125033Sharti return; 324125033Sharti } 325125033Sharti memcpy(buf, cmd, (int)(arg - cmd)); 326125033Sharti buf[arg-cmd] = '\0'; 327125033Sharti arg++; /* Move past the ":" */ 328125033Sharti /* Call the command with the argument */ 329125033Sharti if(!ENGINE_ctrl_cmd_string(e, buf, arg, 0)) 330125033Sharti res = 0; 331125033Sharti } 332125033Sharti if(res) 333125033Sharti BIO_printf(bio_out, "[Success]: %s\n", cmd); 334125033Sharti else 335125033Sharti { 336125033Sharti BIO_printf(bio_out, "[Failure]: %s\n", cmd); 337125243Sharti ERR_print_errors(bio_out); 338125243Sharti } 339125033Sharti } 340125033Sharti } 341106266Sjulian 342106266Sjulianint MAIN(int, char **); 343106266Sjulian 344106266Sjulianint MAIN(int argc, char **argv) 345106266Sjulian { 346106266Sjulian int ret=1,i; 347106266Sjulian const char **pp; 348106266Sjulian int verbose=0, list_cap=0, test_avail=0, test_avail_noise = 0; 349106266Sjulian ENGINE *e; 350106266Sjulian STACK *engines = sk_new_null(); 351106266Sjulian STACK *pre_cmds = sk_new_null(); 352106435Sjulian STACK *post_cmds = sk_new_null(); 353106435Sjulian int badops=1; 354106435Sjulian BIO *bio_out=NULL; 355106435Sjulian const char *indent = " "; 356106435Sjulian 357106435Sjulian apps_startup(); 358106435Sjulian SSL_load_error_strings(); 359106435Sjulian 360106435Sjulian if (bio_err == NULL) 361106435Sjulian bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); 362106435Sjulian 363106435Sjulian if (!load_config(bio_err, NULL)) 364106435Sjulian goto end; 365125243Sharti bio_out=BIO_new_fp(stdout,BIO_NOCLOSE); 366125243Sharti#ifdef OPENSSL_SYS_VMS 367106435Sjulian { 368106435Sjulian BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 369106435Sjulian bio_out = BIO_push(tmpbio, bio_out); 370106435Sjulian } 371106435Sjulian#endif 372106435Sjulian 373106266Sjulian argc--; 374106266Sjulian argv++; 375106266Sjulian while (argc >= 1) 376106266Sjulian { 377106266Sjulian if (strncmp(*argv,"-v",2) == 0) 378106266Sjulian { 379106321Sjulian if(strspn(*argv + 1, "v") < strlen(*argv + 1)) 380106321Sjulian goto skip_arg_loop; 381106321Sjulian if((verbose=strlen(*argv + 1)) > 4) 382106321Sjulian goto skip_arg_loop; 383106266Sjulian } 384106266Sjulian else if (strcmp(*argv,"-c") == 0) 385106266Sjulian list_cap=1; 386106266Sjulian else if (strncmp(*argv,"-t",2) == 0) 387106266Sjulian { 388106266Sjulian test_avail=1; 389106266Sjulian if(strspn(*argv + 1, "t") < strlen(*argv + 1)) 390106266Sjulian goto skip_arg_loop; 391106266Sjulian if((test_avail_noise = strlen(*argv + 1) - 1) > 1) 392106266Sjulian goto skip_arg_loop; 393106321Sjulian } 394106266Sjulian else if (strcmp(*argv,"-pre") == 0) 395106321Sjulian { 396106321Sjulian argc--; argv++; 397106266Sjulian if (argc == 0) 398106321Sjulian goto skip_arg_loop; 399106266Sjulian sk_push(pre_cmds,*argv); 400106321Sjulian } 401106321Sjulian else if (strcmp(*argv,"-post") == 0) 402106321Sjulian { 403106321Sjulian argc--; argv++; 404125077Sharti if (argc == 0) 405125077Sharti goto skip_arg_loop; 406106266Sjulian sk_push(post_cmds,*argv); 407106266Sjulian } 408106266Sjulian else if ((strncmp(*argv,"-h",2) == 0) || 409106266Sjulian (strcmp(*argv,"-?") == 0)) 410106321Sjulian goto skip_arg_loop; 411106266Sjulian else 412106266Sjulian sk_push(engines,*argv); 413125077Sharti argc--; 414106266Sjulian argv++; 415106266Sjulian } 416125077Sharti /* Looks like everything went OK */ 417106321Sjulian badops = 0; 418106266Sjulianskip_arg_loop: 419106266Sjulian 420106266Sjulian if (badops) 421106266Sjulian { 422106266Sjulian for (pp=engine_usage; (*pp != NULL); pp++) 423125031Sharti BIO_printf(bio_err,"%s",*pp); 424106266Sjulian goto end; 425106266Sjulian } 426106266Sjulian 427106266Sjulian if (sk_num(engines) == 0) 428106266Sjulian { 429106266Sjulian for(e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) 430106266Sjulian { 431106266Sjulian sk_push(engines,(char *)ENGINE_get_id(e)); 432106266Sjulian } 433106266Sjulian } 434106266Sjulian 435106321Sjulian for (i=0; i<sk_num(engines); i++) 436106266Sjulian { 437106321Sjulian const char *id = sk_value(engines,i); 438125077Sharti if ((e = ENGINE_by_id(id)) != NULL) 439106321Sjulian { 440106266Sjulian const char *name = ENGINE_get_name(e); 441106266Sjulian /* Do "id" first, then "name". Easier to auto-parse. */ 442106321Sjulian BIO_printf(bio_out, "(%s) %s\n", id, name); 443106321Sjulian util_do_cmds(e, pre_cmds, bio_out, indent); 444125077Sharti if (strcmp(ENGINE_get_id(e), id) != 0) 445106266Sjulian { 446106266Sjulian BIO_printf(bio_out, "Loaded: (%s) %s\n", 447106266Sjulian ENGINE_get_id(e), ENGINE_get_name(e)); 448106266Sjulian } 449106266Sjulian if (list_cap) 450106266Sjulian { 451106266Sjulian int cap_size = 256; 452106266Sjulian char *cap_buf = NULL; 453106266Sjulian int k,n; 454106321Sjulian const int *nids; 455106319Sjulian ENGINE_CIPHERS_PTR fn_c; 456106266Sjulian ENGINE_DIGESTS_PTR fn_d; 457106321Sjulian 458106321Sjulian if (ENGINE_get_RSA(e) != NULL 459125077Sharti && !append_buf(&cap_buf, "RSA", 460106266Sjulian &cap_size, 256)) 461106321Sjulian goto end; 462106321Sjulian if (ENGINE_get_DSA(e) != NULL 463106266Sjulian && !append_buf(&cap_buf, "DSA", 464106266Sjulian &cap_size, 256)) 465106266Sjulian goto end; 466106266Sjulian if (ENGINE_get_DH(e) != NULL 467106435Sjulian && !append_buf(&cap_buf, "DH", 468106435Sjulian &cap_size, 256)) 469106435Sjulian goto end; 470106266Sjulian if (ENGINE_get_RAND(e) != NULL 471125029Sharti && !append_buf(&cap_buf, "RAND", 472106435Sjulian &cap_size, 256)) 473106266Sjulian goto end; 474106435Sjulian 475106266Sjulian fn_c = ENGINE_get_ciphers(e); 476106266Sjulian if(!fn_c) goto skip_ciphers; 477106266Sjulian n = fn_c(e, NULL, &nids, 0); 478106266Sjulian for(k=0 ; k < n ; ++k) 479106266Sjulian if(!append_buf(&cap_buf, 480106319Sjulian OBJ_nid2sn(nids[k]), 481106266Sjulian &cap_size, 256)) 482106266Sjulian goto end; 483106266Sjulian 484125078Shartiskip_ciphers: 485106435Sjulian fn_d = ENGINE_get_digests(e); 486106435Sjulian if(!fn_d) goto skip_digests; 487106266Sjulian n = fn_d(e, NULL, &nids, 0); 488106435Sjulian for(k=0 ; k < n ; ++k) 489106435Sjulian if(!append_buf(&cap_buf, 490106435Sjulian OBJ_nid2sn(nids[k]), 491106435Sjulian &cap_size, 256)) 492106435Sjulian goto end; 493106435Sjulian 494106435Sjulianskip_digests: 495106435Sjulian if (cap_buf && (*cap_buf != '\0')) 496106435Sjulian BIO_printf(bio_out, " [%s]\n", cap_buf); 497106435Sjulian 498106266Sjulian OPENSSL_free(cap_buf); 499106435Sjulian } 500106266Sjulian if(test_avail) 501106266Sjulian { 502106435Sjulian BIO_printf(bio_out, "%s", indent); 503106266Sjulian if (ENGINE_init(e)) 504106266Sjulian { 505106266Sjulian BIO_printf(bio_out, "[ available ]\n"); 506106266Sjulian util_do_cmds(e, post_cmds, bio_out, indent); 507108172Shsu ENGINE_finish(e); 508106266Sjulian } 509106266Sjulian else 510106266Sjulian { 511106266Sjulian BIO_printf(bio_out, "[ unavailable ]\n"); 512108172Shsu if(test_avail_noise) 513106266Sjulian ERR_print_errors_fp(stdout); 514106266Sjulian ERR_clear_error(); 515125077Sharti } 516106266Sjulian } 517106266Sjulian if((verbose > 0) && !util_verbose(e, verbose, bio_out, indent)) 518106266Sjulian goto end; 519106266Sjulian ENGINE_free(e); 520106266Sjulian } 521106266Sjulian else 522106266Sjulian ERR_print_errors(bio_err); 523106266Sjulian } 524106266Sjulian 525106266Sjulian ret=0; 526106266Sjulianend: 527125077Sharti 528106266Sjulian ERR_print_errors(bio_err); 529106319Sjulian sk_pop_free(engines, identity); 530106266Sjulian sk_pop_free(pre_cmds, identity); 531106266Sjulian sk_pop_free(post_cmds, identity); 532106266Sjulian if (bio_out != NULL) BIO_free_all(bio_out); 533106266Sjulian apps_shutdown(); 534106266Sjulian OPENSSL_EXIT(ret); 535106266Sjulian } 536106266Sjulian#else 537106266Sjulian 538106266Sjulian# if PEDANTIC 539106266Sjulianstatic void *dummy=&dummy; 540106266Sjulian# endif 541106266Sjulian 542106266Sjulian#endif 543106266Sjulian