[BACK]Return to openssl.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / openssl

Annotation of src/usr.bin/openssl/openssl.c, Revision 1.1

1.1     ! jsing       1: /* $OpenBSD: openssl.c,v 1.43 2014/07/18 18:01:26 deraadt Exp $ */
        !             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 <err.h>
        !           113: #include <signal.h>
        !           114: #include <stdio.h>
        !           115: #include <string.h>
        !           116: #include <stdlib.h>
        !           117:
        !           118: #include "apps.h"
        !           119:
        !           120: #include <openssl/bio.h>
        !           121: #include <openssl/conf.h>
        !           122: #include <openssl/crypto.h>
        !           123: #include <openssl/err.h>
        !           124: #include <openssl/lhash.h>
        !           125: #include <openssl/pem.h>
        !           126: #include <openssl/rand.h>
        !           127: #include <openssl/ssl.h>
        !           128: #include <openssl/x509.h>
        !           129:
        !           130: #ifndef OPENSSL_NO_ENGINE
        !           131: #include <openssl/engine.h>
        !           132: #endif
        !           133:
        !           134: #include "progs.h"
        !           135: #include "s_apps.h"
        !           136:
        !           137: static void openssl_startup(void);
        !           138: static void openssl_shutdown(void);
        !           139:
        !           140: /* The LHASH callbacks ("hash" & "cmp") have been replaced by functions with the
        !           141:  * base prototypes (we cast each variable inside the function to the required
        !           142:  * type of "FUNCTION*"). This removes the necessity for macro-generated wrapper
        !           143:  * functions. */
        !           144:
        !           145: static LHASH_OF(FUNCTION) *prog_init(void);
        !           146: static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]);
        !           147: static void list_pkey(BIO * out);
        !           148: static void list_cipher(BIO * out);
        !           149: static void list_md(BIO * out);
        !           150: char *default_config_file = NULL;
        !           151:
        !           152: CONF *config = NULL;
        !           153: BIO *bio_err = NULL;
        !           154:
        !           155: static void
        !           156: lock_dbg_cb(int mode, int type, const char *file, int line)
        !           157: {
        !           158:        static int modes[CRYPTO_NUM_LOCKS];     /* = {0, 0, ... } */
        !           159:        const char *errstr = NULL;
        !           160:        int rw;
        !           161:
        !           162:        rw = mode & (CRYPTO_READ | CRYPTO_WRITE);
        !           163:        if (!((rw == CRYPTO_READ) || (rw == CRYPTO_WRITE))) {
        !           164:                errstr = "invalid mode";
        !           165:                goto err;
        !           166:        }
        !           167:        if (type < 0 || type >= CRYPTO_NUM_LOCKS) {
        !           168:                errstr = "type out of bounds";
        !           169:                goto err;
        !           170:        }
        !           171:        if (mode & CRYPTO_LOCK) {
        !           172:                if (modes[type]) {
        !           173:                        errstr = "already locked";
        !           174:                        /*
        !           175:                         * must not happen in a single-threaded program
        !           176:                         * (would deadlock)
        !           177:                         */
        !           178:                        goto err;
        !           179:                }
        !           180:                modes[type] = rw;
        !           181:        } else if (mode & CRYPTO_UNLOCK) {
        !           182:                if (!modes[type]) {
        !           183:                        errstr = "not locked";
        !           184:                        goto err;
        !           185:                }
        !           186:                if (modes[type] != rw) {
        !           187:                        errstr = (rw == CRYPTO_READ) ?
        !           188:                            "CRYPTO_r_unlock on write lock" :
        !           189:                            "CRYPTO_w_unlock on read lock";
        !           190:                }
        !           191:                modes[type] = 0;
        !           192:        } else {
        !           193:                errstr = "invalid mode";
        !           194:                goto err;
        !           195:        }
        !           196:
        !           197: err:
        !           198:        if (errstr) {
        !           199:                /* we cannot use bio_err here */
        !           200:                fprintf(stderr, "openssl (lock_dbg_cb): %s (mode=%d, type=%d) at %s:%d\n",
        !           201:                    errstr, mode, type, file, line);
        !           202:        }
        !           203: }
        !           204:
        !           205: static void
        !           206: openssl_startup(void)
        !           207: {
        !           208:        signal(SIGPIPE, SIG_IGN);
        !           209:
        !           210:        CRYPTO_malloc_init();
        !           211:        OpenSSL_add_all_algorithms();
        !           212:        SSL_library_init();
        !           213:        SSL_load_error_strings();
        !           214:
        !           215: #ifndef OPENSSL_NO_ENGINE
        !           216:        ENGINE_load_builtin_engines();
        !           217: #endif
        !           218:
        !           219:        setup_ui_method();
        !           220: }
        !           221:
        !           222: static void
        !           223: openssl_shutdown(void)
        !           224: {
        !           225:        CONF_modules_unload(1);
        !           226:        destroy_ui_method();
        !           227:        OBJ_cleanup();
        !           228:        EVP_cleanup();
        !           229:
        !           230: #ifndef OPENSSL_NO_ENGINE
        !           231:        ENGINE_cleanup();
        !           232: #endif
        !           233:
        !           234:        CRYPTO_cleanup_all_ex_data();
        !           235:        ERR_remove_thread_state(NULL);
        !           236:        RAND_cleanup();
        !           237:        ERR_free_strings();
        !           238: }
        !           239:
        !           240: int
        !           241: main(int argc, char **argv)
        !           242: {
        !           243:        ARGS arg;
        !           244: #define PROG_NAME_SIZE 39
        !           245:        char pname[PROG_NAME_SIZE + 1];
        !           246:        FUNCTION f, *fp;
        !           247:        const char *prompt;
        !           248:        char buf[1024];
        !           249:        char *to_free = NULL;
        !           250:        int n, i, ret = 0;
        !           251:        char *p;
        !           252:        LHASH_OF(FUNCTION) * prog = NULL;
        !           253:        long errline;
        !           254:
        !           255:        arg.data = NULL;
        !           256:        arg.count = 0;
        !           257:
        !           258:        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
        !           259:        if (bio_err == NULL) {
        !           260:                fprintf(stderr, "openssl: failed to initialise bio_err\n");
        !           261:                exit(1);
        !           262:        }
        !           263:
        !           264:        CRYPTO_set_locking_callback(lock_dbg_cb);
        !           265:
        !           266:        openssl_startup();
        !           267:
        !           268:        /* Lets load up our environment a little */
        !           269:        p = getenv("OPENSSL_CONF");
        !           270:        if (p == NULL)
        !           271:                p = getenv("SSLEAY_CONF");
        !           272:        if (p == NULL) {
        !           273:                p = to_free = make_config_name();
        !           274:                if (p == NULL) {
        !           275:                        BIO_printf(bio_err, "error making config file name\n");
        !           276:                        goto end;
        !           277:                }
        !           278:        }
        !           279:
        !           280:        default_config_file = p;
        !           281:
        !           282:        config = NCONF_new(NULL);
        !           283:        i = NCONF_load(config, p, &errline);
        !           284:        if (i == 0) {
        !           285:                if (ERR_GET_REASON(ERR_peek_last_error()) ==
        !           286:                    CONF_R_NO_SUCH_FILE) {
        !           287:                        BIO_printf(bio_err,
        !           288:                            "WARNING: can't open config file: %s\n", p);
        !           289:                        ERR_clear_error();
        !           290:                        NCONF_free(config);
        !           291:                        config = NULL;
        !           292:                } else {
        !           293:                        ERR_print_errors(bio_err);
        !           294:                        NCONF_free(config);
        !           295:                        exit(1);
        !           296:                }
        !           297:        }
        !           298:
        !           299:        if (!load_config(bio_err, NULL)) {
        !           300:                BIO_printf(bio_err, "failed to load configuration\n");
        !           301:                goto end;
        !           302:        }
        !           303:
        !           304:        prog = prog_init();
        !           305:
        !           306:        /* first check the program name */
        !           307:        program_name(argv[0], pname, sizeof pname);
        !           308:
        !           309:        f.name = pname;
        !           310:        fp = lh_FUNCTION_retrieve(prog, &f);
        !           311:        if (fp != NULL) {
        !           312:                argv[0] = pname;
        !           313:                ret = fp->func(argc, argv);
        !           314:                goto end;
        !           315:        }
        !           316:        /*
        !           317:         * ok, now check that there are not arguments, if there are, run with
        !           318:         * them, shifting the ssleay off the front
        !           319:         */
        !           320:        if (argc != 1) {
        !           321:                argc--;
        !           322:                argv++;
        !           323:                ret = do_cmd(prog, argc, argv);
        !           324:                if (ret < 0)
        !           325:                        ret = 0;
        !           326:                goto end;
        !           327:        }
        !           328:        /* ok, lets enter the old 'OpenSSL>' mode */
        !           329:
        !           330:        for (;;) {
        !           331:                ret = 0;
        !           332:                p = buf;
        !           333:                n = sizeof buf;
        !           334:                i = 0;
        !           335:                for (;;) {
        !           336:                        p[0] = '\0';
        !           337:                        if (i++)
        !           338:                                prompt = ">";
        !           339:                        else
        !           340:                                prompt = "OpenSSL> ";
        !           341:                        fputs(prompt, stdout);
        !           342:                        fflush(stdout);
        !           343:                        if (!fgets(p, n, stdin))
        !           344:                                goto end;
        !           345:                        if (p[0] == '\0')
        !           346:                                goto end;
        !           347:                        i = strlen(p);
        !           348:                        if (i <= 1)
        !           349:                                break;
        !           350:                        if (p[i - 2] != '\\')
        !           351:                                break;
        !           352:                        i -= 2;
        !           353:                        p += i;
        !           354:                        n -= i;
        !           355:                }
        !           356:                if (!chopup_args(&arg, buf, &argc, &argv))
        !           357:                        break;
        !           358:
        !           359:                ret = do_cmd(prog, argc, argv);
        !           360:                if (ret < 0) {
        !           361:                        ret = 0;
        !           362:                        goto end;
        !           363:                }
        !           364:                if (ret != 0)
        !           365:                        BIO_printf(bio_err, "error in %s\n", argv[0]);
        !           366:                (void) BIO_flush(bio_err);
        !           367:        }
        !           368:        BIO_printf(bio_err, "bad exit\n");
        !           369:        ret = 1;
        !           370:
        !           371: end:
        !           372:        free(to_free);
        !           373:
        !           374:        if (config != NULL) {
        !           375:                NCONF_free(config);
        !           376:                config = NULL;
        !           377:        }
        !           378:        if (prog != NULL)
        !           379:                lh_FUNCTION_free(prog);
        !           380:        free(arg.data);
        !           381:
        !           382:        openssl_shutdown();
        !           383:
        !           384:        if (bio_err != NULL) {
        !           385:                BIO_free(bio_err);
        !           386:                bio_err = NULL;
        !           387:        }
        !           388:        return (ret);
        !           389: }
        !           390:
        !           391: #define LIST_STANDARD_COMMANDS "list-standard-commands"
        !           392: #define LIST_MESSAGE_DIGEST_COMMANDS "list-message-digest-commands"
        !           393: #define LIST_MESSAGE_DIGEST_ALGORITHMS "list-message-digest-algorithms"
        !           394: #define LIST_CIPHER_COMMANDS "list-cipher-commands"
        !           395: #define LIST_CIPHER_ALGORITHMS "list-cipher-algorithms"
        !           396: #define LIST_PUBLIC_KEY_ALGORITHMS "list-public-key-algorithms"
        !           397:
        !           398:
        !           399: static int
        !           400: do_cmd(LHASH_OF(FUNCTION) * prog, int argc, char *argv[])
        !           401: {
        !           402:        FUNCTION f, *fp;
        !           403:        int i, ret = 1, tp, nl;
        !           404:
        !           405:        if ((argc <= 0) || (argv[0] == NULL)) {
        !           406:                ret = 0;
        !           407:                goto end;
        !           408:        }
        !           409:        f.name = argv[0];
        !           410:        fp = lh_FUNCTION_retrieve(prog, &f);
        !           411:        if (fp == NULL) {
        !           412:                if (EVP_get_digestbyname(argv[0])) {
        !           413:                        f.type = FUNC_TYPE_MD;
        !           414:                        f.func = dgst_main;
        !           415:                        fp = &f;
        !           416:                } else if (EVP_get_cipherbyname(argv[0])) {
        !           417:                        f.type = FUNC_TYPE_CIPHER;
        !           418:                        f.func = enc_main;
        !           419:                        fp = &f;
        !           420:                }
        !           421:        }
        !           422:        if (fp != NULL) {
        !           423:                ret = fp->func(argc, argv);
        !           424:        } else if ((strncmp(argv[0], "no-", 3)) == 0) {
        !           425:                BIO *bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE);
        !           426:                f.name = argv[0] + 3;
        !           427:                ret = (lh_FUNCTION_retrieve(prog, &f) != NULL);
        !           428:                if (!ret)
        !           429:                        BIO_printf(bio_stdout, "%s\n", argv[0]);
        !           430:                else
        !           431:                        BIO_printf(bio_stdout, "%s\n", argv[0] + 3);
        !           432:                BIO_free_all(bio_stdout);
        !           433:                goto end;
        !           434:        } else if ((strcmp(argv[0], "quit") == 0) ||
        !           435:            (strcmp(argv[0], "q") == 0) ||
        !           436:            (strcmp(argv[0], "exit") == 0) ||
        !           437:            (strcmp(argv[0], "bye") == 0)) {
        !           438:                ret = -1;
        !           439:                goto end;
        !           440:        } else if ((strcmp(argv[0], LIST_STANDARD_COMMANDS) == 0) ||
        !           441:            (strcmp(argv[0], LIST_MESSAGE_DIGEST_COMMANDS) == 0) ||
        !           442:            (strcmp(argv[0], LIST_MESSAGE_DIGEST_ALGORITHMS) == 0) ||
        !           443:            (strcmp(argv[0], LIST_CIPHER_COMMANDS) == 0) ||
        !           444:            (strcmp(argv[0], LIST_CIPHER_ALGORITHMS) == 0) ||
        !           445:            (strcmp(argv[0], LIST_PUBLIC_KEY_ALGORITHMS) == 0)) {
        !           446:                int list_type;
        !           447:                BIO *bio_stdout;
        !           448:
        !           449:                if (strcmp(argv[0], LIST_STANDARD_COMMANDS) == 0)
        !           450:                        list_type = FUNC_TYPE_GENERAL;
        !           451:                else if (strcmp(argv[0], LIST_MESSAGE_DIGEST_COMMANDS) == 0)
        !           452:                        list_type = FUNC_TYPE_MD;
        !           453:                else if (strcmp(argv[0], LIST_MESSAGE_DIGEST_ALGORITHMS) == 0)
        !           454:                        list_type = FUNC_TYPE_MD_ALG;
        !           455:                else if (strcmp(argv[0], LIST_PUBLIC_KEY_ALGORITHMS) == 0)
        !           456:                        list_type = FUNC_TYPE_PKEY;
        !           457:                else if (strcmp(argv[0], LIST_CIPHER_ALGORITHMS) == 0)
        !           458:                        list_type = FUNC_TYPE_CIPHER_ALG;
        !           459:                else            /* strcmp(argv[0],LIST_CIPHER_COMMANDS) == 0 */
        !           460:                        list_type = FUNC_TYPE_CIPHER;
        !           461:                bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE);
        !           462:
        !           463:                if (list_type == FUNC_TYPE_PKEY)
        !           464:                        list_pkey(bio_stdout);
        !           465:                if (list_type == FUNC_TYPE_MD_ALG)
        !           466:                        list_md(bio_stdout);
        !           467:                if (list_type == FUNC_TYPE_CIPHER_ALG)
        !           468:                        list_cipher(bio_stdout);
        !           469:                else {
        !           470:                        for (fp = functions; fp->name != NULL; fp++)
        !           471:                                if (fp->type == list_type)
        !           472:                                        BIO_printf(bio_stdout, "%s\n",
        !           473:                                            fp->name);
        !           474:                }
        !           475:                BIO_free_all(bio_stdout);
        !           476:                ret = 0;
        !           477:                goto end;
        !           478:        } else {
        !           479:                BIO_printf(bio_err,
        !           480:                    "openssl:Error: '%s' is an invalid command.\n",
        !           481:                    argv[0]);
        !           482:                BIO_printf(bio_err, "\nStandard commands");
        !           483:                i = 0;
        !           484:                tp = 0;
        !           485:                for (fp = functions; fp->name != NULL; fp++) {
        !           486:                        nl = 0;
        !           487: #ifdef OPENSSL_NO_CAMELLIA
        !           488:                        if (((i++) % 5) == 0)
        !           489: #else
        !           490:                        if (((i++) % 4) == 0)
        !           491: #endif
        !           492:                        {
        !           493:                                BIO_printf(bio_err, "\n");
        !           494:                                nl = 1;
        !           495:                        }
        !           496:                        if (fp->type != tp) {
        !           497:                                tp = fp->type;
        !           498:                                if (!nl)
        !           499:                                        BIO_printf(bio_err, "\n");
        !           500:                                if (tp == FUNC_TYPE_MD) {
        !           501:                                        i = 1;
        !           502:                                        BIO_printf(bio_err,
        !           503:                                            "\nMessage Digest commands (see the `dgst' command for more details)\n");
        !           504:                                } else if (tp == FUNC_TYPE_CIPHER) {
        !           505:                                        i = 1;
        !           506:                                        BIO_printf(bio_err, "\nCipher commands (see the `enc' command for more details)\n");
        !           507:                                }
        !           508:                        }
        !           509: #ifdef OPENSSL_NO_CAMELLIA
        !           510:                        BIO_printf(bio_err, "%-15s", fp->name);
        !           511: #else
        !           512:                        BIO_printf(bio_err, "%-18s", fp->name);
        !           513: #endif
        !           514:                }
        !           515:                BIO_printf(bio_err, "\n\n");
        !           516:                ret = 0;
        !           517:        }
        !           518: end:
        !           519:        return (ret);
        !           520: }
        !           521:
        !           522: static int
        !           523: SortFnByName(const void *_f1, const void *_f2)
        !           524: {
        !           525:        const FUNCTION *f1 = _f1;
        !           526:        const FUNCTION *f2 = _f2;
        !           527:
        !           528:        if (f1->type != f2->type)
        !           529:                return f1->type - f2->type;
        !           530:        return strcmp(f1->name, f2->name);
        !           531: }
        !           532:
        !           533: static void
        !           534: list_pkey(BIO * out)
        !           535: {
        !           536:        int i;
        !           537:
        !           538:        for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
        !           539:                const EVP_PKEY_ASN1_METHOD *ameth;
        !           540:                int pkey_id, pkey_base_id, pkey_flags;
        !           541:                const char *pinfo, *pem_str;
        !           542:                ameth = EVP_PKEY_asn1_get0(i);
        !           543:                EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags,
        !           544:                    &pinfo, &pem_str, ameth);
        !           545:                if (pkey_flags & ASN1_PKEY_ALIAS) {
        !           546:                        BIO_printf(out, "Name: %s\n",
        !           547:                            OBJ_nid2ln(pkey_id));
        !           548:                        BIO_printf(out, "\tType: Alias to %s\n",
        !           549:                            OBJ_nid2ln(pkey_base_id));
        !           550:                } else {
        !           551:                        BIO_printf(out, "Name: %s\n", pinfo);
        !           552:                        BIO_printf(out, "\tType: %s Algorithm\n",
        !           553:                            pkey_flags & ASN1_PKEY_DYNAMIC ?
        !           554:                            "External" : "Builtin");
        !           555:                        BIO_printf(out, "\tOID: %s\n", OBJ_nid2ln(pkey_id));
        !           556:                        if (pem_str == NULL)
        !           557:                                pem_str = "(none)";
        !           558:                        BIO_printf(out, "\tPEM string: %s\n", pem_str);
        !           559:                }
        !           560:
        !           561:        }
        !           562: }
        !           563:
        !           564: static void
        !           565: list_cipher_fn(const EVP_CIPHER * c, const char *from, const char *to,
        !           566:     void *arg)
        !           567: {
        !           568:        if (c)
        !           569:                BIO_printf(arg, "%s\n", EVP_CIPHER_name(c));
        !           570:        else {
        !           571:                if (!from)
        !           572:                        from = "<undefined>";
        !           573:                if (!to)
        !           574:                        to = "<undefined>";
        !           575:                BIO_printf(arg, "%s => %s\n", from, to);
        !           576:        }
        !           577: }
        !           578:
        !           579: static void
        !           580: list_cipher(BIO * out)
        !           581: {
        !           582:        EVP_CIPHER_do_all_sorted(list_cipher_fn, out);
        !           583: }
        !           584:
        !           585: static void
        !           586: list_md_fn(const EVP_MD * m, const char *from, const char *to, void *arg)
        !           587: {
        !           588:        if (m)
        !           589:                BIO_printf(arg, "%s\n", EVP_MD_name(m));
        !           590:        else {
        !           591:                if (!from)
        !           592:                        from = "<undefined>";
        !           593:                if (!to)
        !           594:                        to = "<undefined>";
        !           595:                BIO_printf(arg, "%s => %s\n", from, to);
        !           596:        }
        !           597: }
        !           598:
        !           599: static void
        !           600: list_md(BIO * out)
        !           601: {
        !           602:        EVP_MD_do_all_sorted(list_md_fn, out);
        !           603: }
        !           604:
        !           605: static int
        !           606: function_cmp(const FUNCTION * a, const FUNCTION * b)
        !           607: {
        !           608:        return strncmp(a->name, b->name, 8);
        !           609: }
        !           610:
        !           611: static IMPLEMENT_LHASH_COMP_FN(function, FUNCTION)
        !           612:
        !           613: static unsigned long
        !           614: function_hash(const FUNCTION * a)
        !           615: {
        !           616:        return lh_strhash(a->name);
        !           617: }
        !           618:
        !           619: static IMPLEMENT_LHASH_HASH_FN(function, FUNCTION)
        !           620:
        !           621: static LHASH_OF(FUNCTION) *
        !           622: prog_init(void)
        !           623: {
        !           624:        LHASH_OF(FUNCTION) * ret;
        !           625:        FUNCTION *f;
        !           626:        size_t i;
        !           627:
        !           628:        /* Purely so it looks nice when the user hits ? */
        !           629:        for (i = 0, f = functions; f->name != NULL; ++f, ++i)
        !           630:                ;
        !           631:        qsort(functions, i, sizeof *functions, SortFnByName);
        !           632:
        !           633:        if ((ret = lh_FUNCTION_new()) == NULL)
        !           634:                return (NULL);
        !           635:
        !           636:        for (f = functions; f->name != NULL; f++)
        !           637:                (void) lh_FUNCTION_insert(ret, f);
        !           638:        return (ret);
        !           639: }