1*440d1414Stb /* $OpenBSD: pkeyutl.c,v 1.20 2023/07/23 11:39:29 tb Exp $ */
2dab3f910Sjsing /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3dab3f910Sjsing * project 2006.
4dab3f910Sjsing */
5dab3f910Sjsing /* ====================================================================
6dab3f910Sjsing * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
7dab3f910Sjsing *
8dab3f910Sjsing * Redistribution and use in source and binary forms, with or without
9dab3f910Sjsing * modification, are permitted provided that the following conditions
10dab3f910Sjsing * are met:
11dab3f910Sjsing *
12dab3f910Sjsing * 1. Redistributions of source code must retain the above copyright
13dab3f910Sjsing * notice, this list of conditions and the following disclaimer.
14dab3f910Sjsing *
15dab3f910Sjsing * 2. Redistributions in binary form must reproduce the above copyright
16dab3f910Sjsing * notice, this list of conditions and the following disclaimer in
17dab3f910Sjsing * the documentation and/or other materials provided with the
18dab3f910Sjsing * distribution.
19dab3f910Sjsing *
20dab3f910Sjsing * 3. All advertising materials mentioning features or use of this
21dab3f910Sjsing * software must display the following acknowledgment:
22dab3f910Sjsing * "This product includes software developed by the OpenSSL Project
23dab3f910Sjsing * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24dab3f910Sjsing *
25dab3f910Sjsing * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26dab3f910Sjsing * endorse or promote products derived from this software without
27dab3f910Sjsing * prior written permission. For written permission, please contact
28dab3f910Sjsing * licensing@OpenSSL.org.
29dab3f910Sjsing *
30dab3f910Sjsing * 5. Products derived from this software may not be called "OpenSSL"
31dab3f910Sjsing * nor may "OpenSSL" appear in their names without prior written
32dab3f910Sjsing * permission of the OpenSSL Project.
33dab3f910Sjsing *
34dab3f910Sjsing * 6. Redistributions of any form whatsoever must retain the following
35dab3f910Sjsing * acknowledgment:
36dab3f910Sjsing * "This product includes software developed by the OpenSSL Project
37dab3f910Sjsing * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38dab3f910Sjsing *
39dab3f910Sjsing * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40dab3f910Sjsing * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41dab3f910Sjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42dab3f910Sjsing * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43dab3f910Sjsing * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44dab3f910Sjsing * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45dab3f910Sjsing * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46dab3f910Sjsing * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47dab3f910Sjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48dab3f910Sjsing * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49dab3f910Sjsing * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50dab3f910Sjsing * OF THE POSSIBILITY OF SUCH DAMAGE.
51dab3f910Sjsing * ====================================================================
52dab3f910Sjsing *
53dab3f910Sjsing * This product includes cryptographic software written by Eric Young
54dab3f910Sjsing * (eay@cryptsoft.com). This product includes software written by Tim
55dab3f910Sjsing * Hudson (tjh@cryptsoft.com).
56dab3f910Sjsing *
57dab3f910Sjsing */
58dab3f910Sjsing
59dab3f910Sjsing #include <string.h>
60dab3f910Sjsing
61dab3f910Sjsing #include "apps.h"
62dab3f910Sjsing
63dab3f910Sjsing #include <openssl/err.h>
64dab3f910Sjsing #include <openssl/evp.h>
65dab3f910Sjsing #include <openssl/pem.h>
66dab3f910Sjsing
67dab3f910Sjsing #define KEY_PRIVKEY 1
68dab3f910Sjsing #define KEY_PUBKEY 2
69dab3f910Sjsing #define KEY_CERT 3
70dab3f910Sjsing
71efc7e65fStb static struct {
7206aa0bd7Sinoguchi int asn1parse;
7306aa0bd7Sinoguchi EVP_PKEY_CTX *ctx;
7406aa0bd7Sinoguchi int hexdump;
7506aa0bd7Sinoguchi char *infile;
7606aa0bd7Sinoguchi int key_type;
7706aa0bd7Sinoguchi int keyform;
7806aa0bd7Sinoguchi int keysize;
7906aa0bd7Sinoguchi char *outfile;
8006aa0bd7Sinoguchi char *passargin;
8106aa0bd7Sinoguchi int peerform;
8206aa0bd7Sinoguchi int pkey_op;
8306aa0bd7Sinoguchi int rev;
8406aa0bd7Sinoguchi char *sigfile;
85e7718adaStb } cfg;
86dab3f910Sjsing
8706aa0bd7Sinoguchi static void pkeyutl_usage(void);
88dab3f910Sjsing
8906aa0bd7Sinoguchi static int init_ctx(char *keyfile);
9006aa0bd7Sinoguchi
9106aa0bd7Sinoguchi static int setup_peer(char *file);
9206aa0bd7Sinoguchi
9306aa0bd7Sinoguchi static int pkeyutl_pkeyopt(char *pkeyopt);
94dab3f910Sjsing
95dab3f910Sjsing static int do_keyop(EVP_PKEY_CTX * ctx, int pkey_op,
96dab3f910Sjsing unsigned char *out, size_t * poutlen,
97dab3f910Sjsing unsigned char *in, size_t inlen);
98dab3f910Sjsing
99ea149709Sguenther static const struct option pkeyutl_options[] = {
10006aa0bd7Sinoguchi {
10106aa0bd7Sinoguchi .name = "asn1parse",
10206aa0bd7Sinoguchi .desc = "ASN.1 parse the output data",
10306aa0bd7Sinoguchi .type = OPTION_FLAG,
104e7718adaStb .opt.flag = &cfg.asn1parse,
10506aa0bd7Sinoguchi },
10606aa0bd7Sinoguchi {
10706aa0bd7Sinoguchi .name = "certin",
10806aa0bd7Sinoguchi .desc = "Input is a certificate containing a public key",
10906aa0bd7Sinoguchi .type = OPTION_VALUE,
11006aa0bd7Sinoguchi .value = KEY_CERT,
111e7718adaStb .opt.value = &cfg.key_type,
11206aa0bd7Sinoguchi },
11306aa0bd7Sinoguchi {
11406aa0bd7Sinoguchi .name = "decrypt",
11506aa0bd7Sinoguchi .desc = "Decrypt the input data using a private key",
11606aa0bd7Sinoguchi .type = OPTION_VALUE,
11706aa0bd7Sinoguchi .value = EVP_PKEY_OP_DECRYPT,
118e7718adaStb .opt.value = &cfg.pkey_op,
11906aa0bd7Sinoguchi },
12006aa0bd7Sinoguchi {
12106aa0bd7Sinoguchi .name = "derive",
12206aa0bd7Sinoguchi .desc = "Derive a shared secret using the peer key",
12306aa0bd7Sinoguchi .type = OPTION_VALUE,
12406aa0bd7Sinoguchi .value = EVP_PKEY_OP_DERIVE,
125e7718adaStb .opt.value = &cfg.pkey_op,
12606aa0bd7Sinoguchi },
12706aa0bd7Sinoguchi {
12806aa0bd7Sinoguchi .name = "encrypt",
12906aa0bd7Sinoguchi .desc = "Encrypt the input data using a public key",
13006aa0bd7Sinoguchi .type = OPTION_VALUE,
13106aa0bd7Sinoguchi .value = EVP_PKEY_OP_ENCRYPT,
132e7718adaStb .opt.value = &cfg.pkey_op,
13306aa0bd7Sinoguchi },
13406aa0bd7Sinoguchi {
13506aa0bd7Sinoguchi .name = "hexdump",
13606aa0bd7Sinoguchi .desc = "Hex dump the output data",
13706aa0bd7Sinoguchi .type = OPTION_FLAG,
138e7718adaStb .opt.flag = &cfg.hexdump,
13906aa0bd7Sinoguchi },
14006aa0bd7Sinoguchi {
14106aa0bd7Sinoguchi .name = "in",
14206aa0bd7Sinoguchi .argname = "file",
14306aa0bd7Sinoguchi .desc = "Input file (default stdin)",
14406aa0bd7Sinoguchi .type = OPTION_ARG,
145e7718adaStb .opt.arg = &cfg.infile,
14606aa0bd7Sinoguchi },
14706aa0bd7Sinoguchi {
14806aa0bd7Sinoguchi .name = "inkey",
14906aa0bd7Sinoguchi .argname = "file",
15006aa0bd7Sinoguchi .desc = "Input key file",
15106aa0bd7Sinoguchi .type = OPTION_ARG_FUNC,
15206aa0bd7Sinoguchi .opt.argfunc = init_ctx,
15306aa0bd7Sinoguchi },
15406aa0bd7Sinoguchi {
15506aa0bd7Sinoguchi .name = "keyform",
15606aa0bd7Sinoguchi .argname = "fmt",
15706aa0bd7Sinoguchi .desc = "Input key format (DER or PEM (default))",
15806aa0bd7Sinoguchi .type = OPTION_ARG_FORMAT,
159e7718adaStb .opt.value = &cfg.keyform,
16006aa0bd7Sinoguchi },
16106aa0bd7Sinoguchi {
16206aa0bd7Sinoguchi .name = "out",
16306aa0bd7Sinoguchi .argname = "file",
16406aa0bd7Sinoguchi .desc = "Output file (default stdout)",
16506aa0bd7Sinoguchi .type = OPTION_ARG,
166e7718adaStb .opt.arg = &cfg.outfile,
16706aa0bd7Sinoguchi },
16806aa0bd7Sinoguchi {
16906aa0bd7Sinoguchi .name = "passin",
17006aa0bd7Sinoguchi .argname = "arg",
17106aa0bd7Sinoguchi .desc = "Key password source",
17206aa0bd7Sinoguchi .type = OPTION_ARG,
173e7718adaStb .opt.arg = &cfg.passargin,
17406aa0bd7Sinoguchi },
17506aa0bd7Sinoguchi {
17606aa0bd7Sinoguchi .name = "peerform",
17706aa0bd7Sinoguchi .argname = "fmt",
17806aa0bd7Sinoguchi .desc = "Input key format (DER or PEM (default))",
17906aa0bd7Sinoguchi .type = OPTION_ARG_FORMAT,
180e7718adaStb .opt.value = &cfg.peerform,
18106aa0bd7Sinoguchi },
18206aa0bd7Sinoguchi {
18306aa0bd7Sinoguchi .name = "peerkey",
18406aa0bd7Sinoguchi .argname = "file",
18506aa0bd7Sinoguchi .desc = "Peer key file",
18606aa0bd7Sinoguchi .type = OPTION_ARG_FUNC,
18706aa0bd7Sinoguchi .opt.argfunc = setup_peer,
18806aa0bd7Sinoguchi },
18906aa0bd7Sinoguchi {
19006aa0bd7Sinoguchi .name = "pkeyopt",
19106aa0bd7Sinoguchi .argname = "opt:value",
19206aa0bd7Sinoguchi .desc = "Public key options",
19306aa0bd7Sinoguchi .type = OPTION_ARG_FUNC,
19406aa0bd7Sinoguchi .opt.argfunc = pkeyutl_pkeyopt,
19506aa0bd7Sinoguchi },
19606aa0bd7Sinoguchi {
19706aa0bd7Sinoguchi .name = "pubin",
19806aa0bd7Sinoguchi .desc = "Input is a public key",
19906aa0bd7Sinoguchi .type = OPTION_VALUE,
20006aa0bd7Sinoguchi .value = KEY_PUBKEY,
201e7718adaStb .opt.value = &cfg.key_type,
20206aa0bd7Sinoguchi },
20306aa0bd7Sinoguchi {
20406aa0bd7Sinoguchi .name = "rev",
20506aa0bd7Sinoguchi .desc = "Reverse the input data",
20606aa0bd7Sinoguchi .type = OPTION_FLAG,
207e7718adaStb .opt.flag = &cfg.rev,
20806aa0bd7Sinoguchi },
20906aa0bd7Sinoguchi {
21006aa0bd7Sinoguchi .name = "sigfile",
21106aa0bd7Sinoguchi .argname = "file",
21206aa0bd7Sinoguchi .desc = "Signature file (verify operation only)",
21306aa0bd7Sinoguchi .type = OPTION_ARG,
214e7718adaStb .opt.arg = &cfg.sigfile,
21506aa0bd7Sinoguchi },
21606aa0bd7Sinoguchi {
21706aa0bd7Sinoguchi .name = "sign",
21806aa0bd7Sinoguchi .desc = "Sign the input data using private key",
21906aa0bd7Sinoguchi .type = OPTION_VALUE,
22006aa0bd7Sinoguchi .value = EVP_PKEY_OP_SIGN,
221e7718adaStb .opt.value = &cfg.pkey_op,
22206aa0bd7Sinoguchi },
22306aa0bd7Sinoguchi {
22406aa0bd7Sinoguchi .name = "verify",
22506aa0bd7Sinoguchi .desc = "Verify the input data using public key",
22606aa0bd7Sinoguchi .type = OPTION_VALUE,
22706aa0bd7Sinoguchi .value = EVP_PKEY_OP_VERIFY,
228e7718adaStb .opt.value = &cfg.pkey_op,
22906aa0bd7Sinoguchi },
23006aa0bd7Sinoguchi {
23106aa0bd7Sinoguchi .name = "verifyrecover",
23206aa0bd7Sinoguchi .desc = "Verify with public key, recover original data",
23306aa0bd7Sinoguchi .type = OPTION_VALUE,
23406aa0bd7Sinoguchi .value = EVP_PKEY_OP_VERIFYRECOVER,
235e7718adaStb .opt.value = &cfg.pkey_op,
23606aa0bd7Sinoguchi },
23706aa0bd7Sinoguchi
23806aa0bd7Sinoguchi {NULL},
23906aa0bd7Sinoguchi };
24006aa0bd7Sinoguchi
24106aa0bd7Sinoguchi static void
pkeyutl_usage(void)242*440d1414Stb pkeyutl_usage(void)
24306aa0bd7Sinoguchi {
24406aa0bd7Sinoguchi fprintf(stderr,
24506aa0bd7Sinoguchi "usage: pkeyutl [-asn1parse] [-certin] [-decrypt] [-derive] "
24606aa0bd7Sinoguchi "[-encrypt]\n"
24706aa0bd7Sinoguchi " [-hexdump] [-in file] [-inkey file] [-keyform fmt]\n"
24806aa0bd7Sinoguchi " [-out file] [-passin arg] [-peerform fmt]\n"
24906aa0bd7Sinoguchi " [-peerkey file] [-pkeyopt opt:value] [-pubin] [-rev]\n"
25006aa0bd7Sinoguchi " [-sigfile file] [-sign] [-verify] [-verifyrecover]\n\n");
25106aa0bd7Sinoguchi options_usage(pkeyutl_options);
25206aa0bd7Sinoguchi fprintf(stderr, "\n");
25306aa0bd7Sinoguchi }
25406aa0bd7Sinoguchi
255dab3f910Sjsing int
pkeyutl_main(int argc,char ** argv)256dab3f910Sjsing pkeyutl_main(int argc, char **argv)
257dab3f910Sjsing {
258dab3f910Sjsing BIO *in = NULL, *out = NULL;
259dab3f910Sjsing
260dab3f910Sjsing unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
261e79bb433Sinoguchi size_t buf_outlen = 0;
262dab3f910Sjsing int buf_inlen = 0, siglen = -1;
263dab3f910Sjsing
264dab3f910Sjsing int ret = 1, rv = -1;
265dab3f910Sjsing
26651811eadSderaadt if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
2679bc487adSdoug perror("pledge");
268e370f0eeSdoug exit(1);
269e370f0eeSdoug }
2709bc487adSdoug
271e7718adaStb memset(&cfg, 0, sizeof(cfg));
272e7718adaStb cfg.pkey_op = EVP_PKEY_OP_SIGN;
273e7718adaStb cfg.key_type = KEY_PRIVKEY;
274e7718adaStb cfg.keyform = FORMAT_PEM;
275e7718adaStb cfg.peerform = FORMAT_PEM;
276e7718adaStb cfg.keysize = -1;
277dab3f910Sjsing
27806aa0bd7Sinoguchi if (options_parse(argc, argv, pkeyutl_options, NULL, NULL) != 0) {
27906aa0bd7Sinoguchi pkeyutl_usage();
280dab3f910Sjsing goto end;
281dab3f910Sjsing }
282dab3f910Sjsing
283e7718adaStb if (!cfg.ctx) {
28406aa0bd7Sinoguchi pkeyutl_usage();
285dab3f910Sjsing goto end;
286dab3f910Sjsing }
287e7718adaStb if (cfg.sigfile &&
288e7718adaStb (cfg.pkey_op != EVP_PKEY_OP_VERIFY)) {
289dab3f910Sjsing BIO_puts(bio_err, "Signature file specified for non verify\n");
290dab3f910Sjsing goto end;
291dab3f910Sjsing }
292e7718adaStb if (!cfg.sigfile &&
293e7718adaStb (cfg.pkey_op == EVP_PKEY_OP_VERIFY)) {
294dab3f910Sjsing BIO_puts(bio_err, "No signature file specified for verify\n");
295dab3f910Sjsing goto end;
296dab3f910Sjsing }
297dab3f910Sjsing
298e7718adaStb if (cfg.pkey_op != EVP_PKEY_OP_DERIVE) {
299e7718adaStb if (cfg.infile) {
300e7718adaStb if (!(in = BIO_new_file(cfg.infile, "rb"))) {
301dab3f910Sjsing BIO_puts(bio_err,
302dab3f910Sjsing "Error Opening Input File\n");
303dab3f910Sjsing ERR_print_errors(bio_err);
304dab3f910Sjsing goto end;
305dab3f910Sjsing }
306dab3f910Sjsing } else
307dab3f910Sjsing in = BIO_new_fp(stdin, BIO_NOCLOSE);
308dab3f910Sjsing }
309e7718adaStb if (cfg.outfile) {
310e7718adaStb if (!(out = BIO_new_file(cfg.outfile, "wb"))) {
311dab3f910Sjsing BIO_printf(bio_err, "Error Creating Output File\n");
312dab3f910Sjsing ERR_print_errors(bio_err);
313dab3f910Sjsing goto end;
314dab3f910Sjsing }
315dab3f910Sjsing } else {
316dab3f910Sjsing out = BIO_new_fp(stdout, BIO_NOCLOSE);
317dab3f910Sjsing }
318dab3f910Sjsing
319e7718adaStb if (cfg.sigfile) {
320e7718adaStb BIO *sigbio = BIO_new_file(cfg.sigfile, "rb");
321dab3f910Sjsing if (!sigbio) {
322dab3f910Sjsing BIO_printf(bio_err, "Can't open signature file %s\n",
323e7718adaStb cfg.sigfile);
324dab3f910Sjsing goto end;
325dab3f910Sjsing }
326e7718adaStb siglen = bio_to_mem(&sig, cfg.keysize * 10, sigbio);
327dab3f910Sjsing BIO_free(sigbio);
328dab3f910Sjsing if (siglen <= 0) {
329dab3f910Sjsing BIO_printf(bio_err, "Error reading signature data\n");
330dab3f910Sjsing goto end;
331dab3f910Sjsing }
332dab3f910Sjsing }
333dab3f910Sjsing if (in) {
334dab3f910Sjsing /* Read the input data */
335e7718adaStb buf_inlen = bio_to_mem(&buf_in, cfg.keysize * 10, in);
336dab3f910Sjsing if (buf_inlen <= 0) {
337dab3f910Sjsing BIO_printf(bio_err, "Error reading input Data\n");
338dab3f910Sjsing exit(1);
339dab3f910Sjsing }
340e7718adaStb if (cfg.rev) {
341dab3f910Sjsing size_t i;
342dab3f910Sjsing unsigned char ctmp;
343dab3f910Sjsing size_t l = (size_t) buf_inlen;
344dab3f910Sjsing for (i = 0; i < l / 2; i++) {
345dab3f910Sjsing ctmp = buf_in[i];
346dab3f910Sjsing buf_in[i] = buf_in[l - 1 - i];
347dab3f910Sjsing buf_in[l - 1 - i] = ctmp;
348dab3f910Sjsing }
349dab3f910Sjsing }
350dab3f910Sjsing }
351e7718adaStb if (cfg.pkey_op == EVP_PKEY_OP_VERIFY) {
352e7718adaStb rv = EVP_PKEY_verify(cfg.ctx, sig, (size_t) siglen,
353dab3f910Sjsing buf_in, (size_t) buf_inlen);
354bc3daf52Sbcook if (rv == 1) {
355dab3f910Sjsing BIO_puts(out, "Signature Verified Successfully\n");
356bc3daf52Sbcook ret = 0;
357bc3daf52Sbcook } else
358bc3daf52Sbcook BIO_puts(out, "Signature Verification Failure\n");
359dab3f910Sjsing if (rv >= 0)
360dab3f910Sjsing goto end;
361dab3f910Sjsing } else {
362e7718adaStb rv = do_keyop(cfg.ctx, cfg.pkey_op, NULL,
36306aa0bd7Sinoguchi (size_t *)&buf_outlen, buf_in, (size_t) buf_inlen);
364dab3f910Sjsing if (rv > 0) {
365dab3f910Sjsing buf_out = malloc(buf_outlen);
366dab3f910Sjsing if (!buf_out)
367dab3f910Sjsing rv = -1;
368dab3f910Sjsing else
369e7718adaStb rv = do_keyop(cfg.ctx,
370e7718adaStb cfg.pkey_op,
371dab3f910Sjsing buf_out, (size_t *) & buf_outlen,
372dab3f910Sjsing buf_in, (size_t) buf_inlen);
373dab3f910Sjsing }
374dab3f910Sjsing }
375dab3f910Sjsing
376dab3f910Sjsing if (rv <= 0) {
377dab3f910Sjsing BIO_printf(bio_err, "Public Key operation error\n");
378dab3f910Sjsing ERR_print_errors(bio_err);
379dab3f910Sjsing goto end;
380dab3f910Sjsing }
381dab3f910Sjsing ret = 0;
382e7718adaStb if (cfg.asn1parse) {
383dab3f910Sjsing if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
384dab3f910Sjsing ERR_print_errors(bio_err);
385e7718adaStb } else if (cfg.hexdump)
386dab3f910Sjsing BIO_dump(out, (char *) buf_out, buf_outlen);
387dab3f910Sjsing else
388dab3f910Sjsing BIO_write(out, buf_out, buf_outlen);
389dab3f910Sjsing
390dab3f910Sjsing end:
391e7718adaStb EVP_PKEY_CTX_free(cfg.ctx);
392dab3f910Sjsing BIO_free(in);
393dab3f910Sjsing BIO_free_all(out);
394dab3f910Sjsing free(buf_in);
395dab3f910Sjsing free(buf_out);
396dab3f910Sjsing free(sig);
397dab3f910Sjsing
398dab3f910Sjsing return ret;
399dab3f910Sjsing }
400dab3f910Sjsing
40106aa0bd7Sinoguchi static int
init_ctx(char * keyfile)40206aa0bd7Sinoguchi init_ctx(char *keyfile)
403dab3f910Sjsing {
404dab3f910Sjsing EVP_PKEY *pkey = NULL;
405dab3f910Sjsing char *passin = NULL;
406dab3f910Sjsing int rv = -1;
407dab3f910Sjsing X509 *x;
40806aa0bd7Sinoguchi
409e7718adaStb if (((cfg.pkey_op == EVP_PKEY_OP_SIGN)
410e7718adaStb || (cfg.pkey_op == EVP_PKEY_OP_DECRYPT)
411e7718adaStb || (cfg.pkey_op == EVP_PKEY_OP_DERIVE))
412e7718adaStb && (cfg.key_type != KEY_PRIVKEY)) {
41306aa0bd7Sinoguchi BIO_printf(bio_err,
41406aa0bd7Sinoguchi "A private key is needed for this operation\n");
415dab3f910Sjsing goto end;
416dab3f910Sjsing }
417e7718adaStb if (!app_passwd(bio_err, cfg.passargin, NULL, &passin,
41806aa0bd7Sinoguchi NULL)) {
419dab3f910Sjsing BIO_printf(bio_err, "Error getting password\n");
420dab3f910Sjsing goto end;
421dab3f910Sjsing }
422e7718adaStb switch (cfg.key_type) {
423dab3f910Sjsing case KEY_PRIVKEY:
424e7718adaStb pkey = load_key(bio_err, keyfile, cfg.keyform, 0,
4255284dfeaSbcook passin, "Private Key");
426dab3f910Sjsing break;
427dab3f910Sjsing
428dab3f910Sjsing case KEY_PUBKEY:
429e7718adaStb pkey = load_pubkey(bio_err, keyfile, cfg.keyform, 0,
4305284dfeaSbcook NULL, "Public Key");
431dab3f910Sjsing break;
432dab3f910Sjsing
433dab3f910Sjsing case KEY_CERT:
434e7718adaStb x = load_cert(bio_err, keyfile, cfg.keyform,
4355284dfeaSbcook NULL, "Certificate");
436dab3f910Sjsing if (x) {
437dab3f910Sjsing pkey = X509_get_pubkey(x);
438dab3f910Sjsing X509_free(x);
439dab3f910Sjsing }
440dab3f910Sjsing break;
441dab3f910Sjsing }
442dab3f910Sjsing
443e7718adaStb cfg.keysize = EVP_PKEY_size(pkey);
444dab3f910Sjsing
445dab3f910Sjsing if (!pkey)
446dab3f910Sjsing goto end;
447dab3f910Sjsing
448e7718adaStb cfg.ctx = EVP_PKEY_CTX_new(pkey, NULL);
449dab3f910Sjsing
450dab3f910Sjsing EVP_PKEY_free(pkey);
451dab3f910Sjsing
452e7718adaStb if (!cfg.ctx)
453dab3f910Sjsing goto end;
454dab3f910Sjsing
455e7718adaStb switch (cfg.pkey_op) {
456dab3f910Sjsing case EVP_PKEY_OP_SIGN:
457e7718adaStb rv = EVP_PKEY_sign_init(cfg.ctx);
458dab3f910Sjsing break;
459dab3f910Sjsing
460dab3f910Sjsing case EVP_PKEY_OP_VERIFY:
461e7718adaStb rv = EVP_PKEY_verify_init(cfg.ctx);
462dab3f910Sjsing break;
463dab3f910Sjsing
464dab3f910Sjsing case EVP_PKEY_OP_VERIFYRECOVER:
465e7718adaStb rv = EVP_PKEY_verify_recover_init(cfg.ctx);
466dab3f910Sjsing break;
467dab3f910Sjsing
468dab3f910Sjsing case EVP_PKEY_OP_ENCRYPT:
469e7718adaStb rv = EVP_PKEY_encrypt_init(cfg.ctx);
470dab3f910Sjsing break;
471dab3f910Sjsing
472dab3f910Sjsing case EVP_PKEY_OP_DECRYPT:
473e7718adaStb rv = EVP_PKEY_decrypt_init(cfg.ctx);
474dab3f910Sjsing break;
475dab3f910Sjsing
476dab3f910Sjsing case EVP_PKEY_OP_DERIVE:
477e7718adaStb rv = EVP_PKEY_derive_init(cfg.ctx);
478dab3f910Sjsing break;
479dab3f910Sjsing }
480dab3f910Sjsing
481dab3f910Sjsing if (rv <= 0) {
482e7718adaStb EVP_PKEY_CTX_free(cfg.ctx);
483e7718adaStb cfg.ctx = NULL;
484dab3f910Sjsing }
485dab3f910Sjsing
48606aa0bd7Sinoguchi end:
487dab3f910Sjsing free(passin);
488dab3f910Sjsing
489e7718adaStb if (!cfg.ctx) {
49006aa0bd7Sinoguchi BIO_puts(bio_err, "Error initializing context\n");
49106aa0bd7Sinoguchi ERR_print_errors(bio_err);
49206aa0bd7Sinoguchi return (1);
49306aa0bd7Sinoguchi }
494dab3f910Sjsing
49506aa0bd7Sinoguchi return (0);
496dab3f910Sjsing }
497dab3f910Sjsing
498dab3f910Sjsing static int
setup_peer(char * file)49906aa0bd7Sinoguchi setup_peer(char *file)
500dab3f910Sjsing {
501dab3f910Sjsing EVP_PKEY *peer = NULL;
502dab3f910Sjsing int ret;
50306aa0bd7Sinoguchi
504e7718adaStb if (!cfg.ctx) {
50506aa0bd7Sinoguchi BIO_puts(bio_err, "-peerkey command before -inkey\n");
50606aa0bd7Sinoguchi return (1);
507dab3f910Sjsing }
508e7718adaStb peer = load_pubkey(bio_err, file, cfg.peerform, 0, NULL,
50906aa0bd7Sinoguchi "Peer Key");
510dab3f910Sjsing
511dab3f910Sjsing if (!peer) {
512dab3f910Sjsing BIO_printf(bio_err, "Error reading peer key %s\n", file);
51306aa0bd7Sinoguchi ERR_print_errors(bio_err);
51406aa0bd7Sinoguchi return (1);
515dab3f910Sjsing }
516e7718adaStb ret = EVP_PKEY_derive_set_peer(cfg.ctx, peer);
517dab3f910Sjsing
518dab3f910Sjsing EVP_PKEY_free(peer);
51906aa0bd7Sinoguchi if (ret <= 0) {
52006aa0bd7Sinoguchi ERR_print_errors(bio_err);
52106aa0bd7Sinoguchi return (1);
52206aa0bd7Sinoguchi }
52306aa0bd7Sinoguchi
52406aa0bd7Sinoguchi return (0);
52506aa0bd7Sinoguchi }
52606aa0bd7Sinoguchi
52706aa0bd7Sinoguchi static int
pkeyutl_pkeyopt(char * pkeyopt)52806aa0bd7Sinoguchi pkeyutl_pkeyopt(char *pkeyopt)
52906aa0bd7Sinoguchi {
530e7718adaStb if (!cfg.ctx) {
53106aa0bd7Sinoguchi BIO_puts(bio_err, "-pkeyopt command before -inkey\n");
53206aa0bd7Sinoguchi return (1);
533e7718adaStb } else if (pkey_ctrl_string(cfg.ctx, pkeyopt) <= 0) {
53406aa0bd7Sinoguchi BIO_puts(bio_err, "parameter setting error\n");
53506aa0bd7Sinoguchi ERR_print_errors(bio_err);
53606aa0bd7Sinoguchi return (1);
53706aa0bd7Sinoguchi }
53806aa0bd7Sinoguchi
53906aa0bd7Sinoguchi return (0);
540dab3f910Sjsing }
541dab3f910Sjsing
542dab3f910Sjsing static int
do_keyop(EVP_PKEY_CTX * ctx,int pkey_op,unsigned char * out,size_t * poutlen,unsigned char * in,size_t inlen)543dab3f910Sjsing do_keyop(EVP_PKEY_CTX * ctx, int pkey_op,
544dab3f910Sjsing unsigned char *out, size_t * poutlen,
545dab3f910Sjsing unsigned char *in, size_t inlen)
546dab3f910Sjsing {
547dab3f910Sjsing int rv = 0;
548dab3f910Sjsing switch (pkey_op) {
549dab3f910Sjsing case EVP_PKEY_OP_VERIFYRECOVER:
550dab3f910Sjsing rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
551dab3f910Sjsing break;
552dab3f910Sjsing
553dab3f910Sjsing case EVP_PKEY_OP_SIGN:
554dab3f910Sjsing rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
555dab3f910Sjsing break;
556dab3f910Sjsing
557dab3f910Sjsing case EVP_PKEY_OP_ENCRYPT:
558dab3f910Sjsing rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
559dab3f910Sjsing break;
560dab3f910Sjsing
561dab3f910Sjsing case EVP_PKEY_OP_DECRYPT:
562dab3f910Sjsing rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
563dab3f910Sjsing break;
564dab3f910Sjsing
565dab3f910Sjsing case EVP_PKEY_OP_DERIVE:
566dab3f910Sjsing rv = EVP_PKEY_derive(ctx, out, poutlen);
567dab3f910Sjsing break;
568dab3f910Sjsing
569dab3f910Sjsing }
570dab3f910Sjsing return rv;
571dab3f910Sjsing }
572