GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/openssl/pkeyutl.c Lines: 142 247 57.5 %
Date: 2017-11-13 Branches: 82 162 50.6 %

Line Branch Exec Source
1
/* $OpenBSD: pkeyutl.c,v 1.11 2017/01/20 08:57:12 deraadt Exp $ */
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);
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
32
	int keysize = -1;
96
97
16
	unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
98
16
	size_t buf_outlen;
99
	int buf_inlen = 0, siglen = -1;
100
101
	int ret = 1, rv = -1;
102
103
16
	if (single_execution) {
104
16
		if (pledge("stdio cpath wpath rpath tty flock", NULL) == -1) {
105
			perror("pledge");
106
			exit(1);
107
		}
108
	}
109
110
16
	argc--;
111
16
	argv++;
112
113
120
	while (argc >= 1) {
114
48
		if (!strcmp(*argv, "-in")) {
115
12
			if (--argc < 1)
116
				badarg = 1;
117
			else
118
12
				infile = *(++argv);
119
36
		} else if (!strcmp(*argv, "-out")) {
120
4
			if (--argc < 1)
121
				badarg = 1;
122
			else
123
4
				outfile = *(++argv);
124
32
		} else if (!strcmp(*argv, "-sigfile")) {
125
4
			if (--argc < 1)
126
				badarg = 1;
127
			else
128
4
				sigfile = *(++argv);
129
28
		} else if (!strcmp(*argv, "-inkey")) {
130
12
			if (--argc < 1)
131
				badarg = 1;
132
			else {
133
12
				ctx = init_ctx(&keysize,
134
12
				    *(++argv), keyform, key_type,
135
				    passargin, pkey_op);
136
12
				if (!ctx) {
137
					BIO_puts(bio_err,
138
					    "Error initializing context\n");
139
					ERR_print_errors(bio_err);
140
					badarg = 1;
141
				}
142
			}
143
16
		} 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
16
		} else if (!strcmp(*argv, "-passin")) {
149
			if (--argc < 1)
150
				badarg = 1;
151
			else
152
				passargin = *(++argv);
153
16
		} else if (strcmp(*argv, "-peerform") == 0) {
154
			if (--argc < 1)
155
				badarg = 1;
156
			else
157
				peerform = str2fmt(*(++argv));
158
16
		} else if (strcmp(*argv, "-keyform") == 0) {
159
			if (--argc < 1)
160
				badarg = 1;
161
			else
162
				keyform = str2fmt(*(++argv));
163
		}
164
16
		else if (!strcmp(*argv, "-pubin"))
165
			key_type = KEY_PUBKEY;
166
16
		else if (!strcmp(*argv, "-certin"))
167
			key_type = KEY_CERT;
168
16
		else if (!strcmp(*argv, "-asn1parse"))
169
			asn1parse = 1;
170
16
		else if (!strcmp(*argv, "-hexdump"))
171
			hexdump = 1;
172
16
		else if (!strcmp(*argv, "-sign"))
173
4
			pkey_op = EVP_PKEY_OP_SIGN;
174
12
		else if (!strcmp(*argv, "-verify"))
175
4
			pkey_op = EVP_PKEY_OP_VERIFY;
176
8
		else if (!strcmp(*argv, "-verifyrecover"))
177
4
			pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
178
4
		else if (!strcmp(*argv, "-rev"))
179
			rev = 1;
180
4
		else if (!strcmp(*argv, "-encrypt"))
181
			pkey_op = EVP_PKEY_OP_ENCRYPT;
182
4
		else if (!strcmp(*argv, "-decrypt"))
183
			pkey_op = EVP_PKEY_OP_DECRYPT;
184
4
		else if (!strcmp(*argv, "-derive"))
185
			pkey_op = EVP_PKEY_OP_DERIVE;
186
4
		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
48
		if (badarg) {
201
4
			usage();
202
4
			goto end;
203
		}
204
44
		argc--;
205
44
		argv++;
206
	}
207
208
12
	if (!ctx) {
209
		usage();
210
		goto end;
211
	}
212
12
	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
12
	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
12
	if (pkey_op != EVP_PKEY_OP_DERIVE) {
222
12
		if (infile) {
223
12
			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
12
	if (outfile) {
233
4
		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
8
		out = BIO_new_fp(stdout, BIO_NOCLOSE);
240
	}
241
242
12
	if (sigfile) {
243
4
		BIO *sigbio = BIO_new_file(sigfile, "rb");
244
4
		if (!sigbio) {
245
			BIO_printf(bio_err, "Can't open signature file %s\n",
246
			    sigfile);
247
			goto end;
248
		}
249
4
		siglen = bio_to_mem(&sig, keysize * 10, sigbio);
250
4
		BIO_free(sigbio);
251
4
		if (siglen <= 0) {
252
			BIO_printf(bio_err, "Error reading signature data\n");
253
			goto end;
254
		}
255
4
	}
256
12
	if (in) {
257
		/* Read the input data */
258
12
		buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
259
12
		if (buf_inlen <= 0) {
260
			BIO_printf(bio_err, "Error reading input Data\n");
261
			exit(1);
262
		}
263
12
		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
12
	if (pkey_op == EVP_PKEY_OP_VERIFY) {
275
8
		rv = EVP_PKEY_verify(ctx, sig, (size_t) siglen,
276
4
		    buf_in, (size_t) buf_inlen);
277
4
		if (rv == 1) {
278
4
			BIO_puts(out, "Signature Verified Successfully\n");
279
			ret = 0;
280
4
		} else
281
			BIO_puts(out, "Signature Verification Failure\n");
282
4
		if (rv >= 0)
283
			goto end;
284
	} else {
285
8
		rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
286
8
		    buf_in, (size_t) buf_inlen);
287
8
		if (rv > 0) {
288
8
			buf_out = malloc(buf_outlen);
289
8
			if (!buf_out)
290
				rv = -1;
291
			else
292
8
				rv = do_keyop(ctx, pkey_op,
293
				    buf_out, (size_t *) & buf_outlen,
294
8
				    buf_in, (size_t) buf_inlen);
295
		}
296
	}
297
298
8
	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
8
	if (asn1parse) {
305
		if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1))
306
			ERR_print_errors(bio_err);
307
8
	} else if (hexdump)
308
		BIO_dump(out, (char *) buf_out, buf_outlen);
309
	else
310
8
		BIO_write(out, buf_out, buf_outlen);
311
312
end:
313
16
	if (ctx)
314
12
		EVP_PKEY_CTX_free(ctx);
315
16
	BIO_free(in);
316
16
	BIO_free_all(out);
317
16
	free(buf_in);
318
16
	free(buf_out);
319
16
	free(sig);
320
321
16
	return ret;
322
16
}
323
324
static void
325
usage()
326
{
327
8
	BIO_printf(bio_err, "Usage: pkeyutl [options]\n");
328
4
	BIO_printf(bio_err, "-in file        input file\n");
329
4
	BIO_printf(bio_err, "-out file       output file\n");
330
4
	BIO_printf(bio_err, "-sigfile file signature file (verify operation only)\n");
331
4
	BIO_printf(bio_err, "-inkey file     input key\n");
332
4
	BIO_printf(bio_err, "-keyform arg    private key format - default PEM\n");
333
4
	BIO_printf(bio_err, "-pubin          input is a public key\n");
334
4
	BIO_printf(bio_err, "-certin         input is a certificate carrying a public key\n");
335
4
	BIO_printf(bio_err, "-pkeyopt X:Y    public key options\n");
336
4
	BIO_printf(bio_err, "-sign           sign with private key\n");
337
4
	BIO_printf(bio_err, "-verify         verify with public key\n");
338
4
	BIO_printf(bio_err, "-verifyrecover  verify with public key, recover original data\n");
339
4
	BIO_printf(bio_err, "-encrypt        encrypt with public key\n");
340
4
	BIO_printf(bio_err, "-decrypt        decrypt with private key\n");
341
4
	BIO_printf(bio_err, "-derive         derive shared secret\n");
342
4
	BIO_printf(bio_err, "-hexdump        hex dump output\n");
343
4
	BIO_printf(bio_err, "-passin arg     pass phrase source\n");
344
345
4
}
346
347
static EVP_PKEY_CTX *
348
init_ctx(int *pkeysize,
349
    char *keyfile, int keyform, int key_type,
350
    char *passargin, int pkey_op)
351
{
352
	EVP_PKEY *pkey = NULL;
353
	EVP_PKEY_CTX *ctx = NULL;
354
24
	char *passin = NULL;
355
	int rv = -1;
356
	X509 *x;
357
36
	if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT)
358
12
		|| (pkey_op == EVP_PKEY_OP_DERIVE))
359
12
	    && (key_type != KEY_PRIVKEY)) {
360
		BIO_printf(bio_err, "A private key is needed for this operation\n");
361
		goto end;
362
	}
363
12
	if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
364
		BIO_printf(bio_err, "Error getting password\n");
365
		goto end;
366
	}
367

24
	switch (key_type) {
368
	case KEY_PRIVKEY:
369
24
		pkey = load_key(bio_err, keyfile, keyform, 0,
370
12
		    passin, "Private Key");
371
12
		break;
372
373
	case KEY_PUBKEY:
374
		pkey = load_pubkey(bio_err, keyfile, keyform, 0,
375
		    NULL, "Public Key");
376
		break;
377
378
	case KEY_CERT:
379
		x = load_cert(bio_err, keyfile, keyform,
380
		    NULL, "Certificate");
381
		if (x) {
382
			pkey = X509_get_pubkey(x);
383
			X509_free(x);
384
		}
385
		break;
386
387
	}
388
389
12
	*pkeysize = EVP_PKEY_size(pkey);
390
391
12
	if (!pkey)
392
		goto end;
393
394
12
	ctx = EVP_PKEY_CTX_new(pkey, NULL);
395
396
12
	EVP_PKEY_free(pkey);
397
398
12
	if (!ctx)
399
		goto end;
400
401

24
	switch (pkey_op) {
402
	case EVP_PKEY_OP_SIGN:
403
4
		rv = EVP_PKEY_sign_init(ctx);
404
4
		break;
405
406
	case EVP_PKEY_OP_VERIFY:
407
4
		rv = EVP_PKEY_verify_init(ctx);
408
4
		break;
409
410
	case EVP_PKEY_OP_VERIFYRECOVER:
411
4
		rv = EVP_PKEY_verify_recover_init(ctx);
412
4
		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
12
	if (rv <= 0) {
428
		EVP_PKEY_CTX_free(ctx);
429
		ctx = NULL;
430
	}
431
end:
432
433
12
	free(passin);
434
435
12
	return ctx;
436
437
438
12
}
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
	}
450
	peer = load_pubkey(bio_err, file, peerform, 0, NULL, "Peer Key");
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

48
	switch (pkey_op) {
472
	case EVP_PKEY_OP_VERIFYRECOVER:
473
8
		rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
474
8
		break;
475
476
	case EVP_PKEY_OP_SIGN:
477
8
		rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
478
8
		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
16
	return rv;
494
}