Annotation of src/usr.bin/openssl/spkac.c, Revision 1.13
1.13 ! tb 1: /* $OpenBSD: spkac.c,v 1.12 2022/11/11 17:07:39 joshua 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;
1.13 ! tb 87: } cfg;
1.3 doug 88:
1.11 guenther 89: static const struct option spkac_options[] = {
1.3 doug 90: {
91: .name = "challenge",
92: .argname = "string",
93: .desc = "Specify challenge string if SPKAC is generated",
94: .type = OPTION_ARG,
1.13 ! tb 95: .opt.arg = &cfg.challenge,
1.3 doug 96: },
97: {
98: .name = "in",
99: .argname = "file",
100: .desc = "Input file (default stdin)",
101: .type = OPTION_ARG,
1.13 ! tb 102: .opt.arg = &cfg.infile,
1.3 doug 103: },
104: {
105: .name = "key",
106: .argname = "file",
107: .desc = "Create SPKAC using private key file",
108: .type = OPTION_ARG,
1.13 ! tb 109: .opt.arg = &cfg.keyfile,
1.3 doug 110: },
111: {
112: .name = "noout",
113: .desc = "Do not print text version of SPKAC",
114: .type = OPTION_FLAG,
1.13 ! tb 115: .opt.flag = &cfg.noout,
1.3 doug 116: },
117: {
118: .name = "out",
119: .argname = "file",
120: .desc = "Output file (default stdout)",
121: .type = OPTION_ARG,
1.13 ! tb 122: .opt.arg = &cfg.outfile,
1.3 doug 123: },
124: {
125: .name = "passin",
126: .argname = "src",
127: .desc = "Input file passphrase source",
128: .type = OPTION_ARG,
1.13 ! tb 129: .opt.arg = &cfg.passargin,
1.3 doug 130: },
131: {
132: .name = "pubkey",
133: .desc = "Output public key of an SPKAC (not used if creating)",
134: .type = OPTION_FLAG,
1.13 ! tb 135: .opt.flag = &cfg.pubkey,
1.3 doug 136: },
137: {
138: .name = "spkac",
139: .argname = "name",
140: .desc = "SPKAC name (default \"SPKAC\")",
141: .type = OPTION_ARG,
1.13 ! tb 142: .opt.arg = &cfg.spkac,
1.3 doug 143: },
144: {
145: .name = "spksect",
146: .argname = "name",
147: .desc = "Name of the section containing SPKAC (default"
148: " \"default\")",
149: .type = OPTION_ARG,
1.13 ! tb 150: .opt.arg = &cfg.spksect,
1.3 doug 151: },
152: {
153: .name = "verify",
154: .desc = "Verify digital signature on supplied SPKAC",
155: .type = OPTION_FLAG,
1.13 ! tb 156: .opt.flag = &cfg.verify,
1.3 doug 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:
1.12 joshua 184: if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
185: perror("pledge");
186: exit(1);
1.6 doug 187: }
1.1 jsing 188:
1.13 ! tb 189: memset(&cfg, 0, sizeof(cfg));
! 190: cfg.spkac = "SPKAC";
! 191: cfg.spksect = "default";
1.1 jsing 192:
1.3 doug 193: if (options_parse(argc, argv, spkac_options, NULL, NULL) != 0) {
194: spkac_usage();
195: return (1);
1.1 jsing 196: }
1.2 jsing 197:
1.13 ! tb 198: if (!app_passwd(bio_err, cfg.passargin, NULL, &passin, NULL)) {
1.1 jsing 199: BIO_printf(bio_err, "Error getting password\n");
200: goto end;
201: }
202:
1.13 ! tb 203: if (cfg.keyfile) {
1.1 jsing 204: pkey = load_key(bio_err,
1.13 ! tb 205: strcmp(cfg.keyfile, "-") ? cfg.keyfile
1.5 bcook 206: : NULL, FORMAT_PEM, 1, passin, "private key");
1.1 jsing 207: if (!pkey) {
208: goto end;
209: }
210: spki = NETSCAPE_SPKI_new();
1.13 ! tb 211: if (cfg.challenge)
1.1 jsing 212: ASN1_STRING_set(spki->spkac->challenge,
1.13 ! tb 213: cfg.challenge,
! 214: (int) strlen(cfg.challenge));
1.1 jsing 215: NETSCAPE_SPKI_set_pubkey(spki, pkey);
216: NETSCAPE_SPKI_sign(spki, pkey, EVP_md5());
217: spkstr = NETSCAPE_SPKI_b64_encode(spki);
218: if (spkstr == NULL) {
219: BIO_printf(bio_err, "Error encoding SPKAC\n");
220: ERR_print_errors(bio_err);
221: goto end;
222: }
223:
1.13 ! tb 224: if (cfg.outfile)
! 225: out = BIO_new_file(cfg.outfile, "w");
1.1 jsing 226: else
227: out = BIO_new_fp(stdout, BIO_NOCLOSE);
228:
229: if (!out) {
230: BIO_printf(bio_err, "Error opening output file\n");
231: ERR_print_errors(bio_err);
232: } else {
233: BIO_printf(out, "SPKAC=%s\n", spkstr);
234: ret = 0;
235: }
236: free(spkstr);
237: goto end;
238: }
1.13 ! tb 239: if (cfg.infile)
! 240: in = BIO_new_file(cfg.infile, "r");
1.1 jsing 241: else
242: in = BIO_new_fp(stdin, BIO_NOCLOSE);
243:
244: if (!in) {
245: BIO_printf(bio_err, "Error opening input file\n");
246: ERR_print_errors(bio_err);
247: goto end;
248: }
249: conf = NCONF_new(NULL);
250: i = NCONF_load_bio(conf, in, NULL);
251:
252: if (!i) {
253: BIO_printf(bio_err, "Error parsing config file\n");
254: ERR_print_errors(bio_err);
255: goto end;
256: }
1.13 ! tb 257: spkstr = NCONF_get_string(conf, cfg.spksect,
! 258: cfg.spkac);
1.1 jsing 259:
260: if (!spkstr) {
1.3 doug 261: BIO_printf(bio_err, "Can't find SPKAC called \"%s\"\n",
1.13 ! tb 262: cfg.spkac);
1.1 jsing 263: ERR_print_errors(bio_err);
264: goto end;
265: }
266: spki = NETSCAPE_SPKI_b64_decode(spkstr, -1);
267:
268: if (!spki) {
269: BIO_printf(bio_err, "Error loading SPKAC\n");
270: ERR_print_errors(bio_err);
271: goto end;
272: }
1.13 ! tb 273: if (cfg.outfile)
! 274: out = BIO_new_file(cfg.outfile, "w");
1.1 jsing 275: else {
276: out = BIO_new_fp(stdout, BIO_NOCLOSE);
277: }
278:
279: if (!out) {
280: BIO_printf(bio_err, "Error opening output file\n");
281: ERR_print_errors(bio_err);
282: goto end;
283: }
1.13 ! tb 284: if (!cfg.noout)
1.1 jsing 285: NETSCAPE_SPKI_print(out, spki);
286: pkey = NETSCAPE_SPKI_get_pubkey(spki);
1.13 ! tb 287: if (cfg.verify) {
1.1 jsing 288: i = NETSCAPE_SPKI_verify(spki, pkey);
289: if (i > 0)
290: BIO_printf(bio_err, "Signature OK\n");
291: else {
292: BIO_printf(bio_err, "Signature Failure\n");
293: ERR_print_errors(bio_err);
294: goto end;
295: }
296: }
1.13 ! tb 297: if (cfg.pubkey)
1.1 jsing 298: PEM_write_bio_PUBKEY(out, pkey);
299:
300: ret = 0;
301:
1.10 jsing 302: end:
1.1 jsing 303: NCONF_free(conf);
304: NETSCAPE_SPKI_free(spki);
305: BIO_free(in);
306: BIO_free_all(out);
307: EVP_PKEY_free(pkey);
308: free(passin);
309:
310: return (ret);
311: }