engine.c revision 160814
1109998Smarkm/* apps/engine.c -*- mode: C; c-file-style: "eay" -*- */ 2109998Smarkm/* Written by Richard Levitte <richard@levitte.org> for the OpenSSL 3109998Smarkm * project 2000. 4109998Smarkm */ 5109998Smarkm/* ==================================================================== 6109998Smarkm * Copyright (c) 2000 The OpenSSL Project. All rights reserved. 7109998Smarkm * 8109998Smarkm * Redistribution and use in source and binary forms, with or without 9109998Smarkm * modification, are permitted provided that the following conditions 10109998Smarkm * are met: 11109998Smarkm * 12109998Smarkm * 1. Redistributions of source code must retain the above copyright 13109998Smarkm * notice, this list of conditions and the following disclaimer. 14109998Smarkm * 15109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 16109998Smarkm * notice, this list of conditions and the following disclaimer in 17109998Smarkm * the documentation and/or other materials provided with the 18109998Smarkm * distribution. 19109998Smarkm * 20109998Smarkm * 3. All advertising materials mentioning features or use of this 21109998Smarkm * software must display the following acknowledgment: 22109998Smarkm * "This product includes software developed by the OpenSSL Project 23109998Smarkm * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24109998Smarkm * 25109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26109998Smarkm * endorse or promote products derived from this software without 27109998Smarkm * prior written permission. For written permission, please contact 28109998Smarkm * licensing@OpenSSL.org. 29109998Smarkm * 30109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 31109998Smarkm * nor may "OpenSSL" appear in their names without prior written 32109998Smarkm * permission of the OpenSSL Project. 33109998Smarkm * 34109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 35109998Smarkm * acknowledgment: 36109998Smarkm * "This product includes software developed by the OpenSSL Project 37109998Smarkm * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38109998Smarkm * 39109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 51109998Smarkm * ==================================================================== 52109998Smarkm * 53109998Smarkm * This product includes cryptographic software written by Eric Young 54109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 55109998Smarkm * Hudson (tjh@cryptsoft.com). 56109998Smarkm * 57109998Smarkm */ 58109998Smarkm 59111147Snectar#ifndef OPENSSL_NO_ENGINE 60111147Snectar 61109998Smarkm#include <stdio.h> 62109998Smarkm#include <stdlib.h> 63109998Smarkm#include <string.h> 64109998Smarkm#ifdef OPENSSL_NO_STDIO 65109998Smarkm#define APPS_WIN16 66109998Smarkm#endif 67109998Smarkm#include "apps.h" 68109998Smarkm#include <openssl/err.h> 69109998Smarkm#include <openssl/engine.h> 70109998Smarkm#include <openssl/ssl.h> 71109998Smarkm 72109998Smarkm#undef PROG 73109998Smarkm#define PROG engine_main 74109998Smarkm 75160814Ssimonstatic const char *engine_usage[]={ 76109998Smarkm"usage: engine opts [engine ...]\n", 77109998Smarkm" -v[v[v[v]]] - verbose mode, for each engine, list its 'control commands'\n", 78109998Smarkm" -vv will additionally display each command's description\n", 79109998Smarkm" -vvv will also add the input flags for each command\n", 80109998Smarkm" -vvvv will also show internal input flags\n", 81109998Smarkm" -c - for each engine, also list the capabilities\n", 82160814Ssimon" -t[t] - for each engine, check that they are really available\n", 83160814Ssimon" -tt will display error trace for unavailable engines\n", 84109998Smarkm" -pre <cmd> - runs command 'cmd' against the ENGINE before any attempts\n", 85109998Smarkm" to load it (if -t is used)\n", 86109998Smarkm" -post <cmd> - runs command 'cmd' against the ENGINE after loading it\n", 87109998Smarkm" (only used if -t is also provided)\n", 88109998Smarkm" NB: -pre and -post will be applied to all ENGINEs supplied on the command\n", 89109998Smarkm" line, or all supported ENGINEs if none are specified.\n", 90109998Smarkm" Eg. '-pre \"SO_PATH:/lib/libdriver.so\"' calls command \"SO_PATH\" with\n", 91109998Smarkm" argument \"/lib/libdriver.so\".\n", 92109998SmarkmNULL 93109998Smarkm}; 94109998Smarkm 95109998Smarkmstatic void identity(void *ptr) 96109998Smarkm { 97109998Smarkm return; 98109998Smarkm } 99109998Smarkm 100109998Smarkmstatic int append_buf(char **buf, const char *s, int *size, int step) 101109998Smarkm { 102109998Smarkm int l = strlen(s); 103109998Smarkm 104109998Smarkm if (*buf == NULL) 105109998Smarkm { 106109998Smarkm *size = step; 107109998Smarkm *buf = OPENSSL_malloc(*size); 108109998Smarkm if (*buf == NULL) 109109998Smarkm return 0; 110109998Smarkm **buf = '\0'; 111109998Smarkm } 112109998Smarkm 113109998Smarkm if (**buf != '\0') 114109998Smarkm l += 2; /* ", " */ 115109998Smarkm 116109998Smarkm if (strlen(*buf) + strlen(s) >= (unsigned int)*size) 117109998Smarkm { 118109998Smarkm *size += step; 119109998Smarkm *buf = OPENSSL_realloc(*buf, *size); 120109998Smarkm } 121109998Smarkm 122109998Smarkm if (*buf == NULL) 123109998Smarkm return 0; 124109998Smarkm 125109998Smarkm if (**buf != '\0') 126127128Snectar BUF_strlcat(*buf, ", ", *size); 127127128Snectar BUF_strlcat(*buf, s, *size); 128109998Smarkm 129109998Smarkm return 1; 130109998Smarkm } 131109998Smarkm 132109998Smarkmstatic int util_flags(BIO *bio_out, unsigned int flags, const char *indent) 133109998Smarkm { 134109998Smarkm int started = 0, err = 0; 135109998Smarkm /* Indent before displaying input flags */ 136109998Smarkm BIO_printf(bio_out, "%s%s(input flags): ", indent, indent); 137109998Smarkm if(flags == 0) 138109998Smarkm { 139109998Smarkm BIO_printf(bio_out, "<no flags>\n"); 140109998Smarkm return 1; 141109998Smarkm } 142109998Smarkm /* If the object is internal, mark it in a way that shows instead of 143109998Smarkm * having it part of all the other flags, even if it really is. */ 144109998Smarkm if(flags & ENGINE_CMD_FLAG_INTERNAL) 145109998Smarkm { 146109998Smarkm BIO_printf(bio_out, "[Internal] "); 147109998Smarkm } 148109998Smarkm 149109998Smarkm if(flags & ENGINE_CMD_FLAG_NUMERIC) 150109998Smarkm { 151109998Smarkm if(started) 152109998Smarkm { 153109998Smarkm BIO_printf(bio_out, "|"); 154109998Smarkm err = 1; 155109998Smarkm } 156109998Smarkm BIO_printf(bio_out, "NUMERIC"); 157109998Smarkm started = 1; 158109998Smarkm } 159109998Smarkm /* Now we check that no combinations of the mutually exclusive NUMERIC, 160109998Smarkm * STRING, and NO_INPUT flags have been used. Future flags that can be 161109998Smarkm * OR'd together with these would need to added after these to preserve 162109998Smarkm * the testing logic. */ 163109998Smarkm if(flags & ENGINE_CMD_FLAG_STRING) 164109998Smarkm { 165109998Smarkm if(started) 166109998Smarkm { 167109998Smarkm BIO_printf(bio_out, "|"); 168109998Smarkm err = 1; 169109998Smarkm } 170109998Smarkm BIO_printf(bio_out, "STRING"); 171109998Smarkm started = 1; 172109998Smarkm } 173109998Smarkm if(flags & ENGINE_CMD_FLAG_NO_INPUT) 174109998Smarkm { 175109998Smarkm if(started) 176109998Smarkm { 177109998Smarkm BIO_printf(bio_out, "|"); 178109998Smarkm err = 1; 179109998Smarkm } 180109998Smarkm BIO_printf(bio_out, "NO_INPUT"); 181109998Smarkm started = 1; 182109998Smarkm } 183109998Smarkm /* Check for unknown flags */ 184109998Smarkm flags = flags & ~ENGINE_CMD_FLAG_NUMERIC & 185109998Smarkm ~ENGINE_CMD_FLAG_STRING & 186109998Smarkm ~ENGINE_CMD_FLAG_NO_INPUT & 187109998Smarkm ~ENGINE_CMD_FLAG_INTERNAL; 188109998Smarkm if(flags) 189109998Smarkm { 190109998Smarkm if(started) BIO_printf(bio_out, "|"); 191109998Smarkm BIO_printf(bio_out, "<0x%04X>", flags); 192109998Smarkm } 193109998Smarkm if(err) 194109998Smarkm BIO_printf(bio_out, " <illegal flags!>"); 195109998Smarkm BIO_printf(bio_out, "\n"); 196109998Smarkm return 1; 197109998Smarkm } 198109998Smarkm 199109998Smarkmstatic int util_verbose(ENGINE *e, int verbose, BIO *bio_out, const char *indent) 200109998Smarkm { 201109998Smarkm static const int line_wrap = 78; 202109998Smarkm int num; 203109998Smarkm int ret = 0; 204109998Smarkm char *name = NULL; 205109998Smarkm char *desc = NULL; 206109998Smarkm int flags; 207109998Smarkm int xpos = 0; 208109998Smarkm STACK *cmds = NULL; 209109998Smarkm if(!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) || 210109998Smarkm ((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE, 211109998Smarkm 0, NULL, NULL)) <= 0)) 212109998Smarkm { 213109998Smarkm#if 0 214109998Smarkm BIO_printf(bio_out, "%s<no control commands>\n", indent); 215109998Smarkm#endif 216109998Smarkm return 1; 217109998Smarkm } 218109998Smarkm 219109998Smarkm cmds = sk_new_null(); 220109998Smarkm 221109998Smarkm if(!cmds) 222109998Smarkm goto err; 223109998Smarkm do { 224109998Smarkm int len; 225109998Smarkm /* Get the command input flags */ 226109998Smarkm if((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, 227109998Smarkm NULL, NULL)) < 0) 228109998Smarkm goto err; 229109998Smarkm if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4) 230109998Smarkm { 231109998Smarkm /* Get the command name */ 232109998Smarkm if((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num, 233109998Smarkm NULL, NULL)) <= 0) 234109998Smarkm goto err; 235109998Smarkm if((name = OPENSSL_malloc(len + 1)) == NULL) 236109998Smarkm goto err; 237109998Smarkm if(ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name, 238109998Smarkm NULL) <= 0) 239109998Smarkm goto err; 240109998Smarkm /* Get the command description */ 241109998Smarkm if((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num, 242109998Smarkm NULL, NULL)) < 0) 243109998Smarkm goto err; 244109998Smarkm if(len > 0) 245109998Smarkm { 246109998Smarkm if((desc = OPENSSL_malloc(len + 1)) == NULL) 247109998Smarkm goto err; 248109998Smarkm if(ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc, 249109998Smarkm NULL) <= 0) 250109998Smarkm goto err; 251109998Smarkm } 252109998Smarkm /* Now decide on the output */ 253109998Smarkm if(xpos == 0) 254109998Smarkm /* Do an indent */ 255109998Smarkm xpos = BIO_printf(bio_out, indent); 256109998Smarkm else 257109998Smarkm /* Otherwise prepend a ", " */ 258109998Smarkm xpos += BIO_printf(bio_out, ", "); 259109998Smarkm if(verbose == 1) 260109998Smarkm { 261109998Smarkm /* We're just listing names, comma-delimited */ 262109998Smarkm if((xpos > (int)strlen(indent)) && 263109998Smarkm (xpos + (int)strlen(name) > line_wrap)) 264109998Smarkm { 265109998Smarkm BIO_printf(bio_out, "\n"); 266109998Smarkm xpos = BIO_printf(bio_out, indent); 267109998Smarkm } 268109998Smarkm xpos += BIO_printf(bio_out, "%s", name); 269109998Smarkm } 270109998Smarkm else 271109998Smarkm { 272109998Smarkm /* We're listing names plus descriptions */ 273109998Smarkm BIO_printf(bio_out, "%s: %s\n", name, 274109998Smarkm (desc == NULL) ? "<no description>" : desc); 275109998Smarkm /* ... and sometimes input flags */ 276109998Smarkm if((verbose >= 3) && !util_flags(bio_out, flags, 277109998Smarkm indent)) 278109998Smarkm goto err; 279109998Smarkm xpos = 0; 280109998Smarkm } 281109998Smarkm } 282109998Smarkm OPENSSL_free(name); name = NULL; 283109998Smarkm if(desc) { OPENSSL_free(desc); desc = NULL; } 284109998Smarkm /* Move to the next command */ 285109998Smarkm num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE, 286109998Smarkm num, NULL, NULL); 287109998Smarkm } while(num > 0); 288109998Smarkm if(xpos > 0) 289109998Smarkm BIO_printf(bio_out, "\n"); 290109998Smarkm ret = 1; 291109998Smarkmerr: 292109998Smarkm if(cmds) sk_pop_free(cmds, identity); 293109998Smarkm if(name) OPENSSL_free(name); 294109998Smarkm if(desc) OPENSSL_free(desc); 295109998Smarkm return ret; 296109998Smarkm } 297109998Smarkm 298109998Smarkmstatic void util_do_cmds(ENGINE *e, STACK *cmds, BIO *bio_out, const char *indent) 299109998Smarkm { 300109998Smarkm int loop, res, num = sk_num(cmds); 301109998Smarkm if(num < 0) 302109998Smarkm { 303109998Smarkm BIO_printf(bio_out, "[Error]: internal stack error\n"); 304109998Smarkm return; 305109998Smarkm } 306109998Smarkm for(loop = 0; loop < num; loop++) 307109998Smarkm { 308109998Smarkm char buf[256]; 309109998Smarkm const char *cmd, *arg; 310109998Smarkm cmd = sk_value(cmds, loop); 311109998Smarkm res = 1; /* assume success */ 312109998Smarkm /* Check if this command has no ":arg" */ 313109998Smarkm if((arg = strstr(cmd, ":")) == NULL) 314109998Smarkm { 315109998Smarkm if(!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0)) 316109998Smarkm res = 0; 317109998Smarkm } 318109998Smarkm else 319109998Smarkm { 320109998Smarkm if((int)(arg - cmd) > 254) 321109998Smarkm { 322109998Smarkm BIO_printf(bio_out,"[Error]: command name too long\n"); 323109998Smarkm return; 324109998Smarkm } 325109998Smarkm memcpy(buf, cmd, (int)(arg - cmd)); 326109998Smarkm buf[arg-cmd] = '\0'; 327109998Smarkm arg++; /* Move past the ":" */ 328109998Smarkm /* Call the command with the argument */ 329109998Smarkm if(!ENGINE_ctrl_cmd_string(e, buf, arg, 0)) 330109998Smarkm res = 0; 331109998Smarkm } 332109998Smarkm if(res) 333109998Smarkm BIO_printf(bio_out, "[Success]: %s\n", cmd); 334109998Smarkm else 335109998Smarkm { 336109998Smarkm BIO_printf(bio_out, "[Failure]: %s\n", cmd); 337109998Smarkm ERR_print_errors(bio_out); 338109998Smarkm } 339109998Smarkm } 340109998Smarkm } 341109998Smarkm 342109998Smarkmint MAIN(int, char **); 343109998Smarkm 344109998Smarkmint MAIN(int argc, char **argv) 345109998Smarkm { 346109998Smarkm int ret=1,i; 347160814Ssimon const char **pp; 348160814Ssimon int verbose=0, list_cap=0, test_avail=0, test_avail_noise = 0; 349109998Smarkm ENGINE *e; 350109998Smarkm STACK *engines = sk_new_null(); 351109998Smarkm STACK *pre_cmds = sk_new_null(); 352109998Smarkm STACK *post_cmds = sk_new_null(); 353109998Smarkm int badops=1; 354109998Smarkm BIO *bio_out=NULL; 355109998Smarkm const char *indent = " "; 356109998Smarkm 357109998Smarkm apps_startup(); 358109998Smarkm SSL_load_error_strings(); 359109998Smarkm 360109998Smarkm if (bio_err == NULL) 361109998Smarkm bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); 362109998Smarkm 363109998Smarkm if (!load_config(bio_err, NULL)) 364109998Smarkm goto end; 365109998Smarkm bio_out=BIO_new_fp(stdout,BIO_NOCLOSE); 366109998Smarkm#ifdef OPENSSL_SYS_VMS 367109998Smarkm { 368109998Smarkm BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 369109998Smarkm bio_out = BIO_push(tmpbio, bio_out); 370109998Smarkm } 371109998Smarkm#endif 372109998Smarkm 373109998Smarkm argc--; 374109998Smarkm argv++; 375109998Smarkm while (argc >= 1) 376109998Smarkm { 377109998Smarkm if (strncmp(*argv,"-v",2) == 0) 378109998Smarkm { 379109998Smarkm if(strspn(*argv + 1, "v") < strlen(*argv + 1)) 380109998Smarkm goto skip_arg_loop; 381109998Smarkm if((verbose=strlen(*argv + 1)) > 4) 382109998Smarkm goto skip_arg_loop; 383109998Smarkm } 384109998Smarkm else if (strcmp(*argv,"-c") == 0) 385109998Smarkm list_cap=1; 386160814Ssimon else if (strncmp(*argv,"-t",2) == 0) 387160814Ssimon { 388109998Smarkm test_avail=1; 389160814Ssimon if(strspn(*argv + 1, "t") < strlen(*argv + 1)) 390160814Ssimon goto skip_arg_loop; 391160814Ssimon if((test_avail_noise = strlen(*argv + 1) - 1) > 1) 392160814Ssimon goto skip_arg_loop; 393160814Ssimon } 394109998Smarkm else if (strcmp(*argv,"-pre") == 0) 395109998Smarkm { 396109998Smarkm argc--; argv++; 397160814Ssimon if (argc == 0) 398160814Ssimon goto skip_arg_loop; 399109998Smarkm sk_push(pre_cmds,*argv); 400109998Smarkm } 401109998Smarkm else if (strcmp(*argv,"-post") == 0) 402109998Smarkm { 403109998Smarkm argc--; argv++; 404160814Ssimon if (argc == 0) 405160814Ssimon goto skip_arg_loop; 406109998Smarkm sk_push(post_cmds,*argv); 407109998Smarkm } 408109998Smarkm else if ((strncmp(*argv,"-h",2) == 0) || 409109998Smarkm (strcmp(*argv,"-?") == 0)) 410109998Smarkm goto skip_arg_loop; 411109998Smarkm else 412109998Smarkm sk_push(engines,*argv); 413109998Smarkm argc--; 414109998Smarkm argv++; 415109998Smarkm } 416109998Smarkm /* Looks like everything went OK */ 417109998Smarkm badops = 0; 418109998Smarkmskip_arg_loop: 419109998Smarkm 420109998Smarkm if (badops) 421109998Smarkm { 422109998Smarkm for (pp=engine_usage; (*pp != NULL); pp++) 423109998Smarkm BIO_printf(bio_err,"%s",*pp); 424109998Smarkm goto end; 425109998Smarkm } 426109998Smarkm 427109998Smarkm if (sk_num(engines) == 0) 428109998Smarkm { 429109998Smarkm for(e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) 430109998Smarkm { 431109998Smarkm sk_push(engines,(char *)ENGINE_get_id(e)); 432109998Smarkm } 433109998Smarkm } 434109998Smarkm 435109998Smarkm for (i=0; i<sk_num(engines); i++) 436109998Smarkm { 437109998Smarkm const char *id = sk_value(engines,i); 438109998Smarkm if ((e = ENGINE_by_id(id)) != NULL) 439109998Smarkm { 440109998Smarkm const char *name = ENGINE_get_name(e); 441109998Smarkm /* Do "id" first, then "name". Easier to auto-parse. */ 442109998Smarkm BIO_printf(bio_out, "(%s) %s\n", id, name); 443109998Smarkm util_do_cmds(e, pre_cmds, bio_out, indent); 444109998Smarkm if (strcmp(ENGINE_get_id(e), id) != 0) 445109998Smarkm { 446109998Smarkm BIO_printf(bio_out, "Loaded: (%s) %s\n", 447109998Smarkm ENGINE_get_id(e), ENGINE_get_name(e)); 448109998Smarkm } 449109998Smarkm if (list_cap) 450109998Smarkm { 451109998Smarkm int cap_size = 256; 452109998Smarkm char *cap_buf = NULL; 453109998Smarkm int k,n; 454109998Smarkm const int *nids; 455109998Smarkm ENGINE_CIPHERS_PTR fn_c; 456109998Smarkm ENGINE_DIGESTS_PTR fn_d; 457109998Smarkm 458109998Smarkm if (ENGINE_get_RSA(e) != NULL 459109998Smarkm && !append_buf(&cap_buf, "RSA", 460109998Smarkm &cap_size, 256)) 461109998Smarkm goto end; 462109998Smarkm if (ENGINE_get_DSA(e) != NULL 463109998Smarkm && !append_buf(&cap_buf, "DSA", 464109998Smarkm &cap_size, 256)) 465109998Smarkm goto end; 466109998Smarkm if (ENGINE_get_DH(e) != NULL 467109998Smarkm && !append_buf(&cap_buf, "DH", 468109998Smarkm &cap_size, 256)) 469109998Smarkm goto end; 470109998Smarkm if (ENGINE_get_RAND(e) != NULL 471109998Smarkm && !append_buf(&cap_buf, "RAND", 472109998Smarkm &cap_size, 256)) 473109998Smarkm goto end; 474109998Smarkm 475109998Smarkm fn_c = ENGINE_get_ciphers(e); 476109998Smarkm if(!fn_c) goto skip_ciphers; 477109998Smarkm n = fn_c(e, NULL, &nids, 0); 478109998Smarkm for(k=0 ; k < n ; ++k) 479109998Smarkm if(!append_buf(&cap_buf, 480109998Smarkm OBJ_nid2sn(nids[k]), 481109998Smarkm &cap_size, 256)) 482109998Smarkm goto end; 483109998Smarkm 484109998Smarkmskip_ciphers: 485109998Smarkm fn_d = ENGINE_get_digests(e); 486109998Smarkm if(!fn_d) goto skip_digests; 487109998Smarkm n = fn_d(e, NULL, &nids, 0); 488109998Smarkm for(k=0 ; k < n ; ++k) 489109998Smarkm if(!append_buf(&cap_buf, 490109998Smarkm OBJ_nid2sn(nids[k]), 491109998Smarkm &cap_size, 256)) 492109998Smarkm goto end; 493109998Smarkm 494109998Smarkmskip_digests: 495109998Smarkm if (cap_buf && (*cap_buf != '\0')) 496109998Smarkm BIO_printf(bio_out, " [%s]\n", cap_buf); 497109998Smarkm 498109998Smarkm OPENSSL_free(cap_buf); 499109998Smarkm } 500109998Smarkm if(test_avail) 501109998Smarkm { 502109998Smarkm BIO_printf(bio_out, "%s", indent); 503109998Smarkm if (ENGINE_init(e)) 504109998Smarkm { 505109998Smarkm BIO_printf(bio_out, "[ available ]\n"); 506109998Smarkm util_do_cmds(e, post_cmds, bio_out, indent); 507109998Smarkm ENGINE_finish(e); 508109998Smarkm } 509109998Smarkm else 510109998Smarkm { 511109998Smarkm BIO_printf(bio_out, "[ unavailable ]\n"); 512160814Ssimon if(test_avail_noise) 513160814Ssimon ERR_print_errors_fp(stdout); 514109998Smarkm ERR_clear_error(); 515109998Smarkm } 516109998Smarkm } 517109998Smarkm if((verbose > 0) && !util_verbose(e, verbose, bio_out, indent)) 518109998Smarkm goto end; 519109998Smarkm ENGINE_free(e); 520109998Smarkm } 521109998Smarkm else 522109998Smarkm ERR_print_errors(bio_err); 523109998Smarkm } 524109998Smarkm 525109998Smarkm ret=0; 526109998Smarkmend: 527160814Ssimon 528109998Smarkm ERR_print_errors(bio_err); 529109998Smarkm sk_pop_free(engines, identity); 530109998Smarkm sk_pop_free(pre_cmds, identity); 531109998Smarkm sk_pop_free(post_cmds, identity); 532109998Smarkm if (bio_out != NULL) BIO_free_all(bio_out); 533109998Smarkm apps_shutdown(); 534109998Smarkm OPENSSL_EXIT(ret); 535109998Smarkm } 536120631Snectar#else 537120631Snectar 538120631Snectar# if PEDANTIC 539120631Snectarstatic void *dummy=&dummy; 540120631Snectar# endif 541120631Snectar 542111147Snectar#endif 543