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