Fix grammar in certificates.txt
[openssl.git] / apps / pkeyutl.c
1 /*
2  * Copyright 2006-2020 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_CTX *init_ctx(const char *kdfalg, int *pkeysize,
24                               const char *keyfile, int keyform, int key_type,
25                               char *passinarg, int pkey_op, ENGINE *e,
26                               const int impl, int rawin, EVP_PKEY **ppkey,
27                               OSSL_LIB_CTX *libctx, const char *propq);
28
29 static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
30                       ENGINE *e);
31
32 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
33                     unsigned char *out, size_t *poutlen,
34                     const unsigned char *in, size_t inlen);
35
36 static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx,
37                         const EVP_MD *md, EVP_PKEY *pkey, BIO *in,
38                         int filesize, unsigned char *sig, int siglen,
39                         unsigned char **out, size_t *poutlen);
40
41 typedef enum OPTION_choice {
42     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
43     OPT_ENGINE, OPT_ENGINE_IMPL, OPT_IN, OPT_OUT,
44     OPT_PUBIN, OPT_CERTIN, OPT_ASN1PARSE, OPT_HEXDUMP, OPT_SIGN,
45     OPT_VERIFY, OPT_VERIFYRECOVER, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
46     OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN,
47     OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_PKEYOPT_PASSIN, OPT_KDF,
48     OPT_KDFLEN, OPT_R_ENUM, OPT_PROV_ENUM,
49     OPT_CONFIG,
50     OPT_RAWIN, OPT_DIGEST
51 } OPTION_CHOICE;
52
53 const OPTIONS pkeyutl_options[] = {
54     OPT_SECTION("General"),
55     {"help", OPT_HELP, '-', "Display this summary"},
56 #ifndef OPENSSL_NO_ENGINE
57     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
58     {"engine_impl", OPT_ENGINE_IMPL, '-',
59      "Also use engine given by -engine for crypto operations"},
60 #endif
61     {"sign", OPT_SIGN, '-', "Sign input data with private key"},
62     {"verify", OPT_VERIFY, '-', "Verify with public key"},
63     {"encrypt", OPT_ENCRYPT, '-', "Encrypt input data with public key"},
64     {"decrypt", OPT_DECRYPT, '-', "Decrypt input data with private key"},
65     {"derive", OPT_DERIVE, '-', "Derive shared secret"},
66     OPT_CONFIG_OPTION,
67
68     OPT_SECTION("Input"),
69     {"in", OPT_IN, '<', "Input file - default stdin"},
70     {"rawin", OPT_RAWIN, '-', "Indicate the input data is in raw form"},
71     {"pubin", OPT_PUBIN, '-', "Input is a public key"},
72     {"inkey", OPT_INKEY, 's', "Input private key file"},
73     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
74     {"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"},
75     {"peerform", OPT_PEERFORM, 'E', "Peer key format (DER/PEM/P12/ENGINE)"},
76     {"certin", OPT_CERTIN, '-', "Input is a cert with a public key"},
77     {"rev", OPT_REV, '-', "Reverse the order of the input buffer"},
78     {"sigfile", OPT_SIGFILE, '<', "Signature file (verify operation only)"},
79     {"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"},
80
81     OPT_SECTION("Output"),
82     {"out", OPT_OUT, '>', "Output file - default stdout"},
83     {"asn1parse", OPT_ASN1PARSE, '-', "asn1parse the output data"},
84     {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"},
85     {"verifyrecover", OPT_VERIFYRECOVER, '-',
86      "Verify with public key, recover original data"},
87
88     OPT_SECTION("Signing/Derivation"),
89     {"digest", OPT_DIGEST, 's',
90      "Specify the digest algorithm when signing the raw input data"},
91     {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"},
92     {"pkeyopt_passin", OPT_PKEYOPT_PASSIN, 's',
93      "Public key option that is read as a passphrase argument opt:passphrase"},
94     {"kdf", OPT_KDF, 's', "Use KDF algorithm"},
95     {"kdflen", OPT_KDFLEN, 'p', "KDF algorithm output length"},
96
97     OPT_R_OPTIONS,
98     OPT_PROV_OPTIONS,
99     {NULL}
100 };
101
102 int pkeyutl_main(int argc, char **argv)
103 {
104     CONF *conf = NULL;
105     BIO *in = NULL, *out = NULL;
106     ENGINE *e = NULL;
107     EVP_PKEY_CTX *ctx = NULL;
108     EVP_PKEY *pkey = NULL;
109     char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL;
110     char hexdump = 0, asn1parse = 0, rev = 0, *prog;
111     unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
112     OPTION_CHOICE o;
113     int buf_inlen = 0, siglen = -1, keyform = FORMAT_PEM, peerform = FORMAT_PEM;
114     int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
115     int engine_impl = 0;
116     int ret = 1, rv = -1;
117     size_t buf_outlen;
118     const char *inkey = NULL;
119     const char *peerkey = NULL;
120     const char *kdfalg = NULL;
121     int kdflen = 0;
122     STACK_OF(OPENSSL_STRING) *pkeyopts = NULL;
123     STACK_OF(OPENSSL_STRING) *pkeyopts_passin = NULL;
124     int rawin = 0;
125     const EVP_MD *md = NULL;
126     int filesize = -1;
127     OSSL_LIB_CTX *libctx = app_get0_libctx();
128     const char *propq = NULL;
129
130     prog = opt_init(argc, argv, pkeyutl_options);
131     while ((o = opt_next()) != OPT_EOF) {
132         switch (o) {
133         case OPT_EOF:
134         case OPT_ERR:
135  opthelp:
136             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
137             goto end;
138         case OPT_HELP:
139             opt_help(pkeyutl_options);
140             ret = 0;
141             goto end;
142         case OPT_IN:
143             infile = opt_arg();
144             break;
145         case OPT_OUT:
146             outfile = opt_arg();
147             break;
148         case OPT_SIGFILE:
149             sigfile = opt_arg();
150             break;
151         case OPT_ENGINE_IMPL:
152             engine_impl = 1;
153             break;
154         case OPT_INKEY:
155             inkey = opt_arg();
156             break;
157         case OPT_PEERKEY:
158             peerkey = opt_arg();
159             break;
160         case OPT_PASSIN:
161             passinarg = opt_arg();
162             break;
163         case OPT_PEERFORM:
164             if (!opt_format(opt_arg(), OPT_FMT_ANY, &peerform))
165                 goto opthelp;
166             break;
167         case OPT_KEYFORM:
168             if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
169                 goto opthelp;
170             break;
171         case OPT_R_CASES:
172             if (!opt_rand(o))
173                 goto end;
174             break;
175         case OPT_CONFIG:
176             conf = app_load_config_modules(opt_arg());
177             if (conf == NULL)
178                 goto end;
179             break;
180         case OPT_PROV_CASES:
181             if (!opt_provider(o))
182                 goto end;
183             break;
184         case OPT_ENGINE:
185             e = setup_engine(opt_arg(), 0);
186             break;
187         case OPT_PUBIN:
188             key_type = KEY_PUBKEY;
189             break;
190         case OPT_CERTIN:
191             key_type = KEY_CERT;
192             break;
193         case OPT_ASN1PARSE:
194             asn1parse = 1;
195             break;
196         case OPT_HEXDUMP:
197             hexdump = 1;
198             break;
199         case OPT_SIGN:
200             pkey_op = EVP_PKEY_OP_SIGN;
201             break;
202         case OPT_VERIFY:
203             pkey_op = EVP_PKEY_OP_VERIFY;
204             break;
205         case OPT_VERIFYRECOVER:
206             pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
207             break;
208         case OPT_ENCRYPT:
209             pkey_op = EVP_PKEY_OP_ENCRYPT;
210             break;
211         case OPT_DECRYPT:
212             pkey_op = EVP_PKEY_OP_DECRYPT;
213             break;
214         case OPT_DERIVE:
215             pkey_op = EVP_PKEY_OP_DERIVE;
216             break;
217         case OPT_KDF:
218             pkey_op = EVP_PKEY_OP_DERIVE;
219             key_type = KEY_NONE;
220             kdfalg = opt_arg();
221             break;
222         case OPT_KDFLEN:
223             kdflen = atoi(opt_arg());
224             break;
225         case OPT_REV:
226             rev = 1;
227             break;
228         case OPT_PKEYOPT:
229             if ((pkeyopts == NULL &&
230                  (pkeyopts = sk_OPENSSL_STRING_new_null()) == NULL) ||
231                 sk_OPENSSL_STRING_push(pkeyopts, opt_arg()) == 0) {
232                 BIO_puts(bio_err, "out of memory\n");
233                 goto end;
234             }
235             break;
236         case OPT_PKEYOPT_PASSIN:
237             if ((pkeyopts_passin == NULL &&
238                  (pkeyopts_passin = sk_OPENSSL_STRING_new_null()) == NULL) ||
239                 sk_OPENSSL_STRING_push(pkeyopts_passin, opt_arg()) == 0) {
240                 BIO_puts(bio_err, "out of memory\n");
241                 goto end;
242             }
243             break;
244         case OPT_RAWIN:
245             rawin = 1;
246             break;
247         case OPT_DIGEST:
248             if (!opt_md(opt_arg(), &md))
249                 goto end;
250             break;
251         }
252     }
253     argc = opt_num_rest();
254     if (argc != 0)
255         goto opthelp;
256
257     if (rawin && pkey_op != EVP_PKEY_OP_SIGN && pkey_op != EVP_PKEY_OP_VERIFY) {
258         BIO_printf(bio_err,
259                    "%s: -rawin can only be used with -sign or -verify\n",
260                    prog);
261         goto opthelp;
262     }
263
264     if (md != NULL && !rawin) {
265         BIO_printf(bio_err,
266                    "%s: -digest can only be used with -rawin\n",
267                    prog);
268         goto opthelp;
269     }
270
271     if (rawin && rev) {
272         BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n",
273                    prog);
274         goto opthelp;
275     }
276
277     if (kdfalg != NULL) {
278         if (kdflen == 0) {
279             BIO_printf(bio_err,
280                        "%s: no KDF length given (-kdflen parameter).\n", prog);
281             goto opthelp;
282         }
283     } else if (inkey == NULL) {
284         BIO_printf(bio_err,
285                    "%s: no private key given (-inkey parameter).\n", prog);
286         goto opthelp;
287     } else if (peerkey != NULL && pkey_op != EVP_PKEY_OP_DERIVE) {
288         BIO_printf(bio_err,
289                    "%s: no peer key given (-peerkey parameter).\n", prog);
290         goto opthelp;
291     }
292     ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type,
293                    passinarg, pkey_op, e, engine_impl, rawin, &pkey,
294                    libctx, propq);
295     if (ctx == NULL) {
296         BIO_printf(bio_err, "%s: Error initializing context\n", prog);
297         ERR_print_errors(bio_err);
298         goto end;
299     }
300     if (peerkey != NULL && !setup_peer(ctx, peerform, peerkey, e)) {
301         BIO_printf(bio_err, "%s: Error setting up peer key\n", prog);
302         ERR_print_errors(bio_err);
303         goto end;
304     }
305     if (pkeyopts != NULL) {
306         int num = sk_OPENSSL_STRING_num(pkeyopts);
307         int i;
308
309         for (i = 0; i < num; ++i) {
310             const char *opt = sk_OPENSSL_STRING_value(pkeyopts, i);
311
312             if (pkey_ctrl_string(ctx, opt) <= 0) {
313                 BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
314                            prog, opt);
315                 ERR_print_errors(bio_err);
316                 goto end;
317             }
318         }
319     }
320     if (pkeyopts_passin != NULL) {
321         int num = sk_OPENSSL_STRING_num(pkeyopts_passin);
322         int i;
323
324         for (i = 0; i < num; i++) {
325             char *opt = sk_OPENSSL_STRING_value(pkeyopts_passin, i);
326             char *passin = strchr(opt, ':');
327             char *passwd;
328
329             if (passin == NULL) {
330                 /* Get password interactively */
331                 char passwd_buf[4096];
332                 int r;
333
334                 BIO_snprintf(passwd_buf, sizeof(passwd_buf), "Enter %s: ", opt);
335                 r = EVP_read_pw_string(passwd_buf, sizeof(passwd_buf) - 1,
336                                        passwd_buf, 0);
337                 if (r < 0) {
338                     if (r == -2)
339                         BIO_puts(bio_err, "user abort\n");
340                     else
341                         BIO_puts(bio_err, "entry failed\n");
342                     goto end;
343                 }
344                 passwd = OPENSSL_strdup(passwd_buf);
345                 if (passwd == NULL) {
346                     BIO_puts(bio_err, "out of memory\n");
347                     goto end;
348                 }
349             } else {
350                 /* Get password as a passin argument: First split option name
351                  * and passphrase argument into two strings */
352                 *passin = 0;
353                 passin++;
354                 if (app_passwd(passin, NULL, &passwd, NULL) == 0) {
355                     BIO_printf(bio_err, "failed to get '%s'\n", opt);
356                     goto end;
357                 }
358             }
359
360             if (EVP_PKEY_CTX_ctrl_str(ctx, opt, passwd) <= 0) {
361                 BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
362                            prog, opt);
363                 goto end;
364             }
365             OPENSSL_free(passwd);
366         }
367     }
368
369     if (sigfile != NULL && (pkey_op != EVP_PKEY_OP_VERIFY)) {
370         BIO_printf(bio_err,
371                    "%s: Signature file specified for non verify\n", prog);
372         goto end;
373     }
374
375     if (sigfile == NULL && (pkey_op == EVP_PKEY_OP_VERIFY)) {
376         BIO_printf(bio_err,
377                    "%s: No signature file specified for verify\n", prog);
378         goto end;
379     }
380
381     if (pkey_op != EVP_PKEY_OP_DERIVE) {
382         in = bio_open_default(infile, 'r', FORMAT_BINARY);
383         if (infile != NULL) {
384             struct stat st;
385
386             if (stat(infile, &st) == 0 && st.st_size <= INT_MAX)
387                 filesize = (int)st.st_size;
388         }
389         if (in == NULL)
390             goto end;
391     }
392     out = bio_open_default(outfile, 'w', FORMAT_BINARY);
393     if (out == NULL)
394         goto end;
395
396     if (sigfile != NULL) {
397         BIO *sigbio = BIO_new_file(sigfile, "rb");
398
399         if (sigbio == NULL) {
400             BIO_printf(bio_err, "Can't open signature file %s\n", sigfile);
401             goto end;
402         }
403         siglen = bio_to_mem(&sig, keysize * 10, sigbio);
404         BIO_free(sigbio);
405         if (siglen < 0) {
406             BIO_printf(bio_err, "Error reading signature data\n");
407             goto end;
408         }
409     }
410
411     /* Raw input data is handled elsewhere */
412     if (in != NULL && !rawin) {
413         /* Read the input data */
414         buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
415         if (buf_inlen < 0) {
416             BIO_printf(bio_err, "Error reading input Data\n");
417             goto end;
418         }
419         if (rev) {
420             size_t i;
421             unsigned char ctmp;
422             size_t l = (size_t)buf_inlen;
423             for (i = 0; i < l / 2; i++) {
424                 ctmp = buf_in[i];
425                 buf_in[i] = buf_in[l - 1 - i];
426                 buf_in[l - 1 - i] = ctmp;
427             }
428         }
429     }
430
431     /* Sanity check the input if the input is not raw */
432     if (!rawin
433             && buf_inlen > EVP_MAX_MD_SIZE
434             && (pkey_op == EVP_PKEY_OP_SIGN
435                 || pkey_op == EVP_PKEY_OP_VERIFY)) {
436         BIO_printf(bio_err,
437                    "Error: The input data looks too long to be a hash\n");
438         goto end;
439     }
440
441     if (pkey_op == EVP_PKEY_OP_VERIFY) {
442         if (rawin) {
443             rv = do_raw_keyop(pkey_op, ctx, md, pkey, in, filesize, sig, siglen,
444                               NULL, 0);
445         } else {
446             rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
447                                  buf_in, (size_t)buf_inlen);
448         }
449         if (rv == 1) {
450             BIO_puts(out, "Signature Verified Successfully\n");
451             ret = 0;
452         } else {
453             BIO_puts(out, "Signature Verification Failure\n");
454         }
455         goto end;
456     }
457     if (kdflen != 0) {
458         buf_outlen = kdflen;
459         rv = 1;
460     } else {
461         if (rawin) {
462             /* rawin allocates the buffer in do_raw_keyop() */
463             rv = do_raw_keyop(pkey_op, ctx, md, pkey, in, filesize, NULL, 0,
464                               &buf_out, (size_t *)&buf_outlen);
465         } else {
466             rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
467                           buf_in, (size_t)buf_inlen);
468             if (rv > 0 && buf_outlen != 0) {
469                 buf_out = app_malloc(buf_outlen, "buffer output");
470                 rv = do_keyop(ctx, pkey_op,
471                               buf_out, (size_t *)&buf_outlen,
472                               buf_in, (size_t)buf_inlen);
473             }
474         }
475     }
476     if (rv <= 0) {
477         if (pkey_op != EVP_PKEY_OP_DERIVE) {
478             BIO_puts(bio_err, "Public Key operation error\n");
479         } else {
480             BIO_puts(bio_err, "Key derivation failed\n");
481         }
482         ERR_print_errors(bio_err);
483         goto end;
484     }
485     ret = 0;
486
487     if (asn1parse) {
488         if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
489             ERR_print_errors(bio_err);
490     } else if (hexdump) {
491         BIO_dump(out, (char *)buf_out, buf_outlen);
492     } else {
493         BIO_write(out, buf_out, buf_outlen);
494     }
495
496  end:
497     EVP_PKEY_CTX_free(ctx);
498     release_engine(e);
499     BIO_free(in);
500     BIO_free_all(out);
501     OPENSSL_free(buf_in);
502     OPENSSL_free(buf_out);
503     OPENSSL_free(sig);
504     sk_OPENSSL_STRING_free(pkeyopts);
505     sk_OPENSSL_STRING_free(pkeyopts_passin);
506     NCONF_free(conf);
507     return ret;
508 }
509
510 static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
511                               const char *keyfile, int keyform, int key_type,
512                               char *passinarg, int pkey_op, ENGINE *e,
513                               const int engine_impl, int rawin,
514                               EVP_PKEY **ppkey,
515                               OSSL_LIB_CTX *libctx, const char *propq)
516 {
517     EVP_PKEY *pkey = NULL;
518     EVP_PKEY_CTX *ctx = NULL;
519     ENGINE *impl = NULL;
520     char *passin = NULL;
521     int rv = -1;
522     X509 *x;
523     if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)
524          || (pkey_op == EVP_PKEY_OP_DERIVE))
525         && (key_type != KEY_PRIVKEY && kdfalg == NULL)) {
526         BIO_printf(bio_err, "A private key is needed for this operation\n");
527         goto end;
528     }
529     if (!app_passwd(passinarg, NULL, &passin, NULL)) {
530         BIO_printf(bio_err, "Error getting password\n");
531         goto end;
532     }
533     switch (key_type) {
534     case KEY_PRIVKEY:
535         pkey = load_key(keyfile, keyform, 0, passin, e, "private key");
536         break;
537
538     case KEY_PUBKEY:
539         pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "public key");
540         break;
541
542     case KEY_CERT:
543         x = load_cert(keyfile, FORMAT_UNDEF, "Certificate");
544         if (x) {
545             pkey = X509_get_pubkey(x);
546             X509_free(x);
547         }
548         break;
549
550     case KEY_NONE:
551         break;
552
553     }
554
555 #ifndef OPENSSL_NO_ENGINE
556     if (engine_impl)
557         impl = e;
558 #endif
559
560     if (kdfalg != NULL) {
561         int kdfnid = OBJ_sn2nid(kdfalg);
562
563         if (kdfnid == NID_undef) {
564             kdfnid = OBJ_ln2nid(kdfalg);
565             if (kdfnid == NID_undef) {
566                 BIO_printf(bio_err, "The given KDF \"%s\" is unknown.\n",
567                            kdfalg);
568                 goto end;
569             }
570         }
571         if (impl != NULL)
572             ctx = EVP_PKEY_CTX_new_id(kdfnid, impl);
573         else
574             ctx = EVP_PKEY_CTX_new_from_name(libctx, kdfalg, propq);
575     } else {
576         if (pkey == NULL)
577             goto end;
578
579         *pkeysize = EVP_PKEY_size(pkey);
580         if (impl != NULL)
581             ctx = EVP_PKEY_CTX_new(pkey, impl);
582         else
583             ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
584         if (ppkey != NULL)
585             *ppkey = pkey;
586         EVP_PKEY_free(pkey);
587     }
588
589     if (ctx == NULL)
590         goto end;
591
592     /*
593      * If rawin then we don't need to actually initialise the EVP_PKEY_CTX
594      * itself. That will get initialised during EVP_DigestSignInit or
595      * EVP_DigestVerifyInit.
596      */
597     if (rawin) {
598         rv = 1;
599     } else {
600         switch (pkey_op) {
601         case EVP_PKEY_OP_SIGN:
602             rv = EVP_PKEY_sign_init(ctx);
603             break;
604
605         case EVP_PKEY_OP_VERIFY:
606             rv = EVP_PKEY_verify_init(ctx);
607             break;
608
609         case EVP_PKEY_OP_VERIFYRECOVER:
610             rv = EVP_PKEY_verify_recover_init(ctx);
611             break;
612
613         case EVP_PKEY_OP_ENCRYPT:
614             rv = EVP_PKEY_encrypt_init(ctx);
615             break;
616
617         case EVP_PKEY_OP_DECRYPT:
618             rv = EVP_PKEY_decrypt_init(ctx);
619             break;
620
621         case EVP_PKEY_OP_DERIVE:
622             rv = EVP_PKEY_derive_init(ctx);
623             break;
624         }
625     }
626
627     if (rv <= 0) {
628         EVP_PKEY_CTX_free(ctx);
629         ctx = NULL;
630     }
631
632  end:
633     OPENSSL_free(passin);
634     return ctx;
635
636 }
637
638 static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
639                       ENGINE *e)
640 {
641     EVP_PKEY *peer = NULL;
642     ENGINE *engine = NULL;
643     int ret;
644
645     if (peerform == FORMAT_ENGINE)
646         engine = e;
647     peer = load_pubkey(file, peerform, 0, NULL, engine, "peer key");
648     if (peer == NULL) {
649         BIO_printf(bio_err, "Error reading peer key %s\n", file);
650         ERR_print_errors(bio_err);
651         return 0;
652     }
653
654     ret = EVP_PKEY_derive_set_peer(ctx, peer);
655
656     EVP_PKEY_free(peer);
657     if (ret <= 0)
658         ERR_print_errors(bio_err);
659     return ret;
660 }
661
662 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
663                     unsigned char *out, size_t *poutlen,
664                     const unsigned char *in, size_t inlen)
665 {
666     int rv = 0;
667     switch (pkey_op) {
668     case EVP_PKEY_OP_VERIFYRECOVER:
669         rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
670         break;
671
672     case EVP_PKEY_OP_SIGN:
673         rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
674         break;
675
676     case EVP_PKEY_OP_ENCRYPT:
677         rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
678         break;
679
680     case EVP_PKEY_OP_DECRYPT:
681         rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
682         break;
683
684     case EVP_PKEY_OP_DERIVE:
685         rv = EVP_PKEY_derive(ctx, out, poutlen);
686         break;
687
688     }
689     return rv;
690 }
691
692 #define TBUF_MAXSIZE 2048
693
694 static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx,
695                         const EVP_MD *md, EVP_PKEY *pkey, BIO *in,
696                         int filesize, unsigned char *sig, int siglen,
697                         unsigned char **out, size_t *poutlen)
698 {
699     int rv = 0;
700     EVP_MD_CTX *mctx = NULL;
701     unsigned char tbuf[TBUF_MAXSIZE];
702     unsigned char *mbuf = NULL;
703     int buf_len = 0;
704
705     if ((mctx = EVP_MD_CTX_new()) == NULL) {
706         BIO_printf(bio_err, "Error: out of memory\n");
707         return rv;
708     }
709     EVP_MD_CTX_set_pkey_ctx(mctx, ctx);
710
711     /* Some algorithms only support oneshot digests */
712     if (EVP_PKEY_id(pkey) == EVP_PKEY_ED25519
713             || EVP_PKEY_id(pkey) == EVP_PKEY_ED448) {
714         if (filesize < 0) {
715             BIO_printf(bio_err,
716                        "Error: unable to determine file size for oneshot operation\n");
717             goto end;
718         }
719         mbuf = app_malloc(filesize, "oneshot sign/verify buffer");
720         switch(pkey_op) {
721         case EVP_PKEY_OP_VERIFY:
722             if (EVP_DigestVerifyInit(mctx, NULL, md, NULL, pkey) != 1)
723                 goto end;
724             buf_len = BIO_read(in, mbuf, filesize);
725             if (buf_len != filesize) {
726                 BIO_printf(bio_err, "Error reading raw input data\n");
727                 goto end;
728             }
729             rv = EVP_DigestVerify(mctx, sig, (size_t)siglen, mbuf, buf_len);
730             break;
731         case EVP_PKEY_OP_SIGN:
732             if (EVP_DigestSignInit(mctx, NULL, md, NULL, pkey) != 1)
733                 goto end;
734             buf_len = BIO_read(in, mbuf, filesize);
735             if (buf_len != filesize) {
736                 BIO_printf(bio_err, "Error reading raw input data\n");
737                 goto end;
738             }
739             rv = EVP_DigestSign(mctx, NULL, poutlen, mbuf, buf_len);
740             if (rv == 1 && out != NULL) {
741                 *out = app_malloc(*poutlen, "buffer output");
742                 rv = EVP_DigestSign(mctx, *out, poutlen, mbuf, buf_len);
743             }
744             break;
745         }
746         goto end;
747     }
748
749     switch(pkey_op) {
750     case EVP_PKEY_OP_VERIFY:
751         if (EVP_DigestVerifyInit(mctx, NULL, md, NULL, pkey) != 1)
752             goto end;
753         for (;;) {
754             buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
755             if (buf_len == 0)
756                 break;
757             if (buf_len < 0) {
758                 BIO_printf(bio_err, "Error reading raw input data\n");
759                 goto end;
760             }
761             rv = EVP_DigestVerifyUpdate(mctx, tbuf, (size_t)buf_len);
762             if (rv != 1) {
763                 BIO_printf(bio_err, "Error verifying raw input data\n");
764                 goto end;
765             }
766         }
767         rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen);
768         break;
769     case EVP_PKEY_OP_SIGN:
770         if (EVP_DigestSignInit(mctx, NULL, md, NULL, pkey) != 1)
771             goto end;
772         for (;;) {
773             buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
774             if (buf_len == 0)
775                 break;
776             if (buf_len < 0) {
777                 BIO_printf(bio_err, "Error reading raw input data\n");
778                 goto end;
779             }
780             rv = EVP_DigestSignUpdate(mctx, tbuf, (size_t)buf_len);
781             if (rv != 1) {
782                 BIO_printf(bio_err, "Error signing raw input data\n");
783                 goto end;
784             }
785         }
786         rv = EVP_DigestSignFinal(mctx, NULL, poutlen);
787         if (rv == 1 && out != NULL) {
788             *out = app_malloc(*poutlen, "buffer output");
789             rv = EVP_DigestSignFinal(mctx, *out, poutlen);
790         }
791         break;
792     }
793
794  end:
795     OPENSSL_free(mbuf);
796     EVP_MD_CTX_free(mctx);
797     return rv;
798 }