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",
102238405Sjkim#ifndef OPENSSL_NO_MD5
103238405Sjkim" -subject_hash_old   - print old-style (MD5) subject hash value\n",
104238405Sjkim#endif
105160814Ssimon" -issuer_hash    - print issuer hash value\n",
106238405Sjkim#ifndef OPENSSL_NO_MD5
107238405Sjkim" -issuer_hash_old    - print old-style (MD5) issuer hash value\n",
108238405Sjkim#endif
109160814Ssimon" -hash           - synonym for -subject_hash\n",
11055714Skris" -subject        - print subject DN\n",
11155714Skris" -issuer         - print issuer DN\n",
11268651Skris" -email          - print email address(es)\n",
11355714Skris" -startdate      - notBefore field\n",
11455714Skris" -enddate        - notAfter field\n",
11559191Skris" -purpose        - print out certificate purposes\n",
11655714Skris" -dates          - both Before and After dates\n",
11755714Skris" -modulus        - print the RSA key modulus\n",
11859191Skris" -pubkey         - output the public key\n",
11955714Skris" -fingerprint    - print the certificate fingerprint\n",
12059191Skris" -alias          - output certificate alias\n",
12155714Skris" -noout          - no certificate output\n",
122109998Smarkm" -ocspid         - print OCSP hash values for the subject name and public key\n",
123194206Ssimon" -ocsp_uri       - print OCSP Responder URL(s)\n",
12459191Skris" -trustout       - output a \"trusted\" certificate\n",
12559191Skris" -clrtrust       - clear all trusted purposes\n",
12659191Skris" -clrreject      - clear all rejected purposes\n",
12759191Skris" -addtrust arg   - trust certificate for a given purpose\n",
12859191Skris" -addreject arg  - reject certificate for a given purpose\n",
12959191Skris" -setalias arg   - set certificate alias\n",
13055714Skris" -days arg       - How long till expiry of a signed certificate - def 30 days\n",
13168651Skris" -checkend arg   - check whether the cert expires in the next arg seconds\n",
13268651Skris"                   exit 1 if so, 0 if not\n",
13355714Skris" -signkey arg    - self sign cert with arg\n",
13455714Skris" -x509toreq      - output a certification request object\n",
13555714Skris" -req            - input is a certificate request, sign and output.\n",
13655714Skris" -CA arg         - set the CA certificate, must be PEM format.\n",
13755714Skris" -CAkey arg      - set the CA key, must be PEM format\n",
13859191Skris"                   missing, it is assumed to be in the CA file.\n",
13955714Skris" -CAcreateserial - create serial number file if it does not exist\n",
140109998Smarkm" -CAserial arg   - serial file\n",
141109998Smarkm" -set_serial     - serial number to use\n",
14255714Skris" -text           - print the certificate in text form\n",
14355714Skris" -C              - print out C code forms\n",
14459191Skris" -md2/-md5/-sha1/-mdc2 - digest to use\n",
14555714Skris" -extfile        - configuration file with X509V3 extensions to add\n",
14659191Skris" -extensions     - section from config file with X509V3 extensions to add\n",
14759191Skris" -clrext         - delete extensions before signing and input certificate\n",
14868651Skris" -nameopt arg    - various certificate name options\n",
149111147Snectar#ifndef OPENSSL_NO_ENGINE
150109998Smarkm" -engine e       - use engine e, possibly a hardware device.\n",
151111147Snectar#endif
152109998Smarkm" -certopt arg    - various certificate text options\n",
15355714SkrisNULL
15455714Skris};
15555714Skris
15655714Skrisstatic int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx);
15759191Skrisstatic int sign (X509 *x, EVP_PKEY *pkey,int days,int clrext, const EVP_MD *digest,
158109998Smarkm						CONF *conf, char *section);
15955714Skrisstatic int x509_certify (X509_STORE *ctx,char *CAfile,const EVP_MD *digest,
160238405Sjkim			 X509 *x,X509 *xca,EVP_PKEY *pkey,
161238405Sjkim			 STACK_OF(OPENSSL_STRING) *sigopts,
162238405Sjkim			 char *serial, int create ,int days, int clrext,
163238405Sjkim			 CONF *conf, char *section, ASN1_INTEGER *sno);
16459191Skrisstatic int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
16555714Skrisstatic int reqfile=0;
16655714Skris
16759191Skrisint MAIN(int, char **);
16859191Skris
16955714Skrisint MAIN(int argc, char **argv)
17055714Skris	{
171109998Smarkm	ENGINE *e = NULL;
17255714Skris	int ret=1;
17355714Skris	X509_REQ *req=NULL;
17455714Skris	X509 *x=NULL,*xca=NULL;
17559191Skris	ASN1_OBJECT *objtmp;
176238405Sjkim	STACK_OF(OPENSSL_STRING) *sigopts = NULL;
17755714Skris	EVP_PKEY *Upkey=NULL,*CApkey=NULL;
178109998Smarkm	ASN1_INTEGER *sno = NULL;
17955714Skris	int i,num,badops=0;
18055714Skris	BIO *out=NULL;
18155714Skris	BIO *STDout=NULL;
18259191Skris	STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
18355714Skris	int informat,outformat,keyformat,CAformat,CAkeyformat;
18455714Skris	char *infile=NULL,*outfile=NULL,*keyfile=NULL,*CAfile=NULL;
18555714Skris	char *CAkeyfile=NULL,*CAserial=NULL;
18659191Skris	char *alias=NULL;
187160814Ssimon	int text=0,serial=0,subject=0,issuer=0,startdate=0,enddate=0;
188160814Ssimon	int next_serial=0;
189160814Ssimon	int subject_hash=0,issuer_hash=0,ocspid=0;
190238405Sjkim#ifndef OPENSSL_NO_MD5
191238405Sjkim	int subject_hash_old=0,issuer_hash_old=0;
192238405Sjkim#endif
19368651Skris	int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0,email=0;
194194206Ssimon	int ocsp_uri=0;
19559191Skris	int trustout=0,clrtrust=0,clrreject=0,aliasout=0,clrext=0;
19655714Skris	int C=0;
19759191Skris	int x509req=0,days=DEF_DAYS,modulus=0,pubkey=0;
19859191Skris	int pprint = 0;
199160814Ssimon	const char **pp;
20055714Skris	X509_STORE *ctx=NULL;
20155714Skris	X509_REQ *rq=NULL;
20255714Skris	int fingerprint=0;
20355714Skris	char buf[256];
204238405Sjkim	const EVP_MD *md_alg,*digest=NULL;
205109998Smarkm	CONF *extconf = NULL;
20659191Skris	char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
20759191Skris	int need_rand = 0;
20868651Skris	int checkend=0,checkoffset=0;
209109998Smarkm	unsigned long nmflag = 0, certflag = 0;
210111147Snectar#ifndef OPENSSL_NO_ENGINE
211109998Smarkm	char *engine=NULL;
212111147Snectar#endif
21355714Skris
21455714Skris	reqfile=0;
21555714Skris
21655714Skris	apps_startup();
21755714Skris
21855714Skris	if (bio_err == NULL)
21955714Skris		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
220109998Smarkm
221109998Smarkm	if (!load_config(bio_err, NULL))
222109998Smarkm		goto end;
22355714Skris	STDout=BIO_new_fp(stdout,BIO_NOCLOSE);
224109998Smarkm#ifdef OPENSSL_SYS_VMS
22568651Skris	{
22668651Skris	BIO *tmpbio = BIO_new(BIO_f_linebuffer());
22768651Skris	STDout = BIO_push(tmpbio, STDout);
22868651Skris	}
22968651Skris#endif
23055714Skris
23155714Skris	informat=FORMAT_PEM;
23255714Skris	outformat=FORMAT_PEM;
23355714Skris	keyformat=FORMAT_PEM;
23455714Skris	CAformat=FORMAT_PEM;
23555714Skris	CAkeyformat=FORMAT_PEM;
23655714Skris
23755714Skris	ctx=X509_STORE_new();
23855714Skris	if (ctx == NULL) goto end;
239238405Sjkim	X509_STORE_set_verify_cb(ctx,callb);
24055714Skris
24155714Skris	argc--;
24255714Skris	argv++;
24355714Skris	num=0;
24455714Skris	while (argc >= 1)
24555714Skris		{
24655714Skris		if 	(strcmp(*argv,"-inform") == 0)
24755714Skris			{
24855714Skris			if (--argc < 1) goto bad;
24955714Skris			informat=str2fmt(*(++argv));
25055714Skris			}
25155714Skris		else if (strcmp(*argv,"-outform") == 0)
25255714Skris			{
25355714Skris			if (--argc < 1) goto bad;
25455714Skris			outformat=str2fmt(*(++argv));
25555714Skris			}
25655714Skris		else if (strcmp(*argv,"-keyform") == 0)
25755714Skris			{
25855714Skris			if (--argc < 1) goto bad;
25955714Skris			keyformat=str2fmt(*(++argv));
26055714Skris			}
26155714Skris		else if (strcmp(*argv,"-req") == 0)
26259191Skris			{
26355714Skris			reqfile=1;
26459191Skris			need_rand = 1;
26559191Skris			}
26655714Skris		else if (strcmp(*argv,"-CAform") == 0)
26755714Skris			{
26855714Skris			if (--argc < 1) goto bad;
26955714Skris			CAformat=str2fmt(*(++argv));
27055714Skris			}
27155714Skris		else if (strcmp(*argv,"-CAkeyform") == 0)
27255714Skris			{
27355714Skris			if (--argc < 1) goto bad;
274100936Snectar			CAkeyformat=str2fmt(*(++argv));
27555714Skris			}
276238405Sjkim		else if (strcmp(*argv,"-sigopt") == 0)
277238405Sjkim			{
278238405Sjkim			if (--argc < 1)
279238405Sjkim				goto bad;
280238405Sjkim			if (!sigopts)
281238405Sjkim				sigopts = sk_OPENSSL_STRING_new_null();
282238405Sjkim			if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
283238405Sjkim				goto bad;
284238405Sjkim			}
28555714Skris		else if (strcmp(*argv,"-days") == 0)
28655714Skris			{
28755714Skris			if (--argc < 1) goto bad;
28855714Skris			days=atoi(*(++argv));
28955714Skris			if (days == 0)
29055714Skris				{
291246772Sjkim				BIO_printf(bio_err,"bad number of days\n");
29255714Skris				goto bad;
29355714Skris				}
29455714Skris			}
29559191Skris		else if (strcmp(*argv,"-passin") == 0)
29659191Skris			{
29759191Skris			if (--argc < 1) goto bad;
29859191Skris			passargin= *(++argv);
29959191Skris			}
30055714Skris		else if (strcmp(*argv,"-extfile") == 0)
30155714Skris			{
30255714Skris			if (--argc < 1) goto bad;
30355714Skris			extfile= *(++argv);
30455714Skris			}
30559191Skris		else if (strcmp(*argv,"-extensions") == 0)
30659191Skris			{
30759191Skris			if (--argc < 1) goto bad;
30859191Skris			extsect= *(++argv);
30959191Skris			}
31055714Skris		else if (strcmp(*argv,"-in") == 0)
31155714Skris			{
31255714Skris			if (--argc < 1) goto bad;
31355714Skris			infile= *(++argv);
31455714Skris			}
31555714Skris		else if (strcmp(*argv,"-out") == 0)
31655714Skris			{
31755714Skris			if (--argc < 1) goto bad;
31855714Skris			outfile= *(++argv);
31955714Skris			}
32055714Skris		else if (strcmp(*argv,"-signkey") == 0)
32155714Skris			{
32255714Skris			if (--argc < 1) goto bad;
32355714Skris			keyfile= *(++argv);
32455714Skris			sign_flag= ++num;
32559191Skris			need_rand = 1;
32655714Skris			}
32755714Skris		else if (strcmp(*argv,"-CA") == 0)
32855714Skris			{
32955714Skris			if (--argc < 1) goto bad;
33055714Skris			CAfile= *(++argv);
33155714Skris			CA_flag= ++num;
33259191Skris			need_rand = 1;
33355714Skris			}
33455714Skris		else if (strcmp(*argv,"-CAkey") == 0)
33555714Skris			{
33655714Skris			if (--argc < 1) goto bad;
33755714Skris			CAkeyfile= *(++argv);
33855714Skris			}
33955714Skris		else if (strcmp(*argv,"-CAserial") == 0)
34055714Skris			{
34155714Skris			if (--argc < 1) goto bad;
34255714Skris			CAserial= *(++argv);
34355714Skris			}
344109998Smarkm		else if (strcmp(*argv,"-set_serial") == 0)
345109998Smarkm			{
346109998Smarkm			if (--argc < 1) goto bad;
347109998Smarkm			if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
348109998Smarkm				goto bad;
349109998Smarkm			}
35059191Skris		else if (strcmp(*argv,"-addtrust") == 0)
35159191Skris			{
35259191Skris			if (--argc < 1) goto bad;
35368651Skris			if (!(objtmp = OBJ_txt2obj(*(++argv), 0)))
35468651Skris				{
35559191Skris				BIO_printf(bio_err,
35659191Skris					"Invalid trust object value %s\n", *argv);
35759191Skris				goto bad;
35868651Skris				}
35968651Skris			if (!trust) trust = sk_ASN1_OBJECT_new_null();
36059191Skris			sk_ASN1_OBJECT_push(trust, objtmp);
36159191Skris			trustout = 1;
36259191Skris			}
36359191Skris		else if (strcmp(*argv,"-addreject") == 0)
36459191Skris			{
36559191Skris			if (--argc < 1) goto bad;
36668651Skris			if (!(objtmp = OBJ_txt2obj(*(++argv), 0)))
36768651Skris				{
36859191Skris				BIO_printf(bio_err,
36959191Skris					"Invalid reject object value %s\n", *argv);
37059191Skris				goto bad;
37168651Skris				}
37268651Skris			if (!reject) reject = sk_ASN1_OBJECT_new_null();
37359191Skris			sk_ASN1_OBJECT_push(reject, objtmp);
37459191Skris			trustout = 1;
37559191Skris			}
37659191Skris		else if (strcmp(*argv,"-setalias") == 0)
37759191Skris			{
37859191Skris			if (--argc < 1) goto bad;
37959191Skris			alias= *(++argv);
38059191Skris			trustout = 1;
38159191Skris			}
382109998Smarkm		else if (strcmp(*argv,"-certopt") == 0)
383109998Smarkm			{
384109998Smarkm			if (--argc < 1) goto bad;
385109998Smarkm			if (!set_cert_ex(&certflag, *(++argv))) goto bad;
386109998Smarkm			}
38768651Skris		else if (strcmp(*argv,"-nameopt") == 0)
38868651Skris			{
38968651Skris			if (--argc < 1) goto bad;
39068651Skris			if (!set_name_ex(&nmflag, *(++argv))) goto bad;
39168651Skris			}
392111147Snectar#ifndef OPENSSL_NO_ENGINE
393109998Smarkm		else if (strcmp(*argv,"-engine") == 0)
394109998Smarkm			{
395109998Smarkm			if (--argc < 1) goto bad;
396109998Smarkm			engine= *(++argv);
397109998Smarkm			}
398111147Snectar#endif
39955714Skris		else if (strcmp(*argv,"-C") == 0)
40055714Skris			C= ++num;
40168651Skris		else if (strcmp(*argv,"-email") == 0)
40268651Skris			email= ++num;
403194206Ssimon		else if (strcmp(*argv,"-ocsp_uri") == 0)
404194206Ssimon			ocsp_uri= ++num;
40555714Skris		else if (strcmp(*argv,"-serial") == 0)
40655714Skris			serial= ++num;
407142425Snectar		else if (strcmp(*argv,"-next_serial") == 0)
408142425Snectar			next_serial= ++num;
40955714Skris		else if (strcmp(*argv,"-modulus") == 0)
41055714Skris			modulus= ++num;
41159191Skris		else if (strcmp(*argv,"-pubkey") == 0)
41259191Skris			pubkey= ++num;
41355714Skris		else if (strcmp(*argv,"-x509toreq") == 0)
41455714Skris			x509req= ++num;
41555714Skris		else if (strcmp(*argv,"-text") == 0)
41655714Skris			text= ++num;
417160814Ssimon		else if (strcmp(*argv,"-hash") == 0
418160814Ssimon			|| strcmp(*argv,"-subject_hash") == 0)
419160814Ssimon			subject_hash= ++num;
420238405Sjkim#ifndef OPENSSL_NO_MD5
421238405Sjkim		else if (strcmp(*argv,"-subject_hash_old") == 0)
422238405Sjkim			subject_hash_old= ++num;
423238405Sjkim#endif
424160814Ssimon		else if (strcmp(*argv,"-issuer_hash") == 0)
425160814Ssimon			issuer_hash= ++num;
426238405Sjkim#ifndef OPENSSL_NO_MD5
427238405Sjkim		else if (strcmp(*argv,"-issuer_hash_old") == 0)
428238405Sjkim			issuer_hash_old= ++num;
429238405Sjkim#endif
43055714Skris		else if (strcmp(*argv,"-subject") == 0)
43155714Skris			subject= ++num;
43255714Skris		else if (strcmp(*argv,"-issuer") == 0)
43355714Skris			issuer= ++num;
43455714Skris		else if (strcmp(*argv,"-fingerprint") == 0)
43555714Skris			fingerprint= ++num;
43655714Skris		else if (strcmp(*argv,"-dates") == 0)
43755714Skris			{
43855714Skris			startdate= ++num;
43955714Skris			enddate= ++num;
44055714Skris			}
44159191Skris		else if (strcmp(*argv,"-purpose") == 0)
44259191Skris			pprint= ++num;
44355714Skris		else if (strcmp(*argv,"-startdate") == 0)
44455714Skris			startdate= ++num;
44555714Skris		else if (strcmp(*argv,"-enddate") == 0)
44655714Skris			enddate= ++num;
44768651Skris		else if (strcmp(*argv,"-checkend") == 0)
44868651Skris			{
44968651Skris			if (--argc < 1) goto bad;
45068651Skris			checkoffset=atoi(*(++argv));
45168651Skris			checkend=1;
45268651Skris			}
45355714Skris		else if (strcmp(*argv,"-noout") == 0)
45455714Skris			noout= ++num;
45559191Skris		else if (strcmp(*argv,"-trustout") == 0)
45659191Skris			trustout= 1;
45759191Skris		else if (strcmp(*argv,"-clrtrust") == 0)
45859191Skris			clrtrust= ++num;
45959191Skris		else if (strcmp(*argv,"-clrreject") == 0)
46059191Skris			clrreject= ++num;
46159191Skris		else if (strcmp(*argv,"-alias") == 0)
46259191Skris			aliasout= ++num;
46355714Skris		else if (strcmp(*argv,"-CAcreateserial") == 0)
46455714Skris			CA_createserial= ++num;
46559191Skris		else if (strcmp(*argv,"-clrext") == 0)
46659191Skris			clrext = 1;
46759191Skris#if 1 /* stay backwards-compatible with 0.9.5; this should go away soon */
46859191Skris		else if (strcmp(*argv,"-crlext") == 0)
46955714Skris			{
47059191Skris			BIO_printf(bio_err,"use -clrext instead of -crlext\n");
47159191Skris			clrext = 1;
47259191Skris			}
47359191Skris#endif
474109998Smarkm		else if (strcmp(*argv,"-ocspid") == 0)
475109998Smarkm			ocspid= ++num;
47659191Skris		else if ((md_alg=EVP_get_digestbyname(*argv + 1)))
47759191Skris			{
47855714Skris			/* ok */
47955714Skris			digest=md_alg;
48055714Skris			}
48155714Skris		else
48255714Skris			{
48355714Skris			BIO_printf(bio_err,"unknown option %s\n",*argv);
48455714Skris			badops=1;
48555714Skris			break;
48655714Skris			}
48755714Skris		argc--;
48855714Skris		argv++;
48955714Skris		}
49055714Skris
49155714Skris	if (badops)
49255714Skris		{
49355714Skrisbad:
49455714Skris		for (pp=x509_usage; (*pp != NULL); pp++)
495109998Smarkm			BIO_printf(bio_err,"%s",*pp);
49655714Skris		goto end;
49755714Skris		}
49855714Skris
499111147Snectar#ifndef OPENSSL_NO_ENGINE
500109998Smarkm        e = setup_engine(bio_err, engine, 0);
501111147Snectar#endif
502109998Smarkm
50359191Skris	if (need_rand)
50459191Skris		app_RAND_load_file(NULL, bio_err, 0);
50559191Skris
50655714Skris	ERR_load_crypto_strings();
50755714Skris
50868651Skris	if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
50968651Skris		{
51059191Skris		BIO_printf(bio_err, "Error getting password\n");
51159191Skris		goto end;
51268651Skris		}
51359191Skris
51455714Skris	if (!X509_STORE_set_default_paths(ctx))
51555714Skris		{
51655714Skris		ERR_print_errors(bio_err);
51755714Skris		goto end;
51855714Skris		}
51955714Skris
52055714Skris	if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM))
52155714Skris		{ CAkeyfile=CAfile; }
52255714Skris	else if ((CA_flag) && (CAkeyfile == NULL))
52355714Skris		{
52455714Skris		BIO_printf(bio_err,"need to specify a CAkey if using the CA command\n");
52555714Skris		goto end;
52655714Skris		}
52755714Skris
52868651Skris	if (extfile)
52968651Skris		{
530109998Smarkm		long errorline = -1;
53155714Skris		X509V3_CTX ctx2;
532109998Smarkm		extconf = NCONF_new(NULL);
533109998Smarkm		if (!NCONF_load(extconf, extfile,&errorline))
53468651Skris			{
53555714Skris			if (errorline <= 0)
53655714Skris				BIO_printf(bio_err,
53755714Skris					"error loading the config file '%s'\n",
53855714Skris								extfile);
53955714Skris                	else
54055714Skris                        	BIO_printf(bio_err,
54155714Skris				       "error on line %ld of config file '%s'\n"
54255714Skris							,errorline,extfile);
54355714Skris			goto end;
54468651Skris			}
545109998Smarkm		if (!extsect)
546109998Smarkm			{
547109998Smarkm			extsect = NCONF_get_string(extconf, "default", "extensions");
548109998Smarkm			if (!extsect)
549109998Smarkm				{
550109998Smarkm				ERR_clear_error();
551109998Smarkm				extsect = "default";
552109998Smarkm				}
553109998Smarkm			}
55455714Skris		X509V3_set_ctx_test(&ctx2);
555109998Smarkm		X509V3_set_nconf(&ctx2, extconf);
556109998Smarkm		if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL))
55768651Skris			{
55855714Skris			BIO_printf(bio_err,
55955714Skris				"Error Loading extension section %s\n",
56055714Skris								 extsect);
56155714Skris			ERR_print_errors(bio_err);
56255714Skris			goto end;
56368651Skris			}
56468651Skris		}
56555714Skris
56655714Skris
56755714Skris	if (reqfile)
56855714Skris		{
56955714Skris		EVP_PKEY *pkey;
57055714Skris		BIO *in;
57155714Skris
57255714Skris		if (!sign_flag && !CA_flag)
57355714Skris			{
57455714Skris			BIO_printf(bio_err,"We need a private key to sign with\n");
57555714Skris			goto end;
57655714Skris			}
57755714Skris		in=BIO_new(BIO_s_file());
57855714Skris		if (in == NULL)
57955714Skris			{
58055714Skris			ERR_print_errors(bio_err);
58155714Skris			goto end;
58255714Skris			}
58355714Skris
58455714Skris		if (infile == NULL)
58555714Skris			BIO_set_fp(in,stdin,BIO_NOCLOSE|BIO_FP_TEXT);
58655714Skris		else
58755714Skris			{
58855714Skris			if (BIO_read_filename(in,infile) <= 0)
58955714Skris				{
59055714Skris				perror(infile);
59168651Skris				BIO_free(in);
59255714Skris				goto end;
59355714Skris				}
59455714Skris			}
59555714Skris		req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
59655714Skris		BIO_free(in);
59755714Skris
59868651Skris		if (req == NULL)
59968651Skris			{
60068651Skris			ERR_print_errors(bio_err);
60168651Skris			goto end;
60268651Skris			}
60355714Skris
60455714Skris		if (	(req->req_info == NULL) ||
60555714Skris			(req->req_info->pubkey == NULL) ||
60655714Skris			(req->req_info->pubkey->public_key == NULL) ||
60755714Skris			(req->req_info->pubkey->public_key->data == NULL))
60855714Skris			{
60955714Skris			BIO_printf(bio_err,"The certificate request appears to corrupted\n");
61055714Skris			BIO_printf(bio_err,"It does not contain a public key\n");
61155714Skris			goto end;
61255714Skris			}
61355714Skris		if ((pkey=X509_REQ_get_pubkey(req)) == NULL)
61455714Skris	                {
61555714Skris	                BIO_printf(bio_err,"error unpacking public key\n");
61655714Skris	                goto end;
61755714Skris	                }
61855714Skris		i=X509_REQ_verify(req,pkey);
61955714Skris		EVP_PKEY_free(pkey);
62055714Skris		if (i < 0)
62155714Skris			{
62255714Skris			BIO_printf(bio_err,"Signature verification error\n");
62355714Skris			ERR_print_errors(bio_err);
62455714Skris			goto end;
62555714Skris			}
62655714Skris	        if (i == 0)
62755714Skris			{
62855714Skris			BIO_printf(bio_err,"Signature did not match the certificate request\n");
62955714Skris			goto end;
63055714Skris			}
63155714Skris		else
63255714Skris			BIO_printf(bio_err,"Signature ok\n");
63355714Skris
63468651Skris		print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag);
63568651Skris
63655714Skris		if ((x=X509_new()) == NULL) goto end;
63755714Skris
638142425Snectar		if (sno == NULL)
639109998Smarkm			{
640142425Snectar			sno = ASN1_INTEGER_new();
641142425Snectar			if (!sno || !rand_serial(NULL, sno))
642109998Smarkm				goto end;
643160814Ssimon			if (!X509_set_serialNumber(x, sno))
644160814Ssimon				goto end;
645160814Ssimon			ASN1_INTEGER_free(sno);
646160814Ssimon			sno = NULL;
647109998Smarkm			}
648160814Ssimon		else if (!X509_set_serialNumber(x, sno))
649142425Snectar			goto end;
650142425Snectar
65155714Skris		if (!X509_set_issuer_name(x,req->req_info->subject)) goto end;
65255714Skris		if (!X509_set_subject_name(x,req->req_info->subject)) goto end;
65355714Skris
65455714Skris		X509_gmtime_adj(X509_get_notBefore(x),0);
655238405Sjkim	        X509_time_adj_ex(X509_get_notAfter(x),days, 0, NULL);
65655714Skris
65755714Skris		pkey = X509_REQ_get_pubkey(req);
65855714Skris		X509_set_pubkey(x,pkey);
65955714Skris		EVP_PKEY_free(pkey);
66055714Skris		}
66155714Skris	else
662109998Smarkm		x=load_cert(bio_err,infile,informat,NULL,e,"Certificate");
66355714Skris
66455714Skris	if (x == NULL) goto end;
66555714Skris	if (CA_flag)
66655714Skris		{
667109998Smarkm		xca=load_cert(bio_err,CAfile,CAformat,NULL,e,"CA Certificate");
66855714Skris		if (xca == NULL) goto end;
66955714Skris		}
67055714Skris
671142425Snectar	if (!noout || text || next_serial)
67255714Skris		{
67355714Skris		OBJ_create("2.99999.3",
67455714Skris			"SET.ex3","SET x509v3 extension 3");
67555714Skris
67655714Skris		out=BIO_new(BIO_s_file());
67755714Skris		if (out == NULL)
67855714Skris			{
67955714Skris			ERR_print_errors(bio_err);
68055714Skris			goto end;
68155714Skris			}
68255714Skris		if (outfile == NULL)
68368651Skris			{
68455714Skris			BIO_set_fp(out,stdout,BIO_NOCLOSE);
685109998Smarkm#ifdef OPENSSL_SYS_VMS
68668651Skris			{
68768651Skris			BIO *tmpbio = BIO_new(BIO_f_linebuffer());
68868651Skris			out = BIO_push(tmpbio, out);
68968651Skris			}
69068651Skris#endif
69168651Skris			}
69255714Skris		else
69355714Skris			{
69455714Skris			if (BIO_write_filename(out,outfile) <= 0)
69555714Skris				{
69655714Skris				perror(outfile);
69755714Skris				goto end;
69855714Skris				}
69955714Skris			}
70055714Skris		}
70155714Skris
70268651Skris	if (alias) X509_alias_set1(x, (unsigned char *)alias, -1);
70359191Skris
70468651Skris	if (clrtrust) X509_trust_clear(x);
70568651Skris	if (clrreject) X509_reject_clear(x);
70659191Skris
70768651Skris	if (trust)
70868651Skris		{
70968651Skris		for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++)
71068651Skris			{
71159191Skris			objtmp = sk_ASN1_OBJECT_value(trust, i);
71259191Skris			X509_add1_trust_object(x, objtmp);
71368651Skris			}
71459191Skris		}
71559191Skris
71668651Skris	if (reject)
71768651Skris		{
71868651Skris		for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++)
71968651Skris			{
72059191Skris			objtmp = sk_ASN1_OBJECT_value(reject, i);
72159191Skris			X509_add1_reject_object(x, objtmp);
72268651Skris			}
72359191Skris		}
72459191Skris
72555714Skris	if (num)
72655714Skris		{
72755714Skris		for (i=1; i<=num; i++)
72855714Skris			{
72955714Skris			if (issuer == i)
73055714Skris				{
73168651Skris				print_name(STDout, "issuer= ",
73268651Skris					X509_get_issuer_name(x), nmflag);
73355714Skris				}
73455714Skris			else if (subject == i)
73555714Skris				{
73668651Skris				print_name(STDout, "subject= ",
73768651Skris					X509_get_subject_name(x), nmflag);
73855714Skris				}
73955714Skris			else if (serial == i)
74055714Skris				{
74155714Skris				BIO_printf(STDout,"serial=");
742160814Ssimon				i2a_ASN1_INTEGER(STDout,
743160814Ssimon					X509_get_serialNumber(x));
74455714Skris				BIO_printf(STDout,"\n");
74555714Skris				}
746142425Snectar			else if (next_serial == i)
747142425Snectar				{
748142425Snectar				BIGNUM *bnser;
749142425Snectar				ASN1_INTEGER *ser;
750142425Snectar				ser = X509_get_serialNumber(x);
751142425Snectar				bnser = ASN1_INTEGER_to_BN(ser, NULL);
752142425Snectar				if (!bnser)
753142425Snectar					goto end;
754142425Snectar				if (!BN_add_word(bnser, 1))
755142425Snectar					goto end;
756142425Snectar				ser = BN_to_ASN1_INTEGER(bnser, NULL);
757142425Snectar				if (!ser)
758142425Snectar					goto end;
759142425Snectar				BN_free(bnser);
760142425Snectar				i2a_ASN1_INTEGER(out, ser);
761142425Snectar				ASN1_INTEGER_free(ser);
762142425Snectar				BIO_puts(out, "\n");
763142425Snectar				}
764194206Ssimon			else if ((email == i) || (ocsp_uri == i))
76568651Skris				{
76668651Skris				int j;
767238405Sjkim				STACK_OF(OPENSSL_STRING) *emlst;
768194206Ssimon				if (email == i)
769194206Ssimon					emlst = X509_get1_email(x);
770194206Ssimon				else
771194206Ssimon					emlst = X509_get1_ocsp(x);
772238405Sjkim				for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
773238405Sjkim					BIO_printf(STDout, "%s\n",
774238405Sjkim						   sk_OPENSSL_STRING_value(emlst, j));
77568651Skris				X509_email_free(emlst);
77668651Skris				}
77759191Skris			else if (aliasout == i)
77859191Skris				{
77959191Skris				unsigned char *alstr;
78059191Skris				alstr = X509_alias_get0(x, NULL);
78168651Skris				if (alstr) BIO_printf(STDout,"%s\n", alstr);
78259191Skris				else BIO_puts(STDout,"<No Alias>\n");
78359191Skris				}
784160814Ssimon			else if (subject_hash == i)
78555714Skris				{
78655714Skris				BIO_printf(STDout,"%08lx\n",X509_subject_name_hash(x));
78755714Skris				}
788238405Sjkim#ifndef OPENSSL_NO_MD5
789238405Sjkim			else if (subject_hash_old == i)
790238405Sjkim				{
791238405Sjkim				BIO_printf(STDout,"%08lx\n",X509_subject_name_hash_old(x));
792238405Sjkim				}
793238405Sjkim#endif
794160814Ssimon			else if (issuer_hash == i)
795160814Ssimon				{
796160814Ssimon				BIO_printf(STDout,"%08lx\n",X509_issuer_name_hash(x));
797160814Ssimon				}
798238405Sjkim#ifndef OPENSSL_NO_MD5
799238405Sjkim			else if (issuer_hash_old == i)
800238405Sjkim				{
801238405Sjkim				BIO_printf(STDout,"%08lx\n",X509_issuer_name_hash_old(x));
802238405Sjkim				}
803238405Sjkim#endif
80459191Skris			else if (pprint == i)
80559191Skris				{
80659191Skris				X509_PURPOSE *ptmp;
80759191Skris				int j;
80859191Skris				BIO_printf(STDout, "Certificate purposes:\n");
80968651Skris				for (j = 0; j < X509_PURPOSE_get_count(); j++)
81059191Skris					{
81159191Skris					ptmp = X509_PURPOSE_get0(j);
81259191Skris					purpose_print(STDout, x, ptmp);
81359191Skris					}
81459191Skris				}
81555714Skris			else
81655714Skris				if (modulus == i)
81755714Skris				{
81855714Skris				EVP_PKEY *pkey;
81955714Skris
82055714Skris				pkey=X509_get_pubkey(x);
82155714Skris				if (pkey == NULL)
82255714Skris					{
82355714Skris					BIO_printf(bio_err,"Modulus=unavailable\n");
82455714Skris					ERR_print_errors(bio_err);
82555714Skris					goto end;
82655714Skris					}
82755714Skris				BIO_printf(STDout,"Modulus=");
828109998Smarkm#ifndef OPENSSL_NO_RSA
82955714Skris				if (pkey->type == EVP_PKEY_RSA)
83055714Skris					BN_print(STDout,pkey->pkey.rsa->n);
83155714Skris				else
83255714Skris#endif
833109998Smarkm#ifndef OPENSSL_NO_DSA
83455714Skris				if (pkey->type == EVP_PKEY_DSA)
83555714Skris					BN_print(STDout,pkey->pkey.dsa->pub_key);
83655714Skris				else
83755714Skris#endif
83855714Skris					BIO_printf(STDout,"Wrong Algorithm type");
83955714Skris				BIO_printf(STDout,"\n");
84055714Skris				EVP_PKEY_free(pkey);
84155714Skris				}
84255714Skris			else
84359191Skris				if (pubkey == i)
84459191Skris				{
84559191Skris				EVP_PKEY *pkey;
84659191Skris
84759191Skris				pkey=X509_get_pubkey(x);
84859191Skris				if (pkey == NULL)
84959191Skris					{
85059191Skris					BIO_printf(bio_err,"Error getting public key\n");
85159191Skris					ERR_print_errors(bio_err);
85259191Skris					goto end;
85359191Skris					}
85459191Skris				PEM_write_bio_PUBKEY(STDout, pkey);
85559191Skris				EVP_PKEY_free(pkey);
85659191Skris				}
85759191Skris			else
85855714Skris				if (C == i)
85955714Skris				{
86055714Skris				unsigned char *d;
86155714Skris				char *m;
86255714Skris				int y,z;
86355714Skris
86455714Skris				X509_NAME_oneline(X509_get_subject_name(x),
865109998Smarkm					buf,sizeof buf);
86655714Skris				BIO_printf(STDout,"/* subject:%s */\n",buf);
86755714Skris				m=X509_NAME_oneline(
868109998Smarkm					X509_get_issuer_name(x),buf,
869109998Smarkm					sizeof buf);
87055714Skris				BIO_printf(STDout,"/* issuer :%s */\n",buf);
87155714Skris
87255714Skris				z=i2d_X509(x,NULL);
87368651Skris				m=OPENSSL_malloc(z);
87455714Skris
87555714Skris				d=(unsigned char *)m;
87655714Skris				z=i2d_X509_NAME(X509_get_subject_name(x),&d);
87755714Skris				BIO_printf(STDout,"unsigned char XXX_subject_name[%d]={\n",z);
87855714Skris				d=(unsigned char *)m;
87955714Skris				for (y=0; y<z; y++)
88055714Skris					{
88155714Skris					BIO_printf(STDout,"0x%02X,",d[y]);
88255714Skris					if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n");
88355714Skris					}
88455714Skris				if (y%16 != 0) BIO_printf(STDout,"\n");
88555714Skris				BIO_printf(STDout,"};\n");
88655714Skris
88755714Skris				z=i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x),&d);
88855714Skris				BIO_printf(STDout,"unsigned char XXX_public_key[%d]={\n",z);
88955714Skris				d=(unsigned char *)m;
89055714Skris				for (y=0; y<z; y++)
89155714Skris					{
89255714Skris					BIO_printf(STDout,"0x%02X,",d[y]);
89355714Skris					if ((y & 0x0f) == 0x0f)
89455714Skris						BIO_printf(STDout,"\n");
89555714Skris					}
89655714Skris				if (y%16 != 0) BIO_printf(STDout,"\n");
89755714Skris				BIO_printf(STDout,"};\n");
89855714Skris
89955714Skris				z=i2d_X509(x,&d);
90055714Skris				BIO_printf(STDout,"unsigned char XXX_certificate[%d]={\n",z);
90155714Skris				d=(unsigned char *)m;
90255714Skris				for (y=0; y<z; y++)
90355714Skris					{
90455714Skris					BIO_printf(STDout,"0x%02X,",d[y]);
90555714Skris					if ((y & 0x0f) == 0x0f)
90655714Skris						BIO_printf(STDout,"\n");
90755714Skris					}
90855714Skris				if (y%16 != 0) BIO_printf(STDout,"\n");
90955714Skris				BIO_printf(STDout,"};\n");
91055714Skris
91168651Skris				OPENSSL_free(m);
91255714Skris				}
91355714Skris			else if (text == i)
91455714Skris				{
915246772Sjkim				X509_print_ex(STDout,x,nmflag, certflag);
91655714Skris				}
91755714Skris			else if (startdate == i)
91855714Skris				{
91955714Skris				BIO_puts(STDout,"notBefore=");
92055714Skris				ASN1_TIME_print(STDout,X509_get_notBefore(x));
92155714Skris				BIO_puts(STDout,"\n");
92255714Skris				}
92355714Skris			else if (enddate == i)
92455714Skris				{
92555714Skris				BIO_puts(STDout,"notAfter=");
92655714Skris				ASN1_TIME_print(STDout,X509_get_notAfter(x));
92755714Skris				BIO_puts(STDout,"\n");
92855714Skris				}
92955714Skris			else if (fingerprint == i)
93055714Skris				{
93155714Skris				int j;
93255714Skris				unsigned int n;
93355714Skris				unsigned char md[EVP_MAX_MD_SIZE];
934238405Sjkim				const EVP_MD *fdig = digest;
93555714Skris
936238405Sjkim				if (!fdig)
937238405Sjkim					fdig = EVP_sha1();
938238405Sjkim
939238405Sjkim				if (!X509_digest(x,fdig,md,&n))
94055714Skris					{
94155714Skris					BIO_printf(bio_err,"out of memory\n");
94255714Skris					goto end;
94355714Skris					}
94459191Skris				BIO_printf(STDout,"%s Fingerprint=",
945238405Sjkim						OBJ_nid2sn(EVP_MD_type(fdig)));
94655714Skris				for (j=0; j<(int)n; j++)
94755714Skris					{
94855714Skris					BIO_printf(STDout,"%02X%c",md[j],
94955714Skris						(j+1 == (int)n)
95055714Skris						?'\n':':');
95155714Skris					}
95255714Skris				}
95355714Skris
95455714Skris			/* should be in the library */
95555714Skris			else if ((sign_flag == i) && (x509req == 0))
95655714Skris				{
95755714Skris				BIO_printf(bio_err,"Getting Private key\n");
95855714Skris				if (Upkey == NULL)
95955714Skris					{
96068651Skris					Upkey=load_key(bio_err,
961109998Smarkm						keyfile, keyformat, 0,
962109998Smarkm						passin, e, "Private key");
96355714Skris					if (Upkey == NULL) goto end;
96455714Skris					}
96555714Skris
96659191Skris				assert(need_rand);
96759191Skris				if (!sign(x,Upkey,days,clrext,digest,
96855714Skris						 extconf, extsect)) goto end;
96955714Skris				}
97055714Skris			else if (CA_flag == i)
97155714Skris				{
97255714Skris				BIO_printf(bio_err,"Getting CA Private Key\n");
97355714Skris				if (CAkeyfile != NULL)
97455714Skris					{
97568651Skris					CApkey=load_key(bio_err,
976109998Smarkm						CAkeyfile, CAkeyformat,
977109998Smarkm						0, passin, e,
978109998Smarkm						"CA Private Key");
97955714Skris					if (CApkey == NULL) goto end;
98055714Skris					}
98155714Skris
98259191Skris				assert(need_rand);
98355714Skris				if (!x509_certify(ctx,CAfile,digest,x,xca,
984238405Sjkim					CApkey, sigopts,
985238405Sjkim					CAserial,CA_createserial,days, clrext,
986109998Smarkm					extconf, extsect, sno))
98755714Skris					goto end;
98855714Skris				}
98955714Skris			else if (x509req == i)
99055714Skris				{
99155714Skris				EVP_PKEY *pk;
99255714Skris
99355714Skris				BIO_printf(bio_err,"Getting request Private Key\n");
99455714Skris				if (keyfile == NULL)
99555714Skris					{
99655714Skris					BIO_printf(bio_err,"no request key file specified\n");
99755714Skris					goto end;
99855714Skris					}
99955714Skris				else
100055714Skris					{
100168651Skris					pk=load_key(bio_err,
1002237657Sjkim						keyfile, keyformat, 0,
1003109998Smarkm						passin, e, "request key");
100455714Skris					if (pk == NULL) goto end;
100555714Skris					}
100655714Skris
100755714Skris				BIO_printf(bio_err,"Generating certificate request\n");
100855714Skris
100959191Skris				rq=X509_to_X509_REQ(x,pk,digest);
101055714Skris				EVP_PKEY_free(pk);
101155714Skris				if (rq == NULL)
101255714Skris					{
101355714Skris					ERR_print_errors(bio_err);
101455714Skris					goto end;
101555714Skris					}
101655714Skris				if (!noout)
101755714Skris					{
101855714Skris					X509_REQ_print(out,rq);
101955714Skris					PEM_write_bio_X509_REQ(out,rq);
102055714Skris					}
102155714Skris				noout=1;
102255714Skris				}
1023109998Smarkm			else if (ocspid == i)
1024109998Smarkm				{
1025109998Smarkm				X509_ocspid_print(out, x);
1026109998Smarkm				}
102755714Skris			}
102855714Skris		}
102955714Skris
103068651Skris	if (checkend)
103168651Skris		{
1032160814Ssimon		time_t tcheck=time(NULL) + checkoffset;
103368651Skris
1034160814Ssimon		if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0)
103568651Skris			{
103668651Skris			BIO_printf(out,"Certificate will expire\n");
103768651Skris			ret=1;
103868651Skris			}
103968651Skris		else
104068651Skris			{
104168651Skris			BIO_printf(out,"Certificate will not expire\n");
104268651Skris			ret=0;
104368651Skris			}
104468651Skris		goto end;
104568651Skris		}
104668651Skris
104755714Skris	if (noout)
104855714Skris		{
104955714Skris		ret=0;
105055714Skris		goto end;
105155714Skris		}
105255714Skris
105355714Skris	if 	(outformat == FORMAT_ASN1)
105455714Skris		i=i2d_X509_bio(out,x);
105568651Skris	else if (outformat == FORMAT_PEM)
105668651Skris		{
105768651Skris		if (trustout) i=PEM_write_bio_X509_AUX(out,x);
105859191Skris		else i=PEM_write_bio_X509(out,x);
105968651Skris		}
106068651Skris	else if (outformat == FORMAT_NETSCAPE)
106155714Skris		{
1062238405Sjkim		NETSCAPE_X509 nx;
1063238405Sjkim		ASN1_OCTET_STRING hdr;
106455714Skris
1065238405Sjkim		hdr.data=(unsigned char *)NETSCAPE_CERT_HDR;
1066238405Sjkim		hdr.length=strlen(NETSCAPE_CERT_HDR);
1067238405Sjkim		nx.header= &hdr;
1068238405Sjkim		nx.cert=x;
106955714Skris
1070238405Sjkim		i=ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509),out,&nx);
107155714Skris		}
107255714Skris	else	{
107355714Skris		BIO_printf(bio_err,"bad output format specified for outfile\n");
107455714Skris		goto end;
107555714Skris		}
107668651Skris	if (!i)
107768651Skris		{
107855714Skris		BIO_printf(bio_err,"unable to write certificate\n");
107955714Skris		ERR_print_errors(bio_err);
108055714Skris		goto end;
108155714Skris		}
108255714Skris	ret=0;
108355714Skrisend:
108459191Skris	if (need_rand)
108559191Skris		app_RAND_write_file(NULL, bio_err);
108655714Skris	OBJ_cleanup();
1087109998Smarkm	NCONF_free(extconf);
108868651Skris	BIO_free_all(out);
108968651Skris	BIO_free_all(STDout);
109055714Skris	X509_STORE_free(ctx);
109155714Skris	X509_REQ_free(req);
109255714Skris	X509_free(x);
109355714Skris	X509_free(xca);
109455714Skris	EVP_PKEY_free(Upkey);
109555714Skris	EVP_PKEY_free(CApkey);
1096238405Sjkim	if (sigopts)
1097238405Sjkim		sk_OPENSSL_STRING_free(sigopts);
109855714Skris	X509_REQ_free(rq);
1099109998Smarkm	ASN1_INTEGER_free(sno);
110059191Skris	sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
110159191Skris	sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
110268651Skris	if (passin) OPENSSL_free(passin);
1103109998Smarkm	apps_shutdown();
1104109998Smarkm	OPENSSL_EXIT(ret);
110555714Skris	}
110655714Skris
1107127128Snectarstatic ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile, int create)
110855714Skris	{
1109109998Smarkm	char *buf = NULL, *p;
1110127128Snectar	ASN1_INTEGER *bs = NULL;
1111109998Smarkm	BIGNUM *serial = NULL;
1112127128Snectar	size_t len;
111355714Skris
1114127128Snectar	len = ((serialfile == NULL)
1115127128Snectar		?(strlen(CAfile)+strlen(POSTFIX)+1)
1116127128Snectar		:(strlen(serialfile)))+1;
1117127128Snectar	buf=OPENSSL_malloc(len);
111855714Skris	if (buf == NULL) { BIO_printf(bio_err,"out of mem\n"); goto end; }
111955714Skris	if (serialfile == NULL)
112055714Skris		{
1121127128Snectar		BUF_strlcpy(buf,CAfile,len);
112255714Skris		for (p=buf; *p; p++)
112355714Skris			if (*p == '.')
112455714Skris				{
112555714Skris				*p='\0';
112655714Skris				break;
112755714Skris				}
1128127128Snectar		BUF_strlcat(buf,POSTFIX,len);
112955714Skris		}
113055714Skris	else
1131127128Snectar		BUF_strlcpy(buf,serialfile,len);
113255714Skris
1133127128Snectar	serial = load_serial(buf, create, NULL);
1134127128Snectar	if (serial == NULL) goto end;
113555714Skris
113655714Skris	if (!BN_add_word(serial,1))
113755714Skris		{ BIO_printf(bio_err,"add_word failure\n"); goto end; }
1138109998Smarkm
1139127128Snectar	if (!save_serial(buf, NULL, serial, &bs)) goto end;
1140127128Snectar
1141127128Snectar end:
1142109998Smarkm	if (buf) OPENSSL_free(buf);
1143109998Smarkm	BN_free(serial);
1144109998Smarkm	return bs;
1145109998Smarkm	}
1146109998Smarkm
1147109998Smarkmstatic int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
1148238405Sjkim	     		X509 *x, X509 *xca, EVP_PKEY *pkey,
1149238405Sjkim			STACK_OF(OPENSSL_STRING) *sigopts,
1150238405Sjkim	  		char *serialfile, int create,
1151238405Sjkim	     		int days, int clrext, CONF *conf, char *section,
1152238405Sjkim			ASN1_INTEGER *sno)
1153109998Smarkm	{
1154109998Smarkm	int ret=0;
1155109998Smarkm	ASN1_INTEGER *bs=NULL;
1156109998Smarkm	X509_STORE_CTX xsc;
1157109998Smarkm	EVP_PKEY *upkey;
1158109998Smarkm
1159109998Smarkm	upkey = X509_get_pubkey(xca);
1160109998Smarkm	EVP_PKEY_copy_parameters(upkey,pkey);
1161109998Smarkm	EVP_PKEY_free(upkey);
1162109998Smarkm
1163109998Smarkm	if(!X509_STORE_CTX_init(&xsc,ctx,x,NULL))
1164109998Smarkm		{
1165109998Smarkm		BIO_printf(bio_err,"Error initialising X509 store\n");
1166109998Smarkm		goto end;
1167109998Smarkm		}
1168109998Smarkm	if (sno) bs = sno;
1169127128Snectar	else if (!(bs = x509_load_serial(CAfile, serialfile, create)))
1170109998Smarkm		goto end;
1171109998Smarkm
1172120631Snectar/*	if (!X509_STORE_add_cert(ctx,x)) goto end;*/
117355714Skris
117455714Skris	/* NOTE: this certificate can/should be self signed, unless it was
117555714Skris	 * a certificate request in which case it is not. */
117655714Skris	X509_STORE_CTX_set_cert(&xsc,x);
1177205128Ssimon	X509_STORE_CTX_set_flags(&xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
1178186872Ssimon	if (!reqfile && X509_verify_cert(&xsc) <= 0)
117955714Skris		goto end;
118055714Skris
118155714Skris	if (!X509_check_private_key(xca,pkey))
118255714Skris		{
118355714Skris		BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
118455714Skris		goto end;
118555714Skris		}
118655714Skris
118755714Skris	if (!X509_set_issuer_name(x,X509_get_subject_name(xca))) goto end;
118855714Skris	if (!X509_set_serialNumber(x,bs)) goto end;
118955714Skris
119055714Skris	if (X509_gmtime_adj(X509_get_notBefore(x),0L) == NULL)
119155714Skris		goto end;
119255714Skris
119355714Skris	/* hardwired expired */
1194238405Sjkim	if (X509_time_adj_ex(X509_get_notAfter(x),days, 0, NULL) == NULL)
119555714Skris		goto end;
119655714Skris
119768651Skris	if (clrext)
119868651Skris		{
119968651Skris		while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0);
120068651Skris		}
120159191Skris
120268651Skris	if (conf)
120368651Skris		{
120455714Skris		X509V3_CTX ctx2;
120555714Skris		X509_set_version(x,2); /* version 3 certificate */
120655714Skris                X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
1207109998Smarkm                X509V3_set_nconf(&ctx2, conf);
1208109998Smarkm                if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end;
120968651Skris		}
121055714Skris
1211238405Sjkim	if (!do_X509_sign(bio_err, x, pkey, digest, sigopts))
1212238405Sjkim		goto end;
121355714Skris	ret=1;
121455714Skrisend:
121555714Skris	X509_STORE_CTX_cleanup(&xsc);
121655714Skris	if (!ret)
121755714Skris		ERR_print_errors(bio_err);
1218109998Smarkm	if (!sno) ASN1_INTEGER_free(bs);
121968651Skris	return ret;
122055714Skris	}
122155714Skris
122255714Skrisstatic int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx)
122355714Skris	{
122455714Skris	int err;
122555714Skris	X509 *err_cert;
122655714Skris
122755714Skris	/* it is ok to use a self signed certificate
122855714Skris	 * This case will catch both the initial ok == 0 and the
122955714Skris	 * final ok == 1 calls to this function */
123055714Skris	err=X509_STORE_CTX_get_error(ctx);
123155714Skris	if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
123268651Skris		return 1;
123355714Skris
123455714Skris	/* BAD we should have gotten an error.  Normally if everything
123555714Skris	 * worked X509_STORE_CTX_get_error(ctx) will still be set to
123655714Skris	 * DEPTH_ZERO_SELF_.... */
123755714Skris	if (ok)
123855714Skris		{
123955714Skris		BIO_printf(bio_err,"error with certificate to be certified - should be self signed\n");
124068651Skris		return 0;
124155714Skris		}
124255714Skris	else
124355714Skris		{
124455714Skris		err_cert=X509_STORE_CTX_get_current_cert(ctx);
124568651Skris		print_name(bio_err, NULL, X509_get_subject_name(err_cert),0);
124655714Skris		BIO_printf(bio_err,"error with certificate - error %d at depth %d\n%s\n",
124755714Skris			err,X509_STORE_CTX_get_error_depth(ctx),
124855714Skris			X509_verify_cert_error_string(err));
124968651Skris		return 1;
125055714Skris		}
125155714Skris	}
125255714Skris
125355714Skris/* self sign */
125459191Skrisstatic int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest,
1255109998Smarkm						CONF *conf, char *section)
125655714Skris	{
125755714Skris
125855714Skris	EVP_PKEY *pktmp;
125955714Skris
126055714Skris	pktmp = X509_get_pubkey(x);
126155714Skris	EVP_PKEY_copy_parameters(pktmp,pkey);
126255714Skris	EVP_PKEY_save_parameters(pktmp,1);
126355714Skris	EVP_PKEY_free(pktmp);
126455714Skris
126555714Skris	if (!X509_set_issuer_name(x,X509_get_subject_name(x))) goto err;
126655714Skris	if (X509_gmtime_adj(X509_get_notBefore(x),0) == NULL) goto err;
126755714Skris
126855714Skris	/* Lets just make it 12:00am GMT, Jan 1 1970 */
126955714Skris	/* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
127055714Skris	/* 28 days to be certified */
127155714Skris
127255714Skris	if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL)
127355714Skris		goto err;
127455714Skris
127555714Skris	if (!X509_set_pubkey(x,pkey)) goto err;
127668651Skris	if (clrext)
127768651Skris		{
127868651Skris		while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0);
127968651Skris		}
128068651Skris	if (conf)
128168651Skris		{
128255714Skris		X509V3_CTX ctx;
128355714Skris		X509_set_version(x,2); /* version 3 certificate */
128455714Skris                X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
1285109998Smarkm                X509V3_set_nconf(&ctx, conf);
1286109998Smarkm                if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) goto err;
128768651Skris		}
128855714Skris	if (!X509_sign(x,pkey,digest)) goto err;
128968651Skris	return 1;
129055714Skriserr:
129155714Skris	ERR_print_errors(bio_err);
129268651Skris	return 0;
129355714Skris	}
129459191Skris
129559191Skrisstatic int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
129659191Skris{
129759191Skris	int id, i, idret;
129859191Skris	char *pname;
129959191Skris	id = X509_PURPOSE_get_id(pt);
130059191Skris	pname = X509_PURPOSE_get0_name(pt);
130168651Skris	for (i = 0; i < 2; i++)
130268651Skris		{
130359191Skris		idret = X509_check_purpose(cert, id, i);
130459191Skris		BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
130568651Skris		if (idret == 1) BIO_printf(bio, "Yes\n");
130659191Skris		else if (idret == 0) BIO_printf(bio, "No\n");
130759191Skris		else BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
130868651Skris		}
130959191Skris	return 1;
131059191Skris}
1311