Home | History | Annotate | Line # | Download | only in apps
      1 /*
      2  * Copyright 2006-2026 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #include "apps.h"
     11 #include "progs.h"
     12 #include <string.h>
     13 #include <openssl/err.h>
     14 #include <openssl/pem.h>
     15 #include <openssl/evp.h>
     16 #include <sys/stat.h>
     17 
     18 #define KEY_NONE 0
     19 #define KEY_PRIVKEY 1
     20 #define KEY_PUBKEY 2
     21 #define KEY_CERT 3
     22 
     23 static EVP_PKEY *get_pkey(const char *kdfalg,
     24     const char *keyfile, int keyform, int key_type,
     25     char *passinarg, int pkey_op, ENGINE *e);
     26 static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
     27     int pkey_op, ENGINE *e,
     28     const int engine_impl, int rawin,
     29     EVP_PKEY *pkey /* ownership is passed to ctx */,
     30     EVP_MD_CTX *mctx, const char *digestname,
     31     const char *kemop, OSSL_LIB_CTX *libctx, const char *propq);
     32 
     33 static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
     34     ENGINE *e);
     35 
     36 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
     37     unsigned char *out, size_t *poutlen,
     38     const unsigned char *in, size_t inlen,
     39     unsigned char *secret, size_t *psecretlen);
     40 
     41 static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
     42     EVP_PKEY *pkey, BIO *in,
     43     int filesize, unsigned char *sig, size_t siglen,
     44     unsigned char **out, size_t *poutlen);
     45 
     46 static int only_nomd(EVP_PKEY *pkey)
     47 {
     48 #define MADE_UP_MAX_MD_NAME_LEN 100
     49     char defname[MADE_UP_MAX_MD_NAME_LEN];
     50     int deftype;
     51 
     52     deftype = EVP_PKEY_get_default_digest_name(pkey, defname, sizeof(defname));
     53     return deftype == 2 /* Mandatory */
     54         && strcmp(defname, "UNDEF") == 0;
     55 }
     56 
     57 typedef enum OPTION_choice {
     58     OPT_COMMON,
     59     OPT_ENGINE,
     60     OPT_ENGINE_IMPL,
     61     OPT_IN,
     62     OPT_OUT,
     63     OPT_PUBIN,
     64     OPT_CERTIN,
     65     OPT_ASN1PARSE,
     66     OPT_HEXDUMP,
     67     OPT_SIGN,
     68     OPT_VERIFY,
     69     OPT_VERIFYRECOVER,
     70     OPT_REV,
     71     OPT_ENCRYPT,
     72     OPT_DECRYPT,
     73     OPT_DERIVE,
     74     OPT_SIGFILE,
     75     OPT_INKEY,
     76     OPT_PEERKEY,
     77     OPT_PASSIN,
     78     OPT_PEERFORM,
     79     OPT_KEYFORM,
     80     OPT_PKEYOPT,
     81     OPT_PKEYOPT_PASSIN,
     82     OPT_KDF,
     83     OPT_KDFLEN,
     84     OPT_R_ENUM,
     85     OPT_PROV_ENUM,
     86     OPT_DECAP,
     87     OPT_ENCAP,
     88     OPT_SECOUT,
     89     OPT_KEMOP,
     90     OPT_CONFIG,
     91     OPT_RAWIN,
     92     OPT_DIGEST
     93 } OPTION_CHOICE;
     94 
     95 const OPTIONS pkeyutl_options[] = {
     96     OPT_SECTION("General"),
     97     { "help", OPT_HELP, '-', "Display this summary" },
     98 #ifndef OPENSSL_NO_ENGINE
     99     { "engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device" },
    100     { "engine_impl", OPT_ENGINE_IMPL, '-',
    101         "Also use engine given by -engine for crypto operations" },
    102 #endif
    103     { "sign", OPT_SIGN, '-', "Sign input data with private key" },
    104     { "verify", OPT_VERIFY, '-', "Verify with public key" },
    105     { "encrypt", OPT_ENCRYPT, '-', "Encrypt input data with public key" },
    106     { "decrypt", OPT_DECRYPT, '-', "Decrypt input data with private key" },
    107     { "derive", OPT_DERIVE, '-', "Derive shared secret from own and peer (EC)DH keys" },
    108     { "decap", OPT_DECAP, '-', "Decapsulate shared secret" },
    109     { "encap", OPT_ENCAP, '-', "Encapsulate shared secret" },
    110     OPT_CONFIG_OPTION,
    111 
    112     OPT_SECTION("Input"),
    113     { "in", OPT_IN, '<', "Input file - default stdin" },
    114     { "inkey", OPT_INKEY, 's', "Input key, by default private key" },
    115     { "pubin", OPT_PUBIN, '-', "Input key is a public key" },
    116     { "passin", OPT_PASSIN, 's', "Input file pass phrase source" },
    117     { "peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation" },
    118     { "peerform", OPT_PEERFORM, 'E', "Peer key format (DER/PEM/P12/ENGINE)" },
    119     { "certin", OPT_CERTIN, '-', "Input is a cert with a public key" },
    120     { "rev", OPT_REV, '-', "Reverse the order of the input buffer" },
    121     { "sigfile", OPT_SIGFILE, '<', "Signature file (verify operation only)" },
    122     { "keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)" },
    123 
    124     OPT_SECTION("Output"),
    125     { "out", OPT_OUT, '>', "Output file - default stdout" },
    126     { "secret", OPT_SECOUT, '>', "File to store secret on encapsulation" },
    127     { "asn1parse", OPT_ASN1PARSE, '-',
    128         "parse the output as ASN.1 data to check its DER encoding and print errors" },
    129     { "hexdump", OPT_HEXDUMP, '-', "Hex dump output" },
    130     { "verifyrecover", OPT_VERIFYRECOVER, '-',
    131         "Verify RSA signature, recovering original signature input data" },
    132 
    133     OPT_SECTION("Signing/Derivation/Encapsulation"),
    134     { "rawin", OPT_RAWIN, '-',
    135         "Indicate that the signature/verification input data is not yet hashed" },
    136     { "digest", OPT_DIGEST, 's',
    137         "The digest algorithm to use for signing/verifying raw input data. Implies -rawin" },
    138     { "pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value" },
    139     { "pkeyopt_passin", OPT_PKEYOPT_PASSIN, 's',
    140         "Public key option that is read as a passphrase argument opt:passphrase" },
    141     { "kdf", OPT_KDF, 's', "Use KDF algorithm" },
    142     { "kdflen", OPT_KDFLEN, 'p', "KDF algorithm output length" },
    143     { "kemop", OPT_KEMOP, 's', "KEM operation specific to the key algorithm" },
    144 
    145     OPT_R_OPTIONS,
    146     OPT_PROV_OPTIONS,
    147     { NULL }
    148 };
    149 
    150 int pkeyutl_main(int argc, char **argv)
    151 {
    152     CONF *conf = NULL;
    153     BIO *in = NULL, *out = NULL, *secout = NULL;
    154     ENGINE *e = NULL;
    155     EVP_PKEY_CTX *ctx = NULL;
    156     EVP_PKEY *pkey = NULL;
    157     char *infile = NULL, *outfile = NULL, *secoutfile = NULL, *sigfile = NULL, *passinarg = NULL;
    158     char hexdump = 0, asn1parse = 0, rev = 0, *prog;
    159     unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL, *secret = NULL;
    160     OPTION_CHOICE o;
    161     size_t buf_inlen = 0, siglen = 0;
    162     int keyform = FORMAT_UNDEF, peerform = FORMAT_UNDEF;
    163     int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
    164     int engine_impl = 0;
    165     int ret = 1, rv = -1;
    166     size_t buf_outlen = 0, secretlen = 0;
    167     const char *inkey = NULL;
    168     const char *peerkey = NULL;
    169     const char *kdfalg = NULL, *digestname = NULL, *kemop = NULL;
    170     int kdflen = 0;
    171     STACK_OF(OPENSSL_STRING) *pkeyopts = NULL;
    172     STACK_OF(OPENSSL_STRING) *pkeyopts_passin = NULL;
    173     int rawin = 0;
    174     EVP_MD_CTX *mctx = NULL;
    175     EVP_MD *md = NULL;
    176     int filesize = -1;
    177     OSSL_LIB_CTX *libctx = app_get0_libctx();
    178 
    179     prog = opt_init(argc, argv, pkeyutl_options);
    180     while ((o = opt_next()) != OPT_EOF) {
    181         switch (o) {
    182         case OPT_EOF:
    183         case OPT_ERR:
    184         opthelp:
    185             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
    186             goto end;
    187         case OPT_HELP:
    188             opt_help(pkeyutl_options);
    189             ret = 0;
    190             goto end;
    191         case OPT_IN:
    192             infile = opt_arg();
    193             break;
    194         case OPT_OUT:
    195             outfile = opt_arg();
    196             break;
    197         case OPT_SECOUT:
    198             secoutfile = opt_arg();
    199             break;
    200         case OPT_SIGFILE:
    201             sigfile = opt_arg();
    202             break;
    203         case OPT_ENGINE_IMPL:
    204             engine_impl = 1;
    205             break;
    206         case OPT_INKEY:
    207             inkey = opt_arg();
    208             break;
    209         case OPT_PEERKEY:
    210             peerkey = opt_arg();
    211             break;
    212         case OPT_PASSIN:
    213             passinarg = opt_arg();
    214             break;
    215         case OPT_PEERFORM:
    216             if (!opt_format(opt_arg(), OPT_FMT_ANY, &peerform))
    217                 goto opthelp;
    218             break;
    219         case OPT_KEYFORM:
    220             if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
    221                 goto opthelp;
    222             break;
    223         case OPT_R_CASES:
    224             if (!opt_rand(o))
    225                 goto end;
    226             break;
    227         case OPT_CONFIG:
    228             conf = app_load_config_modules(opt_arg());
    229             if (conf == NULL)
    230                 goto end;
    231             break;
    232         case OPT_PROV_CASES:
    233             if (!opt_provider(o))
    234                 goto end;
    235             break;
    236         case OPT_ENGINE:
    237             e = setup_engine(opt_arg(), 0);
    238             break;
    239         case OPT_PUBIN:
    240             key_type = KEY_PUBKEY;
    241             break;
    242         case OPT_CERTIN:
    243             key_type = KEY_CERT;
    244             break;
    245         case OPT_ASN1PARSE:
    246             asn1parse = 1;
    247             break;
    248         case OPT_HEXDUMP:
    249             hexdump = 1;
    250             break;
    251         case OPT_SIGN:
    252             pkey_op = EVP_PKEY_OP_SIGN;
    253             break;
    254         case OPT_VERIFY:
    255             pkey_op = EVP_PKEY_OP_VERIFY;
    256             break;
    257         case OPT_VERIFYRECOVER:
    258             pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
    259             break;
    260         case OPT_ENCRYPT:
    261             pkey_op = EVP_PKEY_OP_ENCRYPT;
    262             break;
    263         case OPT_DECRYPT:
    264             pkey_op = EVP_PKEY_OP_DECRYPT;
    265             break;
    266         case OPT_DERIVE:
    267             pkey_op = EVP_PKEY_OP_DERIVE;
    268             break;
    269         case OPT_DECAP:
    270             pkey_op = EVP_PKEY_OP_DECAPSULATE;
    271             break;
    272         case OPT_ENCAP:
    273             key_type = KEY_PUBKEY;
    274             pkey_op = EVP_PKEY_OP_ENCAPSULATE;
    275             break;
    276         case OPT_KEMOP:
    277             kemop = opt_arg();
    278             break;
    279         case OPT_KDF:
    280             pkey_op = EVP_PKEY_OP_DERIVE;
    281             key_type = KEY_NONE;
    282             kdfalg = opt_arg();
    283             break;
    284         case OPT_KDFLEN:
    285             kdflen = atoi(opt_arg());
    286             break;
    287         case OPT_REV:
    288             rev = 1;
    289             break;
    290         case OPT_PKEYOPT:
    291             if ((pkeyopts == NULL && (pkeyopts = sk_OPENSSL_STRING_new_null()) == NULL) || sk_OPENSSL_STRING_push(pkeyopts, opt_arg()) == 0) {
    292                 BIO_puts(bio_err, "out of memory\n");
    293                 goto end;
    294             }
    295             break;
    296         case OPT_PKEYOPT_PASSIN:
    297             if ((pkeyopts_passin == NULL && (pkeyopts_passin = sk_OPENSSL_STRING_new_null()) == NULL) || sk_OPENSSL_STRING_push(pkeyopts_passin, opt_arg()) == 0) {
    298                 BIO_puts(bio_err, "out of memory\n");
    299                 goto end;
    300             }
    301             break;
    302         case OPT_RAWIN:
    303             rawin = 1;
    304             break;
    305         case OPT_DIGEST:
    306             digestname = opt_arg();
    307             break;
    308         }
    309     }
    310 
    311     /* No extra arguments. */
    312     if (!opt_check_rest_arg(NULL))
    313         goto opthelp;
    314 
    315     if (!app_RAND_load())
    316         goto end;
    317 
    318     if (digestname != NULL)
    319         rawin = 1;
    320 
    321     if (kdfalg != NULL) {
    322         if (kdflen == 0) {
    323             BIO_printf(bio_err,
    324                 "%s: no KDF length given (-kdflen parameter).\n", prog);
    325             goto opthelp;
    326         }
    327     } else if (inkey == NULL) {
    328         BIO_printf(bio_err,
    329             "%s: no private key given (-inkey parameter).\n", prog);
    330         goto opthelp;
    331     } else if (peerkey != NULL && pkey_op != EVP_PKEY_OP_DERIVE) {
    332         BIO_printf(bio_err,
    333             "%s: -peerkey option not allowed without -derive.\n", prog);
    334         goto opthelp;
    335     } else if (peerkey == NULL && pkey_op == EVP_PKEY_OP_DERIVE) {
    336         BIO_printf(bio_err,
    337             "%s: missing -peerkey option for -derive operation.\n", prog);
    338         goto opthelp;
    339     }
    340 
    341     pkey = get_pkey(kdfalg, inkey, keyform, key_type, passinarg, pkey_op, e);
    342     if (key_type != KEY_NONE && pkey == NULL) {
    343         BIO_printf(bio_err, "%s: Error loading key\n", prog);
    344         goto end;
    345     }
    346 
    347     if (pkey_op == EVP_PKEY_OP_VERIFYRECOVER && !EVP_PKEY_is_a(pkey, "RSA")) {
    348         BIO_printf(bio_err, "%s: -verifyrecover can be used only with RSA\n", prog);
    349         goto end;
    350     }
    351 
    352     if (pkey_op == EVP_PKEY_OP_SIGN || pkey_op == EVP_PKEY_OP_VERIFY) {
    353         if (only_nomd(pkey)) {
    354             if (digestname != NULL) {
    355                 const char *alg = EVP_PKEY_get0_type_name(pkey);
    356 
    357                 BIO_printf(bio_err,
    358                     "%s: -digest (prehash) is not supported with %s\n",
    359                     prog, alg != NULL ? alg : "(unknown key type)");
    360                 goto end;
    361             }
    362             rawin = 1;
    363         }
    364     } else if (digestname != NULL || rawin) {
    365         BIO_printf(bio_err,
    366             "%s: -digest and -rawin can only be used with -sign or -verify\n", prog);
    367         goto opthelp;
    368     }
    369 
    370     if (rawin && rev) {
    371         BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n", prog);
    372         goto opthelp;
    373     }
    374 
    375     if (rawin) {
    376         if ((mctx = EVP_MD_CTX_new()) == NULL) {
    377             BIO_printf(bio_err, "Error: out of memory\n");
    378             goto end;
    379         }
    380     }
    381     ctx = init_ctx(kdfalg, &keysize, pkey_op, e, engine_impl, rawin, pkey,
    382         mctx, digestname, kemop, libctx, app_get0_propq());
    383     if (ctx == NULL) {
    384         BIO_printf(bio_err, "%s: Error initializing context\n", prog);
    385         goto end;
    386     }
    387     if (peerkey != NULL && !setup_peer(ctx, peerform, peerkey, e)) {
    388         BIO_printf(bio_err, "%s: Error setting up peer key\n", prog);
    389         goto end;
    390     }
    391     if (pkeyopts != NULL) {
    392         int num = sk_OPENSSL_STRING_num(pkeyopts);
    393         int i;
    394 
    395         for (i = 0; i < num; ++i) {
    396             const char *opt = sk_OPENSSL_STRING_value(pkeyopts, i);
    397 
    398             if (pkey_ctrl_string(ctx, opt) <= 0) {
    399                 BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
    400                     prog, opt);
    401                 goto end;
    402             }
    403         }
    404     }
    405     if (pkeyopts_passin != NULL) {
    406         int num = sk_OPENSSL_STRING_num(pkeyopts_passin);
    407         int i;
    408 
    409         for (i = 0; i < num; i++) {
    410             char *opt = sk_OPENSSL_STRING_value(pkeyopts_passin, i);
    411             char *passin = strchr(opt, ':');
    412             char *passwd;
    413 
    414             if (passin == NULL) {
    415                 /* Get password interactively */
    416                 char passwd_buf[4096];
    417                 int r;
    418 
    419                 BIO_snprintf(passwd_buf, sizeof(passwd_buf), "Enter %s: ", opt);
    420                 r = EVP_read_pw_string(passwd_buf, sizeof(passwd_buf) - 1,
    421                     passwd_buf, 0);
    422                 if (r < 0) {
    423                     if (r == -2)
    424                         BIO_puts(bio_err, "user abort\n");
    425                     else
    426                         BIO_puts(bio_err, "entry failed\n");
    427                     goto end;
    428                 }
    429                 passwd = OPENSSL_strdup(passwd_buf);
    430                 if (passwd == NULL) {
    431                     BIO_puts(bio_err, "out of memory\n");
    432                     goto end;
    433                 }
    434             } else {
    435                 /*
    436                  * Get password as a passin argument: First split option name
    437                  * and passphrase argument into two strings
    438                  */
    439                 *passin = 0;
    440                 passin++;
    441                 if (app_passwd(passin, NULL, &passwd, NULL) == 0) {
    442                     BIO_printf(bio_err, "failed to get '%s'\n", opt);
    443                     goto end;
    444                 }
    445             }
    446 
    447             if (EVP_PKEY_CTX_ctrl_str(ctx, opt, passwd) <= 0) {
    448                 BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
    449                     prog, opt);
    450                 OPENSSL_free(passwd);
    451                 goto end;
    452             }
    453             OPENSSL_free(passwd);
    454         }
    455     }
    456 
    457     if (sigfile != NULL && (pkey_op != EVP_PKEY_OP_VERIFY)) {
    458         BIO_printf(bio_err,
    459             "%s: Signature file specified for non verify\n", prog);
    460         goto end;
    461     }
    462 
    463     if (sigfile == NULL && (pkey_op == EVP_PKEY_OP_VERIFY)) {
    464         BIO_printf(bio_err,
    465             "%s: No signature file specified for verify\n", prog);
    466         goto end;
    467     }
    468 
    469     if (pkey_op != EVP_PKEY_OP_DERIVE && pkey_op != EVP_PKEY_OP_ENCAPSULATE) {
    470         in = bio_open_default(infile, 'r', FORMAT_BINARY);
    471         if (infile != NULL) {
    472             struct stat st;
    473 
    474             if (stat(infile, &st) == 0 && st.st_size <= INT_MAX)
    475                 filesize = (int)st.st_size;
    476         }
    477         if (in == NULL)
    478             goto end;
    479     }
    480     if (pkey_op == EVP_PKEY_OP_DECAPSULATE && outfile != NULL) {
    481         if (secoutfile != NULL) {
    482             BIO_printf(bio_err, "%s: Decapsulation produces only a shared "
    483                                 "secret and no output. The '-out' option "
    484                                 "is not applicable.\n",
    485                 prog);
    486             goto end;
    487         }
    488         if ((out = bio_open_owner(outfile, 'w', FORMAT_BINARY)) == NULL)
    489             goto end;
    490     } else {
    491         out = bio_open_default(outfile, 'w', FORMAT_BINARY);
    492         if (out == NULL)
    493             goto end;
    494     }
    495 
    496     if (pkey_op == EVP_PKEY_OP_ENCAPSULATE
    497         || pkey_op == EVP_PKEY_OP_DECAPSULATE) {
    498         if (secoutfile == NULL && pkey_op == EVP_PKEY_OP_ENCAPSULATE) {
    499             BIO_printf(bio_err, "KEM-based shared-secret derivation requires "
    500                                 "the '-secret <file>' option\n");
    501             goto end;
    502         }
    503         /* For backwards compatibility, default decap secrets to the output */
    504         if (secoutfile != NULL
    505             && (secout = bio_open_owner(secoutfile, 'w', FORMAT_BINARY)) == NULL)
    506             goto end;
    507     }
    508 
    509     if (sigfile != NULL) {
    510         BIO *sigbio = BIO_new_file(sigfile, "rb");
    511         size_t maxsiglen = 16 * 1024 * 1024;
    512 
    513         if (sigbio == NULL) {
    514             BIO_printf(bio_err, "Can't open signature file %s\n", sigfile);
    515             goto end;
    516         }
    517         if (!bio_to_mem(&sig, &siglen, maxsiglen, sigbio)) {
    518             BIO_free(sigbio);
    519             BIO_printf(bio_err, "Error reading signature data\n");
    520             goto end;
    521         }
    522         BIO_free(sigbio);
    523     }
    524 
    525     /* Raw input data is handled elsewhere */
    526     if (in != NULL && !rawin) {
    527         /* Read the input data */
    528         if (!bio_to_mem(&buf_in, &buf_inlen, 0, in)) {
    529             BIO_printf(bio_err, "Error reading input Data\n");
    530             goto end;
    531         }
    532         if (rev) {
    533             size_t i;
    534             unsigned char ctmp;
    535             size_t l = buf_inlen;
    536 
    537             for (i = 0; i < l / 2; i++) {
    538                 ctmp = buf_in[i];
    539                 buf_in[i] = buf_in[l - 1 - i];
    540                 buf_in[l - 1 - i] = ctmp;
    541             }
    542         }
    543     }
    544 
    545     /* Sanity check the input if the input is not raw */
    546     if (!rawin
    547         && (pkey_op == EVP_PKEY_OP_SIGN || pkey_op == EVP_PKEY_OP_VERIFY)) {
    548         if (buf_inlen > EVP_MAX_MD_SIZE) {
    549             BIO_printf(bio_err,
    550                 "Error: The non-raw input data length %zd is too long - "
    551                 "max supported hashed size is %d\n",
    552                 buf_inlen, EVP_MAX_MD_SIZE);
    553             goto end;
    554         }
    555     }
    556 
    557     if (pkey_op == EVP_PKEY_OP_VERIFY) {
    558         if (rawin) {
    559             rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, sig, siglen,
    560                 NULL, 0);
    561         } else {
    562             rv = EVP_PKEY_verify(ctx, sig, siglen, buf_in, buf_inlen);
    563         }
    564         if (rv == 1) {
    565             BIO_puts(out, "Signature Verified Successfully\n");
    566             ret = 0;
    567         } else {
    568             BIO_puts(out, "Signature Verification Failure\n");
    569         }
    570         goto end;
    571     }
    572     if (rawin) {
    573         /* rawin allocates the buffer in do_raw_keyop() */
    574         rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, NULL, 0,
    575             &buf_out, (size_t *)&buf_outlen);
    576     } else {
    577         if (kdflen != 0) {
    578             buf_outlen = kdflen;
    579             rv = 1;
    580         } else {
    581             rv = do_keyop(ctx, pkey_op, NULL, &buf_outlen,
    582                 buf_in, buf_inlen, NULL, &secretlen);
    583         }
    584         if (rv > 0
    585             && (secretlen > 0 || (pkey_op != EVP_PKEY_OP_ENCAPSULATE && pkey_op != EVP_PKEY_OP_DECAPSULATE))
    586             && (buf_outlen > 0 || pkey_op == EVP_PKEY_OP_DECAPSULATE)) {
    587             if (buf_outlen > 0)
    588                 buf_out = app_malloc(buf_outlen, "buffer output");
    589             if (secretlen > 0)
    590                 secret = app_malloc(secretlen, "secret output");
    591             rv = do_keyop(ctx, pkey_op,
    592                 buf_out, &buf_outlen,
    593                 buf_in, buf_inlen, secret, &secretlen);
    594         }
    595     }
    596     if (rv <= 0) {
    597         if (pkey_op != EVP_PKEY_OP_DERIVE) {
    598             BIO_puts(bio_err, "Public Key operation error\n");
    599         } else {
    600             BIO_puts(bio_err, "Key derivation failed\n");
    601         }
    602         goto end;
    603     }
    604     ret = 0;
    605 
    606     if (asn1parse) {
    607         if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
    608             ERR_print_errors(bio_err); /* but still return success */
    609     } else if (hexdump) {
    610         BIO_dump(out, (char *)buf_out, buf_outlen);
    611     } else {
    612         BIO_write(out, buf_out, buf_outlen);
    613     }
    614     /* Backwards compatible decap output fallback */
    615     if (secretlen > 0)
    616         BIO_write(secout ? secout : out, secret, secretlen);
    617 
    618 end:
    619     if (ret != 0)
    620         ERR_print_errors(bio_err);
    621     EVP_MD_CTX_free(mctx);
    622     EVP_PKEY_CTX_free(ctx);
    623     EVP_PKEY_free(pkey);
    624     EVP_MD_free(md);
    625     release_engine(e);
    626     BIO_free(in);
    627     BIO_free_all(out);
    628     BIO_free_all(secout);
    629     OPENSSL_free(buf_in);
    630     OPENSSL_free(buf_out);
    631     OPENSSL_free(sig);
    632     OPENSSL_free(secret);
    633     sk_OPENSSL_STRING_free(pkeyopts);
    634     sk_OPENSSL_STRING_free(pkeyopts_passin);
    635     NCONF_free(conf);
    636     return ret;
    637 }
    638 
    639 static EVP_PKEY *get_pkey(const char *kdfalg,
    640     const char *keyfile, int keyform, int key_type,
    641     char *passinarg, int pkey_op, ENGINE *e)
    642 {
    643     EVP_PKEY *pkey = NULL;
    644     char *passin = NULL;
    645     X509 *x;
    646 
    647     if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)
    648             || (pkey_op == EVP_PKEY_OP_DERIVE))
    649         && (key_type != KEY_PRIVKEY && kdfalg == NULL)) {
    650         BIO_printf(bio_err, "A private key is needed for this operation\n");
    651         return NULL;
    652     }
    653     if (!app_passwd(passinarg, NULL, &passin, NULL)) {
    654         BIO_printf(bio_err, "Error getting password\n");
    655         return NULL;
    656     }
    657     switch (key_type) {
    658     case KEY_PRIVKEY:
    659         pkey = load_key(keyfile, keyform, 0, passin, e, "private key");
    660         break;
    661 
    662     case KEY_PUBKEY:
    663         pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "public key");
    664         break;
    665 
    666     case KEY_CERT:
    667         x = load_cert(keyfile, keyform, "Certificate");
    668         if (x) {
    669             pkey = X509_get_pubkey(x);
    670             X509_free(x);
    671         }
    672         break;
    673 
    674     case KEY_NONE:
    675         break;
    676     }
    677     OPENSSL_free(passin);
    678     return pkey;
    679 }
    680 
    681 static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
    682     int pkey_op, ENGINE *e,
    683     const int engine_impl, int rawin,
    684     EVP_PKEY *pkey /* ownership is passed to ctx */,
    685     EVP_MD_CTX *mctx, const char *digestname,
    686     const char *kemop, OSSL_LIB_CTX *libctx, const char *propq)
    687 {
    688     EVP_PKEY_CTX *ctx = NULL;
    689     ENGINE *impl = NULL;
    690     int rv = -1;
    691 
    692 #ifndef OPENSSL_NO_ENGINE
    693     if (engine_impl)
    694         impl = e;
    695 #endif
    696 
    697     if (kdfalg != NULL) {
    698         int kdfnid = OBJ_sn2nid(kdfalg);
    699 
    700         if (kdfnid == NID_undef) {
    701             kdfnid = OBJ_ln2nid(kdfalg);
    702             if (kdfnid == NID_undef) {
    703                 BIO_printf(bio_err, "The given KDF \"%s\" is unknown.\n",
    704                     kdfalg);
    705                 return NULL;
    706             }
    707         }
    708         if (impl != NULL)
    709             ctx = EVP_PKEY_CTX_new_id(kdfnid, impl);
    710         else
    711             ctx = EVP_PKEY_CTX_new_from_name(libctx, kdfalg, propq);
    712     } else {
    713         if (pkey == NULL)
    714             return NULL;
    715 
    716         *pkeysize = EVP_PKEY_get_size(pkey);
    717         if (impl != NULL)
    718             ctx = EVP_PKEY_CTX_new(pkey, impl);
    719         else
    720             ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
    721     }
    722 
    723     if (ctx == NULL)
    724         return NULL;
    725 
    726     if (rawin) {
    727         EVP_MD_CTX_set_pkey_ctx(mctx, ctx);
    728 
    729         switch (pkey_op) {
    730         case EVP_PKEY_OP_SIGN:
    731             rv = EVP_DigestSignInit_ex(mctx, NULL, digestname, libctx, propq,
    732                 pkey, NULL);
    733             break;
    734 
    735         case EVP_PKEY_OP_VERIFY:
    736             rv = EVP_DigestVerifyInit_ex(mctx, NULL, digestname, libctx, propq,
    737                 pkey, NULL);
    738             break;
    739         }
    740 
    741     } else {
    742         switch (pkey_op) {
    743         case EVP_PKEY_OP_SIGN:
    744             rv = EVP_PKEY_sign_init(ctx);
    745             break;
    746 
    747         case EVP_PKEY_OP_VERIFY:
    748             rv = EVP_PKEY_verify_init(ctx);
    749             break;
    750 
    751         case EVP_PKEY_OP_VERIFYRECOVER:
    752             rv = EVP_PKEY_verify_recover_init(ctx);
    753             break;
    754 
    755         case EVP_PKEY_OP_ENCRYPT:
    756             rv = EVP_PKEY_encrypt_init(ctx);
    757             break;
    758 
    759         case EVP_PKEY_OP_DECRYPT:
    760             rv = EVP_PKEY_decrypt_init(ctx);
    761             break;
    762 
    763         case EVP_PKEY_OP_DERIVE:
    764             rv = EVP_PKEY_derive_init(ctx);
    765             break;
    766 
    767         case EVP_PKEY_OP_ENCAPSULATE:
    768             rv = EVP_PKEY_encapsulate_init(ctx, NULL);
    769             if (rv > 0 && kemop != NULL)
    770                 rv = EVP_PKEY_CTX_set_kem_op(ctx, kemop);
    771             break;
    772 
    773         case EVP_PKEY_OP_DECAPSULATE:
    774             rv = EVP_PKEY_decapsulate_init(ctx, NULL);
    775             if (rv > 0 && kemop != NULL)
    776                 rv = EVP_PKEY_CTX_set_kem_op(ctx, kemop);
    777             break;
    778         }
    779     }
    780 
    781     if (rv <= 0) {
    782         EVP_PKEY_CTX_free(ctx);
    783         ctx = NULL;
    784     }
    785 
    786     return ctx;
    787 }
    788 
    789 static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
    790     ENGINE *e)
    791 {
    792     EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
    793     EVP_PKEY *peer = NULL;
    794     ENGINE *engine = NULL;
    795     int ret = 1;
    796 
    797     if (peerform == FORMAT_ENGINE)
    798         engine = e;
    799     peer = load_pubkey(file, peerform, 0, NULL, engine, "peer key");
    800     if (peer == NULL) {
    801         BIO_printf(bio_err, "Error reading peer key %s\n", file);
    802         return 0;
    803     }
    804     if (strcmp(EVP_PKEY_get0_type_name(peer), EVP_PKEY_get0_type_name(pkey)) != 0) {
    805         BIO_printf(bio_err,
    806             "Type of peer public key: %s does not match type of private key: %s\n",
    807             EVP_PKEY_get0_type_name(peer), EVP_PKEY_get0_type_name(pkey));
    808         ret = 0;
    809     } else {
    810         ret = EVP_PKEY_derive_set_peer(ctx, peer) > 0;
    811     }
    812 
    813     EVP_PKEY_free(peer);
    814     return ret;
    815 }
    816 
    817 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
    818     unsigned char *out, size_t *poutlen,
    819     const unsigned char *in, size_t inlen,
    820     unsigned char *secret, size_t *pseclen)
    821 {
    822     int rv = 0;
    823 
    824     switch (pkey_op) {
    825     case EVP_PKEY_OP_VERIFYRECOVER:
    826         rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
    827         break;
    828 
    829     case EVP_PKEY_OP_SIGN:
    830         rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
    831         break;
    832 
    833     case EVP_PKEY_OP_ENCRYPT:
    834         rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
    835         break;
    836 
    837     case EVP_PKEY_OP_DECRYPT:
    838         rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
    839         break;
    840 
    841     case EVP_PKEY_OP_DERIVE:
    842         rv = EVP_PKEY_derive(ctx, out, poutlen);
    843         break;
    844 
    845     case EVP_PKEY_OP_ENCAPSULATE:
    846         rv = EVP_PKEY_encapsulate(ctx, out, poutlen, secret, pseclen);
    847         break;
    848 
    849     case EVP_PKEY_OP_DECAPSULATE:
    850         rv = EVP_PKEY_decapsulate(ctx, secret, pseclen, in, inlen);
    851         break;
    852     }
    853     return rv;
    854 }
    855 
    856 #define TBUF_MAXSIZE 2048
    857 
    858 static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
    859     EVP_PKEY *pkey, BIO *in,
    860     int filesize, unsigned char *sig, size_t siglen,
    861     unsigned char **out, size_t *poutlen)
    862 {
    863     int rv = 0;
    864     unsigned char tbuf[TBUF_MAXSIZE];
    865     unsigned char *mbuf = NULL;
    866     int buf_len = 0;
    867 
    868     /* Some algorithms only support oneshot digests */
    869     if (only_nomd(pkey)) {
    870         if (filesize < 0) {
    871             BIO_printf(bio_err,
    872                 "Error: unable to determine file size for oneshot operation\n");
    873             goto end;
    874         }
    875         mbuf = app_malloc(filesize, "oneshot sign/verify buffer");
    876         switch (pkey_op) {
    877         case EVP_PKEY_OP_VERIFY:
    878             buf_len = BIO_read(in, mbuf, filesize);
    879             if (buf_len != filesize) {
    880                 BIO_printf(bio_err, "Error reading raw input data\n");
    881                 goto end;
    882             }
    883             rv = EVP_DigestVerify(mctx, sig, siglen, mbuf, buf_len);
    884             break;
    885         case EVP_PKEY_OP_SIGN:
    886             buf_len = BIO_read(in, mbuf, filesize);
    887             if (buf_len != filesize) {
    888                 BIO_printf(bio_err, "Error reading raw input data\n");
    889                 goto end;
    890             }
    891             rv = EVP_DigestSign(mctx, NULL, poutlen, mbuf, buf_len);
    892             if (rv == 1 && out != NULL) {
    893                 *out = app_malloc(*poutlen, "buffer output");
    894                 rv = EVP_DigestSign(mctx, *out, poutlen, mbuf, buf_len);
    895             }
    896             break;
    897         }
    898         goto end;
    899     }
    900 
    901     switch (pkey_op) {
    902     case EVP_PKEY_OP_VERIFY:
    903         for (;;) {
    904             buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
    905             if (buf_len == 0)
    906                 break;
    907             if (buf_len < 0) {
    908                 BIO_printf(bio_err, "Error reading raw input data\n");
    909                 goto end;
    910             }
    911             rv = EVP_DigestVerifyUpdate(mctx, tbuf, (size_t)buf_len);
    912             if (rv != 1) {
    913                 BIO_printf(bio_err, "Error verifying raw input data\n");
    914                 goto end;
    915             }
    916         }
    917         rv = EVP_DigestVerifyFinal(mctx, sig, siglen);
    918         break;
    919     case EVP_PKEY_OP_SIGN:
    920         for (;;) {
    921             buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
    922             if (buf_len == 0)
    923                 break;
    924             if (buf_len < 0) {
    925                 BIO_printf(bio_err, "Error reading raw input data\n");
    926                 goto end;
    927             }
    928             rv = EVP_DigestSignUpdate(mctx, tbuf, (size_t)buf_len);
    929             if (rv != 1) {
    930                 BIO_printf(bio_err, "Error signing raw input data\n");
    931                 goto end;
    932             }
    933         }
    934         rv = EVP_DigestSignFinal(mctx, NULL, poutlen);
    935         if (rv == 1 && out != NULL) {
    936             *out = app_malloc(*poutlen, "buffer output");
    937             rv = EVP_DigestSignFinal(mctx, *out, poutlen);
    938         }
    939         break;
    940     }
    941 
    942 end:
    943     OPENSSL_free(mbuf);
    944     return rv;
    945 }
    946