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