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.
8296341Sdelphij *
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).
15296341Sdelphij *
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.
22296341Sdelphij *
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 :-).
37296341Sdelphij * 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)"
40296341Sdelphij *
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.
52296341Sdelphij *
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
64296341Sdelphij# 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
77296341Sdelphij# include <openssl/rsa.h>
78160814Ssimon#endif
79160814Ssimon#ifndef OPENSSL_NO_DSA
80296341Sdelphij# include <openssl/dsa.h>
81160814Ssimon#endif
8255714Skris
8355714Skris#undef PROG
8455714Skris#define PROG x509_main
8555714Skris
8655714Skris#undef POSTFIX
87296341Sdelphij#define POSTFIX ".srl"
88296341Sdelphij#define DEF_DAYS        30
8955714Skris
90296341Sdelphijstatic const char *x509_usage[] = {
91296341Sdelphij    "usage: x509 args\n",
92296341Sdelphij    " -inform arg     - input format - default PEM (one of DER, NET or PEM)\n",
93296341Sdelphij    " -outform arg    - output format - default PEM (one of DER, NET or PEM)\n",
94296341Sdelphij    " -keyform arg    - private key format - default PEM\n",
95296341Sdelphij    " -CAform arg     - CA format - default PEM\n",
96296341Sdelphij    " -CAkeyform arg  - CA key format - default PEM\n",
97296341Sdelphij    " -in arg         - input file - default stdin\n",
98296341Sdelphij    " -out arg        - output file - default stdout\n",
99296341Sdelphij    " -passin arg     - private key password source\n",
100296341Sdelphij    " -serial         - print serial number value\n",
101296341Sdelphij    " -subject_hash   - print subject hash value\n",
102238405Sjkim#ifndef OPENSSL_NO_MD5
103296341Sdelphij    " -subject_hash_old   - print old-style (MD5) subject hash value\n",
104238405Sjkim#endif
105296341Sdelphij    " -issuer_hash    - print issuer hash value\n",
106238405Sjkim#ifndef OPENSSL_NO_MD5
107296341Sdelphij    " -issuer_hash_old    - print old-style (MD5) issuer hash value\n",
108238405Sjkim#endif
109296341Sdelphij    " -hash           - synonym for -subject_hash\n",
110296341Sdelphij    " -subject        - print subject DN\n",
111296341Sdelphij    " -issuer         - print issuer DN\n",
112296341Sdelphij    " -email          - print email address(es)\n",
113296341Sdelphij    " -startdate      - notBefore field\n",
114296341Sdelphij    " -enddate        - notAfter field\n",
115296341Sdelphij    " -purpose        - print out certificate purposes\n",
116296341Sdelphij    " -dates          - both Before and After dates\n",
117296341Sdelphij    " -modulus        - print the RSA key modulus\n",
118296341Sdelphij    " -pubkey         - output the public key\n",
119296341Sdelphij    " -fingerprint    - print the certificate fingerprint\n",
120296341Sdelphij    " -alias          - output certificate alias\n",
121296341Sdelphij    " -noout          - no certificate output\n",
122296341Sdelphij    " -ocspid         - print OCSP hash values for the subject name and public key\n",
123296341Sdelphij    " -ocsp_uri       - print OCSP Responder URL(s)\n",
124296341Sdelphij    " -trustout       - output a \"trusted\" certificate\n",
125296341Sdelphij    " -clrtrust       - clear all trusted purposes\n",
126296341Sdelphij    " -clrreject      - clear all rejected purposes\n",
127296341Sdelphij    " -addtrust arg   - trust certificate for a given purpose\n",
128296341Sdelphij    " -addreject arg  - reject certificate for a given purpose\n",
129296341Sdelphij    " -setalias arg   - set certificate alias\n",
130296341Sdelphij    " -days arg       - How long till expiry of a signed certificate - def 30 days\n",
131296341Sdelphij    " -checkend arg   - check whether the cert expires in the next arg seconds\n",
132296341Sdelphij    "                   exit 1 if so, 0 if not\n",
133296341Sdelphij    " -signkey arg    - self sign cert with arg\n",
134296341Sdelphij    " -x509toreq      - output a certification request object\n",
135296341Sdelphij    " -req            - input is a certificate request, sign and output.\n",
136296341Sdelphij    " -CA arg         - set the CA certificate, must be PEM format.\n",
137296341Sdelphij    " -CAkey arg      - set the CA key, must be PEM format\n",
138296341Sdelphij    "                   missing, it is assumed to be in the CA file.\n",
139296341Sdelphij    " -CAcreateserial - create serial number file if it does not exist\n",
140296341Sdelphij    " -CAserial arg   - serial file\n",
141296341Sdelphij    " -set_serial     - serial number to use\n",
142296341Sdelphij    " -text           - print the certificate in text form\n",
143296341Sdelphij    " -C              - print out C code forms\n",
144296341Sdelphij    " -md2/-md5/-sha1/-mdc2 - digest to use\n",
145296341Sdelphij    " -extfile        - configuration file with X509V3 extensions to add\n",
146296341Sdelphij    " -extensions     - section from config file with X509V3 extensions to add\n",
147296341Sdelphij    " -clrext         - delete extensions before signing and input certificate\n",
148296341Sdelphij    " -nameopt arg    - various certificate name options\n",
149111147Snectar#ifndef OPENSSL_NO_ENGINE
150296341Sdelphij    " -engine e       - use engine e, possibly a hardware device.\n",
151111147Snectar#endif
152296341Sdelphij    " -certopt arg    - various certificate text options\n",
153296341Sdelphij    NULL
15455714Skris};
15555714Skris
15655714Skrisstatic int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx);
157296341Sdelphijstatic int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
158296341Sdelphij                const EVP_MD *digest, CONF *conf, char *section);
159296341Sdelphijstatic int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
160296341Sdelphij                        X509 *x, X509 *xca, EVP_PKEY *pkey,
161296341Sdelphij                        STACK_OF(OPENSSL_STRING) *sigopts, char *serial,
162296341Sdelphij                        int create, int days, int clrext, CONF *conf,
163296341Sdelphij                        char *section, ASN1_INTEGER *sno);
16459191Skrisstatic int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
165296341Sdelphijstatic int reqfile = 0;
16655714Skris
16759191Skrisint MAIN(int, char **);
16859191Skris
16955714Skrisint MAIN(int argc, char **argv)
170296341Sdelphij{
171296341Sdelphij    ENGINE *e = NULL;
172296341Sdelphij    int ret = 1;
173296341Sdelphij    X509_REQ *req = NULL;
174296341Sdelphij    X509 *x = NULL, *xca = NULL;
175296341Sdelphij    ASN1_OBJECT *objtmp;
176296341Sdelphij    STACK_OF(OPENSSL_STRING) *sigopts = NULL;
177296341Sdelphij    EVP_PKEY *Upkey = NULL, *CApkey = NULL;
178296341Sdelphij    ASN1_INTEGER *sno = NULL;
179296341Sdelphij    int i, num, badops = 0;
180296341Sdelphij    BIO *out = NULL;
181296341Sdelphij    BIO *STDout = NULL;
182296341Sdelphij    STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
183296341Sdelphij    int informat, outformat, keyformat, CAformat, CAkeyformat;
184296341Sdelphij    char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
185296341Sdelphij    char *CAkeyfile = NULL, *CAserial = NULL;
186296341Sdelphij    char *alias = NULL;
187296341Sdelphij    int text = 0, serial = 0, subject = 0, issuer = 0, startdate =
188296341Sdelphij        0, enddate = 0;
189296341Sdelphij    int next_serial = 0;
190296341Sdelphij    int subject_hash = 0, issuer_hash = 0, ocspid = 0;
191238405Sjkim#ifndef OPENSSL_NO_MD5
192296341Sdelphij    int subject_hash_old = 0, issuer_hash_old = 0;
193238405Sjkim#endif
194296341Sdelphij    int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0;
195296341Sdelphij    int ocsp_uri = 0;
196296341Sdelphij    int trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0, clrext = 0;
197296341Sdelphij    int C = 0;
198296341Sdelphij    int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0;
199296341Sdelphij    int pprint = 0;
200296341Sdelphij    const char **pp;
201296341Sdelphij    X509_STORE *ctx = NULL;
202296341Sdelphij    X509_REQ *rq = NULL;
203296341Sdelphij    int fingerprint = 0;
204296341Sdelphij    char buf[256];
205296341Sdelphij    const EVP_MD *md_alg, *digest = NULL;
206296341Sdelphij    CONF *extconf = NULL;
207296341Sdelphij    char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
208296341Sdelphij    int need_rand = 0;
209296341Sdelphij    int checkend = 0, checkoffset = 0;
210296341Sdelphij    unsigned long nmflag = 0, certflag = 0;
211111147Snectar#ifndef OPENSSL_NO_ENGINE
212296341Sdelphij    char *engine = NULL;
213111147Snectar#endif
21455714Skris
215296341Sdelphij    reqfile = 0;
21655714Skris
217296341Sdelphij    apps_startup();
21855714Skris
219296341Sdelphij    if (bio_err == NULL)
220296341Sdelphij        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
221109998Smarkm
222296341Sdelphij    if (!load_config(bio_err, NULL))
223296341Sdelphij        goto end;
224296341Sdelphij    STDout = BIO_new_fp(stdout, BIO_NOCLOSE);
225109998Smarkm#ifdef OPENSSL_SYS_VMS
226296341Sdelphij    {
227296341Sdelphij        BIO *tmpbio = BIO_new(BIO_f_linebuffer());
228296341Sdelphij        STDout = BIO_push(tmpbio, STDout);
229296341Sdelphij    }
23068651Skris#endif
23155714Skris
232296341Sdelphij    informat = FORMAT_PEM;
233296341Sdelphij    outformat = FORMAT_PEM;
234296341Sdelphij    keyformat = FORMAT_PEM;
235296341Sdelphij    CAformat = FORMAT_PEM;
236296341Sdelphij    CAkeyformat = FORMAT_PEM;
23755714Skris
238296341Sdelphij    ctx = X509_STORE_new();
239296341Sdelphij    if (ctx == NULL)
240296341Sdelphij        goto end;
241296341Sdelphij    X509_STORE_set_verify_cb(ctx, callb);
24255714Skris
243296341Sdelphij    argc--;
244296341Sdelphij    argv++;
245296341Sdelphij    num = 0;
246296341Sdelphij    while (argc >= 1) {
247296341Sdelphij        if (strcmp(*argv, "-inform") == 0) {
248296341Sdelphij            if (--argc < 1)
249296341Sdelphij                goto bad;
250296341Sdelphij            informat = str2fmt(*(++argv));
251296341Sdelphij        } else if (strcmp(*argv, "-outform") == 0) {
252296341Sdelphij            if (--argc < 1)
253296341Sdelphij                goto bad;
254296341Sdelphij            outformat = str2fmt(*(++argv));
255296341Sdelphij        } else if (strcmp(*argv, "-keyform") == 0) {
256296341Sdelphij            if (--argc < 1)
257296341Sdelphij                goto bad;
258296341Sdelphij            keyformat = str2fmt(*(++argv));
259296341Sdelphij        } else if (strcmp(*argv, "-req") == 0) {
260296341Sdelphij            reqfile = 1;
261296341Sdelphij            need_rand = 1;
262296341Sdelphij        } else if (strcmp(*argv, "-CAform") == 0) {
263296341Sdelphij            if (--argc < 1)
264296341Sdelphij                goto bad;
265296341Sdelphij            CAformat = str2fmt(*(++argv));
266296341Sdelphij        } else if (strcmp(*argv, "-CAkeyform") == 0) {
267296341Sdelphij            if (--argc < 1)
268296341Sdelphij                goto bad;
269296341Sdelphij            CAkeyformat = str2fmt(*(++argv));
270296341Sdelphij        } else if (strcmp(*argv, "-sigopt") == 0) {
271296341Sdelphij            if (--argc < 1)
272296341Sdelphij                goto bad;
273296341Sdelphij            if (!sigopts)
274296341Sdelphij                sigopts = sk_OPENSSL_STRING_new_null();
275296341Sdelphij            if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
276296341Sdelphij                goto bad;
277296341Sdelphij        } else if (strcmp(*argv, "-days") == 0) {
278296341Sdelphij            if (--argc < 1)
279296341Sdelphij                goto bad;
280296341Sdelphij            days = atoi(*(++argv));
281296341Sdelphij            if (days == 0) {
282296341Sdelphij                BIO_printf(bio_err, "bad number of days\n");
283296341Sdelphij                goto bad;
284296341Sdelphij            }
285296341Sdelphij        } else if (strcmp(*argv, "-passin") == 0) {
286296341Sdelphij            if (--argc < 1)
287296341Sdelphij                goto bad;
288296341Sdelphij            passargin = *(++argv);
289296341Sdelphij        } else if (strcmp(*argv, "-extfile") == 0) {
290296341Sdelphij            if (--argc < 1)
291296341Sdelphij                goto bad;
292296341Sdelphij            extfile = *(++argv);
293296341Sdelphij        } else if (strcmp(*argv, "-extensions") == 0) {
294296341Sdelphij            if (--argc < 1)
295296341Sdelphij                goto bad;
296296341Sdelphij            extsect = *(++argv);
297296341Sdelphij        } else if (strcmp(*argv, "-in") == 0) {
298296341Sdelphij            if (--argc < 1)
299296341Sdelphij                goto bad;
300296341Sdelphij            infile = *(++argv);
301296341Sdelphij        } else if (strcmp(*argv, "-out") == 0) {
302296341Sdelphij            if (--argc < 1)
303296341Sdelphij                goto bad;
304296341Sdelphij            outfile = *(++argv);
305296341Sdelphij        } else if (strcmp(*argv, "-signkey") == 0) {
306296341Sdelphij            if (--argc < 1)
307296341Sdelphij                goto bad;
308296341Sdelphij            keyfile = *(++argv);
309296341Sdelphij            sign_flag = ++num;
310296341Sdelphij            need_rand = 1;
311296341Sdelphij        } else if (strcmp(*argv, "-CA") == 0) {
312296341Sdelphij            if (--argc < 1)
313296341Sdelphij                goto bad;
314296341Sdelphij            CAfile = *(++argv);
315296341Sdelphij            CA_flag = ++num;
316296341Sdelphij            need_rand = 1;
317296341Sdelphij        } else if (strcmp(*argv, "-CAkey") == 0) {
318296341Sdelphij            if (--argc < 1)
319296341Sdelphij                goto bad;
320296341Sdelphij            CAkeyfile = *(++argv);
321296341Sdelphij        } else if (strcmp(*argv, "-CAserial") == 0) {
322296341Sdelphij            if (--argc < 1)
323296341Sdelphij                goto bad;
324296341Sdelphij            CAserial = *(++argv);
325296341Sdelphij        } else if (strcmp(*argv, "-set_serial") == 0) {
326296341Sdelphij            if (--argc < 1)
327296341Sdelphij                goto bad;
328296341Sdelphij            if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
329296341Sdelphij                goto bad;
330296341Sdelphij        } else if (strcmp(*argv, "-addtrust") == 0) {
331296341Sdelphij            if (--argc < 1)
332296341Sdelphij                goto bad;
333296341Sdelphij            if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) {
334296341Sdelphij                BIO_printf(bio_err, "Invalid trust object value %s\n", *argv);
335296341Sdelphij                goto bad;
336296341Sdelphij            }
337296341Sdelphij            if (!trust)
338296341Sdelphij                trust = sk_ASN1_OBJECT_new_null();
339296341Sdelphij            sk_ASN1_OBJECT_push(trust, objtmp);
340296341Sdelphij            trustout = 1;
341296341Sdelphij        } else if (strcmp(*argv, "-addreject") == 0) {
342296341Sdelphij            if (--argc < 1)
343296341Sdelphij                goto bad;
344296341Sdelphij            if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) {
345296341Sdelphij                BIO_printf(bio_err,
346296341Sdelphij                           "Invalid reject object value %s\n", *argv);
347296341Sdelphij                goto bad;
348296341Sdelphij            }
349296341Sdelphij            if (!reject)
350296341Sdelphij                reject = sk_ASN1_OBJECT_new_null();
351296341Sdelphij            sk_ASN1_OBJECT_push(reject, objtmp);
352296341Sdelphij            trustout = 1;
353296341Sdelphij        } else if (strcmp(*argv, "-setalias") == 0) {
354296341Sdelphij            if (--argc < 1)
355296341Sdelphij                goto bad;
356296341Sdelphij            alias = *(++argv);
357296341Sdelphij            trustout = 1;
358296341Sdelphij        } else if (strcmp(*argv, "-certopt") == 0) {
359296341Sdelphij            if (--argc < 1)
360296341Sdelphij                goto bad;
361296341Sdelphij            if (!set_cert_ex(&certflag, *(++argv)))
362296341Sdelphij                goto bad;
363296341Sdelphij        } else if (strcmp(*argv, "-nameopt") == 0) {
364296341Sdelphij            if (--argc < 1)
365296341Sdelphij                goto bad;
366296341Sdelphij            if (!set_name_ex(&nmflag, *(++argv)))
367296341Sdelphij                goto bad;
368296341Sdelphij        }
369111147Snectar#ifndef OPENSSL_NO_ENGINE
370296341Sdelphij        else if (strcmp(*argv, "-engine") == 0) {
371296341Sdelphij            if (--argc < 1)
372296341Sdelphij                goto bad;
373296341Sdelphij            engine = *(++argv);
374296341Sdelphij        }
375111147Snectar#endif
376296341Sdelphij        else if (strcmp(*argv, "-C") == 0)
377296341Sdelphij            C = ++num;
378296341Sdelphij        else if (strcmp(*argv, "-email") == 0)
379296341Sdelphij            email = ++num;
380296341Sdelphij        else if (strcmp(*argv, "-ocsp_uri") == 0)
381296341Sdelphij            ocsp_uri = ++num;
382296341Sdelphij        else if (strcmp(*argv, "-serial") == 0)
383296341Sdelphij            serial = ++num;
384296341Sdelphij        else if (strcmp(*argv, "-next_serial") == 0)
385296341Sdelphij            next_serial = ++num;
386296341Sdelphij        else if (strcmp(*argv, "-modulus") == 0)
387296341Sdelphij            modulus = ++num;
388296341Sdelphij        else if (strcmp(*argv, "-pubkey") == 0)
389296341Sdelphij            pubkey = ++num;
390296341Sdelphij        else if (strcmp(*argv, "-x509toreq") == 0)
391296341Sdelphij            x509req = ++num;
392296341Sdelphij        else if (strcmp(*argv, "-text") == 0)
393296341Sdelphij            text = ++num;
394296341Sdelphij        else if (strcmp(*argv, "-hash") == 0
395296341Sdelphij                 || strcmp(*argv, "-subject_hash") == 0)
396296341Sdelphij            subject_hash = ++num;
397238405Sjkim#ifndef OPENSSL_NO_MD5
398296341Sdelphij        else if (strcmp(*argv, "-subject_hash_old") == 0)
399296341Sdelphij            subject_hash_old = ++num;
400238405Sjkim#endif
401296341Sdelphij        else if (strcmp(*argv, "-issuer_hash") == 0)
402296341Sdelphij            issuer_hash = ++num;
403238405Sjkim#ifndef OPENSSL_NO_MD5
404296341Sdelphij        else if (strcmp(*argv, "-issuer_hash_old") == 0)
405296341Sdelphij            issuer_hash_old = ++num;
406238405Sjkim#endif
407296341Sdelphij        else if (strcmp(*argv, "-subject") == 0)
408296341Sdelphij            subject = ++num;
409296341Sdelphij        else if (strcmp(*argv, "-issuer") == 0)
410296341Sdelphij            issuer = ++num;
411296341Sdelphij        else if (strcmp(*argv, "-fingerprint") == 0)
412296341Sdelphij            fingerprint = ++num;
413296341Sdelphij        else if (strcmp(*argv, "-dates") == 0) {
414296341Sdelphij            startdate = ++num;
415296341Sdelphij            enddate = ++num;
416296341Sdelphij        } else if (strcmp(*argv, "-purpose") == 0)
417296341Sdelphij            pprint = ++num;
418296341Sdelphij        else if (strcmp(*argv, "-startdate") == 0)
419296341Sdelphij            startdate = ++num;
420296341Sdelphij        else if (strcmp(*argv, "-enddate") == 0)
421296341Sdelphij            enddate = ++num;
422296341Sdelphij        else if (strcmp(*argv, "-checkend") == 0) {
423296341Sdelphij            if (--argc < 1)
424296341Sdelphij                goto bad;
425296341Sdelphij            checkoffset = atoi(*(++argv));
426296341Sdelphij            checkend = 1;
427296341Sdelphij        } else if (strcmp(*argv, "-noout") == 0)
428296341Sdelphij            noout = ++num;
429296341Sdelphij        else if (strcmp(*argv, "-trustout") == 0)
430296341Sdelphij            trustout = 1;
431296341Sdelphij        else if (strcmp(*argv, "-clrtrust") == 0)
432296341Sdelphij            clrtrust = ++num;
433296341Sdelphij        else if (strcmp(*argv, "-clrreject") == 0)
434296341Sdelphij            clrreject = ++num;
435296341Sdelphij        else if (strcmp(*argv, "-alias") == 0)
436296341Sdelphij            aliasout = ++num;
437296341Sdelphij        else if (strcmp(*argv, "-CAcreateserial") == 0)
438296341Sdelphij            CA_createserial = ++num;
439296341Sdelphij        else if (strcmp(*argv, "-clrext") == 0)
440296341Sdelphij            clrext = 1;
441296341Sdelphij#if 1                           /* stay backwards-compatible with 0.9.5; this
442296341Sdelphij                                 * should go away soon */
443296341Sdelphij        else if (strcmp(*argv, "-crlext") == 0) {
444296341Sdelphij            BIO_printf(bio_err, "use -clrext instead of -crlext\n");
445296341Sdelphij            clrext = 1;
446296341Sdelphij        }
44759191Skris#endif
448296341Sdelphij        else if (strcmp(*argv, "-ocspid") == 0)
449296341Sdelphij            ocspid = ++num;
450296341Sdelphij        else if ((md_alg = EVP_get_digestbyname(*argv + 1))) {
451296341Sdelphij            /* ok */
452296341Sdelphij            digest = md_alg;
453296341Sdelphij        } else {
454296341Sdelphij            BIO_printf(bio_err, "unknown option %s\n", *argv);
455296341Sdelphij            badops = 1;
456296341Sdelphij            break;
457296341Sdelphij        }
458296341Sdelphij        argc--;
459296341Sdelphij        argv++;
460296341Sdelphij    }
46155714Skris
462296341Sdelphij    if (badops) {
463296341Sdelphij bad:
464296341Sdelphij        for (pp = x509_usage; (*pp != NULL); pp++)
465296341Sdelphij            BIO_printf(bio_err, "%s", *pp);
466296341Sdelphij        goto end;
467296341Sdelphij    }
468111147Snectar#ifndef OPENSSL_NO_ENGINE
469296341Sdelphij    e = setup_engine(bio_err, engine, 0);
470111147Snectar#endif
471109998Smarkm
472296341Sdelphij    if (need_rand)
473296341Sdelphij        app_RAND_load_file(NULL, bio_err, 0);
47459191Skris
475296341Sdelphij    ERR_load_crypto_strings();
47655714Skris
477296341Sdelphij    if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
478296341Sdelphij        BIO_printf(bio_err, "Error getting password\n");
479296341Sdelphij        goto end;
480296341Sdelphij    }
48159191Skris
482296341Sdelphij    if (!X509_STORE_set_default_paths(ctx)) {
483296341Sdelphij        ERR_print_errors(bio_err);
484296341Sdelphij        goto end;
485296341Sdelphij    }
48655714Skris
487296341Sdelphij    if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
488296341Sdelphij        CAkeyfile = CAfile;
489296341Sdelphij    } else if ((CA_flag) && (CAkeyfile == NULL)) {
490296341Sdelphij        BIO_printf(bio_err,
491296341Sdelphij                   "need to specify a CAkey if using the CA command\n");
492296341Sdelphij        goto end;
493296341Sdelphij    }
49455714Skris
495296341Sdelphij    if (extfile) {
496296341Sdelphij        long errorline = -1;
497296341Sdelphij        X509V3_CTX ctx2;
498296341Sdelphij        extconf = NCONF_new(NULL);
499296341Sdelphij        if (!NCONF_load(extconf, extfile, &errorline)) {
500296341Sdelphij            if (errorline <= 0)
501296341Sdelphij                BIO_printf(bio_err,
502296341Sdelphij                           "error loading the config file '%s'\n", extfile);
503296341Sdelphij            else
504296341Sdelphij                BIO_printf(bio_err,
505296341Sdelphij                           "error on line %ld of config file '%s'\n",
506296341Sdelphij                           errorline, extfile);
507296341Sdelphij            goto end;
508296341Sdelphij        }
509296341Sdelphij        if (!extsect) {
510296341Sdelphij            extsect = NCONF_get_string(extconf, "default", "extensions");
511296341Sdelphij            if (!extsect) {
512296341Sdelphij                ERR_clear_error();
513296341Sdelphij                extsect = "default";
514296341Sdelphij            }
515296341Sdelphij        }
516296341Sdelphij        X509V3_set_ctx_test(&ctx2);
517296341Sdelphij        X509V3_set_nconf(&ctx2, extconf);
518296341Sdelphij        if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
519296341Sdelphij            BIO_printf(bio_err,
520296341Sdelphij                       "Error Loading extension section %s\n", extsect);
521296341Sdelphij            ERR_print_errors(bio_err);
522296341Sdelphij            goto end;
523296341Sdelphij        }
524296341Sdelphij    }
52555714Skris
526296341Sdelphij    if (reqfile) {
527296341Sdelphij        EVP_PKEY *pkey;
528296341Sdelphij        BIO *in;
52955714Skris
530296341Sdelphij        if (!sign_flag && !CA_flag) {
531296341Sdelphij            BIO_printf(bio_err, "We need a private key to sign with\n");
532296341Sdelphij            goto end;
533296341Sdelphij        }
534296341Sdelphij        in = BIO_new(BIO_s_file());
535296341Sdelphij        if (in == NULL) {
536296341Sdelphij            ERR_print_errors(bio_err);
537296341Sdelphij            goto end;
538296341Sdelphij        }
53955714Skris
540296341Sdelphij        if (infile == NULL)
541296341Sdelphij            BIO_set_fp(in, stdin, BIO_NOCLOSE | BIO_FP_TEXT);
542296341Sdelphij        else {
543296341Sdelphij            if (BIO_read_filename(in, infile) <= 0) {
544296341Sdelphij                perror(infile);
545296341Sdelphij                BIO_free(in);
546296341Sdelphij                goto end;
547296341Sdelphij            }
548296341Sdelphij        }
549296341Sdelphij        req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
550296341Sdelphij        BIO_free(in);
55155714Skris
552296341Sdelphij        if (req == NULL) {
553296341Sdelphij            ERR_print_errors(bio_err);
554296341Sdelphij            goto end;
555296341Sdelphij        }
55655714Skris
557296341Sdelphij        if ((req->req_info == NULL) ||
558296341Sdelphij            (req->req_info->pubkey == NULL) ||
559296341Sdelphij            (req->req_info->pubkey->public_key == NULL) ||
560296341Sdelphij            (req->req_info->pubkey->public_key->data == NULL)) {
561296341Sdelphij            BIO_printf(bio_err,
562296341Sdelphij                       "The certificate request appears to corrupted\n");
563296341Sdelphij            BIO_printf(bio_err, "It does not contain a public key\n");
564296341Sdelphij            goto end;
565296341Sdelphij        }
566296341Sdelphij        if ((pkey = X509_REQ_get_pubkey(req)) == NULL) {
567296341Sdelphij            BIO_printf(bio_err, "error unpacking public key\n");
568296341Sdelphij            goto end;
569296341Sdelphij        }
570296341Sdelphij        i = X509_REQ_verify(req, pkey);
571296341Sdelphij        EVP_PKEY_free(pkey);
572296341Sdelphij        if (i < 0) {
573296341Sdelphij            BIO_printf(bio_err, "Signature verification error\n");
574296341Sdelphij            ERR_print_errors(bio_err);
575296341Sdelphij            goto end;
576296341Sdelphij        }
577296341Sdelphij        if (i == 0) {
578296341Sdelphij            BIO_printf(bio_err,
579296341Sdelphij                       "Signature did not match the certificate request\n");
580296341Sdelphij            goto end;
581296341Sdelphij        } else
582296341Sdelphij            BIO_printf(bio_err, "Signature ok\n");
58355714Skris
584296341Sdelphij        print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
585296341Sdelphij                   nmflag);
58655714Skris
587296341Sdelphij        if ((x = X509_new()) == NULL)
588296341Sdelphij            goto end;
58968651Skris
590296341Sdelphij        if (sno == NULL) {
591296341Sdelphij            sno = ASN1_INTEGER_new();
592296341Sdelphij            if (!sno || !rand_serial(NULL, sno))
593296341Sdelphij                goto end;
594296341Sdelphij            if (!X509_set_serialNumber(x, sno))
595296341Sdelphij                goto end;
596296341Sdelphij            ASN1_INTEGER_free(sno);
597296341Sdelphij            sno = NULL;
598296341Sdelphij        } else if (!X509_set_serialNumber(x, sno))
599296341Sdelphij            goto end;
60055714Skris
601296341Sdelphij        if (!X509_set_issuer_name(x, req->req_info->subject))
602296341Sdelphij            goto end;
603296341Sdelphij        if (!X509_set_subject_name(x, req->req_info->subject))
604296341Sdelphij            goto end;
605142425Snectar
606296341Sdelphij        X509_gmtime_adj(X509_get_notBefore(x), 0);
607296341Sdelphij        X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL);
60855714Skris
609296341Sdelphij        pkey = X509_REQ_get_pubkey(req);
610296341Sdelphij        X509_set_pubkey(x, pkey);
611296341Sdelphij        EVP_PKEY_free(pkey);
612296341Sdelphij    } else
613296341Sdelphij        x = load_cert(bio_err, infile, informat, NULL, e, "Certificate");
61455714Skris
615296341Sdelphij    if (x == NULL)
616296341Sdelphij        goto end;
617296341Sdelphij    if (CA_flag) {
618296341Sdelphij        xca = load_cert(bio_err, CAfile, CAformat, NULL, e, "CA Certificate");
619296341Sdelphij        if (xca == NULL)
620296341Sdelphij            goto end;
621296341Sdelphij    }
62255714Skris
623296341Sdelphij    if (!noout || text || next_serial) {
624296341Sdelphij        OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");
62555714Skris
626296341Sdelphij        out = BIO_new(BIO_s_file());
627296341Sdelphij        if (out == NULL) {
628296341Sdelphij            ERR_print_errors(bio_err);
629296341Sdelphij            goto end;
630296341Sdelphij        }
631296341Sdelphij        if (outfile == NULL) {
632296341Sdelphij            BIO_set_fp(out, stdout, BIO_NOCLOSE);
633109998Smarkm#ifdef OPENSSL_SYS_VMS
634296341Sdelphij            {
635296341Sdelphij                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
636296341Sdelphij                out = BIO_push(tmpbio, out);
637296341Sdelphij            }
63868651Skris#endif
639296341Sdelphij        } else {
640296341Sdelphij            if (BIO_write_filename(out, outfile) <= 0) {
641296341Sdelphij                perror(outfile);
642296341Sdelphij                goto end;
643296341Sdelphij            }
644296341Sdelphij        }
645296341Sdelphij    }
64655714Skris
647296341Sdelphij    if (alias)
648296341Sdelphij        X509_alias_set1(x, (unsigned char *)alias, -1);
64959191Skris
650296341Sdelphij    if (clrtrust)
651296341Sdelphij        X509_trust_clear(x);
652296341Sdelphij    if (clrreject)
653296341Sdelphij        X509_reject_clear(x);
65459191Skris
655296341Sdelphij    if (trust) {
656296341Sdelphij        for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
657296341Sdelphij            objtmp = sk_ASN1_OBJECT_value(trust, i);
658296341Sdelphij            X509_add1_trust_object(x, objtmp);
659296341Sdelphij        }
660296341Sdelphij    }
66159191Skris
662296341Sdelphij    if (reject) {
663296341Sdelphij        for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
664296341Sdelphij            objtmp = sk_ASN1_OBJECT_value(reject, i);
665296341Sdelphij            X509_add1_reject_object(x, objtmp);
666296341Sdelphij        }
667296341Sdelphij    }
66859191Skris
669296341Sdelphij    if (num) {
670296341Sdelphij        for (i = 1; i <= num; i++) {
671296341Sdelphij            if (issuer == i) {
672296341Sdelphij                print_name(STDout, "issuer= ",
673296341Sdelphij                           X509_get_issuer_name(x), nmflag);
674296341Sdelphij            } else if (subject == i) {
675296341Sdelphij                print_name(STDout, "subject= ",
676296341Sdelphij                           X509_get_subject_name(x), nmflag);
677296341Sdelphij            } else if (serial == i) {
678296341Sdelphij                BIO_printf(STDout, "serial=");
679296341Sdelphij                i2a_ASN1_INTEGER(STDout, X509_get_serialNumber(x));
680296341Sdelphij                BIO_printf(STDout, "\n");
681296341Sdelphij            } else if (next_serial == i) {
682296341Sdelphij                BIGNUM *bnser;
683296341Sdelphij                ASN1_INTEGER *ser;
684296341Sdelphij                ser = X509_get_serialNumber(x);
685296341Sdelphij                bnser = ASN1_INTEGER_to_BN(ser, NULL);
686296341Sdelphij                if (!bnser)
687296341Sdelphij                    goto end;
688296341Sdelphij                if (!BN_add_word(bnser, 1))
689296341Sdelphij                    goto end;
690296341Sdelphij                ser = BN_to_ASN1_INTEGER(bnser, NULL);
691296341Sdelphij                if (!ser)
692296341Sdelphij                    goto end;
693296341Sdelphij                BN_free(bnser);
694296341Sdelphij                i2a_ASN1_INTEGER(out, ser);
695296341Sdelphij                ASN1_INTEGER_free(ser);
696296341Sdelphij                BIO_puts(out, "\n");
697296341Sdelphij            } else if ((email == i) || (ocsp_uri == i)) {
698296341Sdelphij                int j;
699296341Sdelphij                STACK_OF(OPENSSL_STRING) *emlst;
700296341Sdelphij                if (email == i)
701296341Sdelphij                    emlst = X509_get1_email(x);
702296341Sdelphij                else
703296341Sdelphij                    emlst = X509_get1_ocsp(x);
704296341Sdelphij                for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
705296341Sdelphij                    BIO_printf(STDout, "%s\n",
706296341Sdelphij                               sk_OPENSSL_STRING_value(emlst, j));
707296341Sdelphij                X509_email_free(emlst);
708296341Sdelphij            } else if (aliasout == i) {
709296341Sdelphij                unsigned char *alstr;
710296341Sdelphij                alstr = X509_alias_get0(x, NULL);
711296341Sdelphij                if (alstr)
712296341Sdelphij                    BIO_printf(STDout, "%s\n", alstr);
713296341Sdelphij                else
714296341Sdelphij                    BIO_puts(STDout, "<No Alias>\n");
715296341Sdelphij            } else if (subject_hash == i) {
716296341Sdelphij                BIO_printf(STDout, "%08lx\n", X509_subject_name_hash(x));
717296341Sdelphij            }
718238405Sjkim#ifndef OPENSSL_NO_MD5
719296341Sdelphij            else if (subject_hash_old == i) {
720296341Sdelphij                BIO_printf(STDout, "%08lx\n", X509_subject_name_hash_old(x));
721296341Sdelphij            }
722238405Sjkim#endif
723296341Sdelphij            else if (issuer_hash == i) {
724296341Sdelphij                BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash(x));
725296341Sdelphij            }
726238405Sjkim#ifndef OPENSSL_NO_MD5
727296341Sdelphij            else if (issuer_hash_old == i) {
728296341Sdelphij                BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash_old(x));
729296341Sdelphij            }
730238405Sjkim#endif
731296341Sdelphij            else if (pprint == i) {
732296341Sdelphij                X509_PURPOSE *ptmp;
733296341Sdelphij                int j;
734296341Sdelphij                BIO_printf(STDout, "Certificate purposes:\n");
735296341Sdelphij                for (j = 0; j < X509_PURPOSE_get_count(); j++) {
736296341Sdelphij                    ptmp = X509_PURPOSE_get0(j);
737296341Sdelphij                    purpose_print(STDout, x, ptmp);
738296341Sdelphij                }
739296341Sdelphij            } else if (modulus == i) {
740296341Sdelphij                EVP_PKEY *pkey;
74155714Skris
742296341Sdelphij                pkey = X509_get_pubkey(x);
743296341Sdelphij                if (pkey == NULL) {
744296341Sdelphij                    BIO_printf(bio_err, "Modulus=unavailable\n");
745296341Sdelphij                    ERR_print_errors(bio_err);
746296341Sdelphij                    goto end;
747296341Sdelphij                }
748296341Sdelphij                BIO_printf(STDout, "Modulus=");
749109998Smarkm#ifndef OPENSSL_NO_RSA
750296341Sdelphij                if (pkey->type == EVP_PKEY_RSA)
751296341Sdelphij                    BN_print(STDout, pkey->pkey.rsa->n);
752296341Sdelphij                else
75355714Skris#endif
754109998Smarkm#ifndef OPENSSL_NO_DSA
755296341Sdelphij                if (pkey->type == EVP_PKEY_DSA)
756296341Sdelphij                    BN_print(STDout, pkey->pkey.dsa->pub_key);
757296341Sdelphij                else
75855714Skris#endif
759296341Sdelphij                    BIO_printf(STDout, "Wrong Algorithm type");
760296341Sdelphij                BIO_printf(STDout, "\n");
761296341Sdelphij                EVP_PKEY_free(pkey);
762296341Sdelphij            } else if (pubkey == i) {
763296341Sdelphij                EVP_PKEY *pkey;
76459191Skris
765296341Sdelphij                pkey = X509_get_pubkey(x);
766296341Sdelphij                if (pkey == NULL) {
767296341Sdelphij                    BIO_printf(bio_err, "Error getting public key\n");
768296341Sdelphij                    ERR_print_errors(bio_err);
769296341Sdelphij                    goto end;
770296341Sdelphij                }
771296341Sdelphij                PEM_write_bio_PUBKEY(STDout, pkey);
772296341Sdelphij                EVP_PKEY_free(pkey);
773296341Sdelphij            } else if (C == i) {
774296341Sdelphij                unsigned char *d;
775296341Sdelphij                char *m;
776296341Sdelphij                int y, z;
77755714Skris
778296341Sdelphij                X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof buf);
779296341Sdelphij                BIO_printf(STDout, "/* subject:%s */\n", buf);
780296341Sdelphij                m = X509_NAME_oneline(X509_get_issuer_name(x), buf,
781296341Sdelphij                                      sizeof buf);
782296341Sdelphij                BIO_printf(STDout, "/* issuer :%s */\n", buf);
78355714Skris
784296341Sdelphij                z = i2d_X509(x, NULL);
785296341Sdelphij                m = OPENSSL_malloc(z);
786296341Sdelphij                if (!m) {
787296341Sdelphij                    BIO_printf(bio_err, "Out of memory\n");
788296341Sdelphij                    ERR_print_errors(bio_err);
789296341Sdelphij                    goto end;
790296341Sdelphij                }
79155714Skris
792296341Sdelphij                d = (unsigned char *)m;
793296341Sdelphij                z = i2d_X509_NAME(X509_get_subject_name(x), &d);
794296341Sdelphij                BIO_printf(STDout, "unsigned char XXX_subject_name[%d]={\n",
795296341Sdelphij                           z);
796296341Sdelphij                d = (unsigned char *)m;
797296341Sdelphij                for (y = 0; y < z; y++) {
798296341Sdelphij                    BIO_printf(STDout, "0x%02X,", d[y]);
799296341Sdelphij                    if ((y & 0x0f) == 0x0f)
800296341Sdelphij                        BIO_printf(STDout, "\n");
801296341Sdelphij                }
802296341Sdelphij                if (y % 16 != 0)
803296341Sdelphij                    BIO_printf(STDout, "\n");
804296341Sdelphij                BIO_printf(STDout, "};\n");
80555714Skris
806296341Sdelphij                z = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
807296341Sdelphij                BIO_printf(STDout, "unsigned char XXX_public_key[%d]={\n", z);
808296341Sdelphij                d = (unsigned char *)m;
809296341Sdelphij                for (y = 0; y < z; y++) {
810296341Sdelphij                    BIO_printf(STDout, "0x%02X,", d[y]);
811296341Sdelphij                    if ((y & 0x0f) == 0x0f)
812296341Sdelphij                        BIO_printf(STDout, "\n");
813296341Sdelphij                }
814296341Sdelphij                if (y % 16 != 0)
815296341Sdelphij                    BIO_printf(STDout, "\n");
816296341Sdelphij                BIO_printf(STDout, "};\n");
81755714Skris
818296341Sdelphij                z = i2d_X509(x, &d);
819296341Sdelphij                BIO_printf(STDout, "unsigned char XXX_certificate[%d]={\n",
820296341Sdelphij                           z);
821296341Sdelphij                d = (unsigned char *)m;
822296341Sdelphij                for (y = 0; y < z; y++) {
823296341Sdelphij                    BIO_printf(STDout, "0x%02X,", d[y]);
824296341Sdelphij                    if ((y & 0x0f) == 0x0f)
825296341Sdelphij                        BIO_printf(STDout, "\n");
826296341Sdelphij                }
827296341Sdelphij                if (y % 16 != 0)
828296341Sdelphij                    BIO_printf(STDout, "\n");
829296341Sdelphij                BIO_printf(STDout, "};\n");
83055714Skris
831296341Sdelphij                OPENSSL_free(m);
832296341Sdelphij            } else if (text == i) {
833296341Sdelphij                X509_print_ex(STDout, x, nmflag, certflag);
834296341Sdelphij            } else if (startdate == i) {
835296341Sdelphij                BIO_puts(STDout, "notBefore=");
836296341Sdelphij                ASN1_TIME_print(STDout, X509_get_notBefore(x));
837296341Sdelphij                BIO_puts(STDout, "\n");
838296341Sdelphij            } else if (enddate == i) {
839296341Sdelphij                BIO_puts(STDout, "notAfter=");
840296341Sdelphij                ASN1_TIME_print(STDout, X509_get_notAfter(x));
841296341Sdelphij                BIO_puts(STDout, "\n");
842296341Sdelphij            } else if (fingerprint == i) {
843296341Sdelphij                int j;
844296341Sdelphij                unsigned int n;
845296341Sdelphij                unsigned char md[EVP_MAX_MD_SIZE];
846296341Sdelphij                const EVP_MD *fdig = digest;
84755714Skris
848296341Sdelphij                if (!fdig)
849296341Sdelphij                    fdig = EVP_sha1();
850238405Sjkim
851296341Sdelphij                if (!X509_digest(x, fdig, md, &n)) {
852296341Sdelphij                    BIO_printf(bio_err, "out of memory\n");
853296341Sdelphij                    goto end;
854296341Sdelphij                }
855296341Sdelphij                BIO_printf(STDout, "%s Fingerprint=",
856296341Sdelphij                           OBJ_nid2sn(EVP_MD_type(fdig)));
857296341Sdelphij                for (j = 0; j < (int)n; j++) {
858296341Sdelphij                    BIO_printf(STDout, "%02X%c", md[j], (j + 1 == (int)n)
859296341Sdelphij                               ? '\n' : ':');
860296341Sdelphij                }
861296341Sdelphij            }
86255714Skris
863296341Sdelphij            /* should be in the library */
864296341Sdelphij            else if ((sign_flag == i) && (x509req == 0)) {
865296341Sdelphij                BIO_printf(bio_err, "Getting Private key\n");
866296341Sdelphij                if (Upkey == NULL) {
867296341Sdelphij                    Upkey = load_key(bio_err,
868296341Sdelphij                                     keyfile, keyformat, 0,
869296341Sdelphij                                     passin, e, "Private key");
870296341Sdelphij                    if (Upkey == NULL)
871296341Sdelphij                        goto end;
872296341Sdelphij                }
87355714Skris
874296341Sdelphij                assert(need_rand);
875296341Sdelphij                if (!sign(x, Upkey, days, clrext, digest, extconf, extsect))
876296341Sdelphij                    goto end;
877296341Sdelphij            } else if (CA_flag == i) {
878296341Sdelphij                BIO_printf(bio_err, "Getting CA Private Key\n");
879296341Sdelphij                if (CAkeyfile != NULL) {
880296341Sdelphij                    CApkey = load_key(bio_err,
881296341Sdelphij                                      CAkeyfile, CAkeyformat,
882296341Sdelphij                                      0, passin, e, "CA Private Key");
883296341Sdelphij                    if (CApkey == NULL)
884296341Sdelphij                        goto end;
885296341Sdelphij                }
88655714Skris
887296341Sdelphij                assert(need_rand);
888296341Sdelphij                if (!x509_certify(ctx, CAfile, digest, x, xca,
889296341Sdelphij                                  CApkey, sigopts,
890296341Sdelphij                                  CAserial, CA_createserial, days, clrext,
891296341Sdelphij                                  extconf, extsect, sno))
892296341Sdelphij                    goto end;
893296341Sdelphij            } else if (x509req == i) {
894296341Sdelphij                EVP_PKEY *pk;
89555714Skris
896296341Sdelphij                BIO_printf(bio_err, "Getting request Private Key\n");
897296341Sdelphij                if (keyfile == NULL) {
898296341Sdelphij                    BIO_printf(bio_err, "no request key file specified\n");
899296341Sdelphij                    goto end;
900296341Sdelphij                } else {
901296341Sdelphij                    pk = load_key(bio_err,
902296341Sdelphij                                  keyfile, keyformat, 0,
903296341Sdelphij                                  passin, e, "request key");
904296341Sdelphij                    if (pk == NULL)
905296341Sdelphij                        goto end;
906296341Sdelphij                }
90755714Skris
908296341Sdelphij                BIO_printf(bio_err, "Generating certificate request\n");
90955714Skris
910296341Sdelphij                rq = X509_to_X509_REQ(x, pk, digest);
911296341Sdelphij                EVP_PKEY_free(pk);
912296341Sdelphij                if (rq == NULL) {
913296341Sdelphij                    ERR_print_errors(bio_err);
914296341Sdelphij                    goto end;
915296341Sdelphij                }
916296341Sdelphij                if (!noout) {
917296341Sdelphij                    X509_REQ_print(out, rq);
918296341Sdelphij                    PEM_write_bio_X509_REQ(out, rq);
919296341Sdelphij                }
920296341Sdelphij                noout = 1;
921296341Sdelphij            } else if (ocspid == i) {
922296341Sdelphij                X509_ocspid_print(out, x);
923296341Sdelphij            }
924296341Sdelphij        }
925296341Sdelphij    }
92668651Skris
927296341Sdelphij    if (checkend) {
928296341Sdelphij        time_t tcheck = time(NULL) + checkoffset;
92968651Skris
930296341Sdelphij        if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) {
931296341Sdelphij            BIO_printf(out, "Certificate will expire\n");
932296341Sdelphij            ret = 1;
933296341Sdelphij        } else {
934296341Sdelphij            BIO_printf(out, "Certificate will not expire\n");
935296341Sdelphij            ret = 0;
936296341Sdelphij        }
937296341Sdelphij        goto end;
938296341Sdelphij    }
93955714Skris
940296341Sdelphij    if (noout) {
941296341Sdelphij        ret = 0;
942296341Sdelphij        goto end;
943296341Sdelphij    }
94455714Skris
945296341Sdelphij    if (outformat == FORMAT_ASN1)
946296341Sdelphij        i = i2d_X509_bio(out, x);
947296341Sdelphij    else if (outformat == FORMAT_PEM) {
948296341Sdelphij        if (trustout)
949296341Sdelphij            i = PEM_write_bio_X509_AUX(out, x);
950296341Sdelphij        else
951296341Sdelphij            i = PEM_write_bio_X509(out, x);
952296341Sdelphij    } else if (outformat == FORMAT_NETSCAPE) {
953296341Sdelphij        NETSCAPE_X509 nx;
954296341Sdelphij        ASN1_OCTET_STRING hdr;
95555714Skris
956296341Sdelphij        hdr.data = (unsigned char *)NETSCAPE_CERT_HDR;
957296341Sdelphij        hdr.length = strlen(NETSCAPE_CERT_HDR);
958296341Sdelphij        nx.header = &hdr;
959296341Sdelphij        nx.cert = x;
96055714Skris
961296341Sdelphij        i = ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509), out, &nx);
962296341Sdelphij    } else {
963296341Sdelphij        BIO_printf(bio_err, "bad output format specified for outfile\n");
964296341Sdelphij        goto end;
965296341Sdelphij    }
966296341Sdelphij    if (!i) {
967296341Sdelphij        BIO_printf(bio_err, "unable to write certificate\n");
968296341Sdelphij        ERR_print_errors(bio_err);
969296341Sdelphij        goto end;
970296341Sdelphij    }
971296341Sdelphij    ret = 0;
972296341Sdelphij end:
973296341Sdelphij    if (need_rand)
974296341Sdelphij        app_RAND_write_file(NULL, bio_err);
975296341Sdelphij    OBJ_cleanup();
976296341Sdelphij    NCONF_free(extconf);
977296341Sdelphij    BIO_free_all(out);
978296341Sdelphij    BIO_free_all(STDout);
979296341Sdelphij    X509_STORE_free(ctx);
980296341Sdelphij    X509_REQ_free(req);
981296341Sdelphij    X509_free(x);
982296341Sdelphij    X509_free(xca);
983296341Sdelphij    EVP_PKEY_free(Upkey);
984296341Sdelphij    EVP_PKEY_free(CApkey);
985296341Sdelphij    if (sigopts)
986296341Sdelphij        sk_OPENSSL_STRING_free(sigopts);
987296341Sdelphij    X509_REQ_free(rq);
988296341Sdelphij    ASN1_INTEGER_free(sno);
989296341Sdelphij    sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
990296341Sdelphij    sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
991296341Sdelphij    if (passin)
992296341Sdelphij        OPENSSL_free(passin);
993296341Sdelphij    apps_shutdown();
994296341Sdelphij    OPENSSL_EXIT(ret);
995296341Sdelphij}
99655714Skris
997296341Sdelphijstatic ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile,
998296341Sdelphij                                      int create)
999296341Sdelphij{
1000296341Sdelphij    char *buf = NULL, *p;
1001296341Sdelphij    ASN1_INTEGER *bs = NULL;
1002296341Sdelphij    BIGNUM *serial = NULL;
1003296341Sdelphij    size_t len;
100455714Skris
1005296341Sdelphij    len = ((serialfile == NULL)
1006296341Sdelphij           ? (strlen(CAfile) + strlen(POSTFIX) + 1)
1007296341Sdelphij           : (strlen(serialfile))) + 1;
1008296341Sdelphij    buf = OPENSSL_malloc(len);
1009296341Sdelphij    if (buf == NULL) {
1010296341Sdelphij        BIO_printf(bio_err, "out of mem\n");
1011296341Sdelphij        goto end;
1012296341Sdelphij    }
1013296341Sdelphij    if (serialfile == NULL) {
1014296341Sdelphij        BUF_strlcpy(buf, CAfile, len);
1015296341Sdelphij        for (p = buf; *p; p++)
1016296341Sdelphij            if (*p == '.') {
1017296341Sdelphij                *p = '\0';
1018296341Sdelphij                break;
1019296341Sdelphij            }
1020296341Sdelphij        BUF_strlcat(buf, POSTFIX, len);
1021296341Sdelphij    } else
1022296341Sdelphij        BUF_strlcpy(buf, serialfile, len);
102355714Skris
1024296341Sdelphij    serial = load_serial(buf, create, NULL);
1025296341Sdelphij    if (serial == NULL)
1026296341Sdelphij        goto end;
1027109998Smarkm
1028296341Sdelphij    if (!BN_add_word(serial, 1)) {
1029296341Sdelphij        BIO_printf(bio_err, "add_word failure\n");
1030296341Sdelphij        goto end;
1031296341Sdelphij    }
1032127128Snectar
1033296341Sdelphij    if (!save_serial(buf, NULL, serial, &bs))
1034296341Sdelphij        goto end;
1035296341Sdelphij
1036127128Snectar end:
1037296341Sdelphij    if (buf)
1038296341Sdelphij        OPENSSL_free(buf);
1039296341Sdelphij    BN_free(serial);
1040296341Sdelphij    return bs;
1041296341Sdelphij}
1042109998Smarkm
1043109998Smarkmstatic int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
1044296341Sdelphij                        X509 *x, X509 *xca, EVP_PKEY *pkey,
1045296341Sdelphij                        STACK_OF(OPENSSL_STRING) *sigopts,
1046296341Sdelphij                        char *serialfile, int create,
1047296341Sdelphij                        int days, int clrext, CONF *conf, char *section,
1048296341Sdelphij                        ASN1_INTEGER *sno)
1049296341Sdelphij{
1050296341Sdelphij    int ret = 0;
1051296341Sdelphij    ASN1_INTEGER *bs = NULL;
1052296341Sdelphij    X509_STORE_CTX xsc;
1053296341Sdelphij    EVP_PKEY *upkey;
1054109998Smarkm
1055296341Sdelphij    upkey = X509_get_pubkey(xca);
1056296341Sdelphij    EVP_PKEY_copy_parameters(upkey, pkey);
1057296341Sdelphij    EVP_PKEY_free(upkey);
1058109998Smarkm
1059296341Sdelphij    if (!X509_STORE_CTX_init(&xsc, ctx, x, NULL)) {
1060296341Sdelphij        BIO_printf(bio_err, "Error initialising X509 store\n");
1061296341Sdelphij        goto end;
1062296341Sdelphij    }
1063296341Sdelphij    if (sno)
1064296341Sdelphij        bs = sno;
1065296341Sdelphij    else if (!(bs = x509_load_serial(CAfile, serialfile, create)))
1066296341Sdelphij        goto end;
1067109998Smarkm
1068296341Sdelphij/*      if (!X509_STORE_add_cert(ctx,x)) goto end;*/
106955714Skris
1070296341Sdelphij    /*
1071296341Sdelphij     * NOTE: this certificate can/should be self signed, unless it was a
1072296341Sdelphij     * certificate request in which case it is not.
1073296341Sdelphij     */
1074296341Sdelphij    X509_STORE_CTX_set_cert(&xsc, x);
1075296341Sdelphij    X509_STORE_CTX_set_flags(&xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
1076296341Sdelphij    if (!reqfile && X509_verify_cert(&xsc) <= 0)
1077296341Sdelphij        goto end;
107855714Skris
1079296341Sdelphij    if (!X509_check_private_key(xca, pkey)) {
1080296341Sdelphij        BIO_printf(bio_err,
1081296341Sdelphij                   "CA certificate and CA private key do not match\n");
1082296341Sdelphij        goto end;
1083296341Sdelphij    }
108455714Skris
1085296341Sdelphij    if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
1086296341Sdelphij        goto end;
1087296341Sdelphij    if (!X509_set_serialNumber(x, bs))
1088296341Sdelphij        goto end;
108955714Skris
1090296341Sdelphij    if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL)
1091296341Sdelphij        goto end;
109255714Skris
1093296341Sdelphij    /* hardwired expired */
1094296341Sdelphij    if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
1095296341Sdelphij        goto end;
109655714Skris
1097296341Sdelphij    if (clrext) {
1098296341Sdelphij        while (X509_get_ext_count(x) > 0)
1099296341Sdelphij            X509_delete_ext(x, 0);
1100296341Sdelphij    }
110159191Skris
1102296341Sdelphij    if (conf) {
1103296341Sdelphij        X509V3_CTX ctx2;
1104296341Sdelphij        X509_set_version(x, 2); /* version 3 certificate */
1105296341Sdelphij        X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
1106296341Sdelphij        X509V3_set_nconf(&ctx2, conf);
1107296341Sdelphij        if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
1108296341Sdelphij            goto end;
1109296341Sdelphij    }
111055714Skris
1111296341Sdelphij    if (!do_X509_sign(bio_err, x, pkey, digest, sigopts))
1112296341Sdelphij        goto end;
1113296341Sdelphij    ret = 1;
1114296341Sdelphij end:
1115296341Sdelphij    X509_STORE_CTX_cleanup(&xsc);
1116296341Sdelphij    if (!ret)
1117296341Sdelphij        ERR_print_errors(bio_err);
1118296341Sdelphij    if (!sno)
1119296341Sdelphij        ASN1_INTEGER_free(bs);
1120296341Sdelphij    return ret;
1121296341Sdelphij}
112255714Skris
112355714Skrisstatic int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx)
1124296341Sdelphij{
1125296341Sdelphij    int err;
1126296341Sdelphij    X509 *err_cert;
112755714Skris
1128296341Sdelphij    /*
1129296341Sdelphij     * it is ok to use a self signed certificate This case will catch both
1130296341Sdelphij     * the initial ok == 0 and the final ok == 1 calls to this function
1131296341Sdelphij     */
1132296341Sdelphij    err = X509_STORE_CTX_get_error(ctx);
1133296341Sdelphij    if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
1134296341Sdelphij        return 1;
113555714Skris
1136296341Sdelphij    /*
1137296341Sdelphij     * BAD we should have gotten an error.  Normally if everything worked
1138296341Sdelphij     * X509_STORE_CTX_get_error(ctx) will still be set to
1139296341Sdelphij     * DEPTH_ZERO_SELF_....
1140296341Sdelphij     */
1141296341Sdelphij    if (ok) {
1142296341Sdelphij        BIO_printf(bio_err,
1143296341Sdelphij                   "error with certificate to be certified - should be self signed\n");
1144296341Sdelphij        return 0;
1145296341Sdelphij    } else {
1146296341Sdelphij        err_cert = X509_STORE_CTX_get_current_cert(ctx);
1147296341Sdelphij        print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
1148296341Sdelphij        BIO_printf(bio_err,
1149296341Sdelphij                   "error with certificate - error %d at depth %d\n%s\n", err,
1150296341Sdelphij                   X509_STORE_CTX_get_error_depth(ctx),
1151296341Sdelphij                   X509_verify_cert_error_string(err));
1152296341Sdelphij        return 1;
1153296341Sdelphij    }
1154296341Sdelphij}
115555714Skris
115655714Skris/* self sign */
1157296341Sdelphijstatic int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
1158296341Sdelphij                const EVP_MD *digest, CONF *conf, char *section)
1159296341Sdelphij{
116055714Skris
1161296341Sdelphij    EVP_PKEY *pktmp;
116255714Skris
1163296341Sdelphij    pktmp = X509_get_pubkey(x);
1164296341Sdelphij    EVP_PKEY_copy_parameters(pktmp, pkey);
1165296341Sdelphij    EVP_PKEY_save_parameters(pktmp, 1);
1166296341Sdelphij    EVP_PKEY_free(pktmp);
116755714Skris
1168296341Sdelphij    if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
1169296341Sdelphij        goto err;
1170296341Sdelphij    if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
1171296341Sdelphij        goto err;
117255714Skris
1173296341Sdelphij    /* Lets just make it 12:00am GMT, Jan 1 1970 */
1174296341Sdelphij    /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
1175296341Sdelphij    /* 28 days to be certified */
117655714Skris
1177296341Sdelphij    if (X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * days) ==
1178296341Sdelphij        NULL)
1179296341Sdelphij        goto err;
118055714Skris
1181296341Sdelphij    if (!X509_set_pubkey(x, pkey))
1182296341Sdelphij        goto err;
1183296341Sdelphij    if (clrext) {
1184296341Sdelphij        while (X509_get_ext_count(x) > 0)
1185296341Sdelphij            X509_delete_ext(x, 0);
1186296341Sdelphij    }
1187296341Sdelphij    if (conf) {
1188296341Sdelphij        X509V3_CTX ctx;
1189296341Sdelphij        X509_set_version(x, 2); /* version 3 certificate */
1190296341Sdelphij        X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
1191296341Sdelphij        X509V3_set_nconf(&ctx, conf);
1192296341Sdelphij        if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
1193296341Sdelphij            goto err;
1194296341Sdelphij    }
1195296341Sdelphij    if (!X509_sign(x, pkey, digest))
1196296341Sdelphij        goto err;
1197296341Sdelphij    return 1;
1198296341Sdelphij err:
1199296341Sdelphij    ERR_print_errors(bio_err);
1200296341Sdelphij    return 0;
1201296341Sdelphij}
120259191Skris
120359191Skrisstatic int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
120459191Skris{
1205296341Sdelphij    int id, i, idret;
1206296341Sdelphij    char *pname;
1207296341Sdelphij    id = X509_PURPOSE_get_id(pt);
1208296341Sdelphij    pname = X509_PURPOSE_get0_name(pt);
1209296341Sdelphij    for (i = 0; i < 2; i++) {
1210296341Sdelphij        idret = X509_check_purpose(cert, id, i);
1211296341Sdelphij        BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
1212296341Sdelphij        if (idret == 1)
1213296341Sdelphij            BIO_printf(bio, "Yes\n");
1214296341Sdelphij        else if (idret == 0)
1215296341Sdelphij            BIO_printf(bio, "No\n");
1216296341Sdelphij        else
1217296341Sdelphij            BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
1218296341Sdelphij    }
1219296341Sdelphij    return 1;
122059191Skris}
1221