openssl.c revision 331638
1/* apps/openssl.c */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to.  The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 *    notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 *    notice, this list of conditions and the following disclaimer in the
30 *    documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 *    must display the following acknowledgement:
33 *    "This product includes cryptographic software written by
34 *     Eric Young (eay@cryptsoft.com)"
35 *    The word 'cryptographic' can be left out if the rouines from the library
36 *    being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 *    the apps directory (application code) you must include an acknowledgement:
39 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58/* ====================================================================
59 * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
60 *
61 * Redistribution and use in source and binary forms, with or without
62 * modification, are permitted provided that the following conditions
63 * are met:
64 *
65 * 1. Redistributions of source code must retain the above copyright
66 *    notice, this list of conditions and the following disclaimer.
67 *
68 * 2. Redistributions in binary form must reproduce the above copyright
69 *    notice, this list of conditions and the following disclaimer in
70 *    the documentation and/or other materials provided with the
71 *    distribution.
72 *
73 * 3. All advertising materials mentioning features or use of this
74 *    software must display the following acknowledgment:
75 *    "This product includes software developed by the OpenSSL Project
76 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77 *
78 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79 *    endorse or promote products derived from this software without
80 *    prior written permission. For written permission, please contact
81 *    openssl-core@openssl.org.
82 *
83 * 5. Products derived from this software may not be called "OpenSSL"
84 *    nor may "OpenSSL" appear in their names without prior written
85 *    permission of the OpenSSL Project.
86 *
87 * 6. Redistributions of any form whatsoever must retain the following
88 *    acknowledgment:
89 *    "This product includes software developed by the OpenSSL Project
90 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91 *
92 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103 * OF THE POSSIBILITY OF SUCH DAMAGE.
104 * ====================================================================
105 *
106 * This product includes cryptographic software written by Eric Young
107 * (eay@cryptsoft.com).  This product includes software written by Tim
108 * Hudson (tjh@cryptsoft.com).
109 *
110 */
111
112#include <stdio.h>
113#include <string.h>
114#include <stdlib.h>
115#define OPENSSL_C               /* tells apps.h to use complete
116                                 * apps_startup() */
117#include "apps.h"
118#include <openssl/bio.h>
119#include <openssl/crypto.h>
120#include <openssl/rand.h>
121#include <openssl/lhash.h>
122#include <openssl/conf.h>
123#include <openssl/x509.h>
124#include <openssl/pem.h>
125#include <openssl/ssl.h>
126#ifndef OPENSSL_NO_ENGINE
127# include <openssl/engine.h>
128#endif
129#define USE_SOCKETS             /* needed for the _O_BINARY defs in the MS
130                                 * world */
131#include "progs.h"
132#include "s_apps.h"
133#include <openssl/err.h>
134#ifdef OPENSSL_FIPS
135# include <openssl/fips.h>
136#endif
137
138/*
139 * The LHASH callbacks ("hash" & "cmp") have been replaced by functions with
140 * the base prototypes (we cast each variable inside the function to the
141 * required type of "FUNCTION*"). This removes the necessity for
142 * macro-generated wrapper functions.
143 */
144
145static LHASH_OF(FUNCTION) *prog_init(void);
146static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]);
147static void list_pkey(BIO *out);
148static void list_cipher(BIO *out);
149static void list_md(BIO *out);
150char *default_config_file = NULL;
151
152/* Make sure there is only one when MONOLITH is defined */
153#ifdef MONOLITH
154CONF *config = NULL;
155BIO *bio_err = NULL;
156#endif
157
158static void lock_dbg_cb(int mode, int type, const char *file, int line)
159{
160    static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */
161    const char *errstr = NULL;
162    int rw;
163
164    rw = mode & (CRYPTO_READ | CRYPTO_WRITE);
165    if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE))) {
166        errstr = "invalid mode";
167        goto err;
168    }
169
170    if (type < 0 || type >= CRYPTO_NUM_LOCKS) {
171        errstr = "type out of bounds";
172        goto err;
173    }
174
175    if (mode & CRYPTO_LOCK) {
176        if (modes[type]) {
177            errstr = "already locked";
178            /*
179             * must not happen in a single-threaded program (would deadlock)
180             */
181            goto err;
182        }
183
184        modes[type] = rw;
185    } else if (mode & CRYPTO_UNLOCK) {
186        if (!modes[type]) {
187            errstr = "not locked";
188            goto err;
189        }
190
191        if (modes[type] != rw) {
192            errstr = (rw == CRYPTO_READ) ?
193                "CRYPTO_r_unlock on write lock" :
194                "CRYPTO_w_unlock on read lock";
195        }
196
197        modes[type] = 0;
198    } else {
199        errstr = "invalid mode";
200        goto err;
201    }
202
203 err:
204    if (errstr) {
205        /* we cannot use bio_err here */
206        fprintf(stderr,
207                "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
208                errstr, mode, type, file, line);
209    }
210}
211
212#if defined( OPENSSL_SYS_VMS) && (__INITIAL_POINTER_SIZE == 64)
213# define ARGV _Argv
214#else
215# define ARGV Argv
216#endif
217
218int main(int Argc, char *ARGV[])
219{
220    ARGS arg;
221#define PROG_NAME_SIZE  39
222    char pname[PROG_NAME_SIZE + 1];
223    FUNCTION f, *fp;
224    MS_STATIC const char *prompt;
225    MS_STATIC char buf[1024];
226    char *to_free = NULL;
227    int n, i, ret = 0;
228    int argc;
229    char **argv, *p;
230    LHASH_OF(FUNCTION) *prog = NULL;
231    long errline;
232
233#if defined( OPENSSL_SYS_VMS) && (__INITIAL_POINTER_SIZE == 64)
234    /*-
235     * 2011-03-22 SMS.
236     * If we have 32-bit pointers everywhere, then we're safe, and
237     * we bypass this mess, as on non-VMS systems.  (See ARGV,
238     * above.)
239     * Problem 1: Compaq/HP C before V7.3 always used 32-bit
240     * pointers for argv[].
241     * Fix 1: For a 32-bit argv[], when we're using 64-bit pointers
242     * everywhere else, we always allocate and use a 64-bit
243     * duplicate of argv[].
244     * Problem 2: Compaq/HP C V7.3 (Alpha, IA64) before ECO1 failed
245     * to NULL-terminate a 64-bit argv[].  (As this was written, the
246     * compiler ECO was available only on IA64.)
247     * Fix 2: Unless advised not to (VMS_TRUST_ARGV), we test a
248     * 64-bit argv[argc] for NULL, and, if necessary, use a
249     * (properly) NULL-terminated (64-bit) duplicate of argv[].
250     * The same code is used in either case to duplicate argv[].
251     * Some of these decisions could be handled in preprocessing,
252     * but the code tends to get even uglier, and the penalty for
253     * deciding at compile- or run-time is tiny.
254     */
255    char **Argv = NULL;
256    int free_Argv = 0;
257
258    if ((sizeof(_Argv) < 8)     /* 32-bit argv[]. */
259# if !defined( VMS_TRUST_ARGV)
260        || (_Argv[Argc] != NULL) /* Untrusted argv[argc] not NULL. */
261# endif
262        ) {
263        int i;
264        Argv = OPENSSL_malloc((Argc + 1) * sizeof(char *));
265        if (Argv == NULL) {
266            ret = -1;
267            goto end;
268        }
269        for (i = 0; i < Argc; i++)
270            Argv[i] = _Argv[i];
271        Argv[Argc] = NULL;      /* Certain NULL termination. */
272        free_Argv = 1;
273    } else {
274        /*
275         * Use the known-good 32-bit argv[] (which needs the type cast to
276         * satisfy the compiler), or the trusted or tested-good 64-bit argv[]
277         * as-is.
278         */
279        Argv = (char **)_Argv;
280    }
281#endif                          /* defined( OPENSSL_SYS_VMS) &&
282                                 * (__INITIAL_POINTER_SIZE == 64) */
283
284    arg.data = NULL;
285    arg.count = 0;
286
287    if (bio_err == NULL)
288        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
289            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
290
291    if (getenv("OPENSSL_DEBUG_MEMORY") != NULL) { /* if not defined, use
292                                                   * compiled-in library
293                                                   * defaults */
294        if (!(0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))) {
295            CRYPTO_malloc_debug_init();
296            CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
297        } else {
298            /* OPENSSL_DEBUG_MEMORY=off */
299            CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
300        }
301    }
302    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
303
304#if 0
305    if (getenv("OPENSSL_DEBUG_LOCKING") != NULL)
306#endif
307    {
308        CRYPTO_set_locking_callback(lock_dbg_cb);
309    }
310
311    if (getenv("OPENSSL_FIPS")) {
312#ifdef OPENSSL_FIPS
313        if (!FIPS_mode_set(1)) {
314            ERR_load_crypto_strings();
315            ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE));
316            EXIT(1);
317        }
318#else
319        fprintf(stderr, "FIPS mode not supported.\n");
320        EXIT(1);
321#endif
322    }
323
324    apps_startup();
325
326    /* Lets load up our environment a little */
327    p = getenv("OPENSSL_CONF");
328    if (p == NULL)
329        p = getenv("SSLEAY_CONF");
330    if (p == NULL)
331        p = to_free = make_config_name();
332
333    default_config_file = p;
334
335    config = NCONF_new(NULL);
336    i = NCONF_load(config, p, &errline);
337    if (i == 0) {
338        if (ERR_GET_REASON(ERR_peek_last_error())
339            == CONF_R_NO_SUCH_FILE) {
340            BIO_printf(bio_err, "WARNING: can't open config file: %s\n", p);
341            ERR_clear_error();
342            NCONF_free(config);
343            config = NULL;
344        } else {
345            ERR_print_errors(bio_err);
346            NCONF_free(config);
347            exit(1);
348        }
349    }
350
351    prog = prog_init();
352
353    /* first check the program name */
354    program_name(Argv[0], pname, sizeof(pname));
355
356    f.name = pname;
357    fp = lh_FUNCTION_retrieve(prog, &f);
358    if (fp != NULL) {
359        Argv[0] = pname;
360        ret = fp->func(Argc, Argv);
361        goto end;
362    }
363
364    /*
365     * ok, now check that there are not arguments, if there are, run with
366     * them, shifting the ssleay off the front
367     */
368    if (Argc != 1) {
369        Argc--;
370        Argv++;
371        ret = do_cmd(prog, Argc, Argv);
372        if (ret < 0)
373            ret = 0;
374        goto end;
375    }
376
377    /* ok, lets enter the old 'OpenSSL>' mode */
378
379    for (;;) {
380        ret = 0;
381        p = buf;
382        n = sizeof(buf);
383        i = 0;
384        for (;;) {
385            p[0] = '\0';
386            if (i++)
387                prompt = ">";
388            else
389                prompt = "OpenSSL> ";
390            fputs(prompt, stdout);
391            fflush(stdout);
392            if (!fgets(p, n, stdin))
393                goto end;
394            if (p[0] == '\0')
395                goto end;
396            i = strlen(p);
397            if (i <= 1)
398                break;
399            if (p[i - 2] != '\\')
400                break;
401            i -= 2;
402            p += i;
403            n -= i;
404        }
405        if (!chopup_args(&arg, buf, &argc, &argv))
406            break;
407
408        ret = do_cmd(prog, argc, argv);
409        if (ret < 0) {
410            ret = 0;
411            goto end;
412        }
413        if (ret != 0)
414            BIO_printf(bio_err, "error in %s\n", argv[0]);
415        (void)BIO_flush(bio_err);
416    }
417    BIO_printf(bio_err, "bad exit\n");
418    ret = 1;
419 end:
420    if (to_free)
421        OPENSSL_free(to_free);
422    if (config != NULL) {
423        NCONF_free(config);
424        config = NULL;
425    }
426    if (prog != NULL)
427        lh_FUNCTION_free(prog);
428    if (arg.data != NULL)
429        OPENSSL_free(arg.data);
430
431#if defined( OPENSSL_SYS_VMS) && (__INITIAL_POINTER_SIZE == 64)
432    /* Free any duplicate Argv[] storage. */
433    if (free_Argv) {
434        OPENSSL_free(Argv);
435    }
436#endif
437    apps_shutdown();
438    CRYPTO_mem_leaks(bio_err);
439    if (bio_err != NULL) {
440        BIO_free(bio_err);
441        bio_err = NULL;
442    }
443
444    OPENSSL_EXIT(ret);
445}
446
447#define LIST_STANDARD_COMMANDS "list-standard-commands"
448#define LIST_MESSAGE_DIGEST_COMMANDS "list-message-digest-commands"
449#define LIST_MESSAGE_DIGEST_ALGORITHMS "list-message-digest-algorithms"
450#define LIST_CIPHER_COMMANDS "list-cipher-commands"
451#define LIST_CIPHER_ALGORITHMS "list-cipher-algorithms"
452#define LIST_PUBLIC_KEY_ALGORITHMS "list-public-key-algorithms"
453
454static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[])
455{
456    FUNCTION f, *fp;
457    int i, ret = 1, tp, nl;
458
459    if ((argc <= 0) || (argv[0] == NULL)) {
460        ret = 0;
461        goto end;
462    }
463    f.name = argv[0];
464    fp = lh_FUNCTION_retrieve(prog, &f);
465    if (fp == NULL) {
466        if (EVP_get_digestbyname(argv[0])) {
467            f.type = FUNC_TYPE_MD;
468            f.func = dgst_main;
469            fp = &f;
470        } else if (EVP_get_cipherbyname(argv[0])) {
471            f.type = FUNC_TYPE_CIPHER;
472            f.func = enc_main;
473            fp = &f;
474        }
475    }
476    if (fp != NULL) {
477        ret = fp->func(argc, argv);
478    } else if ((strncmp(argv[0], "no-", 3)) == 0) {
479        BIO *bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE);
480#ifdef OPENSSL_SYS_VMS
481        {
482            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
483            bio_stdout = BIO_push(tmpbio, bio_stdout);
484        }
485#endif
486        f.name = argv[0] + 3;
487        ret = (lh_FUNCTION_retrieve(prog, &f) != NULL);
488        if (!ret)
489            BIO_printf(bio_stdout, "%s\n", argv[0]);
490        else
491            BIO_printf(bio_stdout, "%s\n", argv[0] + 3);
492        BIO_free_all(bio_stdout);
493        goto end;
494    } else if ((strcmp(argv[0], "quit") == 0) ||
495               (strcmp(argv[0], "q") == 0) ||
496               (strcmp(argv[0], "exit") == 0) ||
497               (strcmp(argv[0], "bye") == 0)) {
498        ret = -1;
499        goto end;
500    } else if ((strcmp(argv[0], LIST_STANDARD_COMMANDS) == 0) ||
501               (strcmp(argv[0], LIST_MESSAGE_DIGEST_COMMANDS) == 0) ||
502               (strcmp(argv[0], LIST_MESSAGE_DIGEST_ALGORITHMS) == 0) ||
503               (strcmp(argv[0], LIST_CIPHER_COMMANDS) == 0) ||
504               (strcmp(argv[0], LIST_CIPHER_ALGORITHMS) == 0) ||
505               (strcmp(argv[0], LIST_PUBLIC_KEY_ALGORITHMS) == 0)) {
506        int list_type;
507        BIO *bio_stdout;
508
509        if (strcmp(argv[0], LIST_STANDARD_COMMANDS) == 0)
510            list_type = FUNC_TYPE_GENERAL;
511        else if (strcmp(argv[0], LIST_MESSAGE_DIGEST_COMMANDS) == 0)
512            list_type = FUNC_TYPE_MD;
513        else if (strcmp(argv[0], LIST_MESSAGE_DIGEST_ALGORITHMS) == 0)
514            list_type = FUNC_TYPE_MD_ALG;
515        else if (strcmp(argv[0], LIST_PUBLIC_KEY_ALGORITHMS) == 0)
516            list_type = FUNC_TYPE_PKEY;
517        else if (strcmp(argv[0], LIST_CIPHER_ALGORITHMS) == 0)
518            list_type = FUNC_TYPE_CIPHER_ALG;
519        else                    /* strcmp(argv[0],LIST_CIPHER_COMMANDS) == 0 */
520            list_type = FUNC_TYPE_CIPHER;
521        bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE);
522#ifdef OPENSSL_SYS_VMS
523        {
524            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
525            bio_stdout = BIO_push(tmpbio, bio_stdout);
526        }
527#endif
528
529        if (!load_config(bio_err, NULL))
530            goto end;
531
532        if (list_type == FUNC_TYPE_PKEY)
533            list_pkey(bio_stdout);
534        if (list_type == FUNC_TYPE_MD_ALG)
535            list_md(bio_stdout);
536        if (list_type == FUNC_TYPE_CIPHER_ALG)
537            list_cipher(bio_stdout);
538        else {
539            for (fp = functions; fp->name != NULL; fp++)
540                if (fp->type == list_type)
541                    BIO_printf(bio_stdout, "%s\n", fp->name);
542        }
543        BIO_free_all(bio_stdout);
544        ret = 0;
545        goto end;
546    } else {
547        BIO_printf(bio_err, "openssl:Error: '%s' is an invalid command.\n",
548                   argv[0]);
549        BIO_printf(bio_err, "\nStandard commands");
550        i = 0;
551        tp = 0;
552        for (fp = functions; fp->name != NULL; fp++) {
553            nl = 0;
554#ifdef OPENSSL_NO_CAMELLIA
555            if (((i++) % 5) == 0)
556#else
557            if (((i++) % 4) == 0)
558#endif
559            {
560                BIO_printf(bio_err, "\n");
561                nl = 1;
562            }
563            if (fp->type != tp) {
564                tp = fp->type;
565                if (!nl)
566                    BIO_printf(bio_err, "\n");
567                if (tp == FUNC_TYPE_MD) {
568                    i = 1;
569                    BIO_printf(bio_err,
570                               "\nMessage Digest commands (see the `dgst' command for more details)\n");
571                } else if (tp == FUNC_TYPE_CIPHER) {
572                    i = 1;
573                    BIO_printf(bio_err,
574                               "\nCipher commands (see the `enc' command for more details)\n");
575                }
576            }
577#ifdef OPENSSL_NO_CAMELLIA
578            BIO_printf(bio_err, "%-15s", fp->name);
579#else
580            BIO_printf(bio_err, "%-18s", fp->name);
581#endif
582        }
583        BIO_printf(bio_err, "\n\n");
584        ret = 0;
585    }
586 end:
587    return (ret);
588}
589
590static int SortFnByName(const void *_f1, const void *_f2)
591{
592    const FUNCTION *f1 = _f1;
593    const FUNCTION *f2 = _f2;
594
595    if (f1->type != f2->type)
596        return f1->type - f2->type;
597    return strcmp(f1->name, f2->name);
598}
599
600static void list_pkey(BIO *out)
601{
602    int i;
603    for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
604        const EVP_PKEY_ASN1_METHOD *ameth;
605        int pkey_id, pkey_base_id, pkey_flags;
606        const char *pinfo, *pem_str;
607        ameth = EVP_PKEY_asn1_get0(i);
608        EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags,
609                                &pinfo, &pem_str, ameth);
610        if (pkey_flags & ASN1_PKEY_ALIAS) {
611            BIO_printf(out, "Name: %s\n", OBJ_nid2ln(pkey_id));
612            BIO_printf(out, "\tType: Alias to %s\n",
613                       OBJ_nid2ln(pkey_base_id));
614        } else {
615            BIO_printf(out, "Name: %s\n", pinfo);
616            BIO_printf(out, "\tType: %s Algorithm\n",
617                       pkey_flags & ASN1_PKEY_DYNAMIC ?
618                       "External" : "Builtin");
619            BIO_printf(out, "\tOID: %s\n", OBJ_nid2ln(pkey_id));
620            if (pem_str == NULL)
621                pem_str = "(none)";
622            BIO_printf(out, "\tPEM string: %s\n", pem_str);
623        }
624
625    }
626}
627
628static void list_cipher_fn(const EVP_CIPHER *c,
629                           const char *from, const char *to, void *arg)
630{
631    if (c)
632        BIO_printf(arg, "%s\n", EVP_CIPHER_name(c));
633    else {
634        if (!from)
635            from = "<undefined>";
636        if (!to)
637            to = "<undefined>";
638        BIO_printf(arg, "%s => %s\n", from, to);
639    }
640}
641
642static void list_cipher(BIO *out)
643{
644    EVP_CIPHER_do_all_sorted(list_cipher_fn, out);
645}
646
647static void list_md_fn(const EVP_MD *m,
648                       const char *from, const char *to, void *arg)
649{
650    if (m)
651        BIO_printf(arg, "%s\n", EVP_MD_name(m));
652    else {
653        if (!from)
654            from = "<undefined>";
655        if (!to)
656            to = "<undefined>";
657        BIO_printf(arg, "%s => %s\n", from, to);
658    }
659}
660
661static void list_md(BIO *out)
662{
663    EVP_MD_do_all_sorted(list_md_fn, out);
664}
665
666static int MS_CALLBACK function_cmp(const FUNCTION * a, const FUNCTION * b)
667{
668    return strncmp(a->name, b->name, 8);
669}
670
671static IMPLEMENT_LHASH_COMP_FN(function, FUNCTION)
672
673static unsigned long MS_CALLBACK function_hash(const FUNCTION * a)
674{
675    return lh_strhash(a->name);
676}
677
678static IMPLEMENT_LHASH_HASH_FN(function, FUNCTION)
679
680static LHASH_OF(FUNCTION) *prog_init(void)
681{
682    LHASH_OF(FUNCTION) *ret;
683    FUNCTION *f;
684    size_t i;
685
686    /* Purely so it looks nice when the user hits ? */
687    for (i = 0, f = functions; f->name != NULL; ++f, ++i) ;
688    qsort(functions, i, sizeof(*functions), SortFnByName);
689
690    if ((ret = lh_FUNCTION_new()) == NULL)
691        return (NULL);
692
693    for (f = functions; f->name != NULL; f++)
694        (void)lh_FUNCTION_insert(ret, f);
695    return (ret);
696}
697