Annotation of src/usr.bin/openssl/pkeyutl.c, Revision 1.6
1.6 ! jsing 1: /* $OpenBSD: pkeyutl.c,v 1.5 2015/07/15 06:16:42 bcook 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,
75: char *passargin, int pkey_op, ENGINE * e);
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: ENGINE *e = NULL;
90: int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
91: int keyform = FORMAT_PEM, peerform = FORMAT_PEM;
92: char badarg = 0, rev = 0;
93: char hexdump = 0, asn1parse = 0;
94: EVP_PKEY_CTX *ctx = NULL;
95: char *passargin = NULL;
96: int keysize = -1;
97:
98: unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
99: size_t buf_outlen;
100: int buf_inlen = 0, siglen = -1;
101:
102: int ret = 1, rv = -1;
103:
104: argc--;
105: argv++;
106:
107: while (argc >= 1) {
108: if (!strcmp(*argv, "-in")) {
109: if (--argc < 1)
110: badarg = 1;
111: else
112: infile = *(++argv);
113: } else if (!strcmp(*argv, "-out")) {
114: if (--argc < 1)
115: badarg = 1;
116: else
117: outfile = *(++argv);
118: } else if (!strcmp(*argv, "-sigfile")) {
119: if (--argc < 1)
120: badarg = 1;
121: else
122: sigfile = *(++argv);
123: } else if (!strcmp(*argv, "-inkey")) {
124: if (--argc < 1)
125: badarg = 1;
126: else {
127: ctx = init_ctx(&keysize,
128: *(++argv), keyform, key_type,
129: passargin, pkey_op, e);
130: if (!ctx) {
131: BIO_puts(bio_err,
132: "Error initializing context\n");
133: ERR_print_errors(bio_err);
134: badarg = 1;
135: }
136: }
137: } else if (!strcmp(*argv, "-peerkey")) {
138: if (--argc < 1)
139: badarg = 1;
140: else if (!setup_peer(bio_err, ctx, peerform, *(++argv)))
141: badarg = 1;
142: } else if (!strcmp(*argv, "-passin")) {
143: if (--argc < 1)
144: badarg = 1;
145: else
146: passargin = *(++argv);
147: } else if (strcmp(*argv, "-peerform") == 0) {
148: if (--argc < 1)
149: badarg = 1;
150: else
151: peerform = str2fmt(*(++argv));
152: } else if (strcmp(*argv, "-keyform") == 0) {
153: if (--argc < 1)
154: badarg = 1;
155: else
156: keyform = str2fmt(*(++argv));
157: }
158: #ifndef OPENSSL_NO_ENGINE
159: else if (!strcmp(*argv, "-engine")) {
160: if (--argc < 1)
161: badarg = 1;
162: else
163: e = setup_engine(bio_err, *(++argv), 0);
164: }
165: #endif
166: else if (!strcmp(*argv, "-pubin"))
167: key_type = KEY_PUBKEY;
168: else if (!strcmp(*argv, "-certin"))
169: key_type = KEY_CERT;
170: else if (!strcmp(*argv, "-asn1parse"))
171: asn1parse = 1;
172: else if (!strcmp(*argv, "-hexdump"))
173: hexdump = 1;
174: else if (!strcmp(*argv, "-sign"))
175: pkey_op = EVP_PKEY_OP_SIGN;
176: else if (!strcmp(*argv, "-verify"))
177: pkey_op = EVP_PKEY_OP_VERIFY;
178: else if (!strcmp(*argv, "-verifyrecover"))
179: pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
180: else if (!strcmp(*argv, "-rev"))
181: rev = 1;
182: else if (!strcmp(*argv, "-encrypt"))
183: pkey_op = EVP_PKEY_OP_ENCRYPT;
184: else if (!strcmp(*argv, "-decrypt"))
185: pkey_op = EVP_PKEY_OP_DECRYPT;
186: else if (!strcmp(*argv, "-derive"))
187: pkey_op = EVP_PKEY_OP_DERIVE;
188: else if (strcmp(*argv, "-pkeyopt") == 0) {
189: if (--argc < 1)
190: badarg = 1;
191: else if (!ctx) {
192: BIO_puts(bio_err,
193: "-pkeyopt command before -inkey\n");
194: badarg = 1;
195: } else if (pkey_ctrl_string(ctx, *(++argv)) <= 0) {
196: BIO_puts(bio_err, "parameter setting error\n");
197: ERR_print_errors(bio_err);
198: goto end;
199: }
200: } else
201: badarg = 1;
202: if (badarg) {
203: usage();
204: goto end;
205: }
206: argc--;
207: argv++;
208: }
209:
210: if (!ctx) {
211: usage();
212: goto end;
213: }
214: if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY)) {
215: BIO_puts(bio_err, "Signature file specified for non verify\n");
216: goto end;
217: }
218: if (!sigfile && (pkey_op == EVP_PKEY_OP_VERIFY)) {
219: BIO_puts(bio_err, "No signature file specified for verify\n");
220: goto end;
221: }
222:
223: if (pkey_op != EVP_PKEY_OP_DERIVE) {
224: if (infile) {
225: if (!(in = BIO_new_file(infile, "rb"))) {
226: BIO_puts(bio_err,
227: "Error Opening Input File\n");
228: ERR_print_errors(bio_err);
229: goto end;
230: }
231: } else
232: in = BIO_new_fp(stdin, BIO_NOCLOSE);
233: }
234: if (outfile) {
235: if (!(out = BIO_new_file(outfile, "wb"))) {
236: BIO_printf(bio_err, "Error Creating Output File\n");
237: ERR_print_errors(bio_err);
238: goto end;
239: }
240: } else {
241: out = BIO_new_fp(stdout, BIO_NOCLOSE);
242: }
243:
244: if (sigfile) {
245: BIO *sigbio = BIO_new_file(sigfile, "rb");
246: if (!sigbio) {
247: BIO_printf(bio_err, "Can't open signature file %s\n",
248: sigfile);
249: goto end;
250: }
251: siglen = bio_to_mem(&sig, keysize * 10, sigbio);
252: BIO_free(sigbio);
253: if (siglen <= 0) {
254: BIO_printf(bio_err, "Error reading signature data\n");
255: goto end;
256: }
257: }
258: if (in) {
259: /* Read the input data */
260: buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
261: if (buf_inlen <= 0) {
262: BIO_printf(bio_err, "Error reading input Data\n");
263: exit(1);
264: }
265: if (rev) {
266: size_t i;
267: unsigned char ctmp;
268: size_t l = (size_t) buf_inlen;
269: for (i = 0; i < l / 2; i++) {
270: ctmp = buf_in[i];
271: buf_in[i] = buf_in[l - 1 - i];
272: buf_in[l - 1 - i] = ctmp;
273: }
274: }
275: }
276: if (pkey_op == EVP_PKEY_OP_VERIFY) {
277: rv = EVP_PKEY_verify(ctx, sig, (size_t) siglen,
278: buf_in, (size_t) buf_inlen);
1.5 bcook 279: if (rv == 1) {
280: BIO_puts(out, "Signature Verified Successfully\n");
281: ret = 0;
282: } else
1.1 jsing 283: BIO_puts(out, "Signature Verification Failure\n");
284: if (rv >= 0)
285: goto end;
286: } else {
1.4 deraadt 287: rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
1.1 jsing 288: buf_in, (size_t) buf_inlen);
289: if (rv > 0) {
290: buf_out = malloc(buf_outlen);
291: if (!buf_out)
292: rv = -1;
293: else
294: rv = do_keyop(ctx, pkey_op,
295: buf_out, (size_t *) & buf_outlen,
296: buf_in, (size_t) buf_inlen);
297: }
298: }
299:
300: if (rv <= 0) {
301: BIO_printf(bio_err, "Public Key operation error\n");
302: ERR_print_errors(bio_err);
303: goto end;
304: }
305: ret = 0;
306: if (asn1parse) {
307: if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
308: ERR_print_errors(bio_err);
309: } else if (hexdump)
310: BIO_dump(out, (char *) buf_out, buf_outlen);
311: else
312: BIO_write(out, buf_out, buf_outlen);
313:
314: end:
315: if (ctx)
316: EVP_PKEY_CTX_free(ctx);
317: BIO_free(in);
318: BIO_free_all(out);
319: free(buf_in);
320: free(buf_out);
321: free(sig);
322:
323: return ret;
324: }
325:
326: static void
327: usage()
328: {
329: BIO_printf(bio_err, "Usage: pkeyutl [options]\n");
330: BIO_printf(bio_err, "-in file input file\n");
331: BIO_printf(bio_err, "-out file output file\n");
332: BIO_printf(bio_err, "-sigfile file signature file (verify operation only)\n");
333: BIO_printf(bio_err, "-inkey file input key\n");
334: BIO_printf(bio_err, "-keyform arg private key format - default PEM\n");
335: BIO_printf(bio_err, "-pubin input is a public key\n");
336: BIO_printf(bio_err, "-certin input is a certificate carrying a public key\n");
337: BIO_printf(bio_err, "-pkeyopt X:Y public key options\n");
338: BIO_printf(bio_err, "-sign sign with private key\n");
339: BIO_printf(bio_err, "-verify verify with public key\n");
340: BIO_printf(bio_err, "-verifyrecover verify with public key, recover original data\n");
341: BIO_printf(bio_err, "-encrypt encrypt with public key\n");
342: BIO_printf(bio_err, "-decrypt decrypt with private key\n");
343: BIO_printf(bio_err, "-derive derive shared secret\n");
344: BIO_printf(bio_err, "-hexdump hex dump output\n");
345: #ifndef OPENSSL_NO_ENGINE
346: BIO_printf(bio_err, "-engine e use engine e, possibly a hardware device.\n");
347: #endif
348: BIO_printf(bio_err, "-passin arg pass phrase source\n");
349:
350: }
351:
352: static EVP_PKEY_CTX *
353: init_ctx(int *pkeysize,
354: char *keyfile, int keyform, int key_type,
355: char *passargin, int pkey_op, ENGINE * e)
356: {
357: EVP_PKEY *pkey = NULL;
358: EVP_PKEY_CTX *ctx = NULL;
359: char *passin = NULL;
360: int rv = -1;
361: X509 *x;
362: if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)
363: || (pkey_op == EVP_PKEY_OP_DERIVE))
364: && (key_type != KEY_PRIVKEY)) {
365: BIO_printf(bio_err, "A private key is needed for this operation\n");
366: goto end;
367: }
368: if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
369: BIO_printf(bio_err, "Error getting password\n");
370: goto end;
371: }
372: switch (key_type) {
373: case KEY_PRIVKEY:
374: pkey = load_key(bio_err, keyfile, keyform, 0,
375: passin, e, "Private Key");
376: break;
377:
378: case KEY_PUBKEY:
379: pkey = load_pubkey(bio_err, keyfile, keyform, 0,
380: NULL, e, "Public Key");
381: break;
382:
383: case KEY_CERT:
384: x = load_cert(bio_err, keyfile, keyform,
385: NULL, e, "Certificate");
386: if (x) {
387: pkey = X509_get_pubkey(x);
388: X509_free(x);
389: }
390: break;
391:
392: }
393:
394: *pkeysize = EVP_PKEY_size(pkey);
395:
396: if (!pkey)
397: goto end;
398:
399: ctx = EVP_PKEY_CTX_new(pkey, e);
400:
401: EVP_PKEY_free(pkey);
402:
403: if (!ctx)
404: goto end;
405:
406: switch (pkey_op) {
407: case EVP_PKEY_OP_SIGN:
408: rv = EVP_PKEY_sign_init(ctx);
409: break;
410:
411: case EVP_PKEY_OP_VERIFY:
412: rv = EVP_PKEY_verify_init(ctx);
413: break;
414:
415: case EVP_PKEY_OP_VERIFYRECOVER:
416: rv = EVP_PKEY_verify_recover_init(ctx);
417: break;
418:
419: case EVP_PKEY_OP_ENCRYPT:
420: rv = EVP_PKEY_encrypt_init(ctx);
421: break;
422:
423: case EVP_PKEY_OP_DECRYPT:
424: rv = EVP_PKEY_decrypt_init(ctx);
425: break;
426:
427: case EVP_PKEY_OP_DERIVE:
428: rv = EVP_PKEY_derive_init(ctx);
429: break;
430: }
431:
432: if (rv <= 0) {
433: EVP_PKEY_CTX_free(ctx);
434: ctx = NULL;
435: }
436: end:
437:
438: free(passin);
439:
440: return ctx;
441:
442:
443: }
444:
445: static int
446: setup_peer(BIO * err, EVP_PKEY_CTX * ctx, int peerform,
447: const char *file)
448: {
449: EVP_PKEY *peer = NULL;
450: int ret;
451: if (!ctx) {
452: BIO_puts(err, "-peerkey command before -inkey\n");
453: return 0;
454: }
455: peer = load_pubkey(bio_err, file, peerform, 0, NULL, NULL, "Peer Key");
456:
457: if (!peer) {
458: BIO_printf(bio_err, "Error reading peer key %s\n", file);
459: ERR_print_errors(err);
460: return 0;
461: }
462: ret = EVP_PKEY_derive_set_peer(ctx, peer);
463:
464: EVP_PKEY_free(peer);
465: if (ret <= 0)
466: ERR_print_errors(err);
467: return ret;
468: }
469:
470: static int
471: do_keyop(EVP_PKEY_CTX * ctx, int pkey_op,
472: unsigned char *out, size_t * poutlen,
473: unsigned char *in, size_t inlen)
474: {
475: int rv = 0;
476: switch (pkey_op) {
477: case EVP_PKEY_OP_VERIFYRECOVER:
478: rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
479: break;
480:
481: case EVP_PKEY_OP_SIGN:
482: rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
483: break;
484:
485: case EVP_PKEY_OP_ENCRYPT:
486: rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
487: break;
488:
489: case EVP_PKEY_OP_DECRYPT:
490: rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
491: break;
492:
493: case EVP_PKEY_OP_DERIVE:
494: rv = EVP_PKEY_derive(ctx, out, poutlen);
495: break;
496:
497: }
498: return rv;
499: }