Annotation of src/usr.bin/openssl/spkac.c, Revision 1.9
1.9 ! deraadt 1: /* $OpenBSD: spkac.c,v 1.8 2015/10/17 15:00:11 doug Exp $ */
1.1 jsing 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"
1.4 deraadt 66: #include "progs.h"
1.1 jsing 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:
1.3 doug 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: };
1.1 jsing 160:
1.3 doug 161: static void
162: spkac_usage(void)
163: {
164: fprintf(stderr,
1.5 bcook 165: "usage: spkac [-challenge string] [-in file] "
1.3 doug 166: "[-key file] [-noout]\n"
167: " [-out file] [-passin src] [-pubkey] [-spkac name] "
168: "[-spksect section]\n"
169: " [-verify]\n\n");
170: options_usage(spkac_options);
171: }
1.1 jsing 172:
173: int
174: spkac_main(int argc, char **argv)
175: {
1.3 doug 176: int i, ret = 1;
1.1 jsing 177: BIO *in = NULL, *out = NULL;
1.3 doug 178: char *passin = NULL;
1.1 jsing 179: char *spkstr = NULL;
180: CONF *conf = NULL;
181: NETSCAPE_SPKI *spki = NULL;
182: EVP_PKEY *pkey = NULL;
1.6 doug 183:
184: if (single_execution) {
1.9 ! deraadt 185: if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
1.6 doug 186: perror("pledge");
1.8 doug 187: exit(1);
188: }
1.6 doug 189: }
1.1 jsing 190:
1.3 doug 191: memset(&spkac_config, 0, sizeof(spkac_config));
192: spkac_config.spkac = "SPKAC";
193: spkac_config.spksect = "default";
1.1 jsing 194:
1.3 doug 195: if (options_parse(argc, argv, spkac_options, NULL, NULL) != 0) {
196: spkac_usage();
197: return (1);
1.1 jsing 198: }
1.2 jsing 199:
1.3 doug 200: if (!app_passwd(bio_err, spkac_config.passargin, NULL, &passin, NULL)) {
1.1 jsing 201: BIO_printf(bio_err, "Error getting password\n");
202: goto end;
203: }
204:
1.3 doug 205: if (spkac_config.keyfile) {
1.1 jsing 206: pkey = load_key(bio_err,
1.3 doug 207: strcmp(spkac_config.keyfile, "-") ? spkac_config.keyfile
1.5 bcook 208: : NULL, FORMAT_PEM, 1, passin, "private key");
1.1 jsing 209: if (!pkey) {
210: goto end;
211: }
212: spki = NETSCAPE_SPKI_new();
1.3 doug 213: if (spkac_config.challenge)
1.1 jsing 214: ASN1_STRING_set(spki->spkac->challenge,
1.3 doug 215: spkac_config.challenge,
216: (int) strlen(spkac_config.challenge));
1.1 jsing 217: NETSCAPE_SPKI_set_pubkey(spki, pkey);
218: NETSCAPE_SPKI_sign(spki, pkey, EVP_md5());
219: spkstr = NETSCAPE_SPKI_b64_encode(spki);
220: if (spkstr == NULL) {
221: BIO_printf(bio_err, "Error encoding SPKAC\n");
222: ERR_print_errors(bio_err);
223: goto end;
224: }
225:
1.3 doug 226: if (spkac_config.outfile)
227: out = BIO_new_file(spkac_config.outfile, "w");
1.1 jsing 228: else
229: out = BIO_new_fp(stdout, BIO_NOCLOSE);
230:
231: if (!out) {
232: BIO_printf(bio_err, "Error opening output file\n");
233: ERR_print_errors(bio_err);
234: } else {
235: BIO_printf(out, "SPKAC=%s\n", spkstr);
236: ret = 0;
237: }
238: free(spkstr);
239: goto end;
240: }
1.3 doug 241: if (spkac_config.infile)
242: in = BIO_new_file(spkac_config.infile, "r");
1.1 jsing 243: else
244: in = BIO_new_fp(stdin, BIO_NOCLOSE);
245:
246: if (!in) {
247: BIO_printf(bio_err, "Error opening input file\n");
248: ERR_print_errors(bio_err);
249: goto end;
250: }
251: conf = NCONF_new(NULL);
252: i = NCONF_load_bio(conf, in, NULL);
253:
254: if (!i) {
255: BIO_printf(bio_err, "Error parsing config file\n");
256: ERR_print_errors(bio_err);
257: goto end;
258: }
1.3 doug 259: spkstr = NCONF_get_string(conf, spkac_config.spksect,
260: spkac_config.spkac);
1.1 jsing 261:
262: if (!spkstr) {
1.3 doug 263: BIO_printf(bio_err, "Can't find SPKAC called \"%s\"\n",
264: spkac_config.spkac);
1.1 jsing 265: ERR_print_errors(bio_err);
266: goto end;
267: }
268: spki = NETSCAPE_SPKI_b64_decode(spkstr, -1);
269:
270: if (!spki) {
271: BIO_printf(bio_err, "Error loading SPKAC\n");
272: ERR_print_errors(bio_err);
273: goto end;
274: }
1.3 doug 275: if (spkac_config.outfile)
276: out = BIO_new_file(spkac_config.outfile, "w");
1.1 jsing 277: else {
278: out = BIO_new_fp(stdout, BIO_NOCLOSE);
279: }
280:
281: if (!out) {
282: BIO_printf(bio_err, "Error opening output file\n");
283: ERR_print_errors(bio_err);
284: goto end;
285: }
1.3 doug 286: if (!spkac_config.noout)
1.1 jsing 287: NETSCAPE_SPKI_print(out, spki);
288: pkey = NETSCAPE_SPKI_get_pubkey(spki);
1.3 doug 289: if (spkac_config.verify) {
1.1 jsing 290: i = NETSCAPE_SPKI_verify(spki, pkey);
291: if (i > 0)
292: 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: }
1.3 doug 299: if (spkac_config.pubkey)
1.1 jsing 300: PEM_write_bio_PUBKEY(out, pkey);
301:
302: ret = 0;
303:
304: end:
305: NCONF_free(conf);
306: NETSCAPE_SPKI_free(spki);
307: BIO_free(in);
308: BIO_free_all(out);
309: EVP_PKEY_free(pkey);
310: free(passin);
311:
312: return (ret);
313: }