GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/openssl/spkac.c Lines: 64 97 66.0 %
Date: 2017-11-13 Branches: 23 42 54.8 %

Line Branch Exec Source
1
/* $OpenBSD: spkac.c,v 1.9 2017/01/20 08:57:12 deraadt Exp $ */
2
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3
 * project 1999. Based on an original idea by Massimiliano Pala
4
 * (madwolf@openca.org).
5
 */
6
/* ====================================================================
7
 * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 *
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 *
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in
18
 *    the documentation and/or other materials provided with the
19
 *    distribution.
20
 *
21
 * 3. All advertising materials mentioning features or use of this
22
 *    software must display the following acknowledgment:
23
 *    "This product includes software developed by the OpenSSL Project
24
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25
 *
26
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27
 *    endorse or promote products derived from this software without
28
 *    prior written permission. For written permission, please contact
29
 *    licensing@OpenSSL.org.
30
 *
31
 * 5. Products derived from this software may not be called "OpenSSL"
32
 *    nor may "OpenSSL" appear in their names without prior written
33
 *    permission of the OpenSSL Project.
34
 *
35
 * 6. Redistributions of any form whatsoever must retain the following
36
 *    acknowledgment:
37
 *    "This product includes software developed by the OpenSSL Project
38
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51
 * OF THE POSSIBILITY OF SUCH DAMAGE.
52
 * ====================================================================
53
 *
54
 * This product includes cryptographic software written by Eric Young
55
 * (eay@cryptsoft.com).  This product includes software written by Tim
56
 * Hudson (tjh@cryptsoft.com).
57
 *
58
 */
59
60
#include <stdio.h>
61
#include <stdlib.h>
62
#include <string.h>
63
#include <time.h>
64
65
#include "apps.h"
66
#include "progs.h"
67
68
#include <openssl/bio.h>
69
#include <openssl/conf.h>
70
#include <openssl/err.h>
71
#include <openssl/evp.h>
72
#include <openssl/lhash.h>
73
#include <openssl/pem.h>
74
#include <openssl/x509.h>
75
76
static struct {
77
	char *challenge;
78
	char *infile;
79
	char *keyfile;
80
	int noout;
81
	char *outfile;
82
	char *passargin;
83
	int pubkey;
84
	char *spkac;
85
	char *spksect;
86
	int verify;
87
} spkac_config;
88
89
static struct option spkac_options[] = {
90
	{
91
		.name = "challenge",
92
		.argname = "string",
93
		.desc = "Specify challenge string if SPKAC is generated",
94
		.type = OPTION_ARG,
95
		.opt.arg = &spkac_config.challenge,
96
	},
97
	{
98
		.name = "in",
99
		.argname = "file",
100
		.desc = "Input file (default stdin)",
101
		.type = OPTION_ARG,
102
		.opt.arg = &spkac_config.infile,
103
	},
104
	{
105
		.name = "key",
106
		.argname = "file",
107
		.desc = "Create SPKAC using private key file",
108
		.type = OPTION_ARG,
109
		.opt.arg = &spkac_config.keyfile,
110
	},
111
	{
112
		.name = "noout",
113
		.desc = "Do not print text version of SPKAC",
114
		.type = OPTION_FLAG,
115
		.opt.flag = &spkac_config.noout,
116
	},
117
	{
118
		.name = "out",
119
		.argname = "file",
120
		.desc = "Output file (default stdout)",
121
		.type = OPTION_ARG,
122
		.opt.arg = &spkac_config.outfile,
123
	},
124
	{
125
		.name = "passin",
126
		.argname = "src",
127
		.desc = "Input file passphrase source",
128
		.type = OPTION_ARG,
129
		.opt.arg = &spkac_config.passargin,
130
	},
131
	{
132
		.name = "pubkey",
133
		.desc = "Output public key of an SPKAC (not used if creating)",
134
		.type = OPTION_FLAG,
135
		.opt.flag = &spkac_config.pubkey,
136
	},
137
	{
138
		.name = "spkac",
139
		.argname = "name",
140
		.desc = "SPKAC name (default \"SPKAC\")",
141
		.type = OPTION_ARG,
142
		.opt.arg = &spkac_config.spkac,
143
	},
144
	{
145
		.name = "spksect",
146
		.argname = "name",
147
		.desc = "Name of the section containing SPKAC (default"
148
		" \"default\")",
149
		.type = OPTION_ARG,
150
		.opt.arg = &spkac_config.spksect,
151
	},
152
	{
153
		.name = "verify",
154
		.desc = "Verify digital signature on supplied SPKAC",
155
		.type = OPTION_FLAG,
156
		.opt.flag = &spkac_config.verify,
157
	},
158
	{ NULL }
159
};
160
161
static void
162
spkac_usage(void)
163
{
164
8
	fprintf(stderr,
165
	    "usage: spkac [-challenge string] [-in file] "
166
	    "[-key file] [-noout]\n"
167
	    "    [-out file] [-passin src] [-pubkey] [-spkac name] "
168
	    "[-spksect section]\n"
169
	    "    [-verify]\n\n");
170
4
	options_usage(spkac_options);
171
4
}
172
173
int
174
spkac_main(int argc, char **argv)
175
{
176
	int i, ret = 1;
177
	BIO *in = NULL, *out = NULL;
178
24
	char *passin = NULL;
179
	char *spkstr = NULL;
180
	CONF *conf = NULL;
181
	NETSCAPE_SPKI *spki = NULL;
182
	EVP_PKEY *pkey = NULL;
183
184
12
	if (single_execution) {
185
12
		if (pledge("stdio cpath wpath rpath tty flock", NULL) == -1) {
186
			perror("pledge");
187
			exit(1);
188
		}
189
	}
190
191
12
	memset(&spkac_config, 0, sizeof(spkac_config));
192
12
	spkac_config.spkac = "SPKAC";
193
12
	spkac_config.spksect = "default";
194
195
12
	if (options_parse(argc, argv, spkac_options, NULL, NULL) != 0) {
196
4
		spkac_usage();
197
4
		return (1);
198
	}
199
200
8
	if (!app_passwd(bio_err, spkac_config.passargin, NULL, &passin, NULL)) {
201
		BIO_printf(bio_err, "Error getting password\n");
202
		goto end;
203
	}
204
205
8
	if (spkac_config.keyfile) {
206
8
		pkey = load_key(bio_err,
207
4
		    strcmp(spkac_config.keyfile, "-") ? spkac_config.keyfile
208
4
		    : NULL, FORMAT_PEM, 1, passin, "private key");
209
4
		if (!pkey) {
210
			goto end;
211
		}
212
4
		spki = NETSCAPE_SPKI_new();
213
4
		if (spkac_config.challenge)
214
8
			ASN1_STRING_set(spki->spkac->challenge,
215
			    spkac_config.challenge,
216
4
			    (int) strlen(spkac_config.challenge));
217
4
		NETSCAPE_SPKI_set_pubkey(spki, pkey);
218
4
		NETSCAPE_SPKI_sign(spki, pkey, EVP_md5());
219
4
		spkstr = NETSCAPE_SPKI_b64_encode(spki);
220
4
		if (spkstr == NULL) {
221
			BIO_printf(bio_err, "Error encoding SPKAC\n");
222
			ERR_print_errors(bio_err);
223
			goto end;
224
		}
225
226
4
		if (spkac_config.outfile)
227
4
			out = BIO_new_file(spkac_config.outfile, "w");
228
		else
229
			out = BIO_new_fp(stdout, BIO_NOCLOSE);
230
231
4
		if (!out) {
232
			BIO_printf(bio_err, "Error opening output file\n");
233
			ERR_print_errors(bio_err);
234
		} else {
235
4
			BIO_printf(out, "SPKAC=%s\n", spkstr);
236
			ret = 0;
237
		}
238
4
		free(spkstr);
239
4
		goto end;
240
	}
241
4
	if (spkac_config.infile)
242
4
		in = BIO_new_file(spkac_config.infile, "r");
243
	else
244
		in = BIO_new_fp(stdin, BIO_NOCLOSE);
245
246
4
	if (!in) {
247
		BIO_printf(bio_err, "Error opening input file\n");
248
		ERR_print_errors(bio_err);
249
		goto end;
250
	}
251
4
	conf = NCONF_new(NULL);
252
4
	i = NCONF_load_bio(conf, in, NULL);
253
254
4
	if (!i) {
255
		BIO_printf(bio_err, "Error parsing config file\n");
256
		ERR_print_errors(bio_err);
257
		goto end;
258
	}
259
8
	spkstr = NCONF_get_string(conf, spkac_config.spksect,
260
4
	    spkac_config.spkac);
261
262
4
	if (!spkstr) {
263
		BIO_printf(bio_err, "Can't find SPKAC called \"%s\"\n",
264
		    spkac_config.spkac);
265
		ERR_print_errors(bio_err);
266
		goto end;
267
	}
268
4
	spki = NETSCAPE_SPKI_b64_decode(spkstr, -1);
269
270
4
	if (!spki) {
271
		BIO_printf(bio_err, "Error loading SPKAC\n");
272
		ERR_print_errors(bio_err);
273
		goto end;
274
	}
275
4
	if (spkac_config.outfile)
276
4
		out = BIO_new_file(spkac_config.outfile, "w");
277
	else {
278
		out = BIO_new_fp(stdout, BIO_NOCLOSE);
279
	}
280
281
4
	if (!out) {
282
		BIO_printf(bio_err, "Error opening output file\n");
283
		ERR_print_errors(bio_err);
284
		goto end;
285
	}
286
4
	if (!spkac_config.noout)
287
4
		NETSCAPE_SPKI_print(out, spki);
288
4
	pkey = NETSCAPE_SPKI_get_pubkey(spki);
289
4
	if (spkac_config.verify) {
290
4
		i = NETSCAPE_SPKI_verify(spki, pkey);
291
4
		if (i > 0)
292
4
			BIO_printf(bio_err, "Signature OK\n");
293
		else {
294
			BIO_printf(bio_err, "Signature Failure\n");
295
			ERR_print_errors(bio_err);
296
			goto end;
297
		}
298
4
	}
299
4
	if (spkac_config.pubkey)
300
		PEM_write_bio_PUBKEY(out, pkey);
301
302
4
	ret = 0;
303
304
end:
305
8
	NCONF_free(conf);
306
8
	NETSCAPE_SPKI_free(spki);
307
8
	BIO_free(in);
308
8
	BIO_free_all(out);
309
8
	EVP_PKEY_free(pkey);
310
8
	free(passin);
311
312
8
	return (ret);
313
12
}