Support raw input data in apps/pkeyutl
[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         EC_KEY *eckey = NULL;
530         const EC_GROUP *group = NULL;
531         int nid;
532
533         if (pkey == NULL)
534             goto end;
535         /* SM2 needs a special treatment */
536         if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) {
537             if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL
538                     || (group = EC_KEY_get0_group(eckey)) == NULL
539                     || (nid = EC_GROUP_get_curve_name(group)) == 0)
540                 goto end;
541             if (nid == NID_sm2)
542                 EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
543         }
544         *pkeysize = EVP_PKEY_size(pkey);
545         ctx = EVP_PKEY_CTX_new(pkey, impl);
546         if (ppkey != NULL)
547             *ppkey = pkey;
548         EVP_PKEY_free(pkey);
549     }
550
551     if (ctx == NULL)
552         goto end;
553
554     switch (pkey_op) {
555     case EVP_PKEY_OP_SIGN:
556         rv = EVP_PKEY_sign_init(ctx);
557         break;
558
559     case EVP_PKEY_OP_VERIFY:
560         rv = EVP_PKEY_verify_init(ctx);
561         break;
562
563     case EVP_PKEY_OP_VERIFYRECOVER:
564         rv = EVP_PKEY_verify_recover_init(ctx);
565         break;
566
567     case EVP_PKEY_OP_ENCRYPT:
568         rv = EVP_PKEY_encrypt_init(ctx);
569         break;
570
571     case EVP_PKEY_OP_DECRYPT:
572         rv = EVP_PKEY_decrypt_init(ctx);
573         break;
574
575     case EVP_PKEY_OP_DERIVE:
576         rv = EVP_PKEY_derive_init(ctx);
577         break;
578     }
579
580     if (rv <= 0) {
581         EVP_PKEY_CTX_free(ctx);
582         ctx = NULL;
583     }
584
585  end:
586     OPENSSL_free(passin);
587     return ctx;
588
589 }
590
591 static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
592                       ENGINE *e)
593 {
594     EVP_PKEY *peer = NULL;
595     ENGINE *engine = NULL;
596     int ret;
597
598     if (peerform == FORMAT_ENGINE)
599         engine = e;
600     peer = load_pubkey(file, peerform, 0, NULL, engine, "Peer Key");
601     if (peer == NULL) {
602         BIO_printf(bio_err, "Error reading peer key %s\n", file);
603         ERR_print_errors(bio_err);
604         return 0;
605     }
606
607     ret = EVP_PKEY_derive_set_peer(ctx, peer);
608
609     EVP_PKEY_free(peer);
610     if (ret <= 0)
611         ERR_print_errors(bio_err);
612     return ret;
613 }
614
615 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
616                     unsigned char *out, size_t *poutlen,
617                     const unsigned char *in, size_t inlen)
618 {
619     int rv = 0;
620     switch (pkey_op) {
621     case EVP_PKEY_OP_VERIFYRECOVER:
622         rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
623         break;
624
625     case EVP_PKEY_OP_SIGN:
626         rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
627         break;
628
629     case EVP_PKEY_OP_ENCRYPT:
630         rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
631         break;
632
633     case EVP_PKEY_OP_DECRYPT:
634         rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
635         break;
636
637     case EVP_PKEY_OP_DERIVE:
638         rv = EVP_PKEY_derive(ctx, out, poutlen);
639         break;
640
641     }
642     return rv;
643 }
644
645 #define TBUF_MAXSIZE 2048
646
647 static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx,
648                         const EVP_MD *md, EVP_PKEY *pkey, BIO *in,
649                         unsigned char *sig, int siglen,
650                         unsigned char **out, size_t *poutlen)
651 {
652     int rv = 0;
653     EVP_MD_CTX *mctx = NULL;
654     unsigned char tbuf[TBUF_MAXSIZE];
655     int tbuf_len = 0;
656
657     if ((mctx = EVP_MD_CTX_new()) == NULL) {
658         BIO_printf(bio_err, "Error: out of memory\n");
659         return rv;
660     }
661     EVP_MD_CTX_set_pkey_ctx(mctx, ctx);
662
663     switch(pkey_op) {
664     case EVP_PKEY_OP_VERIFY:
665         if (EVP_DigestVerifyInit(mctx, NULL, md, NULL, pkey) != 1)
666             goto end;
667         for (;;) {
668             tbuf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
669             if (tbuf_len == 0)
670                 break;
671             if (tbuf_len < 0) {
672                 BIO_printf(bio_err, "Error reading raw input data\n");
673                 goto end;
674             }
675             rv = EVP_DigestVerifyUpdate(mctx, tbuf, (size_t)tbuf_len);
676             if (rv != 1) {
677                 BIO_printf(bio_err, "Error verifying raw input data\n");
678                 goto end;
679             }
680         }
681         rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen);
682         break;
683     case EVP_PKEY_OP_SIGN:
684         if (EVP_DigestSignInit(mctx, NULL, md, NULL, pkey) != 1)
685             goto end;
686         for (;;) {
687             tbuf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
688             if (tbuf_len == 0)
689                 break;
690             if (tbuf_len < 0) {
691                 BIO_printf(bio_err, "Error reading raw input data\n");
692                 goto end;
693             }
694             rv = EVP_DigestSignUpdate(mctx, tbuf, (size_t)tbuf_len);
695             if (rv != 1) {
696                 BIO_printf(bio_err, "Error signing raw input data\n");
697                 goto end;
698             }
699         }
700         rv = EVP_DigestSignFinal(mctx, NULL, poutlen);
701         if (rv == 1 && out != NULL) {
702             *out = app_malloc(*poutlen, "buffer output");
703             rv = EVP_DigestSignFinal(mctx, *out, poutlen);
704         }
705         break;
706     }
707
708  end:
709     EVP_MD_CTX_free(mctx);
710     return rv;
711 }