Annotation of src/usr.bin/openssl/spkac.c, Revision 1.3
1.3 ! doug 1: /* $OpenBSD: spkac.c,v 1.2 2014/08/28 14:23:52 jsing 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"
66:
67: #include <openssl/bio.h>
68: #include <openssl/conf.h>
69: #include <openssl/err.h>
70: #include <openssl/evp.h>
71: #include <openssl/lhash.h>
72: #include <openssl/pem.h>
73: #include <openssl/x509.h>
74:
1.3 ! doug 75: static struct {
! 76: char *challenge;
! 77: #ifndef OPENSSL_NO_ENGINE
! 78: char *engine;
! 79: #endif
! 80: char *infile;
! 81: char *keyfile;
! 82: int noout;
! 83: char *outfile;
! 84: char *passargin;
! 85: int pubkey;
! 86: char *spkac;
! 87: char *spksect;
! 88: int verify;
! 89: } spkac_config;
! 90:
! 91: static struct option spkac_options[] = {
! 92: {
! 93: .name = "challenge",
! 94: .argname = "string",
! 95: .desc = "Specify challenge string if SPKAC is generated",
! 96: .type = OPTION_ARG,
! 97: .opt.arg = &spkac_config.challenge,
! 98: },
! 99: #ifndef OPENSSL_NO_ENGINE
! 100: {
! 101: .name = "engine",
! 102: .argname = "id",
! 103: .desc = "Use the engine specified by the given identifier",
! 104: .type = OPTION_ARG,
! 105: .opt.arg = &spkac_config.engine,
! 106: },
! 107: #endif
! 108: {
! 109: .name = "in",
! 110: .argname = "file",
! 111: .desc = "Input file (default stdin)",
! 112: .type = OPTION_ARG,
! 113: .opt.arg = &spkac_config.infile,
! 114: },
! 115: {
! 116: .name = "key",
! 117: .argname = "file",
! 118: .desc = "Create SPKAC using private key file",
! 119: .type = OPTION_ARG,
! 120: .opt.arg = &spkac_config.keyfile,
! 121: },
! 122: {
! 123: .name = "noout",
! 124: .desc = "Do not print text version of SPKAC",
! 125: .type = OPTION_FLAG,
! 126: .opt.flag = &spkac_config.noout,
! 127: },
! 128: {
! 129: .name = "out",
! 130: .argname = "file",
! 131: .desc = "Output file (default stdout)",
! 132: .type = OPTION_ARG,
! 133: .opt.arg = &spkac_config.outfile,
! 134: },
! 135: {
! 136: .name = "passin",
! 137: .argname = "src",
! 138: .desc = "Input file passphrase source",
! 139: .type = OPTION_ARG,
! 140: .opt.arg = &spkac_config.passargin,
! 141: },
! 142: {
! 143: .name = "pubkey",
! 144: .desc = "Output public key of an SPKAC (not used if creating)",
! 145: .type = OPTION_FLAG,
! 146: .opt.flag = &spkac_config.pubkey,
! 147: },
! 148: {
! 149: .name = "spkac",
! 150: .argname = "name",
! 151: .desc = "SPKAC name (default \"SPKAC\")",
! 152: .type = OPTION_ARG,
! 153: .opt.arg = &spkac_config.spkac,
! 154: },
! 155: {
! 156: .name = "spksect",
! 157: .argname = "name",
! 158: .desc = "Name of the section containing SPKAC (default"
! 159: " \"default\")",
! 160: .type = OPTION_ARG,
! 161: .opt.arg = &spkac_config.spksect,
! 162: },
! 163: {
! 164: .name = "verify",
! 165: .desc = "Verify digital signature on supplied SPKAC",
! 166: .type = OPTION_FLAG,
! 167: .opt.flag = &spkac_config.verify,
! 168: },
! 169: { NULL }
! 170: };
1.1 jsing 171:
1.3 ! doug 172: static void
! 173: spkac_usage(void)
! 174: {
! 175: fprintf(stderr,
! 176: "usage: spkac [-challenge string] [-engine id] [-in file] "
! 177: "[-key file] [-noout]\n"
! 178: " [-out file] [-passin src] [-pubkey] [-spkac name] "
! 179: "[-spksect section]\n"
! 180: " [-verify]\n\n");
! 181: options_usage(spkac_options);
! 182: }
1.1 jsing 183:
184: int
185: spkac_main(int argc, char **argv)
186: {
187: ENGINE *e = NULL;
1.3 ! doug 188: int i, ret = 1;
1.1 jsing 189: BIO *in = NULL, *out = NULL;
1.3 ! doug 190: char *passin = NULL;
1.1 jsing 191: char *spkstr = NULL;
192: CONF *conf = NULL;
193: NETSCAPE_SPKI *spki = NULL;
194: EVP_PKEY *pkey = NULL;
195:
1.3 ! doug 196: memset(&spkac_config, 0, sizeof(spkac_config));
! 197: spkac_config.spkac = "SPKAC";
! 198: spkac_config.spksect = "default";
1.1 jsing 199:
1.3 ! doug 200: if (options_parse(argc, argv, spkac_options, NULL, NULL) != 0) {
! 201: spkac_usage();
! 202: return (1);
1.1 jsing 203: }
1.2 jsing 204:
1.3 ! doug 205: if (!app_passwd(bio_err, spkac_config.passargin, NULL, &passin, NULL)) {
1.1 jsing 206: BIO_printf(bio_err, "Error getting password\n");
207: goto end;
208: }
209: #ifndef OPENSSL_NO_ENGINE
1.3 ! doug 210: e = setup_engine(bio_err, spkac_config.engine, 0);
1.1 jsing 211: #endif
212:
1.3 ! doug 213: if (spkac_config.keyfile) {
1.1 jsing 214: pkey = load_key(bio_err,
1.3 ! doug 215: strcmp(spkac_config.keyfile, "-") ? spkac_config.keyfile
! 216: : NULL, FORMAT_PEM, 1, passin, e, "private key");
1.1 jsing 217: if (!pkey) {
218: goto end;
219: }
220: spki = NETSCAPE_SPKI_new();
1.3 ! doug 221: if (spkac_config.challenge)
1.1 jsing 222: ASN1_STRING_set(spki->spkac->challenge,
1.3 ! doug 223: spkac_config.challenge,
! 224: (int) strlen(spkac_config.challenge));
1.1 jsing 225: NETSCAPE_SPKI_set_pubkey(spki, pkey);
226: NETSCAPE_SPKI_sign(spki, pkey, EVP_md5());
227: spkstr = NETSCAPE_SPKI_b64_encode(spki);
228: if (spkstr == NULL) {
229: BIO_printf(bio_err, "Error encoding SPKAC\n");
230: ERR_print_errors(bio_err);
231: goto end;
232: }
233:
1.3 ! doug 234: if (spkac_config.outfile)
! 235: out = BIO_new_file(spkac_config.outfile, "w");
1.1 jsing 236: else
237: out = BIO_new_fp(stdout, BIO_NOCLOSE);
238:
239: if (!out) {
240: BIO_printf(bio_err, "Error opening output file\n");
241: ERR_print_errors(bio_err);
242: } else {
243: BIO_printf(out, "SPKAC=%s\n", spkstr);
244: ret = 0;
245: }
246: free(spkstr);
247: goto end;
248: }
1.3 ! doug 249: if (spkac_config.infile)
! 250: in = BIO_new_file(spkac_config.infile, "r");
1.1 jsing 251: else
252: in = BIO_new_fp(stdin, BIO_NOCLOSE);
253:
254: if (!in) {
255: BIO_printf(bio_err, "Error opening input file\n");
256: ERR_print_errors(bio_err);
257: goto end;
258: }
259: conf = NCONF_new(NULL);
260: i = NCONF_load_bio(conf, in, NULL);
261:
262: if (!i) {
263: BIO_printf(bio_err, "Error parsing config file\n");
264: ERR_print_errors(bio_err);
265: goto end;
266: }
1.3 ! doug 267: spkstr = NCONF_get_string(conf, spkac_config.spksect,
! 268: spkac_config.spkac);
1.1 jsing 269:
270: if (!spkstr) {
1.3 ! doug 271: BIO_printf(bio_err, "Can't find SPKAC called \"%s\"\n",
! 272: spkac_config.spkac);
1.1 jsing 273: ERR_print_errors(bio_err);
274: goto end;
275: }
276: spki = NETSCAPE_SPKI_b64_decode(spkstr, -1);
277:
278: if (!spki) {
279: BIO_printf(bio_err, "Error loading SPKAC\n");
280: ERR_print_errors(bio_err);
281: goto end;
282: }
1.3 ! doug 283: if (spkac_config.outfile)
! 284: out = BIO_new_file(spkac_config.outfile, "w");
1.1 jsing 285: else {
286: out = BIO_new_fp(stdout, BIO_NOCLOSE);
287: }
288:
289: if (!out) {
290: BIO_printf(bio_err, "Error opening output file\n");
291: ERR_print_errors(bio_err);
292: goto end;
293: }
1.3 ! doug 294: if (!spkac_config.noout)
1.1 jsing 295: NETSCAPE_SPKI_print(out, spki);
296: pkey = NETSCAPE_SPKI_get_pubkey(spki);
1.3 ! doug 297: if (spkac_config.verify) {
1.1 jsing 298: i = NETSCAPE_SPKI_verify(spki, pkey);
299: if (i > 0)
300: BIO_printf(bio_err, "Signature OK\n");
301: else {
302: BIO_printf(bio_err, "Signature Failure\n");
303: ERR_print_errors(bio_err);
304: goto end;
305: }
306: }
1.3 ! doug 307: if (spkac_config.pubkey)
1.1 jsing 308: PEM_write_bio_PUBKEY(out, pkey);
309:
310: ret = 0;
311:
312: end:
313: NCONF_free(conf);
314: NETSCAPE_SPKI_free(spki);
315: BIO_free(in);
316: BIO_free_all(out);
317: EVP_PKEY_free(pkey);
318: free(passin);
319:
320: return (ret);
321: }