x509.c revision 160814
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.
855714Skris *
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).
1555714Skris *
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.
2255714Skris *
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 :-).
3755714Skris * 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)"
4055714Skris *
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.
5255714Skris *
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
6455714Skris#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
77160814Ssimon#include <openssl/rsa.h>
78160814Ssimon#endif
79160814Ssimon#ifndef OPENSSL_NO_DSA
80160814Ssimon#include <openssl/dsa.h>
81160814Ssimon#endif
8255714Skris
8355714Skris#undef PROG
8455714Skris#define PROG x509_main
8555714Skris
8655714Skris#undef POSTFIX
8755714Skris#define	POSTFIX	".srl"
8855714Skris#define DEF_DAYS	30
8955714Skris
90160814Ssimonstatic const char *x509_usage[]={
9155714Skris"usage: x509 args\n",
9255714Skris" -inform arg     - input format - default PEM (one of DER, NET or PEM)\n",
9355714Skris" -outform arg    - output format - default PEM (one of DER, NET or PEM)\n",
9455714Skris" -keyform arg    - private key format - default PEM\n",
9555714Skris" -CAform arg     - CA format - default PEM\n",
9655714Skris" -CAkeyform arg  - CA key format - default PEM\n",
9755714Skris" -in arg         - input file - default stdin\n",
9855714Skris" -out arg        - output file - default stdout\n",
9959191Skris" -passin arg     - private key password source\n",
10055714Skris" -serial         - print serial number value\n",
101160814Ssimon" -subject_hash   - print subject hash value\n",
102160814Ssimon" -issuer_hash    - print issuer hash value\n",
103160814Ssimon" -hash           - synonym for -subject_hash\n",
10455714Skris" -subject        - print subject DN\n",
10555714Skris" -issuer         - print issuer DN\n",
10668651Skris" -email          - print email address(es)\n",
10755714Skris" -startdate      - notBefore field\n",
10855714Skris" -enddate        - notAfter field\n",
10959191Skris" -purpose        - print out certificate purposes\n",
11055714Skris" -dates          - both Before and After dates\n",
11155714Skris" -modulus        - print the RSA key modulus\n",
11259191Skris" -pubkey         - output the public key\n",
11355714Skris" -fingerprint    - print the certificate fingerprint\n",
11459191Skris" -alias          - output certificate alias\n",
11555714Skris" -noout          - no certificate output\n",
116109998Smarkm" -ocspid         - print OCSP hash values for the subject name and public key\n",
11759191Skris" -trustout       - output a \"trusted\" certificate\n",
11859191Skris" -clrtrust       - clear all trusted purposes\n",
11959191Skris" -clrreject      - clear all rejected purposes\n",
12059191Skris" -addtrust arg   - trust certificate for a given purpose\n",
12159191Skris" -addreject arg  - reject certificate for a given purpose\n",
12259191Skris" -setalias arg   - set certificate alias\n",
12355714Skris" -days arg       - How long till expiry of a signed certificate - def 30 days\n",
12468651Skris" -checkend arg   - check whether the cert expires in the next arg seconds\n",
12568651Skris"                   exit 1 if so, 0 if not\n",
12655714Skris" -signkey arg    - self sign cert with arg\n",
12755714Skris" -x509toreq      - output a certification request object\n",
12855714Skris" -req            - input is a certificate request, sign and output.\n",
12955714Skris" -CA arg         - set the CA certificate, must be PEM format.\n",
13055714Skris" -CAkey arg      - set the CA key, must be PEM format\n",
13159191Skris"                   missing, it is assumed to be in the CA file.\n",
13255714Skris" -CAcreateserial - create serial number file if it does not exist\n",
133109998Smarkm" -CAserial arg   - serial file\n",
134109998Smarkm" -set_serial     - serial number to use\n",
13555714Skris" -text           - print the certificate in text form\n",
13655714Skris" -C              - print out C code forms\n",
13759191Skris" -md2/-md5/-sha1/-mdc2 - digest to use\n",
13855714Skris" -extfile        - configuration file with X509V3 extensions to add\n",
13959191Skris" -extensions     - section from config file with X509V3 extensions to add\n",
14059191Skris" -clrext         - delete extensions before signing and input certificate\n",
14168651Skris" -nameopt arg    - various certificate name options\n",
142111147Snectar#ifndef OPENSSL_NO_ENGINE
143109998Smarkm" -engine e       - use engine e, possibly a hardware device.\n",
144111147Snectar#endif
145109998Smarkm" -certopt arg    - various certificate text options\n",
14655714SkrisNULL
14755714Skris};
14855714Skris
14955714Skrisstatic int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx);
15059191Skrisstatic int sign (X509 *x, EVP_PKEY *pkey,int days,int clrext, const EVP_MD *digest,
151109998Smarkm						CONF *conf, char *section);
15255714Skrisstatic int x509_certify (X509_STORE *ctx,char *CAfile,const EVP_MD *digest,
15355714Skris			 X509 *x,X509 *xca,EVP_PKEY *pkey,char *serial,
154109998Smarkm			 int create,int days, int clrext, CONF *conf, char *section,
155109998Smarkm						ASN1_INTEGER *sno);
15659191Skrisstatic int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
15755714Skrisstatic int reqfile=0;
15855714Skris
15959191Skrisint MAIN(int, char **);
16059191Skris
16155714Skrisint MAIN(int argc, char **argv)
16255714Skris	{
163109998Smarkm	ENGINE *e = NULL;
16455714Skris	int ret=1;
16555714Skris	X509_REQ *req=NULL;
16655714Skris	X509 *x=NULL,*xca=NULL;
16759191Skris	ASN1_OBJECT *objtmp;
16855714Skris	EVP_PKEY *Upkey=NULL,*CApkey=NULL;
169109998Smarkm	ASN1_INTEGER *sno = NULL;
17055714Skris	int i,num,badops=0;
17155714Skris	BIO *out=NULL;
17255714Skris	BIO *STDout=NULL;
17359191Skris	STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
17455714Skris	int informat,outformat,keyformat,CAformat,CAkeyformat;
17555714Skris	char *infile=NULL,*outfile=NULL,*keyfile=NULL,*CAfile=NULL;
17655714Skris	char *CAkeyfile=NULL,*CAserial=NULL;
17759191Skris	char *alias=NULL;
178160814Ssimon	int text=0,serial=0,subject=0,issuer=0,startdate=0,enddate=0;
179160814Ssimon	int next_serial=0;
180160814Ssimon	int subject_hash=0,issuer_hash=0,ocspid=0;
18168651Skris	int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0,email=0;
18259191Skris	int trustout=0,clrtrust=0,clrreject=0,aliasout=0,clrext=0;
18355714Skris	int C=0;
18459191Skris	int x509req=0,days=DEF_DAYS,modulus=0,pubkey=0;
18559191Skris	int pprint = 0;
186160814Ssimon	const char **pp;
18755714Skris	X509_STORE *ctx=NULL;
18855714Skris	X509_REQ *rq=NULL;
18955714Skris	int fingerprint=0;
19055714Skris	char buf[256];
191160814Ssimon	const EVP_MD *md_alg,*digest=EVP_sha1();
192109998Smarkm	CONF *extconf = NULL;
19359191Skris	char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
19459191Skris	int need_rand = 0;
19568651Skris	int checkend=0,checkoffset=0;
196109998Smarkm	unsigned long nmflag = 0, certflag = 0;
197111147Snectar#ifndef OPENSSL_NO_ENGINE
198109998Smarkm	char *engine=NULL;
199111147Snectar#endif
20055714Skris
20155714Skris	reqfile=0;
20255714Skris
20355714Skris	apps_startup();
20455714Skris
20555714Skris	if (bio_err == NULL)
20655714Skris		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
207109998Smarkm
208109998Smarkm	if (!load_config(bio_err, NULL))
209109998Smarkm		goto end;
21055714Skris	STDout=BIO_new_fp(stdout,BIO_NOCLOSE);
211109998Smarkm#ifdef OPENSSL_SYS_VMS
21268651Skris	{
21368651Skris	BIO *tmpbio = BIO_new(BIO_f_linebuffer());
21468651Skris	STDout = BIO_push(tmpbio, STDout);
21568651Skris	}
21668651Skris#endif
21755714Skris
21855714Skris	informat=FORMAT_PEM;
21955714Skris	outformat=FORMAT_PEM;
22055714Skris	keyformat=FORMAT_PEM;
22155714Skris	CAformat=FORMAT_PEM;
22255714Skris	CAkeyformat=FORMAT_PEM;
22355714Skris
22455714Skris	ctx=X509_STORE_new();
22555714Skris	if (ctx == NULL) goto end;
22655714Skris	X509_STORE_set_verify_cb_func(ctx,callb);
22755714Skris
22855714Skris	argc--;
22955714Skris	argv++;
23055714Skris	num=0;
23155714Skris	while (argc >= 1)
23255714Skris		{
23355714Skris		if 	(strcmp(*argv,"-inform") == 0)
23455714Skris			{
23555714Skris			if (--argc < 1) goto bad;
23655714Skris			informat=str2fmt(*(++argv));
23755714Skris			}
23855714Skris		else if (strcmp(*argv,"-outform") == 0)
23955714Skris			{
24055714Skris			if (--argc < 1) goto bad;
24155714Skris			outformat=str2fmt(*(++argv));
24255714Skris			}
24355714Skris		else if (strcmp(*argv,"-keyform") == 0)
24455714Skris			{
24555714Skris			if (--argc < 1) goto bad;
24655714Skris			keyformat=str2fmt(*(++argv));
24755714Skris			}
24855714Skris		else if (strcmp(*argv,"-req") == 0)
24959191Skris			{
25055714Skris			reqfile=1;
25159191Skris			need_rand = 1;
25259191Skris			}
25355714Skris		else if (strcmp(*argv,"-CAform") == 0)
25455714Skris			{
25555714Skris			if (--argc < 1) goto bad;
25655714Skris			CAformat=str2fmt(*(++argv));
25755714Skris			}
25855714Skris		else if (strcmp(*argv,"-CAkeyform") == 0)
25955714Skris			{
26055714Skris			if (--argc < 1) goto bad;
261100936Snectar			CAkeyformat=str2fmt(*(++argv));
26255714Skris			}
26355714Skris		else if (strcmp(*argv,"-days") == 0)
26455714Skris			{
26555714Skris			if (--argc < 1) goto bad;
26655714Skris			days=atoi(*(++argv));
26755714Skris			if (days == 0)
26855714Skris				{
26955714Skris				BIO_printf(STDout,"bad number of days\n");
27055714Skris				goto bad;
27155714Skris				}
27255714Skris			}
27359191Skris		else if (strcmp(*argv,"-passin") == 0)
27459191Skris			{
27559191Skris			if (--argc < 1) goto bad;
27659191Skris			passargin= *(++argv);
27759191Skris			}
27855714Skris		else if (strcmp(*argv,"-extfile") == 0)
27955714Skris			{
28055714Skris			if (--argc < 1) goto bad;
28155714Skris			extfile= *(++argv);
28255714Skris			}
28359191Skris		else if (strcmp(*argv,"-extensions") == 0)
28459191Skris			{
28559191Skris			if (--argc < 1) goto bad;
28659191Skris			extsect= *(++argv);
28759191Skris			}
28855714Skris		else if (strcmp(*argv,"-in") == 0)
28955714Skris			{
29055714Skris			if (--argc < 1) goto bad;
29155714Skris			infile= *(++argv);
29255714Skris			}
29355714Skris		else if (strcmp(*argv,"-out") == 0)
29455714Skris			{
29555714Skris			if (--argc < 1) goto bad;
29655714Skris			outfile= *(++argv);
29755714Skris			}
29855714Skris		else if (strcmp(*argv,"-signkey") == 0)
29955714Skris			{
30055714Skris			if (--argc < 1) goto bad;
30155714Skris			keyfile= *(++argv);
30255714Skris			sign_flag= ++num;
30359191Skris			need_rand = 1;
30455714Skris			}
30555714Skris		else if (strcmp(*argv,"-CA") == 0)
30655714Skris			{
30755714Skris			if (--argc < 1) goto bad;
30855714Skris			CAfile= *(++argv);
30955714Skris			CA_flag= ++num;
31059191Skris			need_rand = 1;
31155714Skris			}
31255714Skris		else if (strcmp(*argv,"-CAkey") == 0)
31355714Skris			{
31455714Skris			if (--argc < 1) goto bad;
31555714Skris			CAkeyfile= *(++argv);
31655714Skris			}
31755714Skris		else if (strcmp(*argv,"-CAserial") == 0)
31855714Skris			{
31955714Skris			if (--argc < 1) goto bad;
32055714Skris			CAserial= *(++argv);
32155714Skris			}
322109998Smarkm		else if (strcmp(*argv,"-set_serial") == 0)
323109998Smarkm			{
324109998Smarkm			if (--argc < 1) goto bad;
325109998Smarkm			if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
326109998Smarkm				goto bad;
327109998Smarkm			}
32859191Skris		else if (strcmp(*argv,"-addtrust") == 0)
32959191Skris			{
33059191Skris			if (--argc < 1) goto bad;
33168651Skris			if (!(objtmp = OBJ_txt2obj(*(++argv), 0)))
33268651Skris				{
33359191Skris				BIO_printf(bio_err,
33459191Skris					"Invalid trust object value %s\n", *argv);
33559191Skris				goto bad;
33668651Skris				}
33768651Skris			if (!trust) trust = sk_ASN1_OBJECT_new_null();
33859191Skris			sk_ASN1_OBJECT_push(trust, objtmp);
33959191Skris			trustout = 1;
34059191Skris			}
34159191Skris		else if (strcmp(*argv,"-addreject") == 0)
34259191Skris			{
34359191Skris			if (--argc < 1) goto bad;
34468651Skris			if (!(objtmp = OBJ_txt2obj(*(++argv), 0)))
34568651Skris				{
34659191Skris				BIO_printf(bio_err,
34759191Skris					"Invalid reject object value %s\n", *argv);
34859191Skris				goto bad;
34968651Skris				}
35068651Skris			if (!reject) reject = sk_ASN1_OBJECT_new_null();
35159191Skris			sk_ASN1_OBJECT_push(reject, objtmp);
35259191Skris			trustout = 1;
35359191Skris			}
35459191Skris		else if (strcmp(*argv,"-setalias") == 0)
35559191Skris			{
35659191Skris			if (--argc < 1) goto bad;
35759191Skris			alias= *(++argv);
35859191Skris			trustout = 1;
35959191Skris			}
360109998Smarkm		else if (strcmp(*argv,"-certopt") == 0)
361109998Smarkm			{
362109998Smarkm			if (--argc < 1) goto bad;
363109998Smarkm			if (!set_cert_ex(&certflag, *(++argv))) goto bad;
364109998Smarkm			}
36568651Skris		else if (strcmp(*argv,"-nameopt") == 0)
36668651Skris			{
36768651Skris			if (--argc < 1) goto bad;
36868651Skris			if (!set_name_ex(&nmflag, *(++argv))) goto bad;
36968651Skris			}
370111147Snectar#ifndef OPENSSL_NO_ENGINE
371109998Smarkm		else if (strcmp(*argv,"-engine") == 0)
372109998Smarkm			{
373109998Smarkm			if (--argc < 1) goto bad;
374109998Smarkm			engine= *(++argv);
375109998Smarkm			}
376111147Snectar#endif
37755714Skris		else if (strcmp(*argv,"-C") == 0)
37855714Skris			C= ++num;
37968651Skris		else if (strcmp(*argv,"-email") == 0)
38068651Skris			email= ++num;
38155714Skris		else if (strcmp(*argv,"-serial") == 0)
38255714Skris			serial= ++num;
383142425Snectar		else if (strcmp(*argv,"-next_serial") == 0)
384142425Snectar			next_serial= ++num;
38555714Skris		else if (strcmp(*argv,"-modulus") == 0)
38655714Skris			modulus= ++num;
38759191Skris		else if (strcmp(*argv,"-pubkey") == 0)
38859191Skris			pubkey= ++num;
38955714Skris		else if (strcmp(*argv,"-x509toreq") == 0)
39055714Skris			x509req= ++num;
39155714Skris		else if (strcmp(*argv,"-text") == 0)
39255714Skris			text= ++num;
393160814Ssimon		else if (strcmp(*argv,"-hash") == 0
394160814Ssimon			|| strcmp(*argv,"-subject_hash") == 0)
395160814Ssimon			subject_hash= ++num;
396160814Ssimon		else if (strcmp(*argv,"-issuer_hash") == 0)
397160814Ssimon			issuer_hash= ++num;
39855714Skris		else if (strcmp(*argv,"-subject") == 0)
39955714Skris			subject= ++num;
40055714Skris		else if (strcmp(*argv,"-issuer") == 0)
40155714Skris			issuer= ++num;
40255714Skris		else if (strcmp(*argv,"-fingerprint") == 0)
40355714Skris			fingerprint= ++num;
40455714Skris		else if (strcmp(*argv,"-dates") == 0)
40555714Skris			{
40655714Skris			startdate= ++num;
40755714Skris			enddate= ++num;
40855714Skris			}
40959191Skris		else if (strcmp(*argv,"-purpose") == 0)
41059191Skris			pprint= ++num;
41155714Skris		else if (strcmp(*argv,"-startdate") == 0)
41255714Skris			startdate= ++num;
41355714Skris		else if (strcmp(*argv,"-enddate") == 0)
41455714Skris			enddate= ++num;
41568651Skris		else if (strcmp(*argv,"-checkend") == 0)
41668651Skris			{
41768651Skris			if (--argc < 1) goto bad;
41868651Skris			checkoffset=atoi(*(++argv));
41968651Skris			checkend=1;
42068651Skris			}
42155714Skris		else if (strcmp(*argv,"-noout") == 0)
42255714Skris			noout= ++num;
42359191Skris		else if (strcmp(*argv,"-trustout") == 0)
42459191Skris			trustout= 1;
42559191Skris		else if (strcmp(*argv,"-clrtrust") == 0)
42659191Skris			clrtrust= ++num;
42759191Skris		else if (strcmp(*argv,"-clrreject") == 0)
42859191Skris			clrreject= ++num;
42959191Skris		else if (strcmp(*argv,"-alias") == 0)
43059191Skris			aliasout= ++num;
43155714Skris		else if (strcmp(*argv,"-CAcreateserial") == 0)
43255714Skris			CA_createserial= ++num;
43359191Skris		else if (strcmp(*argv,"-clrext") == 0)
43459191Skris			clrext = 1;
43559191Skris#if 1 /* stay backwards-compatible with 0.9.5; this should go away soon */
43659191Skris		else if (strcmp(*argv,"-crlext") == 0)
43755714Skris			{
43859191Skris			BIO_printf(bio_err,"use -clrext instead of -crlext\n");
43959191Skris			clrext = 1;
44059191Skris			}
44159191Skris#endif
442109998Smarkm		else if (strcmp(*argv,"-ocspid") == 0)
443109998Smarkm			ocspid= ++num;
44459191Skris		else if ((md_alg=EVP_get_digestbyname(*argv + 1)))
44559191Skris			{
44655714Skris			/* ok */
44755714Skris			digest=md_alg;
44855714Skris			}
44955714Skris		else
45055714Skris			{
45155714Skris			BIO_printf(bio_err,"unknown option %s\n",*argv);
45255714Skris			badops=1;
45355714Skris			break;
45455714Skris			}
45555714Skris		argc--;
45655714Skris		argv++;
45755714Skris		}
45855714Skris
45955714Skris	if (badops)
46055714Skris		{
46155714Skrisbad:
46255714Skris		for (pp=x509_usage; (*pp != NULL); pp++)
463109998Smarkm			BIO_printf(bio_err,"%s",*pp);
46455714Skris		goto end;
46555714Skris		}
46655714Skris
467111147Snectar#ifndef OPENSSL_NO_ENGINE
468109998Smarkm        e = setup_engine(bio_err, engine, 0);
469111147Snectar#endif
470109998Smarkm
47159191Skris	if (need_rand)
47259191Skris		app_RAND_load_file(NULL, bio_err, 0);
47359191Skris
47455714Skris	ERR_load_crypto_strings();
47555714Skris
47668651Skris	if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
47768651Skris		{
47859191Skris		BIO_printf(bio_err, "Error getting password\n");
47959191Skris		goto end;
48068651Skris		}
48159191Skris
48255714Skris	if (!X509_STORE_set_default_paths(ctx))
48355714Skris		{
48455714Skris		ERR_print_errors(bio_err);
48555714Skris		goto end;
48655714Skris		}
48755714Skris
48855714Skris	if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM))
48955714Skris		{ CAkeyfile=CAfile; }
49055714Skris	else if ((CA_flag) && (CAkeyfile == NULL))
49155714Skris		{
49255714Skris		BIO_printf(bio_err,"need to specify a CAkey if using the CA command\n");
49355714Skris		goto end;
49455714Skris		}
49555714Skris
49668651Skris	if (extfile)
49768651Skris		{
498109998Smarkm		long errorline = -1;
49955714Skris		X509V3_CTX ctx2;
500109998Smarkm		extconf = NCONF_new(NULL);
501109998Smarkm		if (!NCONF_load(extconf, extfile,&errorline))
50268651Skris			{
50355714Skris			if (errorline <= 0)
50455714Skris				BIO_printf(bio_err,
50555714Skris					"error loading the config file '%s'\n",
50655714Skris								extfile);
50755714Skris                	else
50855714Skris                        	BIO_printf(bio_err,
50955714Skris				       "error on line %ld of config file '%s'\n"
51055714Skris							,errorline,extfile);
51155714Skris			goto end;
51268651Skris			}
513109998Smarkm		if (!extsect)
514109998Smarkm			{
515109998Smarkm			extsect = NCONF_get_string(extconf, "default", "extensions");
516109998Smarkm			if (!extsect)
517109998Smarkm				{
518109998Smarkm				ERR_clear_error();
519109998Smarkm				extsect = "default";
520109998Smarkm				}
521109998Smarkm			}
52255714Skris		X509V3_set_ctx_test(&ctx2);
523109998Smarkm		X509V3_set_nconf(&ctx2, extconf);
524109998Smarkm		if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL))
52568651Skris			{
52655714Skris			BIO_printf(bio_err,
52755714Skris				"Error Loading extension section %s\n",
52855714Skris								 extsect);
52955714Skris			ERR_print_errors(bio_err);
53055714Skris			goto end;
53168651Skris			}
53268651Skris		}
53355714Skris
53455714Skris
53555714Skris	if (reqfile)
53655714Skris		{
53755714Skris		EVP_PKEY *pkey;
53855714Skris		X509_CINF *ci;
53955714Skris		BIO *in;
54055714Skris
54155714Skris		if (!sign_flag && !CA_flag)
54255714Skris			{
54355714Skris			BIO_printf(bio_err,"We need a private key to sign with\n");
54455714Skris			goto end;
54555714Skris			}
54655714Skris		in=BIO_new(BIO_s_file());
54755714Skris		if (in == NULL)
54855714Skris			{
54955714Skris			ERR_print_errors(bio_err);
55055714Skris			goto end;
55155714Skris			}
55255714Skris
55355714Skris		if (infile == NULL)
55455714Skris			BIO_set_fp(in,stdin,BIO_NOCLOSE|BIO_FP_TEXT);
55555714Skris		else
55655714Skris			{
55755714Skris			if (BIO_read_filename(in,infile) <= 0)
55855714Skris				{
55955714Skris				perror(infile);
56068651Skris				BIO_free(in);
56155714Skris				goto end;
56255714Skris				}
56355714Skris			}
56455714Skris		req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
56555714Skris		BIO_free(in);
56655714Skris
56768651Skris		if (req == NULL)
56868651Skris			{
56968651Skris			ERR_print_errors(bio_err);
57068651Skris			goto end;
57168651Skris			}
57255714Skris
57355714Skris		if (	(req->req_info == NULL) ||
57455714Skris			(req->req_info->pubkey == NULL) ||
57555714Skris			(req->req_info->pubkey->public_key == NULL) ||
57655714Skris			(req->req_info->pubkey->public_key->data == NULL))
57755714Skris			{
57855714Skris			BIO_printf(bio_err,"The certificate request appears to corrupted\n");
57955714Skris			BIO_printf(bio_err,"It does not contain a public key\n");
58055714Skris			goto end;
58155714Skris			}
58255714Skris		if ((pkey=X509_REQ_get_pubkey(req)) == NULL)
58355714Skris	                {
58455714Skris	                BIO_printf(bio_err,"error unpacking public key\n");
58555714Skris	                goto end;
58655714Skris	                }
58755714Skris		i=X509_REQ_verify(req,pkey);
58855714Skris		EVP_PKEY_free(pkey);
58955714Skris		if (i < 0)
59055714Skris			{
59155714Skris			BIO_printf(bio_err,"Signature verification error\n");
59255714Skris			ERR_print_errors(bio_err);
59355714Skris			goto end;
59455714Skris			}
59555714Skris	        if (i == 0)
59655714Skris			{
59755714Skris			BIO_printf(bio_err,"Signature did not match the certificate request\n");
59855714Skris			goto end;
59955714Skris			}
60055714Skris		else
60155714Skris			BIO_printf(bio_err,"Signature ok\n");
60255714Skris
60368651Skris		print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag);
60468651Skris
60555714Skris		if ((x=X509_new()) == NULL) goto end;
60655714Skris		ci=x->cert_info;
60755714Skris
608142425Snectar		if (sno == NULL)
609109998Smarkm			{
610142425Snectar			sno = ASN1_INTEGER_new();
611142425Snectar			if (!sno || !rand_serial(NULL, sno))
612109998Smarkm				goto end;
613160814Ssimon			if (!X509_set_serialNumber(x, sno))
614160814Ssimon				goto end;
615160814Ssimon			ASN1_INTEGER_free(sno);
616160814Ssimon			sno = NULL;
617109998Smarkm			}
618160814Ssimon		else if (!X509_set_serialNumber(x, sno))
619142425Snectar			goto end;
620142425Snectar
62155714Skris		if (!X509_set_issuer_name(x,req->req_info->subject)) goto end;
62255714Skris		if (!X509_set_subject_name(x,req->req_info->subject)) goto end;
62355714Skris
62455714Skris		X509_gmtime_adj(X509_get_notBefore(x),0);
62555714Skris	        X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days);
62655714Skris
62755714Skris		pkey = X509_REQ_get_pubkey(req);
62855714Skris		X509_set_pubkey(x,pkey);
62955714Skris		EVP_PKEY_free(pkey);
63055714Skris		}
63155714Skris	else
632109998Smarkm		x=load_cert(bio_err,infile,informat,NULL,e,"Certificate");
63355714Skris
63455714Skris	if (x == NULL) goto end;
63555714Skris	if (CA_flag)
63655714Skris		{
637109998Smarkm		xca=load_cert(bio_err,CAfile,CAformat,NULL,e,"CA Certificate");
63855714Skris		if (xca == NULL) goto end;
63955714Skris		}
64055714Skris
641142425Snectar	if (!noout || text || next_serial)
64255714Skris		{
64355714Skris		OBJ_create("2.99999.3",
64455714Skris			"SET.ex3","SET x509v3 extension 3");
64555714Skris
64655714Skris		out=BIO_new(BIO_s_file());
64755714Skris		if (out == NULL)
64855714Skris			{
64955714Skris			ERR_print_errors(bio_err);
65055714Skris			goto end;
65155714Skris			}
65255714Skris		if (outfile == NULL)
65368651Skris			{
65455714Skris			BIO_set_fp(out,stdout,BIO_NOCLOSE);
655109998Smarkm#ifdef OPENSSL_SYS_VMS
65668651Skris			{
65768651Skris			BIO *tmpbio = BIO_new(BIO_f_linebuffer());
65868651Skris			out = BIO_push(tmpbio, out);
65968651Skris			}
66068651Skris#endif
66168651Skris			}
66255714Skris		else
66355714Skris			{
66455714Skris			if (BIO_write_filename(out,outfile) <= 0)
66555714Skris				{
66655714Skris				perror(outfile);
66755714Skris				goto end;
66855714Skris				}
66955714Skris			}
67055714Skris		}
67155714Skris
67268651Skris	if (alias) X509_alias_set1(x, (unsigned char *)alias, -1);
67359191Skris
67468651Skris	if (clrtrust) X509_trust_clear(x);
67568651Skris	if (clrreject) X509_reject_clear(x);
67659191Skris
67768651Skris	if (trust)
67868651Skris		{
67968651Skris		for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++)
68068651Skris			{
68159191Skris			objtmp = sk_ASN1_OBJECT_value(trust, i);
68259191Skris			X509_add1_trust_object(x, objtmp);
68368651Skris			}
68459191Skris		}
68559191Skris
68668651Skris	if (reject)
68768651Skris		{
68868651Skris		for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++)
68968651Skris			{
69059191Skris			objtmp = sk_ASN1_OBJECT_value(reject, i);
69159191Skris			X509_add1_reject_object(x, objtmp);
69268651Skris			}
69359191Skris		}
69459191Skris
69555714Skris	if (num)
69655714Skris		{
69755714Skris		for (i=1; i<=num; i++)
69855714Skris			{
69955714Skris			if (issuer == i)
70055714Skris				{
70168651Skris				print_name(STDout, "issuer= ",
70268651Skris					X509_get_issuer_name(x), nmflag);
70355714Skris				}
70455714Skris			else if (subject == i)
70555714Skris				{
70668651Skris				print_name(STDout, "subject= ",
70768651Skris					X509_get_subject_name(x), nmflag);
70855714Skris				}
70955714Skris			else if (serial == i)
71055714Skris				{
71155714Skris				BIO_printf(STDout,"serial=");
712160814Ssimon				i2a_ASN1_INTEGER(STDout,
713160814Ssimon					X509_get_serialNumber(x));
71455714Skris				BIO_printf(STDout,"\n");
71555714Skris				}
716142425Snectar			else if (next_serial == i)
717142425Snectar				{
718142425Snectar				BIGNUM *bnser;
719142425Snectar				ASN1_INTEGER *ser;
720142425Snectar				ser = X509_get_serialNumber(x);
721142425Snectar				bnser = ASN1_INTEGER_to_BN(ser, NULL);
722142425Snectar				if (!bnser)
723142425Snectar					goto end;
724142425Snectar				if (!BN_add_word(bnser, 1))
725142425Snectar					goto end;
726142425Snectar				ser = BN_to_ASN1_INTEGER(bnser, NULL);
727142425Snectar				if (!ser)
728142425Snectar					goto end;
729142425Snectar				BN_free(bnser);
730142425Snectar				i2a_ASN1_INTEGER(out, ser);
731142425Snectar				ASN1_INTEGER_free(ser);
732142425Snectar				BIO_puts(out, "\n");
733142425Snectar				}
73468651Skris			else if (email == i)
73568651Skris				{
73668651Skris				int j;
73768651Skris				STACK *emlst;
73868651Skris				emlst = X509_get1_email(x);
73968651Skris				for (j = 0; j < sk_num(emlst); j++)
74068651Skris					BIO_printf(STDout, "%s\n", sk_value(emlst, j));
74168651Skris				X509_email_free(emlst);
74268651Skris				}
74359191Skris			else if (aliasout == i)
74459191Skris				{
74559191Skris				unsigned char *alstr;
74659191Skris				alstr = X509_alias_get0(x, NULL);
74768651Skris				if (alstr) BIO_printf(STDout,"%s\n", alstr);
74859191Skris				else BIO_puts(STDout,"<No Alias>\n");
74959191Skris				}
750160814Ssimon			else if (subject_hash == i)
75155714Skris				{
75255714Skris				BIO_printf(STDout,"%08lx\n",X509_subject_name_hash(x));
75355714Skris				}
754160814Ssimon			else if (issuer_hash == i)
755160814Ssimon				{
756160814Ssimon				BIO_printf(STDout,"%08lx\n",X509_issuer_name_hash(x));
757160814Ssimon				}
75859191Skris			else if (pprint == i)
75959191Skris				{
76059191Skris				X509_PURPOSE *ptmp;
76159191Skris				int j;
76259191Skris				BIO_printf(STDout, "Certificate purposes:\n");
76368651Skris				for (j = 0; j < X509_PURPOSE_get_count(); j++)
76459191Skris					{
76559191Skris					ptmp = X509_PURPOSE_get0(j);
76659191Skris					purpose_print(STDout, x, ptmp);
76759191Skris					}
76859191Skris				}
76955714Skris			else
77055714Skris				if (modulus == i)
77155714Skris				{
77255714Skris				EVP_PKEY *pkey;
77355714Skris
77455714Skris				pkey=X509_get_pubkey(x);
77555714Skris				if (pkey == NULL)
77655714Skris					{
77755714Skris					BIO_printf(bio_err,"Modulus=unavailable\n");
77855714Skris					ERR_print_errors(bio_err);
77955714Skris					goto end;
78055714Skris					}
78155714Skris				BIO_printf(STDout,"Modulus=");
782109998Smarkm#ifndef OPENSSL_NO_RSA
78355714Skris				if (pkey->type == EVP_PKEY_RSA)
78455714Skris					BN_print(STDout,pkey->pkey.rsa->n);
78555714Skris				else
78655714Skris#endif
787109998Smarkm#ifndef OPENSSL_NO_DSA
78855714Skris				if (pkey->type == EVP_PKEY_DSA)
78955714Skris					BN_print(STDout,pkey->pkey.dsa->pub_key);
79055714Skris				else
79155714Skris#endif
79255714Skris					BIO_printf(STDout,"Wrong Algorithm type");
79355714Skris				BIO_printf(STDout,"\n");
79455714Skris				EVP_PKEY_free(pkey);
79555714Skris				}
79655714Skris			else
79759191Skris				if (pubkey == i)
79859191Skris				{
79959191Skris				EVP_PKEY *pkey;
80059191Skris
80159191Skris				pkey=X509_get_pubkey(x);
80259191Skris				if (pkey == NULL)
80359191Skris					{
80459191Skris					BIO_printf(bio_err,"Error getting public key\n");
80559191Skris					ERR_print_errors(bio_err);
80659191Skris					goto end;
80759191Skris					}
80859191Skris				PEM_write_bio_PUBKEY(STDout, pkey);
80959191Skris				EVP_PKEY_free(pkey);
81059191Skris				}
81159191Skris			else
81255714Skris				if (C == i)
81355714Skris				{
81455714Skris				unsigned char *d;
81555714Skris				char *m;
81655714Skris				int y,z;
81755714Skris
81855714Skris				X509_NAME_oneline(X509_get_subject_name(x),
819109998Smarkm					buf,sizeof buf);
82055714Skris				BIO_printf(STDout,"/* subject:%s */\n",buf);
82155714Skris				m=X509_NAME_oneline(
822109998Smarkm					X509_get_issuer_name(x),buf,
823109998Smarkm					sizeof buf);
82455714Skris				BIO_printf(STDout,"/* issuer :%s */\n",buf);
82555714Skris
82655714Skris				z=i2d_X509(x,NULL);
82768651Skris				m=OPENSSL_malloc(z);
82855714Skris
82955714Skris				d=(unsigned char *)m;
83055714Skris				z=i2d_X509_NAME(X509_get_subject_name(x),&d);
83155714Skris				BIO_printf(STDout,"unsigned char XXX_subject_name[%d]={\n",z);
83255714Skris				d=(unsigned char *)m;
83355714Skris				for (y=0; y<z; y++)
83455714Skris					{
83555714Skris					BIO_printf(STDout,"0x%02X,",d[y]);
83655714Skris					if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n");
83755714Skris					}
83855714Skris				if (y%16 != 0) BIO_printf(STDout,"\n");
83955714Skris				BIO_printf(STDout,"};\n");
84055714Skris
84155714Skris				z=i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x),&d);
84255714Skris				BIO_printf(STDout,"unsigned char XXX_public_key[%d]={\n",z);
84355714Skris				d=(unsigned char *)m;
84455714Skris				for (y=0; y<z; y++)
84555714Skris					{
84655714Skris					BIO_printf(STDout,"0x%02X,",d[y]);
84755714Skris					if ((y & 0x0f) == 0x0f)
84855714Skris						BIO_printf(STDout,"\n");
84955714Skris					}
85055714Skris				if (y%16 != 0) BIO_printf(STDout,"\n");
85155714Skris				BIO_printf(STDout,"};\n");
85255714Skris
85355714Skris				z=i2d_X509(x,&d);
85455714Skris				BIO_printf(STDout,"unsigned char XXX_certificate[%d]={\n",z);
85555714Skris				d=(unsigned char *)m;
85655714Skris				for (y=0; y<z; y++)
85755714Skris					{
85855714Skris					BIO_printf(STDout,"0x%02X,",d[y]);
85955714Skris					if ((y & 0x0f) == 0x0f)
86055714Skris						BIO_printf(STDout,"\n");
86155714Skris					}
86255714Skris				if (y%16 != 0) BIO_printf(STDout,"\n");
86355714Skris				BIO_printf(STDout,"};\n");
86455714Skris
86568651Skris				OPENSSL_free(m);
86655714Skris				}
86755714Skris			else if (text == i)
86855714Skris				{
869109998Smarkm				X509_print_ex(out,x,nmflag, certflag);
87055714Skris				}
87155714Skris			else if (startdate == i)
87255714Skris				{
87355714Skris				BIO_puts(STDout,"notBefore=");
87455714Skris				ASN1_TIME_print(STDout,X509_get_notBefore(x));
87555714Skris				BIO_puts(STDout,"\n");
87655714Skris				}
87755714Skris			else if (enddate == i)
87855714Skris				{
87955714Skris				BIO_puts(STDout,"notAfter=");
88055714Skris				ASN1_TIME_print(STDout,X509_get_notAfter(x));
88155714Skris				BIO_puts(STDout,"\n");
88255714Skris				}
88355714Skris			else if (fingerprint == i)
88455714Skris				{
88555714Skris				int j;
88655714Skris				unsigned int n;
88755714Skris				unsigned char md[EVP_MAX_MD_SIZE];
88855714Skris
88959191Skris				if (!X509_digest(x,digest,md,&n))
89055714Skris					{
89155714Skris					BIO_printf(bio_err,"out of memory\n");
89255714Skris					goto end;
89355714Skris					}
89459191Skris				BIO_printf(STDout,"%s Fingerprint=",
89559191Skris						OBJ_nid2sn(EVP_MD_type(digest)));
89655714Skris				for (j=0; j<(int)n; j++)
89755714Skris					{
89855714Skris					BIO_printf(STDout,"%02X%c",md[j],
89955714Skris						(j+1 == (int)n)
90055714Skris						?'\n':':');
90155714Skris					}
90255714Skris				}
90355714Skris
90455714Skris			/* should be in the library */
90555714Skris			else if ((sign_flag == i) && (x509req == 0))
90655714Skris				{
90755714Skris				BIO_printf(bio_err,"Getting Private key\n");
90855714Skris				if (Upkey == NULL)
90955714Skris					{
91068651Skris					Upkey=load_key(bio_err,
911109998Smarkm						keyfile, keyformat, 0,
912109998Smarkm						passin, e, "Private key");
91355714Skris					if (Upkey == NULL) goto end;
91455714Skris					}
915109998Smarkm#ifndef OPENSSL_NO_DSA
91655714Skris		                if (Upkey->type == EVP_PKEY_DSA)
91755714Skris		                        digest=EVP_dss1();
91855714Skris#endif
919160814Ssimon#ifndef OPENSSL_NO_ECDSA
920160814Ssimon				if (Upkey->type == EVP_PKEY_EC)
921160814Ssimon					digest=EVP_ecdsa();
922160814Ssimon#endif
92355714Skris
92459191Skris				assert(need_rand);
92559191Skris				if (!sign(x,Upkey,days,clrext,digest,
92655714Skris						 extconf, extsect)) goto end;
92755714Skris				}
92855714Skris			else if (CA_flag == i)
92955714Skris				{
93055714Skris				BIO_printf(bio_err,"Getting CA Private Key\n");
93155714Skris				if (CAkeyfile != NULL)
93255714Skris					{
93368651Skris					CApkey=load_key(bio_err,
934109998Smarkm						CAkeyfile, CAkeyformat,
935109998Smarkm						0, passin, e,
936109998Smarkm						"CA Private Key");
93755714Skris					if (CApkey == NULL) goto end;
93855714Skris					}
939109998Smarkm#ifndef OPENSSL_NO_DSA
94055714Skris		                if (CApkey->type == EVP_PKEY_DSA)
94155714Skris		                        digest=EVP_dss1();
94255714Skris#endif
943160814Ssimon#ifndef OPENSSL_NO_ECDSA
944160814Ssimon				if (CApkey->type == EVP_PKEY_EC)
945160814Ssimon					digest = EVP_ecdsa();
946160814Ssimon#endif
94755714Skris
94859191Skris				assert(need_rand);
94955714Skris				if (!x509_certify(ctx,CAfile,digest,x,xca,
95059191Skris					CApkey, CAserial,CA_createserial,days, clrext,
951109998Smarkm					extconf, extsect, sno))
95255714Skris					goto end;
95355714Skris				}
95455714Skris			else if (x509req == i)
95555714Skris				{
95655714Skris				EVP_PKEY *pk;
95755714Skris
95855714Skris				BIO_printf(bio_err,"Getting request Private Key\n");
95955714Skris				if (keyfile == NULL)
96055714Skris					{
96155714Skris					BIO_printf(bio_err,"no request key file specified\n");
96255714Skris					goto end;
96355714Skris					}
96455714Skris				else
96555714Skris					{
96668651Skris					pk=load_key(bio_err,
967109998Smarkm						keyfile, FORMAT_PEM, 0,
968109998Smarkm						passin, e, "request key");
96955714Skris					if (pk == NULL) goto end;
97055714Skris					}
97155714Skris
97255714Skris				BIO_printf(bio_err,"Generating certificate request\n");
97355714Skris
974109998Smarkm#ifndef OPENSSL_NO_DSA
97559191Skris		                if (pk->type == EVP_PKEY_DSA)
97659191Skris		                        digest=EVP_dss1();
97776866Skris#endif
978160814Ssimon#ifndef OPENSSL_NO_ECDSA
979160814Ssimon				if (pk->type == EVP_PKEY_EC)
980160814Ssimon					digest=EVP_ecdsa();
981160814Ssimon#endif
98259191Skris
98359191Skris				rq=X509_to_X509_REQ(x,pk,digest);
98455714Skris				EVP_PKEY_free(pk);
98555714Skris				if (rq == NULL)
98655714Skris					{
98755714Skris					ERR_print_errors(bio_err);
98855714Skris					goto end;
98955714Skris					}
99055714Skris				if (!noout)
99155714Skris					{
99255714Skris					X509_REQ_print(out,rq);
99355714Skris					PEM_write_bio_X509_REQ(out,rq);
99455714Skris					}
99555714Skris				noout=1;
99655714Skris				}
997109998Smarkm			else if (ocspid == i)
998109998Smarkm				{
999109998Smarkm				X509_ocspid_print(out, x);
1000109998Smarkm				}
100155714Skris			}
100255714Skris		}
100355714Skris
100468651Skris	if (checkend)
100568651Skris		{
1006160814Ssimon		time_t tcheck=time(NULL) + checkoffset;
100768651Skris
1008160814Ssimon		if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0)
100968651Skris			{
101068651Skris			BIO_printf(out,"Certificate will expire\n");
101168651Skris			ret=1;
101268651Skris			}
101368651Skris		else
101468651Skris			{
101568651Skris			BIO_printf(out,"Certificate will not expire\n");
101668651Skris			ret=0;
101768651Skris			}
101868651Skris		goto end;
101968651Skris		}
102068651Skris
102155714Skris	if (noout)
102255714Skris		{
102355714Skris		ret=0;
102455714Skris		goto end;
102555714Skris		}
102655714Skris
102755714Skris	if 	(outformat == FORMAT_ASN1)
102855714Skris		i=i2d_X509_bio(out,x);
102968651Skris	else if (outformat == FORMAT_PEM)
103068651Skris		{
103168651Skris		if (trustout) i=PEM_write_bio_X509_AUX(out,x);
103259191Skris		else i=PEM_write_bio_X509(out,x);
103368651Skris		}
103468651Skris	else if (outformat == FORMAT_NETSCAPE)
103555714Skris		{
103655714Skris		ASN1_HEADER ah;
103755714Skris		ASN1_OCTET_STRING os;
103855714Skris
103968651Skris		os.data=(unsigned char *)NETSCAPE_CERT_HDR;
104068651Skris		os.length=strlen(NETSCAPE_CERT_HDR);
104155714Skris		ah.header= &os;
104255714Skris		ah.data=(char *)x;
104355714Skris		ah.meth=X509_asn1_meth();
104455714Skris
1045160814Ssimon		i=ASN1_i2d_bio_of(ASN1_HEADER,i2d_ASN1_HEADER,out,&ah);
104655714Skris		}
104755714Skris	else	{
104855714Skris		BIO_printf(bio_err,"bad output format specified for outfile\n");
104955714Skris		goto end;
105055714Skris		}
105168651Skris	if (!i)
105268651Skris		{
105355714Skris		BIO_printf(bio_err,"unable to write certificate\n");
105455714Skris		ERR_print_errors(bio_err);
105555714Skris		goto end;
105655714Skris		}
105755714Skris	ret=0;
105855714Skrisend:
105959191Skris	if (need_rand)
106059191Skris		app_RAND_write_file(NULL, bio_err);
106155714Skris	OBJ_cleanup();
1062109998Smarkm	NCONF_free(extconf);
106368651Skris	BIO_free_all(out);
106468651Skris	BIO_free_all(STDout);
106555714Skris	X509_STORE_free(ctx);
106655714Skris	X509_REQ_free(req);
106755714Skris	X509_free(x);
106855714Skris	X509_free(xca);
106955714Skris	EVP_PKEY_free(Upkey);
107055714Skris	EVP_PKEY_free(CApkey);
107155714Skris	X509_REQ_free(rq);
1072109998Smarkm	ASN1_INTEGER_free(sno);
107359191Skris	sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
107459191Skris	sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
107568651Skris	if (passin) OPENSSL_free(passin);
1076109998Smarkm	apps_shutdown();
1077109998Smarkm	OPENSSL_EXIT(ret);
107855714Skris	}
107955714Skris
1080127128Snectarstatic ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile, int create)
108155714Skris	{
1082109998Smarkm	char *buf = NULL, *p;
1083127128Snectar	ASN1_INTEGER *bs = NULL;
1084109998Smarkm	BIGNUM *serial = NULL;
1085127128Snectar	size_t len;
108655714Skris
1087127128Snectar	len = ((serialfile == NULL)
1088127128Snectar		?(strlen(CAfile)+strlen(POSTFIX)+1)
1089127128Snectar		:(strlen(serialfile)))+1;
1090127128Snectar	buf=OPENSSL_malloc(len);
109155714Skris	if (buf == NULL) { BIO_printf(bio_err,"out of mem\n"); goto end; }
109255714Skris	if (serialfile == NULL)
109355714Skris		{
1094127128Snectar		BUF_strlcpy(buf,CAfile,len);
109555714Skris		for (p=buf; *p; p++)
109655714Skris			if (*p == '.')
109755714Skris				{
109855714Skris				*p='\0';
109955714Skris				break;
110055714Skris				}
1101127128Snectar		BUF_strlcat(buf,POSTFIX,len);
110255714Skris		}
110355714Skris	else
1104127128Snectar		BUF_strlcpy(buf,serialfile,len);
110555714Skris
1106127128Snectar	serial = load_serial(buf, create, NULL);
1107127128Snectar	if (serial == NULL) goto end;
110855714Skris
110955714Skris	if (!BN_add_word(serial,1))
111055714Skris		{ BIO_printf(bio_err,"add_word failure\n"); goto end; }
1111109998Smarkm
1112127128Snectar	if (!save_serial(buf, NULL, serial, &bs)) goto end;
1113127128Snectar
1114127128Snectar end:
1115109998Smarkm	if (buf) OPENSSL_free(buf);
1116109998Smarkm	BN_free(serial);
1117109998Smarkm	return bs;
1118109998Smarkm	}
1119109998Smarkm
1120109998Smarkmstatic int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
1121109998Smarkm	     X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create,
1122109998Smarkm	     int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno)
1123109998Smarkm	{
1124109998Smarkm	int ret=0;
1125109998Smarkm	ASN1_INTEGER *bs=NULL;
1126109998Smarkm	X509_STORE_CTX xsc;
1127109998Smarkm	EVP_PKEY *upkey;
1128109998Smarkm
1129109998Smarkm	upkey = X509_get_pubkey(xca);
1130109998Smarkm	EVP_PKEY_copy_parameters(upkey,pkey);
1131109998Smarkm	EVP_PKEY_free(upkey);
1132109998Smarkm
1133109998Smarkm	if(!X509_STORE_CTX_init(&xsc,ctx,x,NULL))
1134109998Smarkm		{
1135109998Smarkm		BIO_printf(bio_err,"Error initialising X509 store\n");
1136109998Smarkm		goto end;
1137109998Smarkm		}
1138109998Smarkm	if (sno) bs = sno;
1139127128Snectar	else if (!(bs = x509_load_serial(CAfile, serialfile, create)))
1140109998Smarkm		goto end;
1141109998Smarkm
1142120631Snectar/*	if (!X509_STORE_add_cert(ctx,x)) goto end;*/
114355714Skris
114455714Skris	/* NOTE: this certificate can/should be self signed, unless it was
114555714Skris	 * a certificate request in which case it is not. */
114655714Skris	X509_STORE_CTX_set_cert(&xsc,x);
114755714Skris	if (!reqfile && !X509_verify_cert(&xsc))
114855714Skris		goto end;
114955714Skris
115055714Skris	if (!X509_check_private_key(xca,pkey))
115155714Skris		{
115255714Skris		BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
115355714Skris		goto end;
115455714Skris		}
115555714Skris
115655714Skris	if (!X509_set_issuer_name(x,X509_get_subject_name(xca))) goto end;
115755714Skris	if (!X509_set_serialNumber(x,bs)) goto end;
115855714Skris
115955714Skris	if (X509_gmtime_adj(X509_get_notBefore(x),0L) == NULL)
116055714Skris		goto end;
116155714Skris
116255714Skris	/* hardwired expired */
116355714Skris	if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL)
116455714Skris		goto end;
116555714Skris
116668651Skris	if (clrext)
116768651Skris		{
116868651Skris		while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0);
116968651Skris		}
117059191Skris
117168651Skris	if (conf)
117268651Skris		{
117355714Skris		X509V3_CTX ctx2;
117455714Skris		X509_set_version(x,2); /* version 3 certificate */
117555714Skris                X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
1176109998Smarkm                X509V3_set_nconf(&ctx2, conf);
1177109998Smarkm                if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end;
117868651Skris		}
117955714Skris
118055714Skris	if (!X509_sign(x,pkey,digest)) goto end;
118155714Skris	ret=1;
118255714Skrisend:
118355714Skris	X509_STORE_CTX_cleanup(&xsc);
118455714Skris	if (!ret)
118555714Skris		ERR_print_errors(bio_err);
1186109998Smarkm	if (!sno) ASN1_INTEGER_free(bs);
118768651Skris	return ret;
118855714Skris	}
118955714Skris
119055714Skrisstatic int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx)
119155714Skris	{
119255714Skris	int err;
119355714Skris	X509 *err_cert;
119455714Skris
119555714Skris	/* it is ok to use a self signed certificate
119655714Skris	 * This case will catch both the initial ok == 0 and the
119755714Skris	 * final ok == 1 calls to this function */
119855714Skris	err=X509_STORE_CTX_get_error(ctx);
119955714Skris	if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
120068651Skris		return 1;
120155714Skris
120255714Skris	/* BAD we should have gotten an error.  Normally if everything
120355714Skris	 * worked X509_STORE_CTX_get_error(ctx) will still be set to
120455714Skris	 * DEPTH_ZERO_SELF_.... */
120555714Skris	if (ok)
120655714Skris		{
120755714Skris		BIO_printf(bio_err,"error with certificate to be certified - should be self signed\n");
120868651Skris		return 0;
120955714Skris		}
121055714Skris	else
121155714Skris		{
121255714Skris		err_cert=X509_STORE_CTX_get_current_cert(ctx);
121368651Skris		print_name(bio_err, NULL, X509_get_subject_name(err_cert),0);
121455714Skris		BIO_printf(bio_err,"error with certificate - error %d at depth %d\n%s\n",
121555714Skris			err,X509_STORE_CTX_get_error_depth(ctx),
121655714Skris			X509_verify_cert_error_string(err));
121768651Skris		return 1;
121855714Skris		}
121955714Skris	}
122055714Skris
122155714Skris/* self sign */
122259191Skrisstatic int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest,
1223109998Smarkm						CONF *conf, char *section)
122455714Skris	{
122555714Skris
122655714Skris	EVP_PKEY *pktmp;
122755714Skris
122855714Skris	pktmp = X509_get_pubkey(x);
122955714Skris	EVP_PKEY_copy_parameters(pktmp,pkey);
123055714Skris	EVP_PKEY_save_parameters(pktmp,1);
123155714Skris	EVP_PKEY_free(pktmp);
123255714Skris
123355714Skris	if (!X509_set_issuer_name(x,X509_get_subject_name(x))) goto err;
123455714Skris	if (X509_gmtime_adj(X509_get_notBefore(x),0) == NULL) goto err;
123555714Skris
123655714Skris	/* Lets just make it 12:00am GMT, Jan 1 1970 */
123755714Skris	/* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
123855714Skris	/* 28 days to be certified */
123955714Skris
124055714Skris	if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL)
124155714Skris		goto err;
124255714Skris
124355714Skris	if (!X509_set_pubkey(x,pkey)) goto err;
124468651Skris	if (clrext)
124568651Skris		{
124668651Skris		while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0);
124768651Skris		}
124868651Skris	if (conf)
124968651Skris		{
125055714Skris		X509V3_CTX ctx;
125155714Skris		X509_set_version(x,2); /* version 3 certificate */
125255714Skris                X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
1253109998Smarkm                X509V3_set_nconf(&ctx, conf);
1254109998Smarkm                if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) goto err;
125568651Skris		}
125655714Skris	if (!X509_sign(x,pkey,digest)) goto err;
125768651Skris	return 1;
125855714Skriserr:
125955714Skris	ERR_print_errors(bio_err);
126068651Skris	return 0;
126155714Skris	}
126259191Skris
126359191Skrisstatic int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
126459191Skris{
126559191Skris	int id, i, idret;
126659191Skris	char *pname;
126759191Skris	id = X509_PURPOSE_get_id(pt);
126859191Skris	pname = X509_PURPOSE_get0_name(pt);
126968651Skris	for (i = 0; i < 2; i++)
127068651Skris		{
127159191Skris		idret = X509_check_purpose(cert, id, i);
127259191Skris		BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
127368651Skris		if (idret == 1) BIO_printf(bio, "Yes\n");
127459191Skris		else if (idret == 0) BIO_printf(bio, "No\n");
127559191Skris		else BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
127668651Skris		}
127759191Skris	return 1;
127859191Skris}
1279