1 /* $OpenBSD: spkac.c,v 1.10 2018/02/07 05:47:55 jsing 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).
6 /* ====================================================================
7 * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
35 * 6. Redistributions of any form whatsoever must retain the following
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
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 * ====================================================================
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).
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>
89 static struct option spkac_options
[] = {
93 .desc
= "Specify challenge string if SPKAC is generated",
95 .opt
.arg
= &spkac_config
.challenge
,
100 .desc
= "Input file (default stdin)",
102 .opt
.arg
= &spkac_config
.infile
,
107 .desc
= "Create SPKAC using private key file",
109 .opt
.arg
= &spkac_config
.keyfile
,
113 .desc
= "Do not print text version of SPKAC",
115 .opt
.flag
= &spkac_config
.noout
,
120 .desc
= "Output file (default stdout)",
122 .opt
.arg
= &spkac_config
.outfile
,
127 .desc
= "Input file passphrase source",
129 .opt
.arg
= &spkac_config
.passargin
,
133 .desc
= "Output public key of an SPKAC (not used if creating)",
135 .opt
.flag
= &spkac_config
.pubkey
,
140 .desc
= "SPKAC name (default \"SPKAC\")",
142 .opt
.arg
= &spkac_config
.spkac
,
147 .desc
= "Name of the section containing SPKAC (default"
150 .opt
.arg
= &spkac_config
.spksect
,
154 .desc
= "Verify digital signature on supplied SPKAC",
156 .opt
.flag
= &spkac_config
.verify
,
165 "usage: spkac [-challenge string] [-in file] "
166 "[-key file] [-noout]\n"
167 " [-out file] [-passin src] [-pubkey] [-spkac name] "
168 "[-spksect section]\n"
170 options_usage(spkac_options
);
174 spkac_main(int argc
, char **argv
)
177 BIO
*in
= NULL
, *out
= NULL
;
181 NETSCAPE_SPKI
*spki
= NULL
;
182 EVP_PKEY
*pkey
= NULL
;
184 if (single_execution
) {
185 if (pledge("stdio cpath wpath rpath tty", NULL
) == -1) {
191 memset(&spkac_config
, 0, sizeof(spkac_config
));
192 spkac_config
.spkac
= "SPKAC";
193 spkac_config
.spksect
= "default";
195 if (options_parse(argc
, argv
, spkac_options
, NULL
, NULL
) != 0) {
200 if (!app_passwd(bio_err
, spkac_config
.passargin
, NULL
, &passin
, NULL
)) {
201 BIO_printf(bio_err
, "Error getting password\n");
205 if (spkac_config
.keyfile
) {
206 pkey
= load_key(bio_err
,
207 strcmp(spkac_config
.keyfile
, "-") ? spkac_config
.keyfile
208 : NULL
, FORMAT_PEM
, 1, passin
, "private key");
212 spki
= NETSCAPE_SPKI_new();
213 if (spkac_config
.challenge
)
214 ASN1_STRING_set(spki
->spkac
->challenge
,
215 spkac_config
.challenge
,
216 (int) strlen(spkac_config
.challenge
));
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
);
226 if (spkac_config
.outfile
)
227 out
= BIO_new_file(spkac_config
.outfile
, "w");
229 out
= BIO_new_fp(stdout
, BIO_NOCLOSE
);
232 BIO_printf(bio_err
, "Error opening output file\n");
233 ERR_print_errors(bio_err
);
235 BIO_printf(out
, "SPKAC=%s\n", spkstr
);
241 if (spkac_config
.infile
)
242 in
= BIO_new_file(spkac_config
.infile
, "r");
244 in
= BIO_new_fp(stdin
, BIO_NOCLOSE
);
247 BIO_printf(bio_err
, "Error opening input file\n");
248 ERR_print_errors(bio_err
);
251 conf
= NCONF_new(NULL
);
252 i
= NCONF_load_bio(conf
, in
, NULL
);
255 BIO_printf(bio_err
, "Error parsing config file\n");
256 ERR_print_errors(bio_err
);
259 spkstr
= NCONF_get_string(conf
, spkac_config
.spksect
,
263 BIO_printf(bio_err
, "Can't find SPKAC called \"%s\"\n",
265 ERR_print_errors(bio_err
);
268 spki
= NETSCAPE_SPKI_b64_decode(spkstr
, -1);
271 BIO_printf(bio_err
, "Error loading SPKAC\n");
272 ERR_print_errors(bio_err
);
275 if (spkac_config
.outfile
)
276 out
= BIO_new_file(spkac_config
.outfile
, "w");
278 out
= BIO_new_fp(stdout
, BIO_NOCLOSE
);
282 BIO_printf(bio_err
, "Error opening output file\n");
283 ERR_print_errors(bio_err
);
286 if (!spkac_config
.noout
)
287 NETSCAPE_SPKI_print(out
, spki
);
288 pkey
= NETSCAPE_SPKI_get_pubkey(spki
);
289 if (spkac_config
.verify
) {
290 i
= NETSCAPE_SPKI_verify(spki
, pkey
);
292 BIO_printf(bio_err
, "Signature OK\n");
294 BIO_printf(bio_err
, "Signature Failure\n");
295 ERR_print_errors(bio_err
);
299 if (spkac_config
.pubkey
)
300 PEM_write_bio_PUBKEY(out
, pkey
);
306 NETSCAPE_SPKI_free(spki
);