155714Skris/* apps/x509.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8296465Sdelphij *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296465Sdelphij *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22296465Sdelphij *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37296465Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296465Sdelphij *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52296465Sdelphij *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5959191Skris#include <assert.h>
6055714Skris#include <stdio.h>
6155714Skris#include <stdlib.h>
6255714Skris#include <string.h>
63109998Smarkm#ifdef OPENSSL_NO_STDIO
64296465Sdelphij# define APPS_WIN16
6555714Skris#endif
6655714Skris#include "apps.h"
6755714Skris#include <openssl/bio.h>
6855714Skris#include <openssl/asn1.h>
6955714Skris#include <openssl/err.h>
7055714Skris#include <openssl/bn.h>
7155714Skris#include <openssl/evp.h>
7255714Skris#include <openssl/x509.h>
7355714Skris#include <openssl/x509v3.h>
7455714Skris#include <openssl/objects.h>
7555714Skris#include <openssl/pem.h>
76160814Ssimon#ifndef OPENSSL_NO_RSA
77296465Sdelphij# include <openssl/rsa.h>
78160814Ssimon#endif
79160814Ssimon#ifndef OPENSSL_NO_DSA
80296465Sdelphij# include <openssl/dsa.h>
81160814Ssimon#endif
8255714Skris
8355714Skris#undef PROG
8455714Skris#define PROG x509_main
8555714Skris
8655714Skris#undef POSTFIX
87296465Sdelphij#define POSTFIX ".srl"
88296465Sdelphij#define DEF_DAYS        30
8955714Skris
90296465Sdelphijstatic const char *x509_usage[] = {
91296465Sdelphij    "usage: x509 args\n",
92296465Sdelphij    " -inform arg     - input format - default PEM (one of DER, NET or PEM)\n",
93296465Sdelphij    " -outform arg    - output format - default PEM (one of DER, NET or PEM)\n",
94296465Sdelphij    " -keyform arg    - private key format - default PEM\n",
95296465Sdelphij    " -CAform arg     - CA format - default PEM\n",
96296465Sdelphij    " -CAkeyform arg  - CA key format - default PEM\n",
97296465Sdelphij    " -in arg         - input file - default stdin\n",
98296465Sdelphij    " -out arg        - output file - default stdout\n",
99296465Sdelphij    " -passin arg     - private key password source\n",
100296465Sdelphij    " -serial         - print serial number value\n",
101296465Sdelphij    " -subject_hash   - print subject hash value\n",
102296465Sdelphij    " -issuer_hash    - print issuer hash value\n",
103296465Sdelphij    " -hash           - synonym for -subject_hash\n",
104296465Sdelphij    " -subject        - print subject DN\n",
105296465Sdelphij    " -issuer         - print issuer DN\n",
106296465Sdelphij    " -email          - print email address(es)\n",
107296465Sdelphij    " -startdate      - notBefore field\n",
108296465Sdelphij    " -enddate        - notAfter field\n",
109296465Sdelphij    " -purpose        - print out certificate purposes\n",
110296465Sdelphij    " -dates          - both Before and After dates\n",
111296465Sdelphij    " -modulus        - print the RSA key modulus\n",
112296465Sdelphij    " -pubkey         - output the public key\n",
113296465Sdelphij    " -fingerprint    - print the certificate fingerprint\n",
114296465Sdelphij    " -alias          - output certificate alias\n",
115296465Sdelphij    " -noout          - no certificate output\n",
116296465Sdelphij    " -ocspid         - print OCSP hash values for the subject name and public key\n",
117296465Sdelphij    " -ocsp_uri       - print OCSP Responder URL(s)\n",
118296465Sdelphij    " -trustout       - output a \"trusted\" certificate\n",
119296465Sdelphij    " -clrtrust       - clear all trusted purposes\n",
120296465Sdelphij    " -clrreject      - clear all rejected purposes\n",
121296465Sdelphij    " -addtrust arg   - trust certificate for a given purpose\n",
122296465Sdelphij    " -addreject arg  - reject certificate for a given purpose\n",
123296465Sdelphij    " -setalias arg   - set certificate alias\n",
124296465Sdelphij    " -days arg       - How long till expiry of a signed certificate - def 30 days\n",
125296465Sdelphij    " -checkend arg   - check whether the cert expires in the next arg seconds\n",
126296465Sdelphij    "                   exit 1 if so, 0 if not\n",
127296465Sdelphij    " -signkey arg    - self sign cert with arg\n",
128296465Sdelphij    " -x509toreq      - output a certification request object\n",
129296465Sdelphij    " -req            - input is a certificate request, sign and output.\n",
130296465Sdelphij    " -CA arg         - set the CA certificate, must be PEM format.\n",
131296465Sdelphij    " -CAkey arg      - set the CA key, must be PEM format\n",
132296465Sdelphij    "                   missing, it is assumed to be in the CA file.\n",
133296465Sdelphij    " -CAcreateserial - create serial number file if it does not exist\n",
134296465Sdelphij    " -CAserial arg   - serial file\n",
135296465Sdelphij    " -set_serial     - serial number to use\n",
136296465Sdelphij    " -text           - print the certificate in text form\n",
137296465Sdelphij    " -C              - print out C code forms\n",
138296465Sdelphij    " -md2/-md5/-sha1/-mdc2 - digest to use\n",
139296465Sdelphij    " -extfile        - configuration file with X509V3 extensions to add\n",
140296465Sdelphij    " -extensions     - section from config file with X509V3 extensions to add\n",
141296465Sdelphij    " -clrext         - delete extensions before signing and input certificate\n",
142296465Sdelphij    " -nameopt arg    - various certificate name options\n",
143111147Snectar#ifndef OPENSSL_NO_ENGINE
144296465Sdelphij    " -engine e       - use engine e, possibly a hardware device.\n",
145111147Snectar#endif
146296465Sdelphij    " -certopt arg    - various certificate text options\n",
147296465Sdelphij    NULL
14855714Skris};
14955714Skris
15055714Skrisstatic int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx);
151296465Sdelphijstatic int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
152296465Sdelphij                const EVP_MD *digest, CONF *conf, char *section);
153296465Sdelphijstatic int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
154296465Sdelphij                        X509 *x, X509 *xca, EVP_PKEY *pkey, char *serial,
155296465Sdelphij                        int create, int days, int clrext, CONF *conf,
156296465Sdelphij                        char *section, ASN1_INTEGER *sno);
15759191Skrisstatic int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
158296465Sdelphijstatic int reqfile = 0;
15955714Skris
16059191Skrisint MAIN(int, char **);
16159191Skris
16255714Skrisint MAIN(int argc, char **argv)
163296465Sdelphij{
164296465Sdelphij    ENGINE *e = NULL;
165296465Sdelphij    int ret = 1;
166296465Sdelphij    X509_REQ *req = NULL;
167296465Sdelphij    X509 *x = NULL, *xca = NULL;
168296465Sdelphij    ASN1_OBJECT *objtmp;
169296465Sdelphij    EVP_PKEY *Upkey = NULL, *CApkey = NULL;
170296465Sdelphij    ASN1_INTEGER *sno = NULL;
171296465Sdelphij    int i, num, badops = 0;
172296465Sdelphij    BIO *out = NULL;
173296465Sdelphij    BIO *STDout = NULL;
174296465Sdelphij    STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
175296465Sdelphij    int informat, outformat, keyformat, CAformat, CAkeyformat;
176296465Sdelphij    char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
177296465Sdelphij    char *CAkeyfile = NULL, *CAserial = NULL;
178296465Sdelphij    char *alias = NULL;
179296465Sdelphij    int text = 0, serial = 0, subject = 0, issuer = 0, startdate =
180296465Sdelphij        0, enddate = 0;
181296465Sdelphij    int next_serial = 0;
182296465Sdelphij    int subject_hash = 0, issuer_hash = 0, ocspid = 0;
183296465Sdelphij    int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0;
184296465Sdelphij    int ocsp_uri = 0;
185296465Sdelphij    int trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0, clrext = 0;
186296465Sdelphij    int C = 0;
187296465Sdelphij    int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0;
188296465Sdelphij    int pprint = 0;
189296465Sdelphij    const char **pp;
190296465Sdelphij    X509_STORE *ctx = NULL;
191296465Sdelphij    X509_REQ *rq = NULL;
192296465Sdelphij    int fingerprint = 0;
193296465Sdelphij    char buf[256];
194296465Sdelphij    const EVP_MD *md_alg, *digest = EVP_sha1();
195296465Sdelphij    CONF *extconf = NULL;
196296465Sdelphij    char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
197296465Sdelphij    int need_rand = 0;
198296465Sdelphij    int checkend = 0, checkoffset = 0;
199296465Sdelphij    unsigned long nmflag = 0, certflag = 0;
200111147Snectar#ifndef OPENSSL_NO_ENGINE
201296465Sdelphij    char *engine = NULL;
202111147Snectar#endif
20355714Skris
204296465Sdelphij    reqfile = 0;
20555714Skris
206296465Sdelphij    apps_startup();
20755714Skris
208296465Sdelphij    if (bio_err == NULL)
209296465Sdelphij        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
210109998Smarkm
211296465Sdelphij    if (!load_config(bio_err, NULL))
212296465Sdelphij        goto end;
213296465Sdelphij    STDout = BIO_new_fp(stdout, BIO_NOCLOSE);
214109998Smarkm#ifdef OPENSSL_SYS_VMS
215296465Sdelphij    {
216296465Sdelphij        BIO *tmpbio = BIO_new(BIO_f_linebuffer());
217296465Sdelphij        STDout = BIO_push(tmpbio, STDout);
218296465Sdelphij    }
21968651Skris#endif
22055714Skris
221296465Sdelphij    informat = FORMAT_PEM;
222296465Sdelphij    outformat = FORMAT_PEM;
223296465Sdelphij    keyformat = FORMAT_PEM;
224296465Sdelphij    CAformat = FORMAT_PEM;
225296465Sdelphij    CAkeyformat = FORMAT_PEM;
22655714Skris
227296465Sdelphij    ctx = X509_STORE_new();
228296465Sdelphij    if (ctx == NULL)
229296465Sdelphij        goto end;
230296465Sdelphij    X509_STORE_set_verify_cb_func(ctx, callb);
23155714Skris
232296465Sdelphij    argc--;
233296465Sdelphij    argv++;
234296465Sdelphij    num = 0;
235296465Sdelphij    while (argc >= 1) {
236296465Sdelphij        if (strcmp(*argv, "-inform") == 0) {
237296465Sdelphij            if (--argc < 1)
238296465Sdelphij                goto bad;
239296465Sdelphij            informat = str2fmt(*(++argv));
240296465Sdelphij        } else if (strcmp(*argv, "-outform") == 0) {
241296465Sdelphij            if (--argc < 1)
242296465Sdelphij                goto bad;
243296465Sdelphij            outformat = str2fmt(*(++argv));
244296465Sdelphij        } else if (strcmp(*argv, "-keyform") == 0) {
245296465Sdelphij            if (--argc < 1)
246296465Sdelphij                goto bad;
247296465Sdelphij            keyformat = str2fmt(*(++argv));
248296465Sdelphij        } else if (strcmp(*argv, "-req") == 0) {
249296465Sdelphij            reqfile = 1;
250296465Sdelphij            need_rand = 1;
251296465Sdelphij        } else if (strcmp(*argv, "-CAform") == 0) {
252296465Sdelphij            if (--argc < 1)
253296465Sdelphij                goto bad;
254296465Sdelphij            CAformat = str2fmt(*(++argv));
255296465Sdelphij        } else if (strcmp(*argv, "-CAkeyform") == 0) {
256296465Sdelphij            if (--argc < 1)
257296465Sdelphij                goto bad;
258296465Sdelphij            CAkeyformat = str2fmt(*(++argv));
259296465Sdelphij        } else if (strcmp(*argv, "-days") == 0) {
260296465Sdelphij            if (--argc < 1)
261296465Sdelphij                goto bad;
262296465Sdelphij            days = atoi(*(++argv));
263296465Sdelphij            if (days == 0) {
264296465Sdelphij                BIO_printf(STDout, "bad number of days\n");
265296465Sdelphij                goto bad;
266296465Sdelphij            }
267296465Sdelphij        } else if (strcmp(*argv, "-passin") == 0) {
268296465Sdelphij            if (--argc < 1)
269296465Sdelphij                goto bad;
270296465Sdelphij            passargin = *(++argv);
271296465Sdelphij        } else if (strcmp(*argv, "-extfile") == 0) {
272296465Sdelphij            if (--argc < 1)
273296465Sdelphij                goto bad;
274296465Sdelphij            extfile = *(++argv);
275296465Sdelphij        } else if (strcmp(*argv, "-extensions") == 0) {
276296465Sdelphij            if (--argc < 1)
277296465Sdelphij                goto bad;
278296465Sdelphij            extsect = *(++argv);
279296465Sdelphij        } else if (strcmp(*argv, "-in") == 0) {
280296465Sdelphij            if (--argc < 1)
281296465Sdelphij                goto bad;
282296465Sdelphij            infile = *(++argv);
283296465Sdelphij        } else if (strcmp(*argv, "-out") == 0) {
284296465Sdelphij            if (--argc < 1)
285296465Sdelphij                goto bad;
286296465Sdelphij            outfile = *(++argv);
287296465Sdelphij        } else if (strcmp(*argv, "-signkey") == 0) {
288296465Sdelphij            if (--argc < 1)
289296465Sdelphij                goto bad;
290296465Sdelphij            keyfile = *(++argv);
291296465Sdelphij            sign_flag = ++num;
292296465Sdelphij            need_rand = 1;
293296465Sdelphij        } else if (strcmp(*argv, "-CA") == 0) {
294296465Sdelphij            if (--argc < 1)
295296465Sdelphij                goto bad;
296296465Sdelphij            CAfile = *(++argv);
297296465Sdelphij            CA_flag = ++num;
298296465Sdelphij            need_rand = 1;
299296465Sdelphij        } else if (strcmp(*argv, "-CAkey") == 0) {
300296465Sdelphij            if (--argc < 1)
301296465Sdelphij                goto bad;
302296465Sdelphij            CAkeyfile = *(++argv);
303296465Sdelphij        } else if (strcmp(*argv, "-CAserial") == 0) {
304296465Sdelphij            if (--argc < 1)
305296465Sdelphij                goto bad;
306296465Sdelphij            CAserial = *(++argv);
307296465Sdelphij        } else if (strcmp(*argv, "-set_serial") == 0) {
308296465Sdelphij            if (--argc < 1)
309296465Sdelphij                goto bad;
310296465Sdelphij            if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
311296465Sdelphij                goto bad;
312296465Sdelphij        } else if (strcmp(*argv, "-addtrust") == 0) {
313296465Sdelphij            if (--argc < 1)
314296465Sdelphij                goto bad;
315296465Sdelphij            if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) {
316296465Sdelphij                BIO_printf(bio_err, "Invalid trust object value %s\n", *argv);
317296465Sdelphij                goto bad;
318296465Sdelphij            }
319296465Sdelphij            if (!trust)
320296465Sdelphij                trust = sk_ASN1_OBJECT_new_null();
321296465Sdelphij            sk_ASN1_OBJECT_push(trust, objtmp);
322296465Sdelphij            trustout = 1;
323296465Sdelphij        } else if (strcmp(*argv, "-addreject") == 0) {
324296465Sdelphij            if (--argc < 1)
325296465Sdelphij                goto bad;
326296465Sdelphij            if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) {
327296465Sdelphij                BIO_printf(bio_err,
328296465Sdelphij                           "Invalid reject object value %s\n", *argv);
329296465Sdelphij                goto bad;
330296465Sdelphij            }
331296465Sdelphij            if (!reject)
332296465Sdelphij                reject = sk_ASN1_OBJECT_new_null();
333296465Sdelphij            sk_ASN1_OBJECT_push(reject, objtmp);
334296465Sdelphij            trustout = 1;
335296465Sdelphij        } else if (strcmp(*argv, "-setalias") == 0) {
336296465Sdelphij            if (--argc < 1)
337296465Sdelphij                goto bad;
338296465Sdelphij            alias = *(++argv);
339296465Sdelphij            trustout = 1;
340296465Sdelphij        } else if (strcmp(*argv, "-certopt") == 0) {
341296465Sdelphij            if (--argc < 1)
342296465Sdelphij                goto bad;
343296465Sdelphij            if (!set_cert_ex(&certflag, *(++argv)))
344296465Sdelphij                goto bad;
345296465Sdelphij        } else if (strcmp(*argv, "-nameopt") == 0) {
346296465Sdelphij            if (--argc < 1)
347296465Sdelphij                goto bad;
348296465Sdelphij            if (!set_name_ex(&nmflag, *(++argv)))
349296465Sdelphij                goto bad;
350296465Sdelphij        }
351111147Snectar#ifndef OPENSSL_NO_ENGINE
352296465Sdelphij        else if (strcmp(*argv, "-engine") == 0) {
353296465Sdelphij            if (--argc < 1)
354296465Sdelphij                goto bad;
355296465Sdelphij            engine = *(++argv);
356296465Sdelphij        }
357111147Snectar#endif
358296465Sdelphij        else if (strcmp(*argv, "-C") == 0)
359296465Sdelphij            C = ++num;
360296465Sdelphij        else if (strcmp(*argv, "-email") == 0)
361296465Sdelphij            email = ++num;
362296465Sdelphij        else if (strcmp(*argv, "-ocsp_uri") == 0)
363296465Sdelphij            ocsp_uri = ++num;
364296465Sdelphij        else if (strcmp(*argv, "-serial") == 0)
365296465Sdelphij            serial = ++num;
366296465Sdelphij        else if (strcmp(*argv, "-next_serial") == 0)
367296465Sdelphij            next_serial = ++num;
368296465Sdelphij        else if (strcmp(*argv, "-modulus") == 0)
369296465Sdelphij            modulus = ++num;
370296465Sdelphij        else if (strcmp(*argv, "-pubkey") == 0)
371296465Sdelphij            pubkey = ++num;
372296465Sdelphij        else if (strcmp(*argv, "-x509toreq") == 0)
373296465Sdelphij            x509req = ++num;
374296465Sdelphij        else if (strcmp(*argv, "-text") == 0)
375296465Sdelphij            text = ++num;
376296465Sdelphij        else if (strcmp(*argv, "-hash") == 0
377296465Sdelphij                 || strcmp(*argv, "-subject_hash") == 0)
378296465Sdelphij            subject_hash = ++num;
379296465Sdelphij        else if (strcmp(*argv, "-issuer_hash") == 0)
380296465Sdelphij            issuer_hash = ++num;
381296465Sdelphij        else if (strcmp(*argv, "-subject") == 0)
382296465Sdelphij            subject = ++num;
383296465Sdelphij        else if (strcmp(*argv, "-issuer") == 0)
384296465Sdelphij            issuer = ++num;
385296465Sdelphij        else if (strcmp(*argv, "-fingerprint") == 0)
386296465Sdelphij            fingerprint = ++num;
387296465Sdelphij        else if (strcmp(*argv, "-dates") == 0) {
388296465Sdelphij            startdate = ++num;
389296465Sdelphij            enddate = ++num;
390296465Sdelphij        } else if (strcmp(*argv, "-purpose") == 0)
391296465Sdelphij            pprint = ++num;
392296465Sdelphij        else if (strcmp(*argv, "-startdate") == 0)
393296465Sdelphij            startdate = ++num;
394296465Sdelphij        else if (strcmp(*argv, "-enddate") == 0)
395296465Sdelphij            enddate = ++num;
396296465Sdelphij        else if (strcmp(*argv, "-checkend") == 0) {
397296465Sdelphij            if (--argc < 1)
398296465Sdelphij                goto bad;
399296465Sdelphij            checkoffset = atoi(*(++argv));
400296465Sdelphij            checkend = 1;
401296465Sdelphij        } else if (strcmp(*argv, "-noout") == 0)
402296465Sdelphij            noout = ++num;
403296465Sdelphij        else if (strcmp(*argv, "-trustout") == 0)
404296465Sdelphij            trustout = 1;
405296465Sdelphij        else if (strcmp(*argv, "-clrtrust") == 0)
406296465Sdelphij            clrtrust = ++num;
407296465Sdelphij        else if (strcmp(*argv, "-clrreject") == 0)
408296465Sdelphij            clrreject = ++num;
409296465Sdelphij        else if (strcmp(*argv, "-alias") == 0)
410296465Sdelphij            aliasout = ++num;
411296465Sdelphij        else if (strcmp(*argv, "-CAcreateserial") == 0)
412296465Sdelphij            CA_createserial = ++num;
413296465Sdelphij        else if (strcmp(*argv, "-clrext") == 0)
414296465Sdelphij            clrext = 1;
415296465Sdelphij#if 1                           /* stay backwards-compatible with 0.9.5; this
416296465Sdelphij                                 * should go away soon */
417296465Sdelphij        else if (strcmp(*argv, "-crlext") == 0) {
418296465Sdelphij            BIO_printf(bio_err, "use -clrext instead of -crlext\n");
419296465Sdelphij            clrext = 1;
420296465Sdelphij        }
42159191Skris#endif
422296465Sdelphij        else if (strcmp(*argv, "-ocspid") == 0)
423296465Sdelphij            ocspid = ++num;
424296465Sdelphij        else if ((md_alg = EVP_get_digestbyname(*argv + 1))) {
425296465Sdelphij            /* ok */
426296465Sdelphij            digest = md_alg;
427296465Sdelphij        } else {
428296465Sdelphij            BIO_printf(bio_err, "unknown option %s\n", *argv);
429296465Sdelphij            badops = 1;
430296465Sdelphij            break;
431296465Sdelphij        }
432296465Sdelphij        argc--;
433296465Sdelphij        argv++;
434296465Sdelphij    }
43555714Skris
436296465Sdelphij    if (badops) {
437296465Sdelphij bad:
438296465Sdelphij        for (pp = x509_usage; (*pp != NULL); pp++)
439296465Sdelphij            BIO_printf(bio_err, "%s", *pp);
440296465Sdelphij        goto end;
441296465Sdelphij    }
442111147Snectar#ifndef OPENSSL_NO_ENGINE
443296465Sdelphij    e = setup_engine(bio_err, engine, 0);
444111147Snectar#endif
445109998Smarkm
446296465Sdelphij    if (need_rand)
447296465Sdelphij        app_RAND_load_file(NULL, bio_err, 0);
44859191Skris
449296465Sdelphij    ERR_load_crypto_strings();
45055714Skris
451296465Sdelphij    if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
452296465Sdelphij        BIO_printf(bio_err, "Error getting password\n");
453296465Sdelphij        goto end;
454296465Sdelphij    }
45559191Skris
456296465Sdelphij    if (!X509_STORE_set_default_paths(ctx)) {
457296465Sdelphij        ERR_print_errors(bio_err);
458296465Sdelphij        goto end;
459296465Sdelphij    }
46055714Skris
461296465Sdelphij    if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
462296465Sdelphij        CAkeyfile = CAfile;
463296465Sdelphij    } else if ((CA_flag) && (CAkeyfile == NULL)) {
464296465Sdelphij        BIO_printf(bio_err,
465296465Sdelphij                   "need to specify a CAkey if using the CA command\n");
466296465Sdelphij        goto end;
467296465Sdelphij    }
46855714Skris
469296465Sdelphij    if (extfile) {
470296465Sdelphij        long errorline = -1;
471296465Sdelphij        X509V3_CTX ctx2;
472296465Sdelphij        extconf = NCONF_new(NULL);
473296465Sdelphij        if (!NCONF_load(extconf, extfile, &errorline)) {
474296465Sdelphij            if (errorline <= 0)
475296465Sdelphij                BIO_printf(bio_err,
476296465Sdelphij                           "error loading the config file '%s'\n", extfile);
477296465Sdelphij            else
478296465Sdelphij                BIO_printf(bio_err,
479296465Sdelphij                           "error on line %ld of config file '%s'\n",
480296465Sdelphij                           errorline, extfile);
481296465Sdelphij            goto end;
482296465Sdelphij        }
483296465Sdelphij        if (!extsect) {
484296465Sdelphij            extsect = NCONF_get_string(extconf, "default", "extensions");
485296465Sdelphij            if (!extsect) {
486296465Sdelphij                ERR_clear_error();
487296465Sdelphij                extsect = "default";
488296465Sdelphij            }
489296465Sdelphij        }
490296465Sdelphij        X509V3_set_ctx_test(&ctx2);
491296465Sdelphij        X509V3_set_nconf(&ctx2, extconf);
492296465Sdelphij        if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
493296465Sdelphij            BIO_printf(bio_err,
494296465Sdelphij                       "Error Loading extension section %s\n", extsect);
495296465Sdelphij            ERR_print_errors(bio_err);
496296465Sdelphij            goto end;
497296465Sdelphij        }
498296465Sdelphij    }
49955714Skris
500296465Sdelphij    if (reqfile) {
501296465Sdelphij        EVP_PKEY *pkey;
502296465Sdelphij        BIO *in;
50355714Skris
504296465Sdelphij        if (!sign_flag && !CA_flag) {
505296465Sdelphij            BIO_printf(bio_err, "We need a private key to sign with\n");
506296465Sdelphij            goto end;
507296465Sdelphij        }
508296465Sdelphij        in = BIO_new(BIO_s_file());
509296465Sdelphij        if (in == NULL) {
510296465Sdelphij            ERR_print_errors(bio_err);
511296465Sdelphij            goto end;
512296465Sdelphij        }
51355714Skris
514296465Sdelphij        if (infile == NULL)
515296465Sdelphij            BIO_set_fp(in, stdin, BIO_NOCLOSE | BIO_FP_TEXT);
516296465Sdelphij        else {
517296465Sdelphij            if (BIO_read_filename(in, infile) <= 0) {
518296465Sdelphij                perror(infile);
519296465Sdelphij                BIO_free(in);
520296465Sdelphij                goto end;
521296465Sdelphij            }
522296465Sdelphij        }
523296465Sdelphij        req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
524296465Sdelphij        BIO_free(in);
52555714Skris
526296465Sdelphij        if (req == NULL) {
527296465Sdelphij            ERR_print_errors(bio_err);
528296465Sdelphij            goto end;
529296465Sdelphij        }
53055714Skris
531296465Sdelphij        if ((req->req_info == NULL) ||
532296465Sdelphij            (req->req_info->pubkey == NULL) ||
533296465Sdelphij            (req->req_info->pubkey->public_key == NULL) ||
534296465Sdelphij            (req->req_info->pubkey->public_key->data == NULL)) {
535296465Sdelphij            BIO_printf(bio_err,
536296465Sdelphij                       "The certificate request appears to corrupted\n");
537296465Sdelphij            BIO_printf(bio_err, "It does not contain a public key\n");
538296465Sdelphij            goto end;
539296465Sdelphij        }
540296465Sdelphij        if ((pkey = X509_REQ_get_pubkey(req)) == NULL) {
541296465Sdelphij            BIO_printf(bio_err, "error unpacking public key\n");
542296465Sdelphij            goto end;
543296465Sdelphij        }
544296465Sdelphij        i = X509_REQ_verify(req, pkey);
545296465Sdelphij        EVP_PKEY_free(pkey);
546296465Sdelphij        if (i < 0) {
547296465Sdelphij            BIO_printf(bio_err, "Signature verification error\n");
548296465Sdelphij            ERR_print_errors(bio_err);
549296465Sdelphij            goto end;
550296465Sdelphij        }
551296465Sdelphij        if (i == 0) {
552296465Sdelphij            BIO_printf(bio_err,
553296465Sdelphij                       "Signature did not match the certificate request\n");
554296465Sdelphij            goto end;
555296465Sdelphij        } else
556296465Sdelphij            BIO_printf(bio_err, "Signature ok\n");
55755714Skris
558296465Sdelphij        print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
559296465Sdelphij                   nmflag);
56055714Skris
561296465Sdelphij        if ((x = X509_new()) == NULL)
562296465Sdelphij            goto end;
56368651Skris
564296465Sdelphij        if (sno == NULL) {
565296465Sdelphij            sno = ASN1_INTEGER_new();
566296465Sdelphij            if (!sno || !rand_serial(NULL, sno))
567296465Sdelphij                goto end;
568296465Sdelphij            if (!X509_set_serialNumber(x, sno))
569296465Sdelphij                goto end;
570296465Sdelphij            ASN1_INTEGER_free(sno);
571296465Sdelphij            sno = NULL;
572296465Sdelphij        } else if (!X509_set_serialNumber(x, sno))
573296465Sdelphij            goto end;
57455714Skris
575296465Sdelphij        if (!X509_set_issuer_name(x, req->req_info->subject))
576296465Sdelphij            goto end;
577296465Sdelphij        if (!X509_set_subject_name(x, req->req_info->subject))
578296465Sdelphij            goto end;
579142425Snectar
580296465Sdelphij        X509_gmtime_adj(X509_get_notBefore(x), 0);
581296465Sdelphij        X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * days);
58255714Skris
583296465Sdelphij        pkey = X509_REQ_get_pubkey(req);
584296465Sdelphij        X509_set_pubkey(x, pkey);
585296465Sdelphij        EVP_PKEY_free(pkey);
586296465Sdelphij    } else
587296465Sdelphij        x = load_cert(bio_err, infile, informat, NULL, e, "Certificate");
58855714Skris
589296465Sdelphij    if (x == NULL)
590296465Sdelphij        goto end;
591296465Sdelphij    if (CA_flag) {
592296465Sdelphij        xca = load_cert(bio_err, CAfile, CAformat, NULL, e, "CA Certificate");
593296465Sdelphij        if (xca == NULL)
594296465Sdelphij            goto end;
595296465Sdelphij    }
59655714Skris
597296465Sdelphij    if (!noout || text || next_serial) {
598296465Sdelphij        OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");
59955714Skris
600296465Sdelphij        out = BIO_new(BIO_s_file());
601296465Sdelphij        if (out == NULL) {
602296465Sdelphij            ERR_print_errors(bio_err);
603296465Sdelphij            goto end;
604296465Sdelphij        }
605296465Sdelphij        if (outfile == NULL) {
606296465Sdelphij            BIO_set_fp(out, stdout, BIO_NOCLOSE);
607109998Smarkm#ifdef OPENSSL_SYS_VMS
608296465Sdelphij            {
609296465Sdelphij                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
610296465Sdelphij                out = BIO_push(tmpbio, out);
611296465Sdelphij            }
61268651Skris#endif
613296465Sdelphij        } else {
614296465Sdelphij            if (BIO_write_filename(out, outfile) <= 0) {
615296465Sdelphij                perror(outfile);
616296465Sdelphij                goto end;
617296465Sdelphij            }
618296465Sdelphij        }
619296465Sdelphij    }
62055714Skris
621296465Sdelphij    if (alias)
622296465Sdelphij        X509_alias_set1(x, (unsigned char *)alias, -1);
62359191Skris
624296465Sdelphij    if (clrtrust)
625296465Sdelphij        X509_trust_clear(x);
626296465Sdelphij    if (clrreject)
627296465Sdelphij        X509_reject_clear(x);
62859191Skris
629296465Sdelphij    if (trust) {
630296465Sdelphij        for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
631296465Sdelphij            objtmp = sk_ASN1_OBJECT_value(trust, i);
632296465Sdelphij            X509_add1_trust_object(x, objtmp);
633296465Sdelphij        }
634296465Sdelphij    }
63559191Skris
636296465Sdelphij    if (reject) {
637296465Sdelphij        for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
638296465Sdelphij            objtmp = sk_ASN1_OBJECT_value(reject, i);
639296465Sdelphij            X509_add1_reject_object(x, objtmp);
640296465Sdelphij        }
641296465Sdelphij    }
64259191Skris
643296465Sdelphij    if (num) {
644296465Sdelphij        for (i = 1; i <= num; i++) {
645296465Sdelphij            if (issuer == i) {
646296465Sdelphij                print_name(STDout, "issuer= ",
647296465Sdelphij                           X509_get_issuer_name(x), nmflag);
648296465Sdelphij            } else if (subject == i) {
649296465Sdelphij                print_name(STDout, "subject= ",
650296465Sdelphij                           X509_get_subject_name(x), nmflag);
651296465Sdelphij            } else if (serial == i) {
652296465Sdelphij                BIO_printf(STDout, "serial=");
653296465Sdelphij                i2a_ASN1_INTEGER(STDout, X509_get_serialNumber(x));
654296465Sdelphij                BIO_printf(STDout, "\n");
655296465Sdelphij            } else if (next_serial == i) {
656296465Sdelphij                BIGNUM *bnser;
657296465Sdelphij                ASN1_INTEGER *ser;
658296465Sdelphij                ser = X509_get_serialNumber(x);
659296465Sdelphij                bnser = ASN1_INTEGER_to_BN(ser, NULL);
660296465Sdelphij                if (!bnser)
661296465Sdelphij                    goto end;
662296465Sdelphij                if (!BN_add_word(bnser, 1))
663296465Sdelphij                    goto end;
664296465Sdelphij                ser = BN_to_ASN1_INTEGER(bnser, NULL);
665296465Sdelphij                if (!ser)
666296465Sdelphij                    goto end;
667296465Sdelphij                BN_free(bnser);
668296465Sdelphij                i2a_ASN1_INTEGER(out, ser);
669296465Sdelphij                ASN1_INTEGER_free(ser);
670296465Sdelphij                BIO_puts(out, "\n");
671296465Sdelphij            } else if ((email == i) || (ocsp_uri == i)) {
672296465Sdelphij                int j;
673296465Sdelphij                STACK *emlst;
674296465Sdelphij                if (email == i)
675296465Sdelphij                    emlst = X509_get1_email(x);
676296465Sdelphij                else
677296465Sdelphij                    emlst = X509_get1_ocsp(x);
678296465Sdelphij                for (j = 0; j < sk_num(emlst); j++)
679296465Sdelphij                    BIO_printf(STDout, "%s\n", sk_value(emlst, j));
680296465Sdelphij                X509_email_free(emlst);
681296465Sdelphij            } else if (aliasout == i) {
682296465Sdelphij                unsigned char *alstr;
683296465Sdelphij                alstr = X509_alias_get0(x, NULL);
684296465Sdelphij                if (alstr)
685296465Sdelphij                    BIO_printf(STDout, "%s\n", alstr);
686296465Sdelphij                else
687296465Sdelphij                    BIO_puts(STDout, "<No Alias>\n");
688296465Sdelphij            } else if (subject_hash == i) {
689296465Sdelphij                BIO_printf(STDout, "%08lx\n", X509_subject_name_hash(x));
690296465Sdelphij            } else if (issuer_hash == i) {
691296465Sdelphij                BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash(x));
692296465Sdelphij            } else if (pprint == i) {
693296465Sdelphij                X509_PURPOSE *ptmp;
694296465Sdelphij                int j;
695296465Sdelphij                BIO_printf(STDout, "Certificate purposes:\n");
696296465Sdelphij                for (j = 0; j < X509_PURPOSE_get_count(); j++) {
697296465Sdelphij                    ptmp = X509_PURPOSE_get0(j);
698296465Sdelphij                    purpose_print(STDout, x, ptmp);
699296465Sdelphij                }
700296465Sdelphij            } else if (modulus == i) {
701296465Sdelphij                EVP_PKEY *pkey;
70255714Skris
703296465Sdelphij                pkey = X509_get_pubkey(x);
704296465Sdelphij                if (pkey == NULL) {
705296465Sdelphij                    BIO_printf(bio_err, "Modulus=unavailable\n");
706296465Sdelphij                    ERR_print_errors(bio_err);
707296465Sdelphij                    goto end;
708296465Sdelphij                }
709296465Sdelphij                BIO_printf(STDout, "Modulus=");
710109998Smarkm#ifndef OPENSSL_NO_RSA
711296465Sdelphij                if (pkey->type == EVP_PKEY_RSA)
712296465Sdelphij                    BN_print(STDout, pkey->pkey.rsa->n);
713296465Sdelphij                else
71455714Skris#endif
715109998Smarkm#ifndef OPENSSL_NO_DSA
716296465Sdelphij                if (pkey->type == EVP_PKEY_DSA)
717296465Sdelphij                    BN_print(STDout, pkey->pkey.dsa->pub_key);
718296465Sdelphij                else
71955714Skris#endif
720296465Sdelphij                    BIO_printf(STDout, "Wrong Algorithm type");
721296465Sdelphij                BIO_printf(STDout, "\n");
722296465Sdelphij                EVP_PKEY_free(pkey);
723296465Sdelphij            } else if (pubkey == i) {
724296465Sdelphij                EVP_PKEY *pkey;
72559191Skris
726296465Sdelphij                pkey = X509_get_pubkey(x);
727296465Sdelphij                if (pkey == NULL) {
728296465Sdelphij                    BIO_printf(bio_err, "Error getting public key\n");
729296465Sdelphij                    ERR_print_errors(bio_err);
730296465Sdelphij                    goto end;
731296465Sdelphij                }
732296465Sdelphij                PEM_write_bio_PUBKEY(STDout, pkey);
733296465Sdelphij                EVP_PKEY_free(pkey);
734296465Sdelphij            } else if (C == i) {
735296465Sdelphij                unsigned char *d;
736296465Sdelphij                char *m;
737296465Sdelphij                int y, z;
73855714Skris
739296465Sdelphij                X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof buf);
740296465Sdelphij                BIO_printf(STDout, "/* subject:%s */\n", buf);
741296465Sdelphij                m = X509_NAME_oneline(X509_get_issuer_name(x), buf,
742296465Sdelphij                                      sizeof buf);
743296465Sdelphij                BIO_printf(STDout, "/* issuer :%s */\n", buf);
74455714Skris
745296465Sdelphij                z = i2d_X509(x, NULL);
746296465Sdelphij                m = OPENSSL_malloc(z);
74755714Skris
748296465Sdelphij                d = (unsigned char *)m;
749296465Sdelphij                z = i2d_X509_NAME(X509_get_subject_name(x), &d);
750296465Sdelphij                BIO_printf(STDout, "unsigned char XXX_subject_name[%d]={\n",
751296465Sdelphij                           z);
752296465Sdelphij                d = (unsigned char *)m;
753296465Sdelphij                for (y = 0; y < z; y++) {
754296465Sdelphij                    BIO_printf(STDout, "0x%02X,", d[y]);
755296465Sdelphij                    if ((y & 0x0f) == 0x0f)
756296465Sdelphij                        BIO_printf(STDout, "\n");
757296465Sdelphij                }
758296465Sdelphij                if (y % 16 != 0)
759296465Sdelphij                    BIO_printf(STDout, "\n");
760296465Sdelphij                BIO_printf(STDout, "};\n");
76155714Skris
762296465Sdelphij                z = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
763296465Sdelphij                BIO_printf(STDout, "unsigned char XXX_public_key[%d]={\n", z);
764296465Sdelphij                d = (unsigned char *)m;
765296465Sdelphij                for (y = 0; y < z; y++) {
766296465Sdelphij                    BIO_printf(STDout, "0x%02X,", d[y]);
767296465Sdelphij                    if ((y & 0x0f) == 0x0f)
768296465Sdelphij                        BIO_printf(STDout, "\n");
769296465Sdelphij                }
770296465Sdelphij                if (y % 16 != 0)
771296465Sdelphij                    BIO_printf(STDout, "\n");
772296465Sdelphij                BIO_printf(STDout, "};\n");
77355714Skris
774296465Sdelphij                z = i2d_X509(x, &d);
775296465Sdelphij                BIO_printf(STDout, "unsigned char XXX_certificate[%d]={\n",
776296465Sdelphij                           z);
777296465Sdelphij                d = (unsigned char *)m;
778296465Sdelphij                for (y = 0; y < z; y++) {
779296465Sdelphij                    BIO_printf(STDout, "0x%02X,", d[y]);
780296465Sdelphij                    if ((y & 0x0f) == 0x0f)
781296465Sdelphij                        BIO_printf(STDout, "\n");
782296465Sdelphij                }
783296465Sdelphij                if (y % 16 != 0)
784296465Sdelphij                    BIO_printf(STDout, "\n");
785296465Sdelphij                BIO_printf(STDout, "};\n");
78655714Skris
787296465Sdelphij                OPENSSL_free(m);
788296465Sdelphij            } else if (text == i) {
789296465Sdelphij                X509_print_ex(out, x, nmflag, certflag);
790296465Sdelphij            } else if (startdate == i) {
791296465Sdelphij                BIO_puts(STDout, "notBefore=");
792296465Sdelphij                ASN1_TIME_print(STDout, X509_get_notBefore(x));
793296465Sdelphij                BIO_puts(STDout, "\n");
794296465Sdelphij            } else if (enddate == i) {
795296465Sdelphij                BIO_puts(STDout, "notAfter=");
796296465Sdelphij                ASN1_TIME_print(STDout, X509_get_notAfter(x));
797296465Sdelphij                BIO_puts(STDout, "\n");
798296465Sdelphij            } else if (fingerprint == i) {
799296465Sdelphij                int j;
800296465Sdelphij                unsigned int n;
801296465Sdelphij                unsigned char md[EVP_MAX_MD_SIZE];
80255714Skris
803296465Sdelphij                if (!X509_digest(x, digest, md, &n)) {
804296465Sdelphij                    BIO_printf(bio_err, "out of memory\n");
805296465Sdelphij                    goto end;
806296465Sdelphij                }
807296465Sdelphij                BIO_printf(STDout, "%s Fingerprint=",
808296465Sdelphij                           OBJ_nid2sn(EVP_MD_type(digest)));
809296465Sdelphij                for (j = 0; j < (int)n; j++) {
810296465Sdelphij                    BIO_printf(STDout, "%02X%c", md[j], (j + 1 == (int)n)
811296465Sdelphij                               ? '\n' : ':');
812296465Sdelphij                }
813296465Sdelphij            }
81455714Skris
815296465Sdelphij            /* should be in the library */
816296465Sdelphij            else if ((sign_flag == i) && (x509req == 0)) {
817296465Sdelphij                BIO_printf(bio_err, "Getting Private key\n");
818296465Sdelphij                if (Upkey == NULL) {
819296465Sdelphij                    Upkey = load_key(bio_err,
820296465Sdelphij                                     keyfile, keyformat, 0,
821296465Sdelphij                                     passin, e, "Private key");
822296465Sdelphij                    if (Upkey == NULL)
823296465Sdelphij                        goto end;
824296465Sdelphij                }
825109998Smarkm#ifndef OPENSSL_NO_DSA
826296465Sdelphij                if (Upkey->type == EVP_PKEY_DSA)
827296465Sdelphij                    digest = EVP_dss1();
82855714Skris#endif
829160814Ssimon#ifndef OPENSSL_NO_ECDSA
830296465Sdelphij                if (Upkey->type == EVP_PKEY_EC)
831296465Sdelphij                    digest = EVP_ecdsa();
832160814Ssimon#endif
83355714Skris
834296465Sdelphij                assert(need_rand);
835296465Sdelphij                if (!sign(x, Upkey, days, clrext, digest, extconf, extsect))
836296465Sdelphij                    goto end;
837296465Sdelphij            } else if (CA_flag == i) {
838296465Sdelphij                BIO_printf(bio_err, "Getting CA Private Key\n");
839296465Sdelphij                if (CAkeyfile != NULL) {
840296465Sdelphij                    CApkey = load_key(bio_err,
841296465Sdelphij                                      CAkeyfile, CAkeyformat,
842296465Sdelphij                                      0, passin, e, "CA Private Key");
843296465Sdelphij                    if (CApkey == NULL)
844296465Sdelphij                        goto end;
845296465Sdelphij                }
846109998Smarkm#ifndef OPENSSL_NO_DSA
847296465Sdelphij                if (CApkey->type == EVP_PKEY_DSA)
848296465Sdelphij                    digest = EVP_dss1();
84955714Skris#endif
850160814Ssimon#ifndef OPENSSL_NO_ECDSA
851296465Sdelphij                if (CApkey->type == EVP_PKEY_EC)
852296465Sdelphij                    digest = EVP_ecdsa();
853160814Ssimon#endif
85455714Skris
855296465Sdelphij                assert(need_rand);
856296465Sdelphij                if (!x509_certify(ctx, CAfile, digest, x, xca,
857296465Sdelphij                                  CApkey, CAserial, CA_createserial, days,
858296465Sdelphij                                  clrext, extconf, extsect, sno))
859296465Sdelphij                    goto end;
860296465Sdelphij            } else if (x509req == i) {
861296465Sdelphij                EVP_PKEY *pk;
86255714Skris
863296465Sdelphij                BIO_printf(bio_err, "Getting request Private Key\n");
864296465Sdelphij                if (keyfile == NULL) {
865296465Sdelphij                    BIO_printf(bio_err, "no request key file specified\n");
866296465Sdelphij                    goto end;
867296465Sdelphij                } else {
868296465Sdelphij                    pk = load_key(bio_err,
869296465Sdelphij                                  keyfile, keyformat, 0,
870296465Sdelphij                                  passin, e, "request key");
871296465Sdelphij                    if (pk == NULL)
872296465Sdelphij                        goto end;
873296465Sdelphij                }
87455714Skris
875296465Sdelphij                BIO_printf(bio_err, "Generating certificate request\n");
876296465Sdelphij
877109998Smarkm#ifndef OPENSSL_NO_DSA
878296465Sdelphij                if (pk->type == EVP_PKEY_DSA)
879296465Sdelphij                    digest = EVP_dss1();
88076866Skris#endif
881160814Ssimon#ifndef OPENSSL_NO_ECDSA
882296465Sdelphij                if (pk->type == EVP_PKEY_EC)
883296465Sdelphij                    digest = EVP_ecdsa();
884160814Ssimon#endif
88559191Skris
886296465Sdelphij                rq = X509_to_X509_REQ(x, pk, digest);
887296465Sdelphij                EVP_PKEY_free(pk);
888296465Sdelphij                if (rq == NULL) {
889296465Sdelphij                    ERR_print_errors(bio_err);
890296465Sdelphij                    goto end;
891296465Sdelphij                }
892296465Sdelphij                if (!noout) {
893296465Sdelphij                    X509_REQ_print(out, rq);
894296465Sdelphij                    PEM_write_bio_X509_REQ(out, rq);
895296465Sdelphij                }
896296465Sdelphij                noout = 1;
897296465Sdelphij            } else if (ocspid == i) {
898296465Sdelphij                X509_ocspid_print(out, x);
899296465Sdelphij            }
900296465Sdelphij        }
901296465Sdelphij    }
90255714Skris
903296465Sdelphij    if (checkend) {
904296465Sdelphij        time_t tcheck = time(NULL) + checkoffset;
90568651Skris
906296465Sdelphij        if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) {
907296465Sdelphij            BIO_printf(out, "Certificate will expire\n");
908296465Sdelphij            ret = 1;
909296465Sdelphij        } else {
910296465Sdelphij            BIO_printf(out, "Certificate will not expire\n");
911296465Sdelphij            ret = 0;
912296465Sdelphij        }
913296465Sdelphij        goto end;
914296465Sdelphij    }
91568651Skris
916296465Sdelphij    if (noout) {
917296465Sdelphij        ret = 0;
918296465Sdelphij        goto end;
919296465Sdelphij    }
92055714Skris
921296465Sdelphij    if (outformat == FORMAT_ASN1)
922296465Sdelphij        i = i2d_X509_bio(out, x);
923296465Sdelphij    else if (outformat == FORMAT_PEM) {
924296465Sdelphij        if (trustout)
925296465Sdelphij            i = PEM_write_bio_X509_AUX(out, x);
926296465Sdelphij        else
927296465Sdelphij            i = PEM_write_bio_X509(out, x);
928296465Sdelphij    } else if (outformat == FORMAT_NETSCAPE) {
929296465Sdelphij        ASN1_HEADER ah;
930296465Sdelphij        ASN1_OCTET_STRING os;
93155714Skris
932296465Sdelphij        os.data = (unsigned char *)NETSCAPE_CERT_HDR;
933296465Sdelphij        os.length = strlen(NETSCAPE_CERT_HDR);
934296465Sdelphij        ah.header = &os;
935296465Sdelphij        ah.data = (char *)x;
936296465Sdelphij        ah.meth = X509_asn1_meth();
93755714Skris
938296465Sdelphij        i = ASN1_i2d_bio_of(ASN1_HEADER, i2d_ASN1_HEADER, out, &ah);
939296465Sdelphij    } else {
940296465Sdelphij        BIO_printf(bio_err, "bad output format specified for outfile\n");
941296465Sdelphij        goto end;
942296465Sdelphij    }
943296465Sdelphij    if (!i) {
944296465Sdelphij        BIO_printf(bio_err, "unable to write certificate\n");
945296465Sdelphij        ERR_print_errors(bio_err);
946296465Sdelphij        goto end;
947296465Sdelphij    }
948296465Sdelphij    ret = 0;
949296465Sdelphij end:
950296465Sdelphij    if (need_rand)
951296465Sdelphij        app_RAND_write_file(NULL, bio_err);
952296465Sdelphij    OBJ_cleanup();
953296465Sdelphij    NCONF_free(extconf);
954296465Sdelphij    BIO_free_all(out);
955296465Sdelphij    BIO_free_all(STDout);
956296465Sdelphij    X509_STORE_free(ctx);
957296465Sdelphij    X509_REQ_free(req);
958296465Sdelphij    X509_free(x);
959296465Sdelphij    X509_free(xca);
960296465Sdelphij    EVP_PKEY_free(Upkey);
961296465Sdelphij    EVP_PKEY_free(CApkey);
962296465Sdelphij    X509_REQ_free(rq);
963296465Sdelphij    ASN1_INTEGER_free(sno);
964296465Sdelphij    sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
965296465Sdelphij    sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
966296465Sdelphij    if (passin)
967296465Sdelphij        OPENSSL_free(passin);
968296465Sdelphij    apps_shutdown();
969296465Sdelphij    OPENSSL_EXIT(ret);
970296465Sdelphij}
97155714Skris
972296465Sdelphijstatic ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile,
973296465Sdelphij                                      int create)
974296465Sdelphij{
975296465Sdelphij    char *buf = NULL, *p;
976296465Sdelphij    ASN1_INTEGER *bs = NULL;
977296465Sdelphij    BIGNUM *serial = NULL;
978296465Sdelphij    size_t len;
97955714Skris
980296465Sdelphij    len = ((serialfile == NULL)
981296465Sdelphij           ? (strlen(CAfile) + strlen(POSTFIX) + 1)
982296465Sdelphij           : (strlen(serialfile))) + 1;
983296465Sdelphij    buf = OPENSSL_malloc(len);
984296465Sdelphij    if (buf == NULL) {
985296465Sdelphij        BIO_printf(bio_err, "out of mem\n");
986296465Sdelphij        goto end;
987296465Sdelphij    }
988296465Sdelphij    if (serialfile == NULL) {
989296465Sdelphij        BUF_strlcpy(buf, CAfile, len);
990296465Sdelphij        for (p = buf; *p; p++)
991296465Sdelphij            if (*p == '.') {
992296465Sdelphij                *p = '\0';
993296465Sdelphij                break;
994296465Sdelphij            }
995296465Sdelphij        BUF_strlcat(buf, POSTFIX, len);
996296465Sdelphij    } else
997296465Sdelphij        BUF_strlcpy(buf, serialfile, len);
99855714Skris
999296465Sdelphij    serial = load_serial(buf, create, NULL);
1000296465Sdelphij    if (serial == NULL)
1001296465Sdelphij        goto end;
100255714Skris
1003296465Sdelphij    if (!BN_add_word(serial, 1)) {
1004296465Sdelphij        BIO_printf(bio_err, "add_word failure\n");
1005296465Sdelphij        goto end;
1006296465Sdelphij    }
1007109998Smarkm
1008296465Sdelphij    if (!save_serial(buf, NULL, serial, &bs))
1009296465Sdelphij        goto end;
1010127128Snectar
1011127128Snectar end:
1012296465Sdelphij    if (buf)
1013296465Sdelphij        OPENSSL_free(buf);
1014296465Sdelphij    BN_free(serial);
1015296465Sdelphij    return bs;
1016296465Sdelphij}
1017109998Smarkm
1018109998Smarkmstatic int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
1019296465Sdelphij                        X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile,
1020296465Sdelphij                        int create, int days, int clrext, CONF *conf,
1021296465Sdelphij                        char *section, ASN1_INTEGER *sno)
1022296465Sdelphij{
1023296465Sdelphij    int ret = 0;
1024296465Sdelphij    ASN1_INTEGER *bs = NULL;
1025296465Sdelphij    X509_STORE_CTX xsc;
1026296465Sdelphij    EVP_PKEY *upkey;
1027109998Smarkm
1028296465Sdelphij    upkey = X509_get_pubkey(xca);
1029296465Sdelphij    EVP_PKEY_copy_parameters(upkey, pkey);
1030296465Sdelphij    EVP_PKEY_free(upkey);
1031109998Smarkm
1032296465Sdelphij    if (!X509_STORE_CTX_init(&xsc, ctx, x, NULL)) {
1033296465Sdelphij        BIO_printf(bio_err, "Error initialising X509 store\n");
1034296465Sdelphij        goto end;
1035296465Sdelphij    }
1036296465Sdelphij    if (sno)
1037296465Sdelphij        bs = sno;
1038296465Sdelphij    else if (!(bs = x509_load_serial(CAfile, serialfile, create)))
1039296465Sdelphij        goto end;
1040109998Smarkm
1041296465Sdelphij/*      if (!X509_STORE_add_cert(ctx,x)) goto end;*/
104255714Skris
1043296465Sdelphij    /*
1044296465Sdelphij     * NOTE: this certificate can/should be self signed, unless it was a
1045296465Sdelphij     * certificate request in which case it is not.
1046296465Sdelphij     */
1047296465Sdelphij    X509_STORE_CTX_set_cert(&xsc, x);
1048296465Sdelphij    X509_STORE_CTX_set_flags(&xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
1049296465Sdelphij    if (!reqfile && X509_verify_cert(&xsc) <= 0)
1050296465Sdelphij        goto end;
105155714Skris
1052296465Sdelphij    if (!X509_check_private_key(xca, pkey)) {
1053296465Sdelphij        BIO_printf(bio_err,
1054296465Sdelphij                   "CA certificate and CA private key do not match\n");
1055296465Sdelphij        goto end;
1056296465Sdelphij    }
105755714Skris
1058296465Sdelphij    if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
1059296465Sdelphij        goto end;
1060296465Sdelphij    if (!X509_set_serialNumber(x, bs))
1061296465Sdelphij        goto end;
106255714Skris
1063296465Sdelphij    if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL)
1064296465Sdelphij        goto end;
106555714Skris
1066296465Sdelphij    /* hardwired expired */
1067296465Sdelphij    if (X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * days) ==
1068296465Sdelphij        NULL)
1069296465Sdelphij        goto end;
107055714Skris
1071296465Sdelphij    if (clrext) {
1072296465Sdelphij        while (X509_get_ext_count(x) > 0)
1073296465Sdelphij            X509_delete_ext(x, 0);
1074296465Sdelphij    }
107559191Skris
1076296465Sdelphij    if (conf) {
1077296465Sdelphij        X509V3_CTX ctx2;
1078296465Sdelphij        X509_set_version(x, 2); /* version 3 certificate */
1079296465Sdelphij        X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
1080296465Sdelphij        X509V3_set_nconf(&ctx2, conf);
1081296465Sdelphij        if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
1082296465Sdelphij            goto end;
1083296465Sdelphij    }
108455714Skris
1085296465Sdelphij    if (!X509_sign(x, pkey, digest))
1086296465Sdelphij        goto end;
1087296465Sdelphij    ret = 1;
1088296465Sdelphij end:
1089296465Sdelphij    X509_STORE_CTX_cleanup(&xsc);
1090296465Sdelphij    if (!ret)
1091296465Sdelphij        ERR_print_errors(bio_err);
1092296465Sdelphij    if (!sno)
1093296465Sdelphij        ASN1_INTEGER_free(bs);
1094296465Sdelphij    return ret;
1095296465Sdelphij}
109655714Skris
109755714Skrisstatic int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx)
1098296465Sdelphij{
1099296465Sdelphij    int err;
1100296465Sdelphij    X509 *err_cert;
110155714Skris
1102296465Sdelphij    /*
1103296465Sdelphij     * it is ok to use a self signed certificate This case will catch both
1104296465Sdelphij     * the initial ok == 0 and the final ok == 1 calls to this function
1105296465Sdelphij     */
1106296465Sdelphij    err = X509_STORE_CTX_get_error(ctx);
1107296465Sdelphij    if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
1108296465Sdelphij        return 1;
110955714Skris
1110296465Sdelphij    /*
1111296465Sdelphij     * BAD we should have gotten an error.  Normally if everything worked
1112296465Sdelphij     * X509_STORE_CTX_get_error(ctx) will still be set to
1113296465Sdelphij     * DEPTH_ZERO_SELF_....
1114296465Sdelphij     */
1115296465Sdelphij    if (ok) {
1116296465Sdelphij        BIO_printf(bio_err,
1117296465Sdelphij                   "error with certificate to be certified - should be self signed\n");
1118296465Sdelphij        return 0;
1119296465Sdelphij    } else {
1120296465Sdelphij        err_cert = X509_STORE_CTX_get_current_cert(ctx);
1121296465Sdelphij        print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
1122296465Sdelphij        BIO_printf(bio_err,
1123296465Sdelphij                   "error with certificate - error %d at depth %d\n%s\n", err,
1124296465Sdelphij                   X509_STORE_CTX_get_error_depth(ctx),
1125296465Sdelphij                   X509_verify_cert_error_string(err));
1126296465Sdelphij        return 1;
1127296465Sdelphij    }
1128296465Sdelphij}
112955714Skris
113055714Skris/* self sign */
1131296465Sdelphijstatic int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
1132296465Sdelphij                const EVP_MD *digest, CONF *conf, char *section)
1133296465Sdelphij{
113455714Skris
1135296465Sdelphij    EVP_PKEY *pktmp;
113655714Skris
1137296465Sdelphij    pktmp = X509_get_pubkey(x);
1138296465Sdelphij    EVP_PKEY_copy_parameters(pktmp, pkey);
1139296465Sdelphij    EVP_PKEY_save_parameters(pktmp, 1);
1140296465Sdelphij    EVP_PKEY_free(pktmp);
114155714Skris
1142296465Sdelphij    if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
1143296465Sdelphij        goto err;
1144296465Sdelphij    if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
1145296465Sdelphij        goto err;
114655714Skris
1147296465Sdelphij    /* Lets just make it 12:00am GMT, Jan 1 1970 */
1148296465Sdelphij    /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
1149296465Sdelphij    /* 28 days to be certified */
115055714Skris
1151296465Sdelphij    if (X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * days) ==
1152296465Sdelphij        NULL)
1153296465Sdelphij        goto err;
115455714Skris
1155296465Sdelphij    if (!X509_set_pubkey(x, pkey))
1156296465Sdelphij        goto err;
1157296465Sdelphij    if (clrext) {
1158296465Sdelphij        while (X509_get_ext_count(x) > 0)
1159296465Sdelphij            X509_delete_ext(x, 0);
1160296465Sdelphij    }
1161296465Sdelphij    if (conf) {
1162296465Sdelphij        X509V3_CTX ctx;
1163296465Sdelphij        X509_set_version(x, 2); /* version 3 certificate */
1164296465Sdelphij        X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
1165296465Sdelphij        X509V3_set_nconf(&ctx, conf);
1166296465Sdelphij        if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
1167296465Sdelphij            goto err;
1168296465Sdelphij    }
1169296465Sdelphij    if (!X509_sign(x, pkey, digest))
1170296465Sdelphij        goto err;
1171296465Sdelphij    return 1;
1172296465Sdelphij err:
1173296465Sdelphij    ERR_print_errors(bio_err);
1174296465Sdelphij    return 0;
1175296465Sdelphij}
117659191Skris
117759191Skrisstatic int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
117859191Skris{
1179296465Sdelphij    int id, i, idret;
1180296465Sdelphij    char *pname;
1181296465Sdelphij    id = X509_PURPOSE_get_id(pt);
1182296465Sdelphij    pname = X509_PURPOSE_get0_name(pt);
1183296465Sdelphij    for (i = 0; i < 2; i++) {
1184296465Sdelphij        idret = X509_check_purpose(cert, id, i);
1185296465Sdelphij        BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
1186296465Sdelphij        if (idret == 1)
1187296465Sdelphij            BIO_printf(bio, "Yes\n");
1188296465Sdelphij        else if (idret == 0)
1189296465Sdelphij            BIO_printf(bio, "No\n");
1190296465Sdelphij        else
1191296465Sdelphij            BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
1192296465Sdelphij    }
1193296465Sdelphij    return 1;
119459191Skris}
1195