ssl/tsrc/BC/libcrypto/topenssl/src/engine.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* apps/engine.c -*- mode: C; c-file-style: "eay" -*- */
       
     2 /* Written by Richard Levitte <richard@levitte.org> for the OpenSSL
       
     3  * project 2000.
       
     4  */
       
     5 /* ====================================================================
       
     6  * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
       
     7  *
       
     8  * Redistribution and use in source and binary forms, with or without
       
     9  * modification, are permitted provided that the following conditions
       
    10  * are met:
       
    11  *
       
    12  * 1. Redistributions of source code must retain the above copyright
       
    13  *    notice, this list of conditions and the following disclaimer. 
       
    14  *
       
    15  * 2. Redistributions in binary form must reproduce the above copyright
       
    16  *    notice, this list of conditions and the following disclaimer in
       
    17  *    the documentation and/or other materials provided with the
       
    18  *    distribution.
       
    19  *
       
    20  * 3. All advertising materials mentioning features or use of this
       
    21  *    software must display the following acknowledgment:
       
    22  *    "This product includes software developed by the OpenSSL Project
       
    23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
       
    24  *
       
    25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
       
    26  *    endorse or promote products derived from this software without
       
    27  *    prior written permission. For written permission, please contact
       
    28  *    licensing@OpenSSL.org.
       
    29  *
       
    30  * 5. Products derived from this software may not be called "OpenSSL"
       
    31  *    nor may "OpenSSL" appear in their names without prior written
       
    32  *    permission of the OpenSSL Project.
       
    33  *
       
    34  * 6. Redistributions of any form whatsoever must retain the following
       
    35  *    acknowledgment:
       
    36  *    "This product includes software developed by the OpenSSL Project
       
    37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
       
    38  *
       
    39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
       
    40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
       
    43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
       
    45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
       
    46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
       
    47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
       
    48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
       
    49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
       
    50  * OF THE POSSIBILITY OF SUCH DAMAGE.
       
    51  * ====================================================================
       
    52  *
       
    53  * This product includes cryptographic software written by Eric Young
       
    54  * (eay@cryptsoft.com).  This product includes software written by Tim
       
    55  * Hudson (tjh@cryptsoft.com).
       
    56  *
       
    57  */
       
    58 
       
    59 #ifndef OPENSSL_NO_ENGINE
       
    60 
       
    61 #include <stdio.h>
       
    62 #include <stdlib.h>
       
    63 #include <string.h>
       
    64 #ifdef OPENSSL_NO_STDIO
       
    65 #define APPS_WIN16
       
    66 #endif
       
    67 #include "apps.h"
       
    68 #include <openssl/err.h>
       
    69 #include <openssl/engine.h>
       
    70 #include <openssl/ssl.h>
       
    71 
       
    72 
       
    73 #undef PROG
       
    74 #define PROG	engine_main
       
    75 
       
    76 static const char *engine_usage[]={
       
    77 "usage: engine opts [engine ...]\n",
       
    78 " -v[v[v[v]]] - verbose mode, for each engine, list its 'control commands'\n",
       
    79 "               -vv will additionally display each command's description\n",
       
    80 "               -vvv will also add the input flags for each command\n",
       
    81 "               -vvvv will also show internal input flags\n",
       
    82 " -c          - for each engine, also list the capabilities\n",
       
    83 " -t[t]       - for each engine, check that they are really available\n",
       
    84 "               -tt will display error trace for unavailable engines\n",
       
    85 " -pre <cmd>  - runs command 'cmd' against the ENGINE before any attempts\n",
       
    86 "               to load it (if -t is used)\n",
       
    87 " -post <cmd> - runs command 'cmd' against the ENGINE after loading it\n",
       
    88 "               (only used if -t is also provided)\n",
       
    89 " NB: -pre and -post will be applied to all ENGINEs supplied on the command\n",
       
    90 " line, or all supported ENGINEs if none are specified.\n",
       
    91 " Eg. '-pre \"SO_PATH:/lib/libdriver.so\"' calls command \"SO_PATH\" with\n",
       
    92 " argument \"/lib/libdriver.so\".\n",
       
    93 NULL
       
    94 };
       
    95 
       
    96 static void identity(void *ptr)
       
    97 	{
       
    98 	return;
       
    99 	}
       
   100 
       
   101 static int append_buf(char **buf, const char *s, int *size, int step)
       
   102 	{
       
   103 	int l = strlen(s);
       
   104 
       
   105 	if (*buf == NULL)
       
   106 		{
       
   107 		*size = step;
       
   108 		*buf = OPENSSL_malloc(*size);
       
   109 		if (*buf == NULL)
       
   110 			return 0;
       
   111 		**buf = '\0';
       
   112 		}
       
   113 
       
   114 	if (**buf != '\0')
       
   115 		l += 2;		/* ", " */
       
   116 
       
   117 	if (strlen(*buf) + strlen(s) >= (unsigned int)*size)
       
   118 		{
       
   119 		*size += step;
       
   120 		*buf = OPENSSL_realloc(*buf, *size);
       
   121 		}
       
   122 
       
   123 	if (*buf == NULL)
       
   124 		return 0;
       
   125 
       
   126 	if (**buf != '\0')
       
   127 		BUF_strlcat(*buf, ", ", *size);
       
   128 	BUF_strlcat(*buf, s, *size);
       
   129 
       
   130 	return 1;
       
   131 	}
       
   132 
       
   133 static int util_flags(BIO *bio_out, unsigned int flags, const char *indent)
       
   134 	{
       
   135 	int started = 0, err = 0;
       
   136 	/* Indent before displaying input flags */
       
   137 	BIO_printf(bio_out, "%s%s(input flags): ", indent, indent);
       
   138 	if(flags == 0)
       
   139 		{
       
   140 		BIO_printf(bio_out, "<no flags>\n");
       
   141 		return 1;
       
   142 		}
       
   143         /* If the object is internal, mark it in a way that shows instead of
       
   144          * having it part of all the other flags, even if it really is. */
       
   145 	if(flags & ENGINE_CMD_FLAG_INTERNAL)
       
   146 		{
       
   147 		BIO_printf(bio_out, "[Internal] ");
       
   148 		}
       
   149 
       
   150 	if(flags & ENGINE_CMD_FLAG_NUMERIC)
       
   151 		{
       
   152 		if(started)
       
   153 			{
       
   154 			BIO_printf(bio_out, "|");
       
   155 			err = 1;
       
   156 			}
       
   157 		BIO_printf(bio_out, "NUMERIC");
       
   158 		started = 1;
       
   159 		}
       
   160 	/* Now we check that no combinations of the mutually exclusive NUMERIC,
       
   161 	 * STRING, and NO_INPUT flags have been used. Future flags that can be
       
   162 	 * OR'd together with these would need to added after these to preserve
       
   163 	 * the testing logic. */
       
   164 	if(flags & ENGINE_CMD_FLAG_STRING)
       
   165 		{
       
   166 		if(started)
       
   167 			{
       
   168 			BIO_printf(bio_out, "|");
       
   169 			err = 1;
       
   170 			}
       
   171 		BIO_printf(bio_out, "STRING");
       
   172 		started = 1;
       
   173 		}
       
   174 	if(flags & ENGINE_CMD_FLAG_NO_INPUT)
       
   175 		{
       
   176 		if(started)
       
   177 			{
       
   178 			BIO_printf(bio_out, "|");
       
   179 			err = 1;
       
   180 			}
       
   181 		BIO_printf(bio_out, "NO_INPUT");
       
   182 		started = 1;
       
   183 		}
       
   184 	/* Check for unknown flags */
       
   185 	flags = flags & ~ENGINE_CMD_FLAG_NUMERIC &
       
   186 			~ENGINE_CMD_FLAG_STRING &
       
   187 			~ENGINE_CMD_FLAG_NO_INPUT &
       
   188 			~ENGINE_CMD_FLAG_INTERNAL;
       
   189 	if(flags)
       
   190 		{
       
   191 		if(started) BIO_printf(bio_out, "|");
       
   192 		BIO_printf(bio_out, "<0x%04X>", flags);
       
   193 		}
       
   194 	if(err)
       
   195 		BIO_printf(bio_out, "  <illegal flags!>");
       
   196 	BIO_printf(bio_out, "\n");
       
   197 	return 1;
       
   198 	}
       
   199 
       
   200 static int util_verbose(ENGINE *e, int verbose, BIO *bio_out, const char *indent)
       
   201 	{
       
   202 	static const int line_wrap = 78;
       
   203 	int num;
       
   204 	int ret = 0;
       
   205 	char *name = NULL;
       
   206 	char *desc = NULL;
       
   207 	int flags;
       
   208 	int xpos = 0;
       
   209 	STACK *cmds = NULL;
       
   210 	if(!ENGINE_ctrl(e, ENGINE_CTRL_HAS_CTRL_FUNCTION, 0, NULL, NULL) ||
       
   211 			((num = ENGINE_ctrl(e, ENGINE_CTRL_GET_FIRST_CMD_TYPE,
       
   212 					0, NULL, NULL)) <= 0))
       
   213 		{
       
   214 #if 0
       
   215 		BIO_printf(bio_out, "%s<no control commands>\n", indent);
       
   216 #endif
       
   217 		return 1;
       
   218 		}
       
   219 
       
   220 	cmds = sk_new_null();
       
   221 
       
   222 	if(!cmds)
       
   223 		goto err;
       
   224 	do {
       
   225 		int len;
       
   226 		/* Get the command input flags */
       
   227 		if((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num,
       
   228 					NULL, NULL)) < 0)
       
   229 			goto err;
       
   230                 if (!(flags & ENGINE_CMD_FLAG_INTERNAL) || verbose >= 4)
       
   231                         {
       
   232                         /* Get the command name */
       
   233                         if((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_LEN_FROM_CMD, num,
       
   234                                 NULL, NULL)) <= 0)
       
   235                                 goto err;
       
   236                         if((name = OPENSSL_malloc(len + 1)) == NULL)
       
   237                                 goto err;
       
   238                         if(ENGINE_ctrl(e, ENGINE_CTRL_GET_NAME_FROM_CMD, num, name,
       
   239                                 NULL) <= 0)
       
   240                                 goto err;
       
   241                         /* Get the command description */
       
   242                         if((len = ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_LEN_FROM_CMD, num,
       
   243                                 NULL, NULL)) < 0)
       
   244                                 goto err;
       
   245                         if(len > 0)
       
   246                                 {
       
   247                                 if((desc = OPENSSL_malloc(len + 1)) == NULL)
       
   248                                         goto err;
       
   249                                 if(ENGINE_ctrl(e, ENGINE_CTRL_GET_DESC_FROM_CMD, num, desc,
       
   250                                         NULL) <= 0)
       
   251                                         goto err;
       
   252                                 }
       
   253                         /* Now decide on the output */
       
   254                         if(xpos == 0)
       
   255                                 /* Do an indent */
       
   256                                 xpos = BIO_printf(bio_out, indent);
       
   257                         else
       
   258                                 /* Otherwise prepend a ", " */
       
   259                                 xpos += BIO_printf(bio_out, ", ");
       
   260                         if(verbose == 1)
       
   261                                 {
       
   262                                 /* We're just listing names, comma-delimited */
       
   263                                 if((xpos > (int)strlen(indent)) &&
       
   264 					(xpos + (int)strlen(name) > line_wrap))
       
   265                                         {
       
   266                                         BIO_printf(bio_out, "\n");
       
   267                                         xpos = BIO_printf(bio_out, indent);
       
   268                                         }
       
   269                                 xpos += BIO_printf(bio_out, "%s", name);
       
   270                                 }
       
   271                         else
       
   272                                 {
       
   273                                 /* We're listing names plus descriptions */
       
   274                                 BIO_printf(bio_out, "%s: %s\n", name,
       
   275                                         (desc == NULL) ? "<no description>" : desc);
       
   276                                 /* ... and sometimes input flags */
       
   277                                 if((verbose >= 3) && !util_flags(bio_out, flags,
       
   278                                         indent))
       
   279                                         goto err;
       
   280                                 xpos = 0;
       
   281                                 }
       
   282                         }
       
   283 		OPENSSL_free(name); name = NULL;
       
   284 		if(desc) { OPENSSL_free(desc); desc = NULL; }
       
   285 		/* Move to the next command */
       
   286 		num = ENGINE_ctrl(e, ENGINE_CTRL_GET_NEXT_CMD_TYPE,
       
   287 					num, NULL, NULL);
       
   288 		} while(num > 0);
       
   289 	if(xpos > 0)
       
   290 		BIO_printf(bio_out, "\n");
       
   291 	ret = 1;
       
   292 err:
       
   293 	if(cmds) sk_pop_free(cmds, identity);
       
   294 	if(name) OPENSSL_free(name);
       
   295 	if(desc) OPENSSL_free(desc);
       
   296 	return ret;
       
   297 	}
       
   298 
       
   299 static void util_do_cmds(ENGINE *e, STACK *cmds, BIO *bio_out, const char *indent)
       
   300 	{
       
   301 	int loop, res, num = sk_num(cmds);
       
   302 	if(num < 0)
       
   303 		{
       
   304 		BIO_printf(bio_out, "[Error]: internal stack error\n");
       
   305 		return;
       
   306 		}
       
   307 	for(loop = 0; loop < num; loop++)
       
   308 		{
       
   309 		char buf[256];
       
   310 		const char *cmd, *arg;
       
   311 		cmd = sk_value(cmds, loop);
       
   312 		res = 1; /* assume success */
       
   313 		/* Check if this command has no ":arg" */
       
   314 		if((arg = strstr(cmd, ":")) == NULL)
       
   315 			{
       
   316 			if(!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0))
       
   317 				res = 0;
       
   318 			}
       
   319 		else
       
   320 			{
       
   321 			if((int)(arg - cmd) > 254)
       
   322 				{
       
   323 				BIO_printf(bio_out,"[Error]: command name too long\n");
       
   324 				return;
       
   325 				}
       
   326 			memcpy(buf, cmd, (int)(arg - cmd));
       
   327 			buf[arg-cmd] = '\0';
       
   328 			arg++; /* Move past the ":" */
       
   329 			/* Call the command with the argument */
       
   330 			if(!ENGINE_ctrl_cmd_string(e, buf, arg, 0))
       
   331 				res = 0;
       
   332 			}
       
   333 		if(res)
       
   334 			BIO_printf(bio_out, "[Success]: %s\n", cmd);
       
   335 		else
       
   336 			{
       
   337 			BIO_printf(bio_out, "[Failure]: %s\n", cmd);
       
   338 			ERR_print_errors(bio_out);
       
   339 			}
       
   340 		}
       
   341 	}
       
   342 
       
   343 int MAIN(int, char **);
       
   344 
       
   345 int MAIN(int argc, char **argv)
       
   346 	{
       
   347 	int ret=1,i;
       
   348 	const char **pp;
       
   349 	int verbose=0, list_cap=0, test_avail=0, test_avail_noise = 0;
       
   350 	ENGINE *e;
       
   351 	STACK *engines = sk_new_null();
       
   352 	STACK *pre_cmds = sk_new_null();
       
   353 	STACK *post_cmds = sk_new_null();
       
   354 	int badops=1;
       
   355 	BIO *bio_out=NULL;
       
   356 	const char *indent = "     ";
       
   357 
       
   358 	apps_startup();
       
   359 	SSL_load_error_strings();
       
   360 
       
   361 	if (bio_err == NULL)
       
   362 		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
       
   363 
       
   364 	if (!load_config(bio_err, NULL))
       
   365 		goto end;
       
   366 	bio_out=BIO_new_fp(stdout,BIO_NOCLOSE);
       
   367 
       
   368 #ifdef OPENSSL_SYS_VMS
       
   369 	{
       
   370 	BIO *tmpbio = BIO_new(BIO_f_linebuffer());
       
   371 	bio_out = BIO_push(tmpbio, bio_out);
       
   372 	}
       
   373 #endif
       
   374 
       
   375 	argc--;
       
   376 	argv++;
       
   377 	while (argc >= 1)
       
   378 		{
       
   379 		if (strncmp(*argv,"-v",2) == 0)
       
   380 			{
       
   381 			if(strspn(*argv + 1, "v") < strlen(*argv + 1))
       
   382 				goto skip_arg_loop;
       
   383 			if((verbose=strlen(*argv + 1)) > 4)
       
   384 				goto skip_arg_loop;
       
   385 			}
       
   386 		else if (strcmp(*argv,"-c") == 0)
       
   387 			list_cap=1;
       
   388 		else if (strncmp(*argv,"-t",2) == 0)
       
   389 			{
       
   390 			test_avail=1;
       
   391 			if(strspn(*argv + 1, "t") < strlen(*argv + 1))
       
   392 				goto skip_arg_loop;
       
   393 			if((test_avail_noise = strlen(*argv + 1) - 1) > 1)
       
   394 				goto skip_arg_loop;
       
   395 			}
       
   396 		else if (strcmp(*argv,"-pre") == 0)
       
   397 			{
       
   398 			argc--; argv++;
       
   399 			if (argc == 0)
       
   400 				goto skip_arg_loop;
       
   401 			sk_push(pre_cmds,*argv);
       
   402 			}
       
   403 		else if (strcmp(*argv,"-post") == 0)
       
   404 			{
       
   405 			argc--; argv++;
       
   406 			if (argc == 0)
       
   407 				goto skip_arg_loop;
       
   408 			sk_push(post_cmds,*argv);
       
   409 			}
       
   410 		else if ((strncmp(*argv,"-h",2) == 0) ||
       
   411 				(strcmp(*argv,"-?") == 0))
       
   412 			goto skip_arg_loop;
       
   413 		else
       
   414 			sk_push(engines,*argv);
       
   415 		argc--;
       
   416 		argv++;
       
   417 		}
       
   418 	/* Looks like everything went OK */
       
   419 	badops = 0;
       
   420 skip_arg_loop:
       
   421 
       
   422 	if (badops)
       
   423 		{
       
   424 		for (pp=engine_usage; (*pp != NULL); pp++)
       
   425 			BIO_printf(bio_err,"%s",*pp);
       
   426 		goto end;
       
   427 		}
       
   428 
       
   429 	if (sk_num(engines) == 0)
       
   430 		{
       
   431 		for(e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e))
       
   432 			{
       
   433 			sk_push(engines,(char *)ENGINE_get_id(e));
       
   434 			}
       
   435 		}
       
   436 
       
   437 	for (i=0; i<sk_num(engines); i++)
       
   438 		{
       
   439 		const char *id = sk_value(engines,i);
       
   440 		if ((e = ENGINE_by_id(id)) != NULL)
       
   441 			{
       
   442 			const char *name = ENGINE_get_name(e);
       
   443 			/* Do "id" first, then "name". Easier to auto-parse. */
       
   444 			BIO_printf(bio_out, "(%s) %s\n", id, name);
       
   445 			util_do_cmds(e, pre_cmds, bio_out, indent);
       
   446 			if (strcmp(ENGINE_get_id(e), id) != 0)
       
   447 				{
       
   448 				BIO_printf(bio_out, "Loaded: (%s) %s\n",
       
   449 					ENGINE_get_id(e), ENGINE_get_name(e));
       
   450 				}
       
   451 			if (list_cap)
       
   452 				{
       
   453 				int cap_size = 256;
       
   454 				char *cap_buf = NULL;
       
   455 				int k,n;
       
   456 				const int *nids;
       
   457 				ENGINE_CIPHERS_PTR fn_c;
       
   458 				ENGINE_DIGESTS_PTR fn_d;
       
   459 
       
   460 				if (ENGINE_get_RSA(e) != NULL
       
   461 					&& !append_buf(&cap_buf, "RSA",
       
   462 						&cap_size, 256))
       
   463 					goto end;
       
   464 				if (ENGINE_get_DSA(e) != NULL
       
   465 					&& !append_buf(&cap_buf, "DSA",
       
   466 						&cap_size, 256))
       
   467 					goto end;
       
   468 				if (ENGINE_get_DH(e) != NULL
       
   469 					&& !append_buf(&cap_buf, "DH",
       
   470 						&cap_size, 256))
       
   471 					goto end;
       
   472 				if (ENGINE_get_RAND(e) != NULL
       
   473 					&& !append_buf(&cap_buf, "RAND",
       
   474 						&cap_size, 256))
       
   475 					goto end;
       
   476 
       
   477 				fn_c = ENGINE_get_ciphers(e);
       
   478 				if(!fn_c) goto skip_ciphers;
       
   479 				n = fn_c(e, NULL, &nids, 0);
       
   480 				for(k=0 ; k < n ; ++k)
       
   481 					if(!append_buf(&cap_buf,
       
   482 						       OBJ_nid2sn(nids[k]),
       
   483 						       &cap_size, 256))
       
   484 						goto end;
       
   485 
       
   486 skip_ciphers:
       
   487 				fn_d = ENGINE_get_digests(e);
       
   488 				if(!fn_d) goto skip_digests;
       
   489 				n = fn_d(e, NULL, &nids, 0);
       
   490 				for(k=0 ; k < n ; ++k)
       
   491 					if(!append_buf(&cap_buf,
       
   492 						       OBJ_nid2sn(nids[k]),
       
   493 						       &cap_size, 256))
       
   494 						goto end;
       
   495 
       
   496 skip_digests:
       
   497 				if (cap_buf && (*cap_buf != '\0'))
       
   498 					BIO_printf(bio_out, " [%s]\n", cap_buf);
       
   499 
       
   500 				OPENSSL_free(cap_buf);
       
   501 				}
       
   502 			if(test_avail)
       
   503 				{
       
   504 				BIO_printf(bio_out, "%s", indent);
       
   505 				if (ENGINE_init(e))
       
   506 					{
       
   507 					BIO_printf(bio_out, "[ available ]\n");
       
   508 					util_do_cmds(e, post_cmds, bio_out, indent);
       
   509 					ENGINE_finish(e);
       
   510 					}
       
   511 				else
       
   512 					{
       
   513 					BIO_printf(bio_out, "[ unavailable ]\n");
       
   514 					if(test_avail_noise)
       
   515 					ERR_print_errors_fp(stdout);
       
   516 					ERR_clear_error();
       
   517 					}
       
   518 				}
       
   519 			if((verbose > 0) && !util_verbose(e, verbose, bio_out, indent))
       
   520 				goto end;
       
   521 			ENGINE_free(e);
       
   522 			}
       
   523 		else
       
   524 			ERR_print_errors(bio_err);
       
   525 		}
       
   526 
       
   527 	ret=0;
       
   528 end:
       
   529 
       
   530 	ERR_print_errors(bio_err);
       
   531 	sk_pop_free(engines, identity);
       
   532 	sk_pop_free(pre_cmds, identity);
       
   533 	sk_pop_free(post_cmds, identity);
       
   534 	if (bio_out != NULL) BIO_free_all(bio_out);
       
   535 	apps_shutdown();
       
   536 	OPENSSL_EXIT(ret);
       
   537 	}
       
   538 #else
       
   539 
       
   540 # if PEDANTIC
       
   541 static void *dummy=&dummy;
       
   542 # endif
       
   543 
       
   544 #endif