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