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