Annotation of src/usr.bin/openssl/pkeyutl.c, Revision 1.12
1.12 ! inoguchi 1: /* $OpenBSD: pkeyutl.c,v 1.11 2017/01/20 08:57:12 deraadt Exp $ */
1.1 jsing 2: /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3: * project 2006.
4: */
5: /* ====================================================================
6: * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: *
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: *
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in
17: * the documentation and/or other materials provided with the
18: * distribution.
19: *
20: * 3. All advertising materials mentioning features or use of this
21: * software must display the following acknowledgment:
22: * "This product includes software developed by the OpenSSL Project
23: * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24: *
25: * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26: * endorse or promote products derived from this software without
27: * prior written permission. For written permission, please contact
28: * licensing@OpenSSL.org.
29: *
30: * 5. Products derived from this software may not be called "OpenSSL"
31: * nor may "OpenSSL" appear in their names without prior written
32: * permission of the OpenSSL Project.
33: *
34: * 6. Redistributions of any form whatsoever must retain the following
35: * acknowledgment:
36: * "This product includes software developed by the OpenSSL Project
37: * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38: *
39: * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50: * OF THE POSSIBILITY OF SUCH DAMAGE.
51: * ====================================================================
52: *
53: * This product includes cryptographic software written by Eric Young
54: * (eay@cryptsoft.com). This product includes software written by Tim
55: * Hudson (tjh@cryptsoft.com).
56: *
57: */
58:
59: #include <string.h>
60:
61: #include "apps.h"
62:
63: #include <openssl/err.h>
64: #include <openssl/evp.h>
65: #include <openssl/pem.h>
66:
67: #define KEY_PRIVKEY 1
68: #define KEY_PUBKEY 2
69: #define KEY_CERT 3
70:
71: static void usage(void);
72:
73: static EVP_PKEY_CTX *init_ctx(int *pkeysize,
74: char *keyfile, int keyform, int key_type,
1.7 bcook 75: char *passargin, int pkey_op);
1.1 jsing 76:
77: static int setup_peer(BIO * err, EVP_PKEY_CTX * ctx, int peerform,
78: const char *file);
79:
80: static int do_keyop(EVP_PKEY_CTX * ctx, int pkey_op,
81: unsigned char *out, size_t * poutlen,
82: unsigned char *in, size_t inlen);
83:
84: int
85: pkeyutl_main(int argc, char **argv)
86: {
87: BIO *in = NULL, *out = NULL;
88: char *infile = NULL, *outfile = NULL, *sigfile = NULL;
89: int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
90: int keyform = FORMAT_PEM, peerform = FORMAT_PEM;
91: char badarg = 0, rev = 0;
92: char hexdump = 0, asn1parse = 0;
93: EVP_PKEY_CTX *ctx = NULL;
94: char *passargin = NULL;
95: int keysize = -1;
96:
97: unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
1.12 ! inoguchi 98: size_t buf_outlen = 0;
1.1 jsing 99: int buf_inlen = 0, siglen = -1;
100:
101: int ret = 1, rv = -1;
1.8 doug 102:
103: if (single_execution) {
1.11 deraadt 104: if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
1.8 doug 105: perror("pledge");
1.10 doug 106: exit(1);
107: }
1.8 doug 108: }
1.1 jsing 109:
110: argc--;
111: argv++;
112:
113: while (argc >= 1) {
114: if (!strcmp(*argv, "-in")) {
115: if (--argc < 1)
116: badarg = 1;
117: else
118: infile = *(++argv);
119: } else if (!strcmp(*argv, "-out")) {
120: if (--argc < 1)
121: badarg = 1;
122: else
123: outfile = *(++argv);
124: } else if (!strcmp(*argv, "-sigfile")) {
125: if (--argc < 1)
126: badarg = 1;
127: else
128: sigfile = *(++argv);
129: } else if (!strcmp(*argv, "-inkey")) {
130: if (--argc < 1)
131: badarg = 1;
132: else {
133: ctx = init_ctx(&keysize,
134: *(++argv), keyform, key_type,
1.7 bcook 135: passargin, pkey_op);
1.1 jsing 136: if (!ctx) {
137: BIO_puts(bio_err,
138: "Error initializing context\n");
139: ERR_print_errors(bio_err);
140: badarg = 1;
141: }
142: }
143: } else if (!strcmp(*argv, "-peerkey")) {
144: if (--argc < 1)
145: badarg = 1;
146: else if (!setup_peer(bio_err, ctx, peerform, *(++argv)))
147: badarg = 1;
148: } else if (!strcmp(*argv, "-passin")) {
149: if (--argc < 1)
150: badarg = 1;
151: else
152: passargin = *(++argv);
153: } else if (strcmp(*argv, "-peerform") == 0) {
154: if (--argc < 1)
155: badarg = 1;
156: else
157: peerform = str2fmt(*(++argv));
158: } else if (strcmp(*argv, "-keyform") == 0) {
159: if (--argc < 1)
160: badarg = 1;
161: else
162: keyform = str2fmt(*(++argv));
163: }
164: else if (!strcmp(*argv, "-pubin"))
165: key_type = KEY_PUBKEY;
166: else if (!strcmp(*argv, "-certin"))
167: key_type = KEY_CERT;
168: else if (!strcmp(*argv, "-asn1parse"))
169: asn1parse = 1;
170: else if (!strcmp(*argv, "-hexdump"))
171: hexdump = 1;
172: else if (!strcmp(*argv, "-sign"))
173: pkey_op = EVP_PKEY_OP_SIGN;
174: else if (!strcmp(*argv, "-verify"))
175: pkey_op = EVP_PKEY_OP_VERIFY;
176: else if (!strcmp(*argv, "-verifyrecover"))
177: pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
178: else if (!strcmp(*argv, "-rev"))
179: rev = 1;
180: else if (!strcmp(*argv, "-encrypt"))
181: pkey_op = EVP_PKEY_OP_ENCRYPT;
182: else if (!strcmp(*argv, "-decrypt"))
183: pkey_op = EVP_PKEY_OP_DECRYPT;
184: else if (!strcmp(*argv, "-derive"))
185: pkey_op = EVP_PKEY_OP_DERIVE;
186: else if (strcmp(*argv, "-pkeyopt") == 0) {
187: if (--argc < 1)
188: badarg = 1;
189: else if (!ctx) {
190: BIO_puts(bio_err,
191: "-pkeyopt command before -inkey\n");
192: badarg = 1;
193: } else if (pkey_ctrl_string(ctx, *(++argv)) <= 0) {
194: BIO_puts(bio_err, "parameter setting error\n");
195: ERR_print_errors(bio_err);
196: goto end;
197: }
198: } else
199: badarg = 1;
200: if (badarg) {
201: usage();
202: goto end;
203: }
204: argc--;
205: argv++;
206: }
207:
208: if (!ctx) {
209: usage();
210: goto end;
211: }
212: if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY)) {
213: BIO_puts(bio_err, "Signature file specified for non verify\n");
214: goto end;
215: }
216: if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY)) {
217: BIO_puts(bio_err, "No signature file specified for verify\n");
218: goto end;
219: }
220:
221: if (pkey_op != EVP_PKEY_OP_DERIVE) {
222: if (infile) {
223: if (!(in = BIO_new_file(infile, "rb"))) {
224: BIO_puts(bio_err,
225: "Error Opening Input File\n");
226: ERR_print_errors(bio_err);
227: goto end;
228: }
229: } else
230: in = BIO_new_fp(stdin, BIO_NOCLOSE);
231: }
232: if (outfile) {
233: if (!(out = BIO_new_file(outfile, "wb"))) {
234: BIO_printf(bio_err, "Error Creating Output File\n");
235: ERR_print_errors(bio_err);
236: goto end;
237: }
238: } else {
239: out = BIO_new_fp(stdout, BIO_NOCLOSE);
240: }
241:
242: if (sigfile) {
243: BIO *sigbio = BIO_new_file(sigfile, "rb");
244: if (!sigbio) {
245: BIO_printf(bio_err, "Can't open signature file %s\n",
246: sigfile);
247: goto end;
248: }
249: siglen = bio_to_mem(&sig, keysize * 10, sigbio);
250: BIO_free(sigbio);
251: if (siglen <= 0) {
252: BIO_printf(bio_err, "Error reading signature data\n");
253: goto end;
254: }
255: }
256: if (in) {
257: /* Read the input data */
258: buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
259: if (buf_inlen <= 0) {
260: BIO_printf(bio_err, "Error reading input Data\n");
261: exit(1);
262: }
263: if (rev) {
264: size_t i;
265: unsigned char ctmp;
266: size_t l = (size_t) buf_inlen;
267: for (i = 0; i < l / 2; i++) {
268: ctmp = buf_in[i];
269: buf_in[i] = buf_in[l - 1 - i];
270: buf_in[l - 1 - i] = ctmp;
271: }
272: }
273: }
274: if (pkey_op == EVP_PKEY_OP_VERIFY) {
275: rv = EVP_PKEY_verify(ctx, sig, (size_t) siglen,
276: buf_in, (size_t) buf_inlen);
1.5 bcook 277: if (rv == 1) {
278: BIO_puts(out, "Signature Verified Successfully\n");
279: ret = 0;
280: } else
1.1 jsing 281: BIO_puts(out, "Signature Verification Failure\n");
282: if (rv >= 0)
283: goto end;
284: } else {
1.4 deraadt 285: rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
1.1 jsing 286: buf_in, (size_t) buf_inlen);
287: if (rv > 0) {
288: buf_out = malloc(buf_outlen);
289: if (!buf_out)
290: rv = -1;
291: else
292: rv = do_keyop(ctx, pkey_op,
293: buf_out, (size_t *) & buf_outlen,
294: buf_in, (size_t) buf_inlen);
295: }
296: }
297:
298: if (rv <= 0) {
299: BIO_printf(bio_err, "Public Key operation error\n");
300: ERR_print_errors(bio_err);
301: goto end;
302: }
303: ret = 0;
304: if (asn1parse) {
305: if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
306: ERR_print_errors(bio_err);
307: } else if (hexdump)
308: BIO_dump(out, (char *) buf_out, buf_outlen);
309: else
310: BIO_write(out, buf_out, buf_outlen);
311:
312: end:
313: if (ctx)
314: EVP_PKEY_CTX_free(ctx);
315: BIO_free(in);
316: BIO_free_all(out);
317: free(buf_in);
318: free(buf_out);
319: free(sig);
320:
321: return ret;
322: }
323:
324: static void
325: usage()
326: {
327: BIO_printf(bio_err, "Usage: pkeyutl [options]\n");
328: BIO_printf(bio_err, "-in file input file\n");
329: BIO_printf(bio_err, "-out file output file\n");
330: BIO_printf(bio_err, "-sigfile file signature file (verify operation only)\n");
331: BIO_printf(bio_err, "-inkey file input key\n");
332: BIO_printf(bio_err, "-keyform arg private key format - default PEM\n");
333: BIO_printf(bio_err, "-pubin input is a public key\n");
334: BIO_printf(bio_err, "-certin input is a certificate carrying a public key\n");
335: BIO_printf(bio_err, "-pkeyopt X:Y public key options\n");
336: BIO_printf(bio_err, "-sign sign with private key\n");
337: BIO_printf(bio_err, "-verify verify with public key\n");
338: BIO_printf(bio_err, "-verifyrecover verify with public key, recover original data\n");
339: BIO_printf(bio_err, "-encrypt encrypt with public key\n");
340: BIO_printf(bio_err, "-decrypt decrypt with private key\n");
341: BIO_printf(bio_err, "-derive derive shared secret\n");
342: BIO_printf(bio_err, "-hexdump hex dump output\n");
343: BIO_printf(bio_err, "-passin arg pass phrase source\n");
344:
345: }
346:
347: static EVP_PKEY_CTX *
348: init_ctx(int *pkeysize,
349: char *keyfile, int keyform, int key_type,
1.7 bcook 350: char *passargin, int pkey_op)
1.1 jsing 351: {
352: EVP_PKEY *pkey = NULL;
353: EVP_PKEY_CTX *ctx = NULL;
354: char *passin = NULL;
355: int rv = -1;
356: X509 *x;
357: if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)
358: || (pkey_op == EVP_PKEY_OP_DERIVE))
359: && (key_type != KEY_PRIVKEY)) {
360: BIO_printf(bio_err, "A private key is needed for this operation\n");
361: goto end;
362: }
363: if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
364: BIO_printf(bio_err, "Error getting password\n");
365: goto end;
366: }
367: switch (key_type) {
368: case KEY_PRIVKEY:
369: pkey = load_key(bio_err, keyfile, keyform, 0,
1.7 bcook 370: passin, "Private Key");
1.1 jsing 371: break;
372:
373: case KEY_PUBKEY:
374: pkey = load_pubkey(bio_err, keyfile, keyform, 0,
1.7 bcook 375: NULL, "Public Key");
1.1 jsing 376: break;
377:
378: case KEY_CERT:
379: x = load_cert(bio_err, keyfile, keyform,
1.7 bcook 380: NULL, "Certificate");
1.1 jsing 381: if (x) {
382: pkey = X509_get_pubkey(x);
383: X509_free(x);
384: }
385: break;
386:
387: }
388:
389: *pkeysize = EVP_PKEY_size(pkey);
390:
391: if (!pkey)
392: goto end;
393:
1.7 bcook 394: ctx = EVP_PKEY_CTX_new(pkey, NULL);
1.1 jsing 395:
396: EVP_PKEY_free(pkey);
397:
398: if (!ctx)
399: goto end;
400:
401: switch (pkey_op) {
402: case EVP_PKEY_OP_SIGN:
403: rv = EVP_PKEY_sign_init(ctx);
404: break;
405:
406: case EVP_PKEY_OP_VERIFY:
407: rv = EVP_PKEY_verify_init(ctx);
408: break;
409:
410: case EVP_PKEY_OP_VERIFYRECOVER:
411: rv = EVP_PKEY_verify_recover_init(ctx);
412: break;
413:
414: case EVP_PKEY_OP_ENCRYPT:
415: rv = EVP_PKEY_encrypt_init(ctx);
416: break;
417:
418: case EVP_PKEY_OP_DECRYPT:
419: rv = EVP_PKEY_decrypt_init(ctx);
420: break;
421:
422: case EVP_PKEY_OP_DERIVE:
423: rv = EVP_PKEY_derive_init(ctx);
424: break;
425: }
426:
427: if (rv <= 0) {
428: EVP_PKEY_CTX_free(ctx);
429: ctx = NULL;
430: }
431: end:
432:
433: free(passin);
434:
435: return ctx;
436:
437:
438: }
439:
440: static int
441: setup_peer(BIO * err, EVP_PKEY_CTX * ctx, int peerform,
442: const char *file)
443: {
444: EVP_PKEY *peer = NULL;
445: int ret;
446: if (!ctx) {
447: BIO_puts(err, "-peerkey command before -inkey\n");
448: return 0;
449: }
1.7 bcook 450: peer = load_pubkey(bio_err, file, peerform, 0, NULL, "Peer Key");
1.1 jsing 451:
452: if (!peer) {
453: BIO_printf(bio_err, "Error reading peer key %s\n", file);
454: ERR_print_errors(err);
455: return 0;
456: }
457: ret = EVP_PKEY_derive_set_peer(ctx, peer);
458:
459: EVP_PKEY_free(peer);
460: if (ret <= 0)
461: ERR_print_errors(err);
462: return ret;
463: }
464:
465: static int
466: do_keyop(EVP_PKEY_CTX * ctx, int pkey_op,
467: unsigned char *out, size_t * poutlen,
468: unsigned char *in, size_t inlen)
469: {
470: int rv = 0;
471: switch (pkey_op) {
472: case EVP_PKEY_OP_VERIFYRECOVER:
473: rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
474: break;
475:
476: case EVP_PKEY_OP_SIGN:
477: rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
478: break;
479:
480: case EVP_PKEY_OP_ENCRYPT:
481: rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
482: break;
483:
484: case EVP_PKEY_OP_DECRYPT:
485: rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
486: break;
487:
488: case EVP_PKEY_OP_DERIVE:
489: rv = EVP_PKEY_derive(ctx, out, poutlen);
490: break;
491:
492: }
493: return rv;
494: }