xref: /netbsd-src/crypto/external/bsd/openssl/dist/apps/pkeyutl.c (revision 4778aede4608a995eaeedca856a7a71a2fa5c675)
1635165faSspz /*
2*4778aedeSchristos  * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
3a89c9211Schristos  *
4b0d17251Schristos  * Licensed under the Apache License 2.0 (the "License").  You may not use
5c7da899bSchristos  * this file except in compliance with the License.  You can obtain a copy
6c7da899bSchristos  * in the file LICENSE in the source distribution or at
7c7da899bSchristos  * https://www.openssl.org/source/license.html
8a89c9211Schristos  */
9a89c9211Schristos 
10a89c9211Schristos #include "apps.h"
1113d40330Schristos #include "progs.h"
12a89c9211Schristos #include <string.h>
13a89c9211Schristos #include <openssl/err.h>
14a89c9211Schristos #include <openssl/pem.h>
15a89c9211Schristos #include <openssl/evp.h>
16b0d17251Schristos #include <sys/stat.h>
17a89c9211Schristos 
18c7da899bSchristos #define KEY_NONE        0
19a89c9211Schristos #define KEY_PRIVKEY     1
20a89c9211Schristos #define KEY_PUBKEY      2
21a89c9211Schristos #define KEY_CERT        3
22a89c9211Schristos 
23c7da899bSchristos static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
24218f7bfcSspz                               const char *keyfile, int keyform, int key_type,
25c7da899bSchristos                               char *passinarg, int pkey_op, ENGINE *e,
26b0d17251Schristos                               const int impl, int rawin, EVP_PKEY **ppkey,
27b0d17251Schristos                               EVP_MD_CTX *mctx, const char *digestname,
28b0d17251Schristos                               OSSL_LIB_CTX *libctx, const char *propq);
29a89c9211Schristos 
30c7da899bSchristos static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
31c7da899bSchristos                       ENGINE *e);
32a89c9211Schristos 
33a89c9211Schristos static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
34a89c9211Schristos                     unsigned char *out, size_t *poutlen,
35c7da899bSchristos                     const unsigned char *in, size_t inlen);
36a89c9211Schristos 
37b0d17251Schristos static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
38b0d17251Schristos                         EVP_PKEY *pkey, BIO *in,
39b0d17251Schristos                         int filesize, unsigned char *sig, int siglen,
40b0d17251Schristos                         unsigned char **out, size_t *poutlen);
41b0d17251Schristos 
42c7da899bSchristos typedef enum OPTION_choice {
43b0d17251Schristos     OPT_COMMON,
44c7da899bSchristos     OPT_ENGINE, OPT_ENGINE_IMPL, OPT_IN, OPT_OUT,
45c7da899bSchristos     OPT_PUBIN, OPT_CERTIN, OPT_ASN1PARSE, OPT_HEXDUMP, OPT_SIGN,
46c7da899bSchristos     OPT_VERIFY, OPT_VERIFYRECOVER, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
47c7da899bSchristos     OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN,
48b0d17251Schristos     OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_PKEYOPT_PASSIN, OPT_KDF,
49b0d17251Schristos     OPT_KDFLEN, OPT_R_ENUM, OPT_PROV_ENUM,
50b0d17251Schristos     OPT_CONFIG,
51b0d17251Schristos     OPT_RAWIN, OPT_DIGEST
52c7da899bSchristos } OPTION_CHOICE;
53a89c9211Schristos 
5413d40330Schristos const OPTIONS pkeyutl_options[] = {
55b0d17251Schristos     OPT_SECTION("General"),
56c7da899bSchristos     {"help", OPT_HELP, '-', "Display this summary"},
57c7da899bSchristos #ifndef OPENSSL_NO_ENGINE
58c7da899bSchristos     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
59c7da899bSchristos     {"engine_impl", OPT_ENGINE_IMPL, '-',
60c7da899bSchristos      "Also use engine given by -engine for crypto operations"},
61c7da899bSchristos #endif
62b0d17251Schristos     {"sign", OPT_SIGN, '-', "Sign input data with private key"},
63b0d17251Schristos     {"verify", OPT_VERIFY, '-', "Verify with public key"},
64b0d17251Schristos     {"encrypt", OPT_ENCRYPT, '-', "Encrypt input data with public key"},
65b0d17251Schristos     {"decrypt", OPT_DECRYPT, '-', "Decrypt input data with private key"},
66b0d17251Schristos     {"derive", OPT_DERIVE, '-', "Derive shared secret"},
67b0d17251Schristos     OPT_CONFIG_OPTION,
68b0d17251Schristos 
69b0d17251Schristos     OPT_SECTION("Input"),
70b0d17251Schristos     {"in", OPT_IN, '<', "Input file - default stdin"},
71b0d17251Schristos     {"rawin", OPT_RAWIN, '-', "Indicate the input data is in raw form"},
72b0d17251Schristos     {"pubin", OPT_PUBIN, '-', "Input is a public key"},
73b0d17251Schristos     {"inkey", OPT_INKEY, 's', "Input private key file"},
74b0d17251Schristos     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
75b0d17251Schristos     {"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"},
76b0d17251Schristos     {"peerform", OPT_PEERFORM, 'E', "Peer key format (DER/PEM/P12/ENGINE)"},
77b0d17251Schristos     {"certin", OPT_CERTIN, '-', "Input is a cert with a public key"},
78b0d17251Schristos     {"rev", OPT_REV, '-', "Reverse the order of the input buffer"},
79b0d17251Schristos     {"sigfile", OPT_SIGFILE, '<', "Signature file (verify operation only)"},
80b0d17251Schristos     {"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"},
81b0d17251Schristos 
82b0d17251Schristos     OPT_SECTION("Output"),
83b0d17251Schristos     {"out", OPT_OUT, '>', "Output file - default stdout"},
84b0d17251Schristos     {"asn1parse", OPT_ASN1PARSE, '-', "asn1parse the output data"},
85b0d17251Schristos     {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"},
86b0d17251Schristos     {"verifyrecover", OPT_VERIFYRECOVER, '-',
87b0d17251Schristos      "Verify with public key, recover original data"},
88b0d17251Schristos 
89b0d17251Schristos     OPT_SECTION("Signing/Derivation"),
90b0d17251Schristos     {"digest", OPT_DIGEST, 's',
91b0d17251Schristos      "Specify the digest algorithm when signing the raw input data"},
92b0d17251Schristos     {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"},
93b0d17251Schristos     {"pkeyopt_passin", OPT_PKEYOPT_PASSIN, 's',
94b0d17251Schristos      "Public key option that is read as a passphrase argument opt:passphrase"},
95b0d17251Schristos     {"kdf", OPT_KDF, 's', "Use KDF algorithm"},
96b0d17251Schristos     {"kdflen", OPT_KDFLEN, 'p', "KDF algorithm output length"},
97b0d17251Schristos 
98b0d17251Schristos     OPT_R_OPTIONS,
99b0d17251Schristos     OPT_PROV_OPTIONS,
100c7da899bSchristos     {NULL}
101c7da899bSchristos };
102c7da899bSchristos 
pkeyutl_main(int argc,char ** argv)103c7da899bSchristos int pkeyutl_main(int argc, char **argv)
104a89c9211Schristos {
105b0d17251Schristos     CONF *conf = NULL;
106a89c9211Schristos     BIO *in = NULL, *out = NULL;
107a89c9211Schristos     ENGINE *e = NULL;
108a89c9211Schristos     EVP_PKEY_CTX *ctx = NULL;
109b0d17251Schristos     EVP_PKEY *pkey = NULL;
110c7da899bSchristos     char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL;
111c7da899bSchristos     char hexdump = 0, asn1parse = 0, rev = 0, *prog;
112a89c9211Schristos     unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
113c7da899bSchristos     OPTION_CHOICE o;
114b0d17251Schristos     int buf_inlen = 0, siglen = -1;
115b0d17251Schristos     int keyform = FORMAT_UNDEF, peerform = FORMAT_UNDEF;
116c7da899bSchristos     int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
117c7da899bSchristos     int engine_impl = 0;
118c7da899bSchristos     int ret = 1, rv = -1;
119c7da899bSchristos     size_t buf_outlen;
120218f7bfcSspz     const char *inkey = NULL;
121218f7bfcSspz     const char *peerkey = NULL;
122b0d17251Schristos     const char *kdfalg = NULL, *digestname = NULL;
123c7da899bSchristos     int kdflen = 0;
124218f7bfcSspz     STACK_OF(OPENSSL_STRING) *pkeyopts = NULL;
125b0d17251Schristos     STACK_OF(OPENSSL_STRING) *pkeyopts_passin = NULL;
126b0d17251Schristos     int rawin = 0;
127b0d17251Schristos     EVP_MD_CTX *mctx = NULL;
128b0d17251Schristos     EVP_MD *md = NULL;
129b0d17251Schristos     int filesize = -1;
130b0d17251Schristos     OSSL_LIB_CTX *libctx = app_get0_libctx();
131a89c9211Schristos 
132c7da899bSchristos     prog = opt_init(argc, argv, pkeyutl_options);
133c7da899bSchristos     while ((o = opt_next()) != OPT_EOF) {
134c7da899bSchristos         switch (o) {
135c7da899bSchristos         case OPT_EOF:
136c7da899bSchristos         case OPT_ERR:
137c7da899bSchristos  opthelp:
138c7da899bSchristos             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
139a89c9211Schristos             goto end;
140c7da899bSchristos         case OPT_HELP:
141c7da899bSchristos             opt_help(pkeyutl_options);
142c7da899bSchristos             ret = 0;
143c7da899bSchristos             goto end;
144c7da899bSchristos         case OPT_IN:
145c7da899bSchristos             infile = opt_arg();
146c7da899bSchristos             break;
147c7da899bSchristos         case OPT_OUT:
148c7da899bSchristos             outfile = opt_arg();
149c7da899bSchristos             break;
150c7da899bSchristos         case OPT_SIGFILE:
151c7da899bSchristos             sigfile = opt_arg();
152c7da899bSchristos             break;
153c7da899bSchristos         case OPT_ENGINE_IMPL:
154218f7bfcSspz             engine_impl = 1;
155c7da899bSchristos             break;
156c7da899bSchristos         case OPT_INKEY:
157c7da899bSchristos             inkey = opt_arg();
158c7da899bSchristos             break;
159c7da899bSchristos         case OPT_PEERKEY:
160c7da899bSchristos             peerkey = opt_arg();
161c7da899bSchristos             break;
162c7da899bSchristos         case OPT_PASSIN:
163c7da899bSchristos             passinarg = opt_arg();
164c7da899bSchristos             break;
165c7da899bSchristos         case OPT_PEERFORM:
166b0d17251Schristos             if (!opt_format(opt_arg(), OPT_FMT_ANY, &peerform))
167c7da899bSchristos                 goto opthelp;
168c7da899bSchristos             break;
169c7da899bSchristos         case OPT_KEYFORM:
170b0d17251Schristos             if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
171c7da899bSchristos                 goto opthelp;
172c7da899bSchristos             break;
17313d40330Schristos         case OPT_R_CASES:
17413d40330Schristos             if (!opt_rand(o))
17513d40330Schristos                 goto end;
17613d40330Schristos             break;
177b0d17251Schristos         case OPT_CONFIG:
178b0d17251Schristos             conf = app_load_config_modules(opt_arg());
179b0d17251Schristos             if (conf == NULL)
180b0d17251Schristos                 goto end;
181b0d17251Schristos             break;
182b0d17251Schristos         case OPT_PROV_CASES:
183b0d17251Schristos             if (!opt_provider(o))
184b0d17251Schristos                 goto end;
185b0d17251Schristos             break;
186c7da899bSchristos         case OPT_ENGINE:
187c7da899bSchristos             e = setup_engine(opt_arg(), 0);
188c7da899bSchristos             break;
189c7da899bSchristos         case OPT_PUBIN:
190a89c9211Schristos             key_type = KEY_PUBKEY;
191c7da899bSchristos             break;
192c7da899bSchristos         case OPT_CERTIN:
193a89c9211Schristos             key_type = KEY_CERT;
194c7da899bSchristos             break;
195c7da899bSchristos         case OPT_ASN1PARSE:
196a89c9211Schristos             asn1parse = 1;
197c7da899bSchristos             break;
198c7da899bSchristos         case OPT_HEXDUMP:
199a89c9211Schristos             hexdump = 1;
200c7da899bSchristos             break;
201c7da899bSchristos         case OPT_SIGN:
202a89c9211Schristos             pkey_op = EVP_PKEY_OP_SIGN;
203c7da899bSchristos             break;
204c7da899bSchristos         case OPT_VERIFY:
205a89c9211Schristos             pkey_op = EVP_PKEY_OP_VERIFY;
206c7da899bSchristos             break;
207c7da899bSchristos         case OPT_VERIFYRECOVER:
208a89c9211Schristos             pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
209c7da899bSchristos             break;
210c7da899bSchristos         case OPT_ENCRYPT:
211a89c9211Schristos             pkey_op = EVP_PKEY_OP_ENCRYPT;
212c7da899bSchristos             break;
213c7da899bSchristos         case OPT_DECRYPT:
214a89c9211Schristos             pkey_op = EVP_PKEY_OP_DECRYPT;
215c7da899bSchristos             break;
216c7da899bSchristos         case OPT_DERIVE:
217a89c9211Schristos             pkey_op = EVP_PKEY_OP_DERIVE;
218c7da899bSchristos             break;
219c7da899bSchristos         case OPT_KDF:
220c7da899bSchristos             pkey_op = EVP_PKEY_OP_DERIVE;
221c7da899bSchristos             key_type = KEY_NONE;
222c7da899bSchristos             kdfalg = opt_arg();
223c7da899bSchristos             break;
224c7da899bSchristos         case OPT_KDFLEN:
225c7da899bSchristos             kdflen = atoi(opt_arg());
226c7da899bSchristos             break;
227c7da899bSchristos         case OPT_REV:
228218f7bfcSspz             rev = 1;
229c7da899bSchristos             break;
230c7da899bSchristos         case OPT_PKEYOPT:
231c7da899bSchristos             if ((pkeyopts == NULL &&
232218f7bfcSspz                  (pkeyopts = sk_OPENSSL_STRING_new_null()) == NULL) ||
233c7da899bSchristos                 sk_OPENSSL_STRING_push(pkeyopts, opt_arg()) == 0) {
234218f7bfcSspz                 BIO_puts(bio_err, "out of memory\n");
235a89c9211Schristos                 goto end;
236a89c9211Schristos             }
237c7da899bSchristos             break;
238b0d17251Schristos         case OPT_PKEYOPT_PASSIN:
239b0d17251Schristos             if ((pkeyopts_passin == NULL &&
240b0d17251Schristos                  (pkeyopts_passin = sk_OPENSSL_STRING_new_null()) == NULL) ||
241b0d17251Schristos                 sk_OPENSSL_STRING_push(pkeyopts_passin, opt_arg()) == 0) {
242b0d17251Schristos                 BIO_puts(bio_err, "out of memory\n");
243b0d17251Schristos                 goto end;
244b0d17251Schristos             }
245b0d17251Schristos             break;
246b0d17251Schristos         case OPT_RAWIN:
247b0d17251Schristos             rawin = 1;
248b0d17251Schristos             break;
249b0d17251Schristos         case OPT_DIGEST:
250b0d17251Schristos             digestname = opt_arg();
251b0d17251Schristos             break;
252a89c9211Schristos         }
253a89c9211Schristos     }
254b0d17251Schristos 
255b0d17251Schristos     /* No extra arguments. */
256c7da899bSchristos     argc = opt_num_rest();
257c7da899bSchristos     if (argc != 0)
258c7da899bSchristos         goto opthelp;
259a89c9211Schristos 
260b0d17251Schristos     if (!app_RAND_load())
261b0d17251Schristos         goto end;
262b0d17251Schristos 
263b0d17251Schristos     if (rawin && pkey_op != EVP_PKEY_OP_SIGN && pkey_op != EVP_PKEY_OP_VERIFY) {
264b0d17251Schristos         BIO_printf(bio_err,
265b0d17251Schristos                    "%s: -rawin can only be used with -sign or -verify\n",
266b0d17251Schristos                    prog);
267b0d17251Schristos         goto opthelp;
268b0d17251Schristos     }
269b0d17251Schristos 
270b0d17251Schristos     if (digestname != NULL && !rawin) {
271b0d17251Schristos         BIO_printf(bio_err,
272b0d17251Schristos                    "%s: -digest can only be used with -rawin\n",
273b0d17251Schristos                    prog);
274b0d17251Schristos         goto opthelp;
275b0d17251Schristos     }
276b0d17251Schristos 
277b0d17251Schristos     if (rawin && rev) {
278b0d17251Schristos         BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n",
279b0d17251Schristos                    prog);
280b0d17251Schristos         goto opthelp;
281b0d17251Schristos     }
282b0d17251Schristos 
283c7da899bSchristos     if (kdfalg != NULL) {
28453060421Schristos         if (kdflen == 0) {
28553060421Schristos             BIO_printf(bio_err,
28653060421Schristos                        "%s: no KDF length given (-kdflen parameter).\n", prog);
287c7da899bSchristos             goto opthelp;
28853060421Schristos         }
28953060421Schristos     } else if (inkey == NULL) {
29053060421Schristos         BIO_printf(bio_err,
29153060421Schristos                    "%s: no private key given (-inkey parameter).\n", prog);
29253060421Schristos         goto opthelp;
29353060421Schristos     } else if (peerkey != NULL && pkey_op != EVP_PKEY_OP_DERIVE) {
29453060421Schristos         BIO_printf(bio_err,
29553060421Schristos                    "%s: no peer key given (-peerkey parameter).\n", prog);
296c7da899bSchristos         goto opthelp;
297a89c9211Schristos     }
298b0d17251Schristos 
299b0d17251Schristos     if (rawin) {
300b0d17251Schristos         if ((mctx = EVP_MD_CTX_new()) == NULL) {
301b0d17251Schristos             BIO_printf(bio_err, "Error: out of memory\n");
302b0d17251Schristos             goto end;
303b0d17251Schristos         }
304b0d17251Schristos     }
305c7da899bSchristos     ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type,
306b0d17251Schristos                    passinarg, pkey_op, e, engine_impl, rawin, &pkey,
307b0d17251Schristos                    mctx, digestname, libctx, app_get0_propq());
308c7da899bSchristos     if (ctx == NULL) {
309c7da899bSchristos         BIO_printf(bio_err, "%s: Error initializing context\n", prog);
310218f7bfcSspz         goto end;
311218f7bfcSspz     }
312c7da899bSchristos     if (peerkey != NULL && !setup_peer(ctx, peerform, peerkey, e)) {
313c7da899bSchristos         BIO_printf(bio_err, "%s: Error setting up peer key\n", prog);
314218f7bfcSspz         goto end;
315218f7bfcSspz     }
316218f7bfcSspz     if (pkeyopts != NULL) {
317218f7bfcSspz         int num = sk_OPENSSL_STRING_num(pkeyopts);
318218f7bfcSspz         int i;
319218f7bfcSspz 
320218f7bfcSspz         for (i = 0; i < num; ++i) {
321218f7bfcSspz             const char *opt = sk_OPENSSL_STRING_value(pkeyopts, i);
322218f7bfcSspz 
323218f7bfcSspz             if (pkey_ctrl_string(ctx, opt) <= 0) {
32453060421Schristos                 BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
32553060421Schristos                            prog, opt);
326218f7bfcSspz                 goto end;
327218f7bfcSspz             }
328218f7bfcSspz         }
329218f7bfcSspz     }
330b0d17251Schristos     if (pkeyopts_passin != NULL) {
331b0d17251Schristos         int num = sk_OPENSSL_STRING_num(pkeyopts_passin);
332b0d17251Schristos         int i;
333b0d17251Schristos 
334b0d17251Schristos         for (i = 0; i < num; i++) {
335b0d17251Schristos             char *opt = sk_OPENSSL_STRING_value(pkeyopts_passin, i);
336b0d17251Schristos             char *passin = strchr(opt, ':');
337b0d17251Schristos             char *passwd;
338b0d17251Schristos 
339b0d17251Schristos             if (passin == NULL) {
340b0d17251Schristos                 /* Get password interactively */
341b0d17251Schristos                 char passwd_buf[4096];
342b0d17251Schristos                 int r;
343b0d17251Schristos 
344b0d17251Schristos                 BIO_snprintf(passwd_buf, sizeof(passwd_buf), "Enter %s: ", opt);
345b0d17251Schristos                 r = EVP_read_pw_string(passwd_buf, sizeof(passwd_buf) - 1,
346b0d17251Schristos                                        passwd_buf, 0);
347b0d17251Schristos                 if (r < 0) {
348b0d17251Schristos                     if (r == -2)
349b0d17251Schristos                         BIO_puts(bio_err, "user abort\n");
350b0d17251Schristos                     else
351b0d17251Schristos                         BIO_puts(bio_err, "entry failed\n");
352b0d17251Schristos                     goto end;
353b0d17251Schristos                 }
354b0d17251Schristos                 passwd = OPENSSL_strdup(passwd_buf);
355b0d17251Schristos                 if (passwd == NULL) {
356b0d17251Schristos                     BIO_puts(bio_err, "out of memory\n");
357b0d17251Schristos                     goto end;
358b0d17251Schristos                 }
359b0d17251Schristos             } else {
360b0d17251Schristos                 /* Get password as a passin argument: First split option name
361b0d17251Schristos                  * and passphrase argument into two strings */
362b0d17251Schristos                 *passin = 0;
363b0d17251Schristos                 passin++;
364b0d17251Schristos                 if (app_passwd(passin, NULL, &passwd, NULL) == 0) {
365b0d17251Schristos                     BIO_printf(bio_err, "failed to get '%s'\n", opt);
366b0d17251Schristos                     goto end;
367b0d17251Schristos                 }
368b0d17251Schristos             }
369b0d17251Schristos 
370b0d17251Schristos             if (EVP_PKEY_CTX_ctrl_str(ctx, opt, passwd) <= 0) {
371b0d17251Schristos                 BIO_printf(bio_err, "%s: Can't set parameter \"%s\":\n",
372b0d17251Schristos                            prog, opt);
373b0d17251Schristos                 goto end;
374b0d17251Schristos             }
375b0d17251Schristos             OPENSSL_free(passwd);
376b0d17251Schristos         }
377b0d17251Schristos     }
378a89c9211Schristos 
37913d40330Schristos     if (sigfile != NULL && (pkey_op != EVP_PKEY_OP_VERIFY)) {
380c7da899bSchristos         BIO_printf(bio_err,
381c7da899bSchristos                    "%s: Signature file specified for non verify\n", prog);
382a89c9211Schristos         goto end;
383a89c9211Schristos     }
384a89c9211Schristos 
38513d40330Schristos     if (sigfile == NULL && (pkey_op == EVP_PKEY_OP_VERIFY)) {
386c7da899bSchristos         BIO_printf(bio_err,
387c7da899bSchristos                    "%s: No signature file specified for verify\n", prog);
388a89c9211Schristos         goto end;
389a89c9211Schristos     }
390a89c9211Schristos 
391635165faSspz     if (pkey_op != EVP_PKEY_OP_DERIVE) {
392c7da899bSchristos         in = bio_open_default(infile, 'r', FORMAT_BINARY);
393b0d17251Schristos         if (infile != NULL) {
394b0d17251Schristos             struct stat st;
395b0d17251Schristos 
396b0d17251Schristos             if (stat(infile, &st) == 0 && st.st_size <= INT_MAX)
397b0d17251Schristos                 filesize = (int)st.st_size;
398b0d17251Schristos         }
399c7da899bSchristos         if (in == NULL)
400a89c9211Schristos             goto end;
401a89c9211Schristos     }
402c7da899bSchristos     out = bio_open_default(outfile, 'w', FORMAT_BINARY);
403c7da899bSchristos     if (out == NULL)
404a89c9211Schristos         goto end;
405a89c9211Schristos 
40613d40330Schristos     if (sigfile != NULL) {
407a89c9211Schristos         BIO *sigbio = BIO_new_file(sigfile, "rb");
40813d40330Schristos 
40913d40330Schristos         if (sigbio == NULL) {
410635165faSspz             BIO_printf(bio_err, "Can't open signature file %s\n", sigfile);
411a89c9211Schristos             goto end;
412a89c9211Schristos         }
413a89c9211Schristos         siglen = bio_to_mem(&sig, keysize * 10, sigbio);
414a89c9211Schristos         BIO_free(sigbio);
415218f7bfcSspz         if (siglen < 0) {
416a89c9211Schristos             BIO_printf(bio_err, "Error reading signature data\n");
417a89c9211Schristos             goto end;
418a89c9211Schristos         }
419a89c9211Schristos     }
420a89c9211Schristos 
421b0d17251Schristos     /* Raw input data is handled elsewhere */
422b0d17251Schristos     if (in != NULL && !rawin) {
423a89c9211Schristos         /* Read the input data */
424*4778aedeSchristos         buf_inlen = bio_to_mem(&buf_in, -1, in);
425218f7bfcSspz         if (buf_inlen < 0) {
426a89c9211Schristos             BIO_printf(bio_err, "Error reading input Data\n");
42713d40330Schristos             goto end;
428a89c9211Schristos         }
429635165faSspz         if (rev) {
430a89c9211Schristos             size_t i;
431a89c9211Schristos             unsigned char ctmp;
432a89c9211Schristos             size_t l = (size_t)buf_inlen;
433635165faSspz             for (i = 0; i < l / 2; i++) {
434a89c9211Schristos                 ctmp = buf_in[i];
435a89c9211Schristos                 buf_in[i] = buf_in[l - 1 - i];
436a89c9211Schristos                 buf_in[l - 1 - i] = ctmp;
437a89c9211Schristos             }
438a89c9211Schristos         }
439a89c9211Schristos     }
440a89c9211Schristos 
441b0d17251Schristos     /* Sanity check the input if the input is not raw */
442b0d17251Schristos     if (!rawin
443b0d17251Schristos             && buf_inlen > EVP_MAX_MD_SIZE
44413d40330Schristos             && (pkey_op == EVP_PKEY_OP_SIGN
4457d004720Schristos                 || pkey_op == EVP_PKEY_OP_VERIFY)) {
44613d40330Schristos         BIO_printf(bio_err,
44713d40330Schristos                    "Error: The input data looks too long to be a hash\n");
44813d40330Schristos         goto end;
44913d40330Schristos     }
45013d40330Schristos 
451635165faSspz     if (pkey_op == EVP_PKEY_OP_VERIFY) {
452b0d17251Schristos         if (rawin) {
453b0d17251Schristos             rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, sig, siglen,
454b0d17251Schristos                               NULL, 0);
455b0d17251Schristos         } else {
456a89c9211Schristos             rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen,
457a89c9211Schristos                                  buf_in, (size_t)buf_inlen);
458b0d17251Schristos         }
459c7da899bSchristos         if (rv == 1) {
460a89c9211Schristos             BIO_puts(out, "Signature Verified Successfully\n");
461c7da899bSchristos             ret = 0;
46213d40330Schristos         } else {
463c7da899bSchristos             BIO_puts(out, "Signature Verification Failure\n");
46413d40330Schristos         }
465a89c9211Schristos         goto end;
466c7da899bSchristos     }
467b0d17251Schristos     if (rawin) {
468b0d17251Schristos         /* rawin allocates the buffer in do_raw_keyop() */
469b0d17251Schristos         rv = do_raw_keyop(pkey_op, mctx, pkey, in, filesize, NULL, 0,
470b0d17251Schristos                           &buf_out, (size_t *)&buf_outlen);
471b0d17251Schristos     } else {
472c7da899bSchristos         if (kdflen != 0) {
473c7da899bSchristos             buf_outlen = kdflen;
474c7da899bSchristos             rv = 1;
475635165faSspz         } else {
476a89c9211Schristos             rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
477a89c9211Schristos                           buf_in, (size_t)buf_inlen);
478c7da899bSchristos         }
479218f7bfcSspz         if (rv > 0 && buf_outlen != 0) {
480c7da899bSchristos             buf_out = app_malloc(buf_outlen, "buffer output");
481a89c9211Schristos             rv = do_keyop(ctx, pkey_op,
482a89c9211Schristos                           buf_out, (size_t *)&buf_outlen,
483a89c9211Schristos                           buf_in, (size_t)buf_inlen);
484a89c9211Schristos         }
485b0d17251Schristos     }
486635165faSspz     if (rv <= 0) {
48753060421Schristos         if (pkey_op != EVP_PKEY_OP_DERIVE) {
488c7da899bSchristos             BIO_puts(bio_err, "Public Key operation error\n");
48953060421Schristos         } else {
49053060421Schristos             BIO_puts(bio_err, "Key derivation failed\n");
49153060421Schristos         }
492a89c9211Schristos         goto end;
493a89c9211Schristos     }
494a89c9211Schristos     ret = 0;
495c7da899bSchristos 
496635165faSspz     if (asn1parse) {
497a89c9211Schristos         if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
498b0d17251Schristos             ERR_print_errors(bio_err); /* but still return success */
49913d40330Schristos     } else if (hexdump) {
500a89c9211Schristos         BIO_dump(out, (char *)buf_out, buf_outlen);
50113d40330Schristos     } else {
502a89c9211Schristos         BIO_write(out, buf_out, buf_outlen);
50313d40330Schristos     }
504a89c9211Schristos 
505a89c9211Schristos  end:
506b0d17251Schristos     if (ret != 0)
507b0d17251Schristos         ERR_print_errors(bio_err);
508b0d17251Schristos     EVP_MD_CTX_free(mctx);
509a89c9211Schristos     EVP_PKEY_CTX_free(ctx);
510b0d17251Schristos     EVP_MD_free(md);
51134505c60Sspz     release_engine(e);
512a89c9211Schristos     BIO_free(in);
513a89c9211Schristos     BIO_free_all(out);
514a89c9211Schristos     OPENSSL_free(buf_in);
515a89c9211Schristos     OPENSSL_free(buf_out);
516a89c9211Schristos     OPENSSL_free(sig);
517218f7bfcSspz     sk_OPENSSL_STRING_free(pkeyopts);
518b0d17251Schristos     sk_OPENSSL_STRING_free(pkeyopts_passin);
519b0d17251Schristos     NCONF_free(conf);
520a89c9211Schristos     return ret;
521a89c9211Schristos }
522a89c9211Schristos 
init_ctx(const char * kdfalg,int * pkeysize,const char * keyfile,int keyform,int key_type,char * passinarg,int pkey_op,ENGINE * e,const int engine_impl,int rawin,EVP_PKEY ** ppkey,EVP_MD_CTX * mctx,const char * digestname,OSSL_LIB_CTX * libctx,const char * propq)523c7da899bSchristos static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
524218f7bfcSspz                               const char *keyfile, int keyform, int key_type,
525c7da899bSchristos                               char *passinarg, int pkey_op, ENGINE *e,
526b0d17251Schristos                               const int engine_impl, int rawin,
527b0d17251Schristos                               EVP_PKEY **ppkey, EVP_MD_CTX *mctx, const char *digestname,
528b0d17251Schristos                               OSSL_LIB_CTX *libctx, const char *propq)
529a89c9211Schristos {
530a89c9211Schristos     EVP_PKEY *pkey = NULL;
531a89c9211Schristos     EVP_PKEY_CTX *ctx = NULL;
532218f7bfcSspz     ENGINE *impl = NULL;
533a89c9211Schristos     char *passin = NULL;
534a89c9211Schristos     int rv = -1;
535a89c9211Schristos     X509 *x;
536b0d17251Schristos 
537a89c9211Schristos     if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)
538a89c9211Schristos          || (pkey_op == EVP_PKEY_OP_DERIVE))
539c7da899bSchristos         && (key_type != KEY_PRIVKEY && kdfalg == NULL)) {
540a89c9211Schristos         BIO_printf(bio_err, "A private key is needed for this operation\n");
541a89c9211Schristos         goto end;
542a89c9211Schristos     }
543c7da899bSchristos     if (!app_passwd(passinarg, NULL, &passin, NULL)) {
544a89c9211Schristos         BIO_printf(bio_err, "Error getting password\n");
545a89c9211Schristos         goto end;
546a89c9211Schristos     }
547635165faSspz     switch (key_type) {
548a89c9211Schristos     case KEY_PRIVKEY:
549b0d17251Schristos         pkey = load_key(keyfile, keyform, 0, passin, e, "private key");
550a89c9211Schristos         break;
551a89c9211Schristos 
552a89c9211Schristos     case KEY_PUBKEY:
553b0d17251Schristos         pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "public key");
554a89c9211Schristos         break;
555a89c9211Schristos 
556a89c9211Schristos     case KEY_CERT:
557c7da899bSchristos         x = load_cert(keyfile, keyform, "Certificate");
558635165faSspz         if (x) {
559a89c9211Schristos             pkey = X509_get_pubkey(x);
560a89c9211Schristos             X509_free(x);
561a89c9211Schristos         }
562a89c9211Schristos         break;
563a89c9211Schristos 
564c7da899bSchristos     case KEY_NONE:
565c7da899bSchristos         break;
566c7da899bSchristos 
567a89c9211Schristos     }
568a89c9211Schristos 
569218f7bfcSspz #ifndef OPENSSL_NO_ENGINE
570218f7bfcSspz     if (engine_impl)
571218f7bfcSspz         impl = e;
572218f7bfcSspz #endif
573218f7bfcSspz 
57413d40330Schristos     if (kdfalg != NULL) {
575c7da899bSchristos         int kdfnid = OBJ_sn2nid(kdfalg);
57653060421Schristos 
57753060421Schristos         if (kdfnid == NID_undef) {
57853060421Schristos             kdfnid = OBJ_ln2nid(kdfalg);
57953060421Schristos             if (kdfnid == NID_undef) {
58053060421Schristos                 BIO_printf(bio_err, "The given KDF \"%s\" is unknown.\n",
58153060421Schristos                            kdfalg);
582c7da899bSchristos                 goto end;
58353060421Schristos             }
58453060421Schristos         }
585b0d17251Schristos         if (impl != NULL)
586c7da899bSchristos             ctx = EVP_PKEY_CTX_new_id(kdfnid, impl);
587b0d17251Schristos         else
588b0d17251Schristos             ctx = EVP_PKEY_CTX_new_from_name(libctx, kdfalg, propq);
589c7da899bSchristos     } else {
590c7da899bSchristos         if (pkey == NULL)
591c7da899bSchristos             goto end;
592b0d17251Schristos 
593b0d17251Schristos         *pkeysize = EVP_PKEY_get_size(pkey);
594b0d17251Schristos         if (impl != NULL)
595218f7bfcSspz             ctx = EVP_PKEY_CTX_new(pkey, impl);
596b0d17251Schristos         else
597b0d17251Schristos             ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
598b0d17251Schristos         if (ppkey != NULL)
599b0d17251Schristos             *ppkey = pkey;
600a89c9211Schristos         EVP_PKEY_free(pkey);
601c7da899bSchristos     }
602a89c9211Schristos 
603c7da899bSchristos     if (ctx == NULL)
604a89c9211Schristos         goto end;
605a89c9211Schristos 
606b0d17251Schristos     if (rawin) {
607b0d17251Schristos         EVP_MD_CTX_set_pkey_ctx(mctx, ctx);
608b0d17251Schristos 
609b0d17251Schristos         switch (pkey_op) {
610b0d17251Schristos         case EVP_PKEY_OP_SIGN:
611b0d17251Schristos             rv = EVP_DigestSignInit_ex(mctx, NULL, digestname, libctx, propq,
612b0d17251Schristos                                        pkey, NULL);
613b0d17251Schristos             break;
614b0d17251Schristos 
615b0d17251Schristos         case EVP_PKEY_OP_VERIFY:
616b0d17251Schristos             rv = EVP_DigestVerifyInit_ex(mctx, NULL, digestname, libctx, propq,
617b0d17251Schristos                                          pkey, NULL);
618b0d17251Schristos             break;
619b0d17251Schristos         }
620b0d17251Schristos 
621b0d17251Schristos     } else {
622635165faSspz         switch (pkey_op) {
623a89c9211Schristos         case EVP_PKEY_OP_SIGN:
624a89c9211Schristos             rv = EVP_PKEY_sign_init(ctx);
625a89c9211Schristos             break;
626a89c9211Schristos 
627a89c9211Schristos         case EVP_PKEY_OP_VERIFY:
628a89c9211Schristos             rv = EVP_PKEY_verify_init(ctx);
629a89c9211Schristos             break;
630a89c9211Schristos 
631a89c9211Schristos         case EVP_PKEY_OP_VERIFYRECOVER:
632a89c9211Schristos             rv = EVP_PKEY_verify_recover_init(ctx);
633a89c9211Schristos             break;
634a89c9211Schristos 
635a89c9211Schristos         case EVP_PKEY_OP_ENCRYPT:
636a89c9211Schristos             rv = EVP_PKEY_encrypt_init(ctx);
637a89c9211Schristos             break;
638a89c9211Schristos 
639a89c9211Schristos         case EVP_PKEY_OP_DECRYPT:
640a89c9211Schristos             rv = EVP_PKEY_decrypt_init(ctx);
641a89c9211Schristos             break;
642a89c9211Schristos 
643a89c9211Schristos         case EVP_PKEY_OP_DERIVE:
644a89c9211Schristos             rv = EVP_PKEY_derive_init(ctx);
645a89c9211Schristos             break;
646a89c9211Schristos         }
647b0d17251Schristos     }
648a89c9211Schristos 
649635165faSspz     if (rv <= 0) {
650a89c9211Schristos         EVP_PKEY_CTX_free(ctx);
651a89c9211Schristos         ctx = NULL;
652a89c9211Schristos     }
653a89c9211Schristos 
654a89c9211Schristos  end:
655a89c9211Schristos     OPENSSL_free(passin);
656a89c9211Schristos     return ctx;
657a89c9211Schristos 
658a89c9211Schristos }
659a89c9211Schristos 
setup_peer(EVP_PKEY_CTX * ctx,int peerform,const char * file,ENGINE * e)660c7da899bSchristos static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file,
661c7da899bSchristos                       ENGINE *e)
662a89c9211Schristos {
663a89c9211Schristos     EVP_PKEY *peer = NULL;
664218f7bfcSspz     ENGINE *engine = NULL;
665a89c9211Schristos     int ret;
666a89c9211Schristos 
667218f7bfcSspz     if (peerform == FORMAT_ENGINE)
668218f7bfcSspz         engine = e;
669b0d17251Schristos     peer = load_pubkey(file, peerform, 0, NULL, engine, "peer key");
67013d40330Schristos     if (peer == NULL) {
671a89c9211Schristos         BIO_printf(bio_err, "Error reading peer key %s\n", file);
672a89c9211Schristos         return 0;
673a89c9211Schristos     }
674a89c9211Schristos 
675b0d17251Schristos     ret = EVP_PKEY_derive_set_peer(ctx, peer) > 0;
676a89c9211Schristos 
677a89c9211Schristos     EVP_PKEY_free(peer);
678a89c9211Schristos     return ret;
679a89c9211Schristos }
680a89c9211Schristos 
do_keyop(EVP_PKEY_CTX * ctx,int pkey_op,unsigned char * out,size_t * poutlen,const unsigned char * in,size_t inlen)681a89c9211Schristos static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
682a89c9211Schristos                     unsigned char *out, size_t *poutlen,
683c7da899bSchristos                     const unsigned char *in, size_t inlen)
684a89c9211Schristos {
685a89c9211Schristos     int rv = 0;
686635165faSspz     switch (pkey_op) {
687a89c9211Schristos     case EVP_PKEY_OP_VERIFYRECOVER:
688a89c9211Schristos         rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
689a89c9211Schristos         break;
690a89c9211Schristos 
691a89c9211Schristos     case EVP_PKEY_OP_SIGN:
692a89c9211Schristos         rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
693a89c9211Schristos         break;
694a89c9211Schristos 
695a89c9211Schristos     case EVP_PKEY_OP_ENCRYPT:
696a89c9211Schristos         rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
697a89c9211Schristos         break;
698a89c9211Schristos 
699a89c9211Schristos     case EVP_PKEY_OP_DECRYPT:
700a89c9211Schristos         rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
701a89c9211Schristos         break;
702a89c9211Schristos 
703a89c9211Schristos     case EVP_PKEY_OP_DERIVE:
704a89c9211Schristos         rv = EVP_PKEY_derive(ctx, out, poutlen);
705a89c9211Schristos         break;
706a89c9211Schristos 
707a89c9211Schristos     }
708a89c9211Schristos     return rv;
709a89c9211Schristos }
710b0d17251Schristos 
711b0d17251Schristos #define TBUF_MAXSIZE 2048
712b0d17251Schristos 
do_raw_keyop(int pkey_op,EVP_MD_CTX * mctx,EVP_PKEY * pkey,BIO * in,int filesize,unsigned char * sig,int siglen,unsigned char ** out,size_t * poutlen)713b0d17251Schristos static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx,
714b0d17251Schristos                         EVP_PKEY *pkey, BIO *in,
715b0d17251Schristos                         int filesize, unsigned char *sig, int siglen,
716b0d17251Schristos                         unsigned char **out, size_t *poutlen)
717b0d17251Schristos {
718b0d17251Schristos     int rv = 0;
719b0d17251Schristos     unsigned char tbuf[TBUF_MAXSIZE];
720b0d17251Schristos     unsigned char *mbuf = NULL;
721b0d17251Schristos     int buf_len = 0;
722b0d17251Schristos 
723b0d17251Schristos     /* Some algorithms only support oneshot digests */
724b0d17251Schristos     if (EVP_PKEY_get_id(pkey) == EVP_PKEY_ED25519
725b0d17251Schristos             || EVP_PKEY_get_id(pkey) == EVP_PKEY_ED448) {
726b0d17251Schristos         if (filesize < 0) {
727b0d17251Schristos             BIO_printf(bio_err,
728b0d17251Schristos                        "Error: unable to determine file size for oneshot operation\n");
729b0d17251Schristos             goto end;
730b0d17251Schristos         }
731b0d17251Schristos         mbuf = app_malloc(filesize, "oneshot sign/verify buffer");
732b0d17251Schristos         switch(pkey_op) {
733b0d17251Schristos         case EVP_PKEY_OP_VERIFY:
734b0d17251Schristos             buf_len = BIO_read(in, mbuf, filesize);
735b0d17251Schristos             if (buf_len != filesize) {
736b0d17251Schristos                 BIO_printf(bio_err, "Error reading raw input data\n");
737b0d17251Schristos                 goto end;
738b0d17251Schristos             }
739b0d17251Schristos             rv = EVP_DigestVerify(mctx, sig, (size_t)siglen, mbuf, buf_len);
740b0d17251Schristos             break;
741b0d17251Schristos         case EVP_PKEY_OP_SIGN:
742b0d17251Schristos             buf_len = BIO_read(in, mbuf, filesize);
743b0d17251Schristos             if (buf_len != filesize) {
744b0d17251Schristos                 BIO_printf(bio_err, "Error reading raw input data\n");
745b0d17251Schristos                 goto end;
746b0d17251Schristos             }
747b0d17251Schristos             rv = EVP_DigestSign(mctx, NULL, poutlen, mbuf, buf_len);
748b0d17251Schristos             if (rv == 1 && out != NULL) {
749b0d17251Schristos                 *out = app_malloc(*poutlen, "buffer output");
750b0d17251Schristos                 rv = EVP_DigestSign(mctx, *out, poutlen, mbuf, buf_len);
751b0d17251Schristos             }
752b0d17251Schristos             break;
753b0d17251Schristos         }
754b0d17251Schristos         goto end;
755b0d17251Schristos     }
756b0d17251Schristos 
757b0d17251Schristos     switch(pkey_op) {
758b0d17251Schristos     case EVP_PKEY_OP_VERIFY:
759b0d17251Schristos         for (;;) {
760b0d17251Schristos             buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
761b0d17251Schristos             if (buf_len == 0)
762b0d17251Schristos                 break;
763b0d17251Schristos             if (buf_len < 0) {
764b0d17251Schristos                 BIO_printf(bio_err, "Error reading raw input data\n");
765b0d17251Schristos                 goto end;
766b0d17251Schristos             }
767b0d17251Schristos             rv = EVP_DigestVerifyUpdate(mctx, tbuf, (size_t)buf_len);
768b0d17251Schristos             if (rv != 1) {
769b0d17251Schristos                 BIO_printf(bio_err, "Error verifying raw input data\n");
770b0d17251Schristos                 goto end;
771b0d17251Schristos             }
772b0d17251Schristos         }
773b0d17251Schristos         rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen);
774b0d17251Schristos         break;
775b0d17251Schristos     case EVP_PKEY_OP_SIGN:
776b0d17251Schristos         for (;;) {
777b0d17251Schristos             buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
778b0d17251Schristos             if (buf_len == 0)
779b0d17251Schristos                 break;
780b0d17251Schristos             if (buf_len < 0) {
781b0d17251Schristos                 BIO_printf(bio_err, "Error reading raw input data\n");
782b0d17251Schristos                 goto end;
783b0d17251Schristos             }
784b0d17251Schristos             rv = EVP_DigestSignUpdate(mctx, tbuf, (size_t)buf_len);
785b0d17251Schristos             if (rv != 1) {
786b0d17251Schristos                 BIO_printf(bio_err, "Error signing raw input data\n");
787b0d17251Schristos                 goto end;
788b0d17251Schristos             }
789b0d17251Schristos         }
790b0d17251Schristos         rv = EVP_DigestSignFinal(mctx, NULL, poutlen);
791b0d17251Schristos         if (rv == 1 && out != NULL) {
792b0d17251Schristos             *out = app_malloc(*poutlen, "buffer output");
793b0d17251Schristos             rv = EVP_DigestSignFinal(mctx, *out, poutlen);
794b0d17251Schristos         }
795b0d17251Schristos         break;
796b0d17251Schristos     }
797b0d17251Schristos 
798b0d17251Schristos  end:
799b0d17251Schristos     OPENSSL_free(mbuf);
800b0d17251Schristos     return rv;
801b0d17251Schristos }
802