sl@0: /* apps/spkac.c */ sl@0: sl@0: /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL sl@0: * project 1999. Based on an original idea by Massimiliano Pala sl@0: * (madwolf@openca.org). sl@0: */ sl@0: /* ==================================================================== sl@0: * Copyright (c) 1999 The OpenSSL Project. All rights reserved. sl@0: * sl@0: * Redistribution and use in source and binary forms, with or without sl@0: * modification, are permitted provided that the following conditions sl@0: * are met: sl@0: * sl@0: * 1. Redistributions of source code must retain the above copyright sl@0: * notice, this list of conditions and the following disclaimer. sl@0: * sl@0: * 2. Redistributions in binary form must reproduce the above copyright sl@0: * notice, this list of conditions and the following disclaimer in sl@0: * the documentation and/or other materials provided with the sl@0: * distribution. sl@0: * sl@0: * 3. All advertising materials mentioning features or use of this sl@0: * software must display the following acknowledgment: sl@0: * "This product includes software developed by the OpenSSL Project sl@0: * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" sl@0: * sl@0: * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to sl@0: * endorse or promote products derived from this software without sl@0: * prior written permission. For written permission, please contact sl@0: * licensing@OpenSSL.org. sl@0: * sl@0: * 5. Products derived from this software may not be called "OpenSSL" sl@0: * nor may "OpenSSL" appear in their names without prior written sl@0: * permission of the OpenSSL Project. sl@0: * sl@0: * 6. Redistributions of any form whatsoever must retain the following sl@0: * acknowledgment: sl@0: * "This product includes software developed by the OpenSSL Project sl@0: * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" sl@0: * sl@0: * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY sl@0: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE sl@0: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR sl@0: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR sl@0: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, sl@0: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT sl@0: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; sl@0: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) sl@0: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, sl@0: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) sl@0: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED sl@0: * OF THE POSSIBILITY OF SUCH DAMAGE. sl@0: * ==================================================================== sl@0: * sl@0: * This product includes cryptographic software written by Eric Young sl@0: * (eay@cryptsoft.com). This product includes software written by Tim sl@0: * Hudson (tjh@cryptsoft.com). sl@0: * sl@0: */ sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "apps.h" sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #undef PROG sl@0: #define PROG spkac_main sl@0: sl@0: /* -in arg - input file - default stdin sl@0: * -out arg - output file - default stdout sl@0: */ sl@0: sl@0: sl@0: int MAIN(int, char **); sl@0: sl@0: int MAIN(int argc, char **argv) sl@0: { sl@0: ENGINE *e = NULL; sl@0: int i,badops=0, ret = 1; sl@0: BIO *in = NULL,*out = NULL; sl@0: int verify=0,noout=0,pubkey=0; sl@0: char *infile = NULL,*outfile = NULL,*prog; sl@0: char *passargin = NULL, *passin = NULL; sl@0: const char *spkac = "SPKAC", *spksect = "default"; sl@0: char *spkstr = NULL; sl@0: char *challenge = NULL, *keyfile = NULL; sl@0: CONF *conf = NULL; sl@0: NETSCAPE_SPKI *spki = NULL; sl@0: EVP_PKEY *pkey = NULL; sl@0: #ifndef OPENSSL_NO_ENGINE sl@0: char *engine=NULL; sl@0: #endif sl@0: sl@0: apps_startup(); sl@0: sl@0: if (!bio_err) sl@0: bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); sl@0: sl@0: sl@0: if (!load_config(bio_err, NULL)) sl@0: goto end; sl@0: sl@0: prog=argv[0]; sl@0: argc--; sl@0: argv++; sl@0: while (argc >= 1) sl@0: { sl@0: if (strcmp(*argv,"-in") == 0) sl@0: { sl@0: if (--argc < 1) goto bad; sl@0: infile= *(++argv); sl@0: } sl@0: else if (strcmp(*argv,"-out") == 0) sl@0: { sl@0: if (--argc < 1) goto bad; sl@0: outfile= *(++argv); sl@0: } sl@0: else if (strcmp(*argv,"-passin") == 0) sl@0: { sl@0: if (--argc < 1) goto bad; sl@0: passargin= *(++argv); sl@0: } sl@0: else if (strcmp(*argv,"-key") == 0) sl@0: { sl@0: if (--argc < 1) goto bad; sl@0: keyfile= *(++argv); sl@0: } sl@0: else if (strcmp(*argv,"-challenge") == 0) sl@0: { sl@0: if (--argc < 1) goto bad; sl@0: challenge= *(++argv); sl@0: } sl@0: else if (strcmp(*argv,"-spkac") == 0) sl@0: { sl@0: if (--argc < 1) goto bad; sl@0: spkac= *(++argv); sl@0: } sl@0: else if (strcmp(*argv,"-spksect") == 0) sl@0: { sl@0: if (--argc < 1) goto bad; sl@0: spksect= *(++argv); sl@0: } sl@0: #ifndef OPENSSL_NO_ENGINE sl@0: else if (strcmp(*argv,"-engine") == 0) sl@0: { sl@0: if (--argc < 1) goto bad; sl@0: engine= *(++argv); sl@0: } sl@0: #endif sl@0: else if (strcmp(*argv,"-noout") == 0) sl@0: noout=1; sl@0: else if (strcmp(*argv,"-pubkey") == 0) sl@0: pubkey=1; sl@0: else if (strcmp(*argv,"-verify") == 0) sl@0: verify=1; sl@0: else badops = 1; sl@0: argc--; sl@0: argv++; sl@0: } sl@0: sl@0: if (badops) sl@0: { sl@0: bad: sl@0: BIO_printf(bio_err,"%s [options]\n",prog); sl@0: BIO_printf(bio_err,"where options are\n"); sl@0: BIO_printf(bio_err," -in arg input file\n"); sl@0: BIO_printf(bio_err," -out arg output file\n"); sl@0: BIO_printf(bio_err," -key arg create SPKAC using private key\n"); sl@0: BIO_printf(bio_err," -passin arg input file pass phrase source\n"); sl@0: BIO_printf(bio_err," -challenge arg challenge string\n"); sl@0: BIO_printf(bio_err," -spkac arg alternative SPKAC name\n"); sl@0: BIO_printf(bio_err," -noout don't print SPKAC\n"); sl@0: BIO_printf(bio_err," -pubkey output public key\n"); sl@0: BIO_printf(bio_err," -verify verify SPKAC signature\n"); sl@0: #ifndef OPENSSL_NO_ENGINE sl@0: BIO_printf(bio_err," -engine e use engine e, possibly a hardware device.\n"); sl@0: #endif sl@0: goto end; sl@0: } sl@0: sl@0: ERR_load_crypto_strings(); sl@0: if(!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { sl@0: BIO_printf(bio_err, "Error getting password\n"); sl@0: goto end; sl@0: } sl@0: sl@0: #ifndef OPENSSL_NO_ENGINE sl@0: e = setup_engine(bio_err, engine, 0); sl@0: #endif sl@0: sl@0: if(keyfile) { sl@0: pkey = load_key(bio_err, sl@0: strcmp(keyfile, "-") ? keyfile : NULL, sl@0: FORMAT_PEM, 1, passin, e, "private key"); sl@0: if(!pkey) { sl@0: goto end; sl@0: } sl@0: spki = NETSCAPE_SPKI_new(); sl@0: if(challenge) ASN1_STRING_set(spki->spkac->challenge, sl@0: challenge, (int)strlen(challenge)); sl@0: NETSCAPE_SPKI_set_pubkey(spki, pkey); sl@0: NETSCAPE_SPKI_sign(spki, pkey, EVP_md5()); sl@0: spkstr = NETSCAPE_SPKI_b64_encode(spki); sl@0: sl@0: if (outfile) out = BIO_new_file(outfile, "w"); sl@0: else { sl@0: out = BIO_new_fp(stdout, BIO_NOCLOSE); sl@0: #ifdef OPENSSL_SYS_VMS sl@0: { sl@0: BIO *tmpbio = BIO_new(BIO_f_linebuffer()); sl@0: out = BIO_push(tmpbio, out); sl@0: } sl@0: #endif sl@0: } sl@0: sl@0: if(!out) { sl@0: BIO_printf(bio_err, "Error opening output file\n"); sl@0: ERR_print_errors(bio_err); sl@0: goto end; sl@0: } sl@0: BIO_printf(out, "SPKAC=%s\n", spkstr); sl@0: OPENSSL_free(spkstr); sl@0: ret = 0; sl@0: goto end; sl@0: } sl@0: sl@0: sl@0: sl@0: if (infile) in = BIO_new_file(infile, "r"); sl@0: else in = BIO_new_fp(stdin, BIO_NOCLOSE); sl@0: sl@0: if(!in) { sl@0: BIO_printf(bio_err, "Error opening input file\n"); sl@0: ERR_print_errors(bio_err); sl@0: goto end; sl@0: } sl@0: sl@0: conf = NCONF_new(NULL); sl@0: i = NCONF_load_bio(conf, in, NULL); sl@0: sl@0: if(!i) { sl@0: BIO_printf(bio_err, "Error parsing config file\n"); sl@0: ERR_print_errors(bio_err); sl@0: goto end; sl@0: } sl@0: sl@0: spkstr = NCONF_get_string(conf, spksect, spkac); sl@0: sl@0: if(!spkstr) { sl@0: BIO_printf(bio_err, "Can't find SPKAC called \"%s\"\n", spkac); sl@0: ERR_print_errors(bio_err); sl@0: goto end; sl@0: } sl@0: sl@0: spki = NETSCAPE_SPKI_b64_decode(spkstr, -1); sl@0: sl@0: if(!spki) { sl@0: BIO_printf(bio_err, "Error loading SPKAC\n"); sl@0: ERR_print_errors(bio_err); sl@0: goto end; sl@0: } sl@0: sl@0: if (outfile) out = BIO_new_file(outfile, "w"); sl@0: else { sl@0: out = BIO_new_fp(stdout, BIO_NOCLOSE); sl@0: #ifdef OPENSSL_SYS_VMS sl@0: { sl@0: BIO *tmpbio = BIO_new(BIO_f_linebuffer()); sl@0: out = BIO_push(tmpbio, out); sl@0: } sl@0: #endif sl@0: } sl@0: sl@0: if(!out) { sl@0: BIO_printf(bio_err, "Error opening output file\n"); sl@0: ERR_print_errors(bio_err); sl@0: goto end; sl@0: } sl@0: sl@0: if(!noout) NETSCAPE_SPKI_print(out, spki); sl@0: pkey = NETSCAPE_SPKI_get_pubkey(spki); sl@0: if(verify) { sl@0: i = NETSCAPE_SPKI_verify(spki, pkey); sl@0: if(i) BIO_printf(bio_err, "Signature OK\n"); sl@0: else { sl@0: BIO_printf(bio_err, "Signature Failure\n"); sl@0: ERR_print_errors(bio_err); sl@0: goto end; sl@0: } sl@0: } sl@0: if(pubkey) PEM_write_bio_PUBKEY(out, pkey); sl@0: sl@0: ret = 0; sl@0: sl@0: end: sl@0: NCONF_free(conf); sl@0: NETSCAPE_SPKI_free(spki); sl@0: BIO_free(in); sl@0: BIO_free_all(out); sl@0: EVP_PKEY_free(pkey); sl@0: if(passin) OPENSSL_free(passin); sl@0: apps_shutdown(); sl@0: OPENSSL_EXIT(ret); sl@0: }