10Sstevel@tonic-gate /* apps/x509.c */
20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30Sstevel@tonic-gate * All rights reserved.
40Sstevel@tonic-gate *
50Sstevel@tonic-gate * This package is an SSL implementation written
60Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com).
70Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as
100Sstevel@tonic-gate * the following conditions are aheared to. The following conditions
110Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA,
120Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation
130Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms
140Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150Sstevel@tonic-gate *
160Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in
170Sstevel@tonic-gate * the code are not to be removed.
180Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution
190Sstevel@tonic-gate * as the author of the parts of the library used.
200Sstevel@tonic-gate * This can be in the form of a textual message at program startup or
210Sstevel@tonic-gate * in documentation (online or textual) provided with the package.
220Sstevel@tonic-gate *
230Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
240Sstevel@tonic-gate * modification, are permitted provided that the following conditions
250Sstevel@tonic-gate * are met:
260Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright
270Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
280Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
290Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
300Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
310Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software
320Sstevel@tonic-gate * must display the following acknowledgement:
330Sstevel@tonic-gate * "This product includes cryptographic software written by
340Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)"
350Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library
360Sstevel@tonic-gate * being used are not cryptographic related :-).
370Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from
380Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement:
390Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400Sstevel@tonic-gate *
410Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
510Sstevel@tonic-gate * SUCH DAMAGE.
520Sstevel@tonic-gate *
530Sstevel@tonic-gate * The licence and distribution terms for any publically available version or
540Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be
550Sstevel@tonic-gate * copied and put under another distribution licence
560Sstevel@tonic-gate * [including the GNU Public Licence.]
570Sstevel@tonic-gate */
580Sstevel@tonic-gate
590Sstevel@tonic-gate #include <assert.h>
600Sstevel@tonic-gate #include <stdio.h>
610Sstevel@tonic-gate #include <stdlib.h>
620Sstevel@tonic-gate #include <string.h>
630Sstevel@tonic-gate #ifdef OPENSSL_NO_STDIO
640Sstevel@tonic-gate #define APPS_WIN16
650Sstevel@tonic-gate #endif
660Sstevel@tonic-gate #include "apps.h"
670Sstevel@tonic-gate #include <openssl/bio.h>
680Sstevel@tonic-gate #include <openssl/asn1.h>
690Sstevel@tonic-gate #include <openssl/err.h>
700Sstevel@tonic-gate #include <openssl/bn.h>
710Sstevel@tonic-gate #include <openssl/evp.h>
720Sstevel@tonic-gate #include <openssl/x509.h>
730Sstevel@tonic-gate #include <openssl/x509v3.h>
740Sstevel@tonic-gate #include <openssl/objects.h>
750Sstevel@tonic-gate #include <openssl/pem.h>
762139Sjp161948 #ifndef OPENSSL_NO_RSA
772139Sjp161948 #include <openssl/rsa.h>
782139Sjp161948 #endif
792139Sjp161948 #ifndef OPENSSL_NO_DSA
802139Sjp161948 #include <openssl/dsa.h>
812139Sjp161948 #endif
820Sstevel@tonic-gate
830Sstevel@tonic-gate #undef PROG
840Sstevel@tonic-gate #define PROG x509_main
850Sstevel@tonic-gate
860Sstevel@tonic-gate #undef POSTFIX
870Sstevel@tonic-gate #define POSTFIX ".srl"
880Sstevel@tonic-gate #define DEF_DAYS 30
890Sstevel@tonic-gate
902139Sjp161948 static const char *x509_usage[]={
910Sstevel@tonic-gate "usage: x509 args\n",
920Sstevel@tonic-gate " -inform arg - input format - default PEM (one of DER, NET or PEM)\n",
930Sstevel@tonic-gate " -outform arg - output format - default PEM (one of DER, NET or PEM)\n",
940Sstevel@tonic-gate " -keyform arg - private key format - default PEM\n",
950Sstevel@tonic-gate " -CAform arg - CA format - default PEM\n",
960Sstevel@tonic-gate " -CAkeyform arg - CA key format - default PEM\n",
970Sstevel@tonic-gate " -in arg - input file - default stdin\n",
980Sstevel@tonic-gate " -out arg - output file - default stdout\n",
990Sstevel@tonic-gate " -passin arg - private key password source\n",
1000Sstevel@tonic-gate " -serial - print serial number value\n",
1012139Sjp161948 " -subject_hash - print subject hash value\n",
1022139Sjp161948 " -issuer_hash - print issuer hash value\n",
1032139Sjp161948 " -hash - synonym for -subject_hash\n",
1040Sstevel@tonic-gate " -subject - print subject DN\n",
1050Sstevel@tonic-gate " -issuer - print issuer DN\n",
1060Sstevel@tonic-gate " -email - print email address(es)\n",
1070Sstevel@tonic-gate " -startdate - notBefore field\n",
1080Sstevel@tonic-gate " -enddate - notAfter field\n",
1090Sstevel@tonic-gate " -purpose - print out certificate purposes\n",
1100Sstevel@tonic-gate " -dates - both Before and After dates\n",
1110Sstevel@tonic-gate " -modulus - print the RSA key modulus\n",
1120Sstevel@tonic-gate " -pubkey - output the public key\n",
1130Sstevel@tonic-gate " -fingerprint - print the certificate fingerprint\n",
1140Sstevel@tonic-gate " -alias - output certificate alias\n",
1150Sstevel@tonic-gate " -noout - no certificate output\n",
1160Sstevel@tonic-gate " -ocspid - print OCSP hash values for the subject name and public key\n",
1170Sstevel@tonic-gate " -trustout - output a \"trusted\" certificate\n",
1180Sstevel@tonic-gate " -clrtrust - clear all trusted purposes\n",
1190Sstevel@tonic-gate " -clrreject - clear all rejected purposes\n",
1200Sstevel@tonic-gate " -addtrust arg - trust certificate for a given purpose\n",
1210Sstevel@tonic-gate " -addreject arg - reject certificate for a given purpose\n",
1220Sstevel@tonic-gate " -setalias arg - set certificate alias\n",
1230Sstevel@tonic-gate " -days arg - How long till expiry of a signed certificate - def 30 days\n",
1240Sstevel@tonic-gate " -checkend arg - check whether the cert expires in the next arg seconds\n",
1250Sstevel@tonic-gate " exit 1 if so, 0 if not\n",
1260Sstevel@tonic-gate " -signkey arg - self sign cert with arg\n",
1270Sstevel@tonic-gate " -x509toreq - output a certification request object\n",
1280Sstevel@tonic-gate " -req - input is a certificate request, sign and output.\n",
1290Sstevel@tonic-gate " -CA arg - set the CA certificate, must be PEM format.\n",
1300Sstevel@tonic-gate " -CAkey arg - set the CA key, must be PEM format\n",
1310Sstevel@tonic-gate " missing, it is assumed to be in the CA file.\n",
1320Sstevel@tonic-gate " -CAcreateserial - create serial number file if it does not exist\n",
1330Sstevel@tonic-gate " -CAserial arg - serial file\n",
1340Sstevel@tonic-gate " -set_serial - serial number to use\n",
1350Sstevel@tonic-gate " -text - print the certificate in text form\n",
1360Sstevel@tonic-gate " -C - print out C code forms\n",
1370Sstevel@tonic-gate " -md2/-md5/-sha1/-mdc2 - digest to use\n",
1380Sstevel@tonic-gate " -extfile - configuration file with X509V3 extensions to add\n",
1390Sstevel@tonic-gate " -extensions - section from config file with X509V3 extensions to add\n",
1400Sstevel@tonic-gate " -clrext - delete extensions before signing and input certificate\n",
1410Sstevel@tonic-gate " -nameopt arg - various certificate name options\n",
1420Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
1430Sstevel@tonic-gate " -engine e - use engine e, possibly a hardware device.\n",
1440Sstevel@tonic-gate #endif
1450Sstevel@tonic-gate " -certopt arg - various certificate text options\n",
1460Sstevel@tonic-gate NULL
1470Sstevel@tonic-gate };
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx);
1500Sstevel@tonic-gate static int sign (X509 *x, EVP_PKEY *pkey,int days,int clrext, const EVP_MD *digest,
1510Sstevel@tonic-gate CONF *conf, char *section);
1520Sstevel@tonic-gate static int x509_certify (X509_STORE *ctx,char *CAfile,const EVP_MD *digest,
1530Sstevel@tonic-gate X509 *x,X509 *xca,EVP_PKEY *pkey,char *serial,
1540Sstevel@tonic-gate int create,int days, int clrext, CONF *conf, char *section,
1550Sstevel@tonic-gate ASN1_INTEGER *sno);
1560Sstevel@tonic-gate static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
1570Sstevel@tonic-gate static int reqfile=0;
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate int MAIN(int, char **);
1600Sstevel@tonic-gate
MAIN(int argc,char ** argv)1610Sstevel@tonic-gate int MAIN(int argc, char **argv)
1620Sstevel@tonic-gate {
1630Sstevel@tonic-gate ENGINE *e = NULL;
1640Sstevel@tonic-gate int ret=1;
1650Sstevel@tonic-gate X509_REQ *req=NULL;
1660Sstevel@tonic-gate X509 *x=NULL,*xca=NULL;
1670Sstevel@tonic-gate ASN1_OBJECT *objtmp;
1680Sstevel@tonic-gate EVP_PKEY *Upkey=NULL,*CApkey=NULL;
1690Sstevel@tonic-gate ASN1_INTEGER *sno = NULL;
1700Sstevel@tonic-gate int i,num,badops=0;
1710Sstevel@tonic-gate BIO *out=NULL;
1720Sstevel@tonic-gate BIO *STDout=NULL;
1730Sstevel@tonic-gate STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
1740Sstevel@tonic-gate int informat,outformat,keyformat,CAformat,CAkeyformat;
1750Sstevel@tonic-gate char *infile=NULL,*outfile=NULL,*keyfile=NULL,*CAfile=NULL;
1760Sstevel@tonic-gate char *CAkeyfile=NULL,*CAserial=NULL;
1770Sstevel@tonic-gate char *alias=NULL;
1782139Sjp161948 int text=0,serial=0,subject=0,issuer=0,startdate=0,enddate=0;
1792139Sjp161948 int next_serial=0;
1802139Sjp161948 int subject_hash=0,issuer_hash=0,ocspid=0;
1810Sstevel@tonic-gate int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0,email=0;
1820Sstevel@tonic-gate int trustout=0,clrtrust=0,clrreject=0,aliasout=0,clrext=0;
1830Sstevel@tonic-gate int C=0;
1840Sstevel@tonic-gate int x509req=0,days=DEF_DAYS,modulus=0,pubkey=0;
1850Sstevel@tonic-gate int pprint = 0;
1862139Sjp161948 const char **pp;
1870Sstevel@tonic-gate X509_STORE *ctx=NULL;
1880Sstevel@tonic-gate X509_REQ *rq=NULL;
1890Sstevel@tonic-gate int fingerprint=0;
1900Sstevel@tonic-gate char buf[256];
1912139Sjp161948 const EVP_MD *md_alg,*digest=EVP_sha1();
1920Sstevel@tonic-gate CONF *extconf = NULL;
1930Sstevel@tonic-gate char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
1940Sstevel@tonic-gate int need_rand = 0;
1950Sstevel@tonic-gate int checkend=0,checkoffset=0;
1960Sstevel@tonic-gate unsigned long nmflag = 0, certflag = 0;
1970Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
1980Sstevel@tonic-gate char *engine=NULL;
1990Sstevel@tonic-gate #endif
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate reqfile=0;
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate apps_startup();
2040Sstevel@tonic-gate
2050Sstevel@tonic-gate if (bio_err == NULL)
2060Sstevel@tonic-gate bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate if (!load_config(bio_err, NULL))
2090Sstevel@tonic-gate goto end;
2100Sstevel@tonic-gate STDout=BIO_new_fp(stdout,BIO_NOCLOSE);
2110Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
2120Sstevel@tonic-gate {
2130Sstevel@tonic-gate BIO *tmpbio = BIO_new(BIO_f_linebuffer());
2140Sstevel@tonic-gate STDout = BIO_push(tmpbio, STDout);
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate #endif
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate informat=FORMAT_PEM;
2190Sstevel@tonic-gate outformat=FORMAT_PEM;
2200Sstevel@tonic-gate keyformat=FORMAT_PEM;
2210Sstevel@tonic-gate CAformat=FORMAT_PEM;
2220Sstevel@tonic-gate CAkeyformat=FORMAT_PEM;
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate ctx=X509_STORE_new();
2250Sstevel@tonic-gate if (ctx == NULL) goto end;
2260Sstevel@tonic-gate X509_STORE_set_verify_cb_func(ctx,callb);
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate argc--;
2290Sstevel@tonic-gate argv++;
2300Sstevel@tonic-gate num=0;
2310Sstevel@tonic-gate while (argc >= 1)
2320Sstevel@tonic-gate {
2330Sstevel@tonic-gate if (strcmp(*argv,"-inform") == 0)
2340Sstevel@tonic-gate {
2350Sstevel@tonic-gate if (--argc < 1) goto bad;
2360Sstevel@tonic-gate informat=str2fmt(*(++argv));
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate else if (strcmp(*argv,"-outform") == 0)
2390Sstevel@tonic-gate {
2400Sstevel@tonic-gate if (--argc < 1) goto bad;
2410Sstevel@tonic-gate outformat=str2fmt(*(++argv));
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate else if (strcmp(*argv,"-keyform") == 0)
2440Sstevel@tonic-gate {
2450Sstevel@tonic-gate if (--argc < 1) goto bad;
2460Sstevel@tonic-gate keyformat=str2fmt(*(++argv));
2470Sstevel@tonic-gate }
2480Sstevel@tonic-gate else if (strcmp(*argv,"-req") == 0)
2490Sstevel@tonic-gate {
2500Sstevel@tonic-gate reqfile=1;
2510Sstevel@tonic-gate need_rand = 1;
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate else if (strcmp(*argv,"-CAform") == 0)
2540Sstevel@tonic-gate {
2550Sstevel@tonic-gate if (--argc < 1) goto bad;
2560Sstevel@tonic-gate CAformat=str2fmt(*(++argv));
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate else if (strcmp(*argv,"-CAkeyform") == 0)
2590Sstevel@tonic-gate {
2600Sstevel@tonic-gate if (--argc < 1) goto bad;
2610Sstevel@tonic-gate CAkeyformat=str2fmt(*(++argv));
2620Sstevel@tonic-gate }
2630Sstevel@tonic-gate else if (strcmp(*argv,"-days") == 0)
2640Sstevel@tonic-gate {
2650Sstevel@tonic-gate if (--argc < 1) goto bad;
2660Sstevel@tonic-gate days=atoi(*(++argv));
2670Sstevel@tonic-gate if (days == 0)
2680Sstevel@tonic-gate {
2690Sstevel@tonic-gate BIO_printf(STDout,"bad number of days\n");
2700Sstevel@tonic-gate goto bad;
2710Sstevel@tonic-gate }
2720Sstevel@tonic-gate }
2730Sstevel@tonic-gate else if (strcmp(*argv,"-passin") == 0)
2740Sstevel@tonic-gate {
2750Sstevel@tonic-gate if (--argc < 1) goto bad;
2760Sstevel@tonic-gate passargin= *(++argv);
2770Sstevel@tonic-gate }
2780Sstevel@tonic-gate else if (strcmp(*argv,"-extfile") == 0)
2790Sstevel@tonic-gate {
2800Sstevel@tonic-gate if (--argc < 1) goto bad;
2810Sstevel@tonic-gate extfile= *(++argv);
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate else if (strcmp(*argv,"-extensions") == 0)
2840Sstevel@tonic-gate {
2850Sstevel@tonic-gate if (--argc < 1) goto bad;
2860Sstevel@tonic-gate extsect= *(++argv);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate else if (strcmp(*argv,"-in") == 0)
2890Sstevel@tonic-gate {
2900Sstevel@tonic-gate if (--argc < 1) goto bad;
2910Sstevel@tonic-gate infile= *(++argv);
2920Sstevel@tonic-gate }
2930Sstevel@tonic-gate else if (strcmp(*argv,"-out") == 0)
2940Sstevel@tonic-gate {
2950Sstevel@tonic-gate if (--argc < 1) goto bad;
2960Sstevel@tonic-gate outfile= *(++argv);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate else if (strcmp(*argv,"-signkey") == 0)
2990Sstevel@tonic-gate {
3000Sstevel@tonic-gate if (--argc < 1) goto bad;
3010Sstevel@tonic-gate keyfile= *(++argv);
3020Sstevel@tonic-gate sign_flag= ++num;
3030Sstevel@tonic-gate need_rand = 1;
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate else if (strcmp(*argv,"-CA") == 0)
3060Sstevel@tonic-gate {
3070Sstevel@tonic-gate if (--argc < 1) goto bad;
3080Sstevel@tonic-gate CAfile= *(++argv);
3090Sstevel@tonic-gate CA_flag= ++num;
3100Sstevel@tonic-gate need_rand = 1;
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate else if (strcmp(*argv,"-CAkey") == 0)
3130Sstevel@tonic-gate {
3140Sstevel@tonic-gate if (--argc < 1) goto bad;
3150Sstevel@tonic-gate CAkeyfile= *(++argv);
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate else if (strcmp(*argv,"-CAserial") == 0)
3180Sstevel@tonic-gate {
3190Sstevel@tonic-gate if (--argc < 1) goto bad;
3200Sstevel@tonic-gate CAserial= *(++argv);
3210Sstevel@tonic-gate }
3220Sstevel@tonic-gate else if (strcmp(*argv,"-set_serial") == 0)
3230Sstevel@tonic-gate {
3240Sstevel@tonic-gate if (--argc < 1) goto bad;
3250Sstevel@tonic-gate if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
3260Sstevel@tonic-gate goto bad;
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate else if (strcmp(*argv,"-addtrust") == 0)
3290Sstevel@tonic-gate {
3300Sstevel@tonic-gate if (--argc < 1) goto bad;
3310Sstevel@tonic-gate if (!(objtmp = OBJ_txt2obj(*(++argv), 0)))
3320Sstevel@tonic-gate {
3330Sstevel@tonic-gate BIO_printf(bio_err,
3340Sstevel@tonic-gate "Invalid trust object value %s\n", *argv);
3350Sstevel@tonic-gate goto bad;
3360Sstevel@tonic-gate }
3370Sstevel@tonic-gate if (!trust) trust = sk_ASN1_OBJECT_new_null();
3380Sstevel@tonic-gate sk_ASN1_OBJECT_push(trust, objtmp);
3390Sstevel@tonic-gate trustout = 1;
3400Sstevel@tonic-gate }
3410Sstevel@tonic-gate else if (strcmp(*argv,"-addreject") == 0)
3420Sstevel@tonic-gate {
3430Sstevel@tonic-gate if (--argc < 1) goto bad;
3440Sstevel@tonic-gate if (!(objtmp = OBJ_txt2obj(*(++argv), 0)))
3450Sstevel@tonic-gate {
3460Sstevel@tonic-gate BIO_printf(bio_err,
3470Sstevel@tonic-gate "Invalid reject object value %s\n", *argv);
3480Sstevel@tonic-gate goto bad;
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate if (!reject) reject = sk_ASN1_OBJECT_new_null();
3510Sstevel@tonic-gate sk_ASN1_OBJECT_push(reject, objtmp);
3520Sstevel@tonic-gate trustout = 1;
3530Sstevel@tonic-gate }
3540Sstevel@tonic-gate else if (strcmp(*argv,"-setalias") == 0)
3550Sstevel@tonic-gate {
3560Sstevel@tonic-gate if (--argc < 1) goto bad;
3570Sstevel@tonic-gate alias= *(++argv);
3580Sstevel@tonic-gate trustout = 1;
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate else if (strcmp(*argv,"-certopt") == 0)
3610Sstevel@tonic-gate {
3620Sstevel@tonic-gate if (--argc < 1) goto bad;
3630Sstevel@tonic-gate if (!set_cert_ex(&certflag, *(++argv))) goto bad;
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate else if (strcmp(*argv,"-nameopt") == 0)
3660Sstevel@tonic-gate {
3670Sstevel@tonic-gate if (--argc < 1) goto bad;
3680Sstevel@tonic-gate if (!set_name_ex(&nmflag, *(++argv))) goto bad;
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
3710Sstevel@tonic-gate else if (strcmp(*argv,"-engine") == 0)
3720Sstevel@tonic-gate {
3730Sstevel@tonic-gate if (--argc < 1) goto bad;
3740Sstevel@tonic-gate engine= *(++argv);
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate #endif
3770Sstevel@tonic-gate else if (strcmp(*argv,"-C") == 0)
3780Sstevel@tonic-gate C= ++num;
3790Sstevel@tonic-gate else if (strcmp(*argv,"-email") == 0)
3800Sstevel@tonic-gate email= ++num;
3810Sstevel@tonic-gate else if (strcmp(*argv,"-serial") == 0)
3820Sstevel@tonic-gate serial= ++num;
3832139Sjp161948 else if (strcmp(*argv,"-next_serial") == 0)
3842139Sjp161948 next_serial= ++num;
3850Sstevel@tonic-gate else if (strcmp(*argv,"-modulus") == 0)
3860Sstevel@tonic-gate modulus= ++num;
3870Sstevel@tonic-gate else if (strcmp(*argv,"-pubkey") == 0)
3880Sstevel@tonic-gate pubkey= ++num;
3890Sstevel@tonic-gate else if (strcmp(*argv,"-x509toreq") == 0)
3900Sstevel@tonic-gate x509req= ++num;
3910Sstevel@tonic-gate else if (strcmp(*argv,"-text") == 0)
3920Sstevel@tonic-gate text= ++num;
3932139Sjp161948 else if (strcmp(*argv,"-hash") == 0
3942139Sjp161948 || strcmp(*argv,"-subject_hash") == 0)
3952139Sjp161948 subject_hash= ++num;
3962139Sjp161948 else if (strcmp(*argv,"-issuer_hash") == 0)
3972139Sjp161948 issuer_hash= ++num;
3980Sstevel@tonic-gate else if (strcmp(*argv,"-subject") == 0)
3990Sstevel@tonic-gate subject= ++num;
4000Sstevel@tonic-gate else if (strcmp(*argv,"-issuer") == 0)
4010Sstevel@tonic-gate issuer= ++num;
4020Sstevel@tonic-gate else if (strcmp(*argv,"-fingerprint") == 0)
4030Sstevel@tonic-gate fingerprint= ++num;
4040Sstevel@tonic-gate else if (strcmp(*argv,"-dates") == 0)
4050Sstevel@tonic-gate {
4060Sstevel@tonic-gate startdate= ++num;
4070Sstevel@tonic-gate enddate= ++num;
4080Sstevel@tonic-gate }
4090Sstevel@tonic-gate else if (strcmp(*argv,"-purpose") == 0)
4100Sstevel@tonic-gate pprint= ++num;
4110Sstevel@tonic-gate else if (strcmp(*argv,"-startdate") == 0)
4120Sstevel@tonic-gate startdate= ++num;
4130Sstevel@tonic-gate else if (strcmp(*argv,"-enddate") == 0)
4140Sstevel@tonic-gate enddate= ++num;
4150Sstevel@tonic-gate else if (strcmp(*argv,"-checkend") == 0)
4160Sstevel@tonic-gate {
4170Sstevel@tonic-gate if (--argc < 1) goto bad;
4180Sstevel@tonic-gate checkoffset=atoi(*(++argv));
4190Sstevel@tonic-gate checkend=1;
4200Sstevel@tonic-gate }
4210Sstevel@tonic-gate else if (strcmp(*argv,"-noout") == 0)
4220Sstevel@tonic-gate noout= ++num;
4230Sstevel@tonic-gate else if (strcmp(*argv,"-trustout") == 0)
4240Sstevel@tonic-gate trustout= 1;
4250Sstevel@tonic-gate else if (strcmp(*argv,"-clrtrust") == 0)
4260Sstevel@tonic-gate clrtrust= ++num;
4270Sstevel@tonic-gate else if (strcmp(*argv,"-clrreject") == 0)
4280Sstevel@tonic-gate clrreject= ++num;
4290Sstevel@tonic-gate else if (strcmp(*argv,"-alias") == 0)
4300Sstevel@tonic-gate aliasout= ++num;
4310Sstevel@tonic-gate else if (strcmp(*argv,"-CAcreateserial") == 0)
4320Sstevel@tonic-gate CA_createserial= ++num;
4330Sstevel@tonic-gate else if (strcmp(*argv,"-clrext") == 0)
4340Sstevel@tonic-gate clrext = 1;
4350Sstevel@tonic-gate #if 1 /* stay backwards-compatible with 0.9.5; this should go away soon */
4360Sstevel@tonic-gate else if (strcmp(*argv,"-crlext") == 0)
4370Sstevel@tonic-gate {
4380Sstevel@tonic-gate BIO_printf(bio_err,"use -clrext instead of -crlext\n");
4390Sstevel@tonic-gate clrext = 1;
4400Sstevel@tonic-gate }
4410Sstevel@tonic-gate #endif
4420Sstevel@tonic-gate else if (strcmp(*argv,"-ocspid") == 0)
4430Sstevel@tonic-gate ocspid= ++num;
4440Sstevel@tonic-gate else if ((md_alg=EVP_get_digestbyname(*argv + 1)))
4450Sstevel@tonic-gate {
4460Sstevel@tonic-gate /* ok */
4470Sstevel@tonic-gate digest=md_alg;
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate else
4500Sstevel@tonic-gate {
4510Sstevel@tonic-gate BIO_printf(bio_err,"unknown option %s\n",*argv);
4520Sstevel@tonic-gate badops=1;
4530Sstevel@tonic-gate break;
4540Sstevel@tonic-gate }
4550Sstevel@tonic-gate argc--;
4560Sstevel@tonic-gate argv++;
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate if (badops)
4600Sstevel@tonic-gate {
4610Sstevel@tonic-gate bad:
4620Sstevel@tonic-gate for (pp=x509_usage; (*pp != NULL); pp++)
4630Sstevel@tonic-gate BIO_printf(bio_err,"%s",*pp);
4640Sstevel@tonic-gate goto end;
4650Sstevel@tonic-gate }
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
4680Sstevel@tonic-gate e = setup_engine(bio_err, engine, 0);
4690Sstevel@tonic-gate #endif
4700Sstevel@tonic-gate
4710Sstevel@tonic-gate if (need_rand)
4720Sstevel@tonic-gate app_RAND_load_file(NULL, bio_err, 0);
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate ERR_load_crypto_strings();
4750Sstevel@tonic-gate
4760Sstevel@tonic-gate if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
4770Sstevel@tonic-gate {
4780Sstevel@tonic-gate BIO_printf(bio_err, "Error getting password\n");
4790Sstevel@tonic-gate goto end;
4800Sstevel@tonic-gate }
4810Sstevel@tonic-gate
4820Sstevel@tonic-gate if (!X509_STORE_set_default_paths(ctx))
4830Sstevel@tonic-gate {
4840Sstevel@tonic-gate ERR_print_errors(bio_err);
4850Sstevel@tonic-gate goto end;
4860Sstevel@tonic-gate }
4870Sstevel@tonic-gate
4880Sstevel@tonic-gate if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM))
4890Sstevel@tonic-gate { CAkeyfile=CAfile; }
4900Sstevel@tonic-gate else if ((CA_flag) && (CAkeyfile == NULL))
4910Sstevel@tonic-gate {
4920Sstevel@tonic-gate BIO_printf(bio_err,"need to specify a CAkey if using the CA command\n");
4930Sstevel@tonic-gate goto end;
4940Sstevel@tonic-gate }
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate if (extfile)
4970Sstevel@tonic-gate {
4980Sstevel@tonic-gate long errorline = -1;
4990Sstevel@tonic-gate X509V3_CTX ctx2;
5000Sstevel@tonic-gate extconf = NCONF_new(NULL);
5010Sstevel@tonic-gate if (!NCONF_load(extconf, extfile,&errorline))
5020Sstevel@tonic-gate {
5030Sstevel@tonic-gate if (errorline <= 0)
5040Sstevel@tonic-gate BIO_printf(bio_err,
5050Sstevel@tonic-gate "error loading the config file '%s'\n",
5060Sstevel@tonic-gate extfile);
5070Sstevel@tonic-gate else
5080Sstevel@tonic-gate BIO_printf(bio_err,
5090Sstevel@tonic-gate "error on line %ld of config file '%s'\n"
5100Sstevel@tonic-gate ,errorline,extfile);
5110Sstevel@tonic-gate goto end;
5120Sstevel@tonic-gate }
5130Sstevel@tonic-gate if (!extsect)
5140Sstevel@tonic-gate {
5150Sstevel@tonic-gate extsect = NCONF_get_string(extconf, "default", "extensions");
5160Sstevel@tonic-gate if (!extsect)
5170Sstevel@tonic-gate {
5180Sstevel@tonic-gate ERR_clear_error();
5190Sstevel@tonic-gate extsect = "default";
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate X509V3_set_ctx_test(&ctx2);
5230Sstevel@tonic-gate X509V3_set_nconf(&ctx2, extconf);
5240Sstevel@tonic-gate if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL))
5250Sstevel@tonic-gate {
5260Sstevel@tonic-gate BIO_printf(bio_err,
5270Sstevel@tonic-gate "Error Loading extension section %s\n",
5280Sstevel@tonic-gate extsect);
5290Sstevel@tonic-gate ERR_print_errors(bio_err);
5300Sstevel@tonic-gate goto end;
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate }
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate if (reqfile)
5360Sstevel@tonic-gate {
5370Sstevel@tonic-gate EVP_PKEY *pkey;
5380Sstevel@tonic-gate X509_CINF *ci;
5390Sstevel@tonic-gate BIO *in;
5400Sstevel@tonic-gate
5410Sstevel@tonic-gate if (!sign_flag && !CA_flag)
5420Sstevel@tonic-gate {
5430Sstevel@tonic-gate BIO_printf(bio_err,"We need a private key to sign with\n");
5440Sstevel@tonic-gate goto end;
5450Sstevel@tonic-gate }
5460Sstevel@tonic-gate in=BIO_new(BIO_s_file());
5470Sstevel@tonic-gate if (in == NULL)
5480Sstevel@tonic-gate {
5490Sstevel@tonic-gate ERR_print_errors(bio_err);
5500Sstevel@tonic-gate goto end;
5510Sstevel@tonic-gate }
5520Sstevel@tonic-gate
5530Sstevel@tonic-gate if (infile == NULL)
5540Sstevel@tonic-gate BIO_set_fp(in,stdin,BIO_NOCLOSE|BIO_FP_TEXT);
5550Sstevel@tonic-gate else
5560Sstevel@tonic-gate {
5570Sstevel@tonic-gate if (BIO_read_filename(in,infile) <= 0)
5580Sstevel@tonic-gate {
5590Sstevel@tonic-gate perror(infile);
5600Sstevel@tonic-gate BIO_free(in);
5610Sstevel@tonic-gate goto end;
5620Sstevel@tonic-gate }
5630Sstevel@tonic-gate }
5640Sstevel@tonic-gate req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
5650Sstevel@tonic-gate BIO_free(in);
5660Sstevel@tonic-gate
5670Sstevel@tonic-gate if (req == NULL)
5680Sstevel@tonic-gate {
5690Sstevel@tonic-gate ERR_print_errors(bio_err);
5700Sstevel@tonic-gate goto end;
5710Sstevel@tonic-gate }
5720Sstevel@tonic-gate
5730Sstevel@tonic-gate if ( (req->req_info == NULL) ||
5740Sstevel@tonic-gate (req->req_info->pubkey == NULL) ||
5750Sstevel@tonic-gate (req->req_info->pubkey->public_key == NULL) ||
5760Sstevel@tonic-gate (req->req_info->pubkey->public_key->data == NULL))
5770Sstevel@tonic-gate {
5780Sstevel@tonic-gate BIO_printf(bio_err,"The certificate request appears to corrupted\n");
5790Sstevel@tonic-gate BIO_printf(bio_err,"It does not contain a public key\n");
5800Sstevel@tonic-gate goto end;
5810Sstevel@tonic-gate }
5820Sstevel@tonic-gate if ((pkey=X509_REQ_get_pubkey(req)) == NULL)
5830Sstevel@tonic-gate {
5840Sstevel@tonic-gate BIO_printf(bio_err,"error unpacking public key\n");
5850Sstevel@tonic-gate goto end;
5860Sstevel@tonic-gate }
5870Sstevel@tonic-gate i=X509_REQ_verify(req,pkey);
5880Sstevel@tonic-gate EVP_PKEY_free(pkey);
5890Sstevel@tonic-gate if (i < 0)
5900Sstevel@tonic-gate {
5910Sstevel@tonic-gate BIO_printf(bio_err,"Signature verification error\n");
5920Sstevel@tonic-gate ERR_print_errors(bio_err);
5930Sstevel@tonic-gate goto end;
5940Sstevel@tonic-gate }
5950Sstevel@tonic-gate if (i == 0)
5960Sstevel@tonic-gate {
5970Sstevel@tonic-gate BIO_printf(bio_err,"Signature did not match the certificate request\n");
5980Sstevel@tonic-gate goto end;
5990Sstevel@tonic-gate }
6000Sstevel@tonic-gate else
6010Sstevel@tonic-gate BIO_printf(bio_err,"Signature ok\n");
6020Sstevel@tonic-gate
6030Sstevel@tonic-gate print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag);
6040Sstevel@tonic-gate
6050Sstevel@tonic-gate if ((x=X509_new()) == NULL) goto end;
6060Sstevel@tonic-gate ci=x->cert_info;
6070Sstevel@tonic-gate
6082139Sjp161948 if (sno == NULL)
6090Sstevel@tonic-gate {
6102139Sjp161948 sno = ASN1_INTEGER_new();
6112139Sjp161948 if (!sno || !rand_serial(NULL, sno))
6122139Sjp161948 goto end;
6132139Sjp161948 if (!X509_set_serialNumber(x, sno))
6140Sstevel@tonic-gate goto end;
6152139Sjp161948 ASN1_INTEGER_free(sno);
6162139Sjp161948 sno = NULL;
6170Sstevel@tonic-gate }
6182139Sjp161948 else if (!X509_set_serialNumber(x, sno))
6192139Sjp161948 goto end;
6202139Sjp161948
6210Sstevel@tonic-gate if (!X509_set_issuer_name(x,req->req_info->subject)) goto end;
6220Sstevel@tonic-gate if (!X509_set_subject_name(x,req->req_info->subject)) goto end;
6230Sstevel@tonic-gate
6240Sstevel@tonic-gate X509_gmtime_adj(X509_get_notBefore(x),0);
6250Sstevel@tonic-gate X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days);
6260Sstevel@tonic-gate
6270Sstevel@tonic-gate pkey = X509_REQ_get_pubkey(req);
6280Sstevel@tonic-gate X509_set_pubkey(x,pkey);
6290Sstevel@tonic-gate EVP_PKEY_free(pkey);
6300Sstevel@tonic-gate }
6310Sstevel@tonic-gate else
6320Sstevel@tonic-gate x=load_cert(bio_err,infile,informat,NULL,e,"Certificate");
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate if (x == NULL) goto end;
6350Sstevel@tonic-gate if (CA_flag)
6360Sstevel@tonic-gate {
6370Sstevel@tonic-gate xca=load_cert(bio_err,CAfile,CAformat,NULL,e,"CA Certificate");
6380Sstevel@tonic-gate if (xca == NULL) goto end;
6390Sstevel@tonic-gate }
6400Sstevel@tonic-gate
6412139Sjp161948 if (!noout || text || next_serial)
6420Sstevel@tonic-gate {
6430Sstevel@tonic-gate OBJ_create("2.99999.3",
6440Sstevel@tonic-gate "SET.ex3","SET x509v3 extension 3");
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate out=BIO_new(BIO_s_file());
6470Sstevel@tonic-gate if (out == NULL)
6480Sstevel@tonic-gate {
6490Sstevel@tonic-gate ERR_print_errors(bio_err);
6500Sstevel@tonic-gate goto end;
6510Sstevel@tonic-gate }
6520Sstevel@tonic-gate if (outfile == NULL)
6530Sstevel@tonic-gate {
6540Sstevel@tonic-gate BIO_set_fp(out,stdout,BIO_NOCLOSE);
6550Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS
6560Sstevel@tonic-gate {
6570Sstevel@tonic-gate BIO *tmpbio = BIO_new(BIO_f_linebuffer());
6580Sstevel@tonic-gate out = BIO_push(tmpbio, out);
6590Sstevel@tonic-gate }
6600Sstevel@tonic-gate #endif
6610Sstevel@tonic-gate }
6620Sstevel@tonic-gate else
6630Sstevel@tonic-gate {
6640Sstevel@tonic-gate if (BIO_write_filename(out,outfile) <= 0)
6650Sstevel@tonic-gate {
6660Sstevel@tonic-gate perror(outfile);
6670Sstevel@tonic-gate goto end;
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate }
6700Sstevel@tonic-gate }
6710Sstevel@tonic-gate
6720Sstevel@tonic-gate if (alias) X509_alias_set1(x, (unsigned char *)alias, -1);
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate if (clrtrust) X509_trust_clear(x);
6750Sstevel@tonic-gate if (clrreject) X509_reject_clear(x);
6760Sstevel@tonic-gate
6770Sstevel@tonic-gate if (trust)
6780Sstevel@tonic-gate {
6790Sstevel@tonic-gate for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++)
6800Sstevel@tonic-gate {
6810Sstevel@tonic-gate objtmp = sk_ASN1_OBJECT_value(trust, i);
6820Sstevel@tonic-gate X509_add1_trust_object(x, objtmp);
6830Sstevel@tonic-gate }
6840Sstevel@tonic-gate }
6850Sstevel@tonic-gate
6860Sstevel@tonic-gate if (reject)
6870Sstevel@tonic-gate {
6880Sstevel@tonic-gate for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++)
6890Sstevel@tonic-gate {
6900Sstevel@tonic-gate objtmp = sk_ASN1_OBJECT_value(reject, i);
6910Sstevel@tonic-gate X509_add1_reject_object(x, objtmp);
6920Sstevel@tonic-gate }
6930Sstevel@tonic-gate }
6940Sstevel@tonic-gate
6950Sstevel@tonic-gate if (num)
6960Sstevel@tonic-gate {
6970Sstevel@tonic-gate for (i=1; i<=num; i++)
6980Sstevel@tonic-gate {
6990Sstevel@tonic-gate if (issuer == i)
7000Sstevel@tonic-gate {
7010Sstevel@tonic-gate print_name(STDout, "issuer= ",
7020Sstevel@tonic-gate X509_get_issuer_name(x), nmflag);
7030Sstevel@tonic-gate }
7040Sstevel@tonic-gate else if (subject == i)
7050Sstevel@tonic-gate {
7060Sstevel@tonic-gate print_name(STDout, "subject= ",
7070Sstevel@tonic-gate X509_get_subject_name(x), nmflag);
7080Sstevel@tonic-gate }
7090Sstevel@tonic-gate else if (serial == i)
7100Sstevel@tonic-gate {
7110Sstevel@tonic-gate BIO_printf(STDout,"serial=");
7122139Sjp161948 i2a_ASN1_INTEGER(STDout,
7132139Sjp161948 X509_get_serialNumber(x));
7140Sstevel@tonic-gate BIO_printf(STDout,"\n");
7150Sstevel@tonic-gate }
7162139Sjp161948 else if (next_serial == i)
7172139Sjp161948 {
7182139Sjp161948 BIGNUM *bnser;
7192139Sjp161948 ASN1_INTEGER *ser;
7202139Sjp161948 ser = X509_get_serialNumber(x);
7212139Sjp161948 bnser = ASN1_INTEGER_to_BN(ser, NULL);
7222139Sjp161948 if (!bnser)
7232139Sjp161948 goto end;
7242139Sjp161948 if (!BN_add_word(bnser, 1))
7252139Sjp161948 goto end;
7262139Sjp161948 ser = BN_to_ASN1_INTEGER(bnser, NULL);
7272139Sjp161948 if (!ser)
7282139Sjp161948 goto end;
7292139Sjp161948 BN_free(bnser);
7302139Sjp161948 i2a_ASN1_INTEGER(out, ser);
7312139Sjp161948 ASN1_INTEGER_free(ser);
7322139Sjp161948 BIO_puts(out, "\n");
7332139Sjp161948 }
7340Sstevel@tonic-gate else if (email == i)
7350Sstevel@tonic-gate {
7360Sstevel@tonic-gate int j;
7370Sstevel@tonic-gate STACK *emlst;
7380Sstevel@tonic-gate emlst = X509_get1_email(x);
7390Sstevel@tonic-gate for (j = 0; j < sk_num(emlst); j++)
7400Sstevel@tonic-gate BIO_printf(STDout, "%s\n", sk_value(emlst, j));
7410Sstevel@tonic-gate X509_email_free(emlst);
7420Sstevel@tonic-gate }
7430Sstevel@tonic-gate else if (aliasout == i)
7440Sstevel@tonic-gate {
7450Sstevel@tonic-gate unsigned char *alstr;
7460Sstevel@tonic-gate alstr = X509_alias_get0(x, NULL);
7470Sstevel@tonic-gate if (alstr) BIO_printf(STDout,"%s\n", alstr);
7480Sstevel@tonic-gate else BIO_puts(STDout,"<No Alias>\n");
7490Sstevel@tonic-gate }
7502139Sjp161948 else if (subject_hash == i)
7510Sstevel@tonic-gate {
7520Sstevel@tonic-gate BIO_printf(STDout,"%08lx\n",X509_subject_name_hash(x));
7530Sstevel@tonic-gate }
7542139Sjp161948 else if (issuer_hash == i)
7552139Sjp161948 {
7562139Sjp161948 BIO_printf(STDout,"%08lx\n",X509_issuer_name_hash(x));
7572139Sjp161948 }
7580Sstevel@tonic-gate else if (pprint == i)
7590Sstevel@tonic-gate {
7600Sstevel@tonic-gate X509_PURPOSE *ptmp;
7610Sstevel@tonic-gate int j;
7620Sstevel@tonic-gate BIO_printf(STDout, "Certificate purposes:\n");
7630Sstevel@tonic-gate for (j = 0; j < X509_PURPOSE_get_count(); j++)
7640Sstevel@tonic-gate {
7650Sstevel@tonic-gate ptmp = X509_PURPOSE_get0(j);
7660Sstevel@tonic-gate purpose_print(STDout, x, ptmp);
7670Sstevel@tonic-gate }
7680Sstevel@tonic-gate }
7690Sstevel@tonic-gate else
7700Sstevel@tonic-gate if (modulus == i)
7710Sstevel@tonic-gate {
7720Sstevel@tonic-gate EVP_PKEY *pkey;
7730Sstevel@tonic-gate
7740Sstevel@tonic-gate pkey=X509_get_pubkey(x);
7750Sstevel@tonic-gate if (pkey == NULL)
7760Sstevel@tonic-gate {
7770Sstevel@tonic-gate BIO_printf(bio_err,"Modulus=unavailable\n");
7780Sstevel@tonic-gate ERR_print_errors(bio_err);
7790Sstevel@tonic-gate goto end;
7800Sstevel@tonic-gate }
7810Sstevel@tonic-gate BIO_printf(STDout,"Modulus=");
7820Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
7830Sstevel@tonic-gate if (pkey->type == EVP_PKEY_RSA)
7840Sstevel@tonic-gate BN_print(STDout,pkey->pkey.rsa->n);
7850Sstevel@tonic-gate else
7860Sstevel@tonic-gate #endif
7870Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
7880Sstevel@tonic-gate if (pkey->type == EVP_PKEY_DSA)
7890Sstevel@tonic-gate BN_print(STDout,pkey->pkey.dsa->pub_key);
7900Sstevel@tonic-gate else
7910Sstevel@tonic-gate #endif
7920Sstevel@tonic-gate BIO_printf(STDout,"Wrong Algorithm type");
7930Sstevel@tonic-gate BIO_printf(STDout,"\n");
7940Sstevel@tonic-gate EVP_PKEY_free(pkey);
7950Sstevel@tonic-gate }
7960Sstevel@tonic-gate else
7970Sstevel@tonic-gate if (pubkey == i)
7980Sstevel@tonic-gate {
7990Sstevel@tonic-gate EVP_PKEY *pkey;
8000Sstevel@tonic-gate
8010Sstevel@tonic-gate pkey=X509_get_pubkey(x);
8020Sstevel@tonic-gate if (pkey == NULL)
8030Sstevel@tonic-gate {
8040Sstevel@tonic-gate BIO_printf(bio_err,"Error getting public key\n");
8050Sstevel@tonic-gate ERR_print_errors(bio_err);
8060Sstevel@tonic-gate goto end;
8070Sstevel@tonic-gate }
8080Sstevel@tonic-gate PEM_write_bio_PUBKEY(STDout, pkey);
8090Sstevel@tonic-gate EVP_PKEY_free(pkey);
8100Sstevel@tonic-gate }
8110Sstevel@tonic-gate else
8120Sstevel@tonic-gate if (C == i)
8130Sstevel@tonic-gate {
8140Sstevel@tonic-gate unsigned char *d;
8150Sstevel@tonic-gate char *m;
8160Sstevel@tonic-gate int y,z;
8170Sstevel@tonic-gate
8180Sstevel@tonic-gate X509_NAME_oneline(X509_get_subject_name(x),
8190Sstevel@tonic-gate buf,sizeof buf);
8200Sstevel@tonic-gate BIO_printf(STDout,"/* subject:%s */\n",buf);
8210Sstevel@tonic-gate m=X509_NAME_oneline(
8220Sstevel@tonic-gate X509_get_issuer_name(x),buf,
8230Sstevel@tonic-gate sizeof buf);
8240Sstevel@tonic-gate BIO_printf(STDout,"/* issuer :%s */\n",buf);
8250Sstevel@tonic-gate
8260Sstevel@tonic-gate z=i2d_X509(x,NULL);
8270Sstevel@tonic-gate m=OPENSSL_malloc(z);
8280Sstevel@tonic-gate
8290Sstevel@tonic-gate d=(unsigned char *)m;
8300Sstevel@tonic-gate z=i2d_X509_NAME(X509_get_subject_name(x),&d);
8310Sstevel@tonic-gate BIO_printf(STDout,"unsigned char XXX_subject_name[%d]={\n",z);
8320Sstevel@tonic-gate d=(unsigned char *)m;
8330Sstevel@tonic-gate for (y=0; y<z; y++)
8340Sstevel@tonic-gate {
8350Sstevel@tonic-gate BIO_printf(STDout,"0x%02X,",d[y]);
8360Sstevel@tonic-gate if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n");
8370Sstevel@tonic-gate }
8380Sstevel@tonic-gate if (y%16 != 0) BIO_printf(STDout,"\n");
8390Sstevel@tonic-gate BIO_printf(STDout,"};\n");
8400Sstevel@tonic-gate
8410Sstevel@tonic-gate z=i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x),&d);
8420Sstevel@tonic-gate BIO_printf(STDout,"unsigned char XXX_public_key[%d]={\n",z);
8430Sstevel@tonic-gate d=(unsigned char *)m;
8440Sstevel@tonic-gate for (y=0; y<z; y++)
8450Sstevel@tonic-gate {
8460Sstevel@tonic-gate BIO_printf(STDout,"0x%02X,",d[y]);
8470Sstevel@tonic-gate if ((y & 0x0f) == 0x0f)
8480Sstevel@tonic-gate BIO_printf(STDout,"\n");
8490Sstevel@tonic-gate }
8500Sstevel@tonic-gate if (y%16 != 0) BIO_printf(STDout,"\n");
8510Sstevel@tonic-gate BIO_printf(STDout,"};\n");
8520Sstevel@tonic-gate
8530Sstevel@tonic-gate z=i2d_X509(x,&d);
8540Sstevel@tonic-gate BIO_printf(STDout,"unsigned char XXX_certificate[%d]={\n",z);
8550Sstevel@tonic-gate d=(unsigned char *)m;
8560Sstevel@tonic-gate for (y=0; y<z; y++)
8570Sstevel@tonic-gate {
8580Sstevel@tonic-gate BIO_printf(STDout,"0x%02X,",d[y]);
8590Sstevel@tonic-gate if ((y & 0x0f) == 0x0f)
8600Sstevel@tonic-gate BIO_printf(STDout,"\n");
8610Sstevel@tonic-gate }
8620Sstevel@tonic-gate if (y%16 != 0) BIO_printf(STDout,"\n");
8630Sstevel@tonic-gate BIO_printf(STDout,"};\n");
8640Sstevel@tonic-gate
8650Sstevel@tonic-gate OPENSSL_free(m);
8660Sstevel@tonic-gate }
8670Sstevel@tonic-gate else if (text == i)
8680Sstevel@tonic-gate {
8690Sstevel@tonic-gate X509_print_ex(out,x,nmflag, certflag);
8700Sstevel@tonic-gate }
8710Sstevel@tonic-gate else if (startdate == i)
8720Sstevel@tonic-gate {
8730Sstevel@tonic-gate BIO_puts(STDout,"notBefore=");
8740Sstevel@tonic-gate ASN1_TIME_print(STDout,X509_get_notBefore(x));
8750Sstevel@tonic-gate BIO_puts(STDout,"\n");
8760Sstevel@tonic-gate }
8770Sstevel@tonic-gate else if (enddate == i)
8780Sstevel@tonic-gate {
8790Sstevel@tonic-gate BIO_puts(STDout,"notAfter=");
8800Sstevel@tonic-gate ASN1_TIME_print(STDout,X509_get_notAfter(x));
8810Sstevel@tonic-gate BIO_puts(STDout,"\n");
8820Sstevel@tonic-gate }
8830Sstevel@tonic-gate else if (fingerprint == i)
8840Sstevel@tonic-gate {
8850Sstevel@tonic-gate int j;
8860Sstevel@tonic-gate unsigned int n;
8870Sstevel@tonic-gate unsigned char md[EVP_MAX_MD_SIZE];
8880Sstevel@tonic-gate
8890Sstevel@tonic-gate if (!X509_digest(x,digest,md,&n))
8900Sstevel@tonic-gate {
8910Sstevel@tonic-gate BIO_printf(bio_err,"out of memory\n");
8920Sstevel@tonic-gate goto end;
8930Sstevel@tonic-gate }
8940Sstevel@tonic-gate BIO_printf(STDout,"%s Fingerprint=",
8950Sstevel@tonic-gate OBJ_nid2sn(EVP_MD_type(digest)));
8960Sstevel@tonic-gate for (j=0; j<(int)n; j++)
8970Sstevel@tonic-gate {
8980Sstevel@tonic-gate BIO_printf(STDout,"%02X%c",md[j],
8990Sstevel@tonic-gate (j+1 == (int)n)
9000Sstevel@tonic-gate ?'\n':':');
9010Sstevel@tonic-gate }
9020Sstevel@tonic-gate }
9030Sstevel@tonic-gate
9040Sstevel@tonic-gate /* should be in the library */
9050Sstevel@tonic-gate else if ((sign_flag == i) && (x509req == 0))
9060Sstevel@tonic-gate {
9070Sstevel@tonic-gate BIO_printf(bio_err,"Getting Private key\n");
9080Sstevel@tonic-gate if (Upkey == NULL)
9090Sstevel@tonic-gate {
9100Sstevel@tonic-gate Upkey=load_key(bio_err,
9110Sstevel@tonic-gate keyfile, keyformat, 0,
9120Sstevel@tonic-gate passin, e, "Private key");
9130Sstevel@tonic-gate if (Upkey == NULL) goto end;
9140Sstevel@tonic-gate }
9150Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
9160Sstevel@tonic-gate if (Upkey->type == EVP_PKEY_DSA)
9170Sstevel@tonic-gate digest=EVP_dss1();
9180Sstevel@tonic-gate #endif
9192139Sjp161948 #ifndef OPENSSL_NO_ECDSA
9202139Sjp161948 if (Upkey->type == EVP_PKEY_EC)
9212139Sjp161948 digest=EVP_ecdsa();
9222139Sjp161948 #endif
9230Sstevel@tonic-gate
9240Sstevel@tonic-gate assert(need_rand);
9250Sstevel@tonic-gate if (!sign(x,Upkey,days,clrext,digest,
9260Sstevel@tonic-gate extconf, extsect)) goto end;
9270Sstevel@tonic-gate }
9280Sstevel@tonic-gate else if (CA_flag == i)
9290Sstevel@tonic-gate {
9300Sstevel@tonic-gate BIO_printf(bio_err,"Getting CA Private Key\n");
9310Sstevel@tonic-gate if (CAkeyfile != NULL)
9320Sstevel@tonic-gate {
9330Sstevel@tonic-gate CApkey=load_key(bio_err,
9340Sstevel@tonic-gate CAkeyfile, CAkeyformat,
9350Sstevel@tonic-gate 0, passin, e,
9360Sstevel@tonic-gate "CA Private Key");
9370Sstevel@tonic-gate if (CApkey == NULL) goto end;
9380Sstevel@tonic-gate }
9390Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
9400Sstevel@tonic-gate if (CApkey->type == EVP_PKEY_DSA)
9410Sstevel@tonic-gate digest=EVP_dss1();
9420Sstevel@tonic-gate #endif
9432139Sjp161948 #ifndef OPENSSL_NO_ECDSA
9442139Sjp161948 if (CApkey->type == EVP_PKEY_EC)
9452139Sjp161948 digest = EVP_ecdsa();
9462139Sjp161948 #endif
9470Sstevel@tonic-gate
9480Sstevel@tonic-gate assert(need_rand);
9490Sstevel@tonic-gate if (!x509_certify(ctx,CAfile,digest,x,xca,
9500Sstevel@tonic-gate CApkey, CAserial,CA_createserial,days, clrext,
9510Sstevel@tonic-gate extconf, extsect, sno))
9520Sstevel@tonic-gate goto end;
9530Sstevel@tonic-gate }
9540Sstevel@tonic-gate else if (x509req == i)
9550Sstevel@tonic-gate {
9560Sstevel@tonic-gate EVP_PKEY *pk;
9570Sstevel@tonic-gate
9580Sstevel@tonic-gate BIO_printf(bio_err,"Getting request Private Key\n");
9590Sstevel@tonic-gate if (keyfile == NULL)
9600Sstevel@tonic-gate {
9610Sstevel@tonic-gate BIO_printf(bio_err,"no request key file specified\n");
9620Sstevel@tonic-gate goto end;
9630Sstevel@tonic-gate }
9640Sstevel@tonic-gate else
9650Sstevel@tonic-gate {
9660Sstevel@tonic-gate pk=load_key(bio_err,
9670Sstevel@tonic-gate keyfile, FORMAT_PEM, 0,
9680Sstevel@tonic-gate passin, e, "request key");
9690Sstevel@tonic-gate if (pk == NULL) goto end;
9700Sstevel@tonic-gate }
9710Sstevel@tonic-gate
9720Sstevel@tonic-gate BIO_printf(bio_err,"Generating certificate request\n");
9730Sstevel@tonic-gate
9740Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
9750Sstevel@tonic-gate if (pk->type == EVP_PKEY_DSA)
9760Sstevel@tonic-gate digest=EVP_dss1();
9770Sstevel@tonic-gate #endif
9782139Sjp161948 #ifndef OPENSSL_NO_ECDSA
9792139Sjp161948 if (pk->type == EVP_PKEY_EC)
9802139Sjp161948 digest=EVP_ecdsa();
9812139Sjp161948 #endif
9820Sstevel@tonic-gate
9830Sstevel@tonic-gate rq=X509_to_X509_REQ(x,pk,digest);
9840Sstevel@tonic-gate EVP_PKEY_free(pk);
9850Sstevel@tonic-gate if (rq == NULL)
9860Sstevel@tonic-gate {
9870Sstevel@tonic-gate ERR_print_errors(bio_err);
9880Sstevel@tonic-gate goto end;
9890Sstevel@tonic-gate }
9900Sstevel@tonic-gate if (!noout)
9910Sstevel@tonic-gate {
9920Sstevel@tonic-gate X509_REQ_print(out,rq);
9930Sstevel@tonic-gate PEM_write_bio_X509_REQ(out,rq);
9940Sstevel@tonic-gate }
9950Sstevel@tonic-gate noout=1;
9960Sstevel@tonic-gate }
9970Sstevel@tonic-gate else if (ocspid == i)
9980Sstevel@tonic-gate {
9990Sstevel@tonic-gate X509_ocspid_print(out, x);
10000Sstevel@tonic-gate }
10010Sstevel@tonic-gate }
10020Sstevel@tonic-gate }
10030Sstevel@tonic-gate
10040Sstevel@tonic-gate if (checkend)
10050Sstevel@tonic-gate {
10062139Sjp161948 time_t tcheck=time(NULL) + checkoffset;
10070Sstevel@tonic-gate
10082139Sjp161948 if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0)
10090Sstevel@tonic-gate {
10100Sstevel@tonic-gate BIO_printf(out,"Certificate will expire\n");
10110Sstevel@tonic-gate ret=1;
10120Sstevel@tonic-gate }
10130Sstevel@tonic-gate else
10140Sstevel@tonic-gate {
10150Sstevel@tonic-gate BIO_printf(out,"Certificate will not expire\n");
10160Sstevel@tonic-gate ret=0;
10170Sstevel@tonic-gate }
10180Sstevel@tonic-gate goto end;
10190Sstevel@tonic-gate }
10200Sstevel@tonic-gate
10210Sstevel@tonic-gate if (noout)
10220Sstevel@tonic-gate {
10230Sstevel@tonic-gate ret=0;
10240Sstevel@tonic-gate goto end;
10250Sstevel@tonic-gate }
10260Sstevel@tonic-gate
10270Sstevel@tonic-gate if (outformat == FORMAT_ASN1)
10280Sstevel@tonic-gate i=i2d_X509_bio(out,x);
10290Sstevel@tonic-gate else if (outformat == FORMAT_PEM)
10300Sstevel@tonic-gate {
10310Sstevel@tonic-gate if (trustout) i=PEM_write_bio_X509_AUX(out,x);
10320Sstevel@tonic-gate else i=PEM_write_bio_X509(out,x);
10330Sstevel@tonic-gate }
10340Sstevel@tonic-gate else if (outformat == FORMAT_NETSCAPE)
10350Sstevel@tonic-gate {
10360Sstevel@tonic-gate ASN1_HEADER ah;
10370Sstevel@tonic-gate ASN1_OCTET_STRING os;
10380Sstevel@tonic-gate
10390Sstevel@tonic-gate os.data=(unsigned char *)NETSCAPE_CERT_HDR;
10400Sstevel@tonic-gate os.length=strlen(NETSCAPE_CERT_HDR);
10410Sstevel@tonic-gate ah.header= &os;
10420Sstevel@tonic-gate ah.data=(char *)x;
10430Sstevel@tonic-gate ah.meth=X509_asn1_meth();
10440Sstevel@tonic-gate
10452139Sjp161948 i=ASN1_i2d_bio_of(ASN1_HEADER,i2d_ASN1_HEADER,out,&ah);
10460Sstevel@tonic-gate }
10470Sstevel@tonic-gate else {
10480Sstevel@tonic-gate BIO_printf(bio_err,"bad output format specified for outfile\n");
10490Sstevel@tonic-gate goto end;
10500Sstevel@tonic-gate }
10510Sstevel@tonic-gate if (!i)
10520Sstevel@tonic-gate {
10530Sstevel@tonic-gate BIO_printf(bio_err,"unable to write certificate\n");
10540Sstevel@tonic-gate ERR_print_errors(bio_err);
10550Sstevel@tonic-gate goto end;
10560Sstevel@tonic-gate }
10570Sstevel@tonic-gate ret=0;
10580Sstevel@tonic-gate end:
10590Sstevel@tonic-gate if (need_rand)
10600Sstevel@tonic-gate app_RAND_write_file(NULL, bio_err);
10610Sstevel@tonic-gate OBJ_cleanup();
10620Sstevel@tonic-gate NCONF_free(extconf);
10630Sstevel@tonic-gate BIO_free_all(out);
10640Sstevel@tonic-gate BIO_free_all(STDout);
10650Sstevel@tonic-gate X509_STORE_free(ctx);
10660Sstevel@tonic-gate X509_REQ_free(req);
10670Sstevel@tonic-gate X509_free(x);
10680Sstevel@tonic-gate X509_free(xca);
10690Sstevel@tonic-gate EVP_PKEY_free(Upkey);
10700Sstevel@tonic-gate EVP_PKEY_free(CApkey);
10710Sstevel@tonic-gate X509_REQ_free(rq);
10720Sstevel@tonic-gate ASN1_INTEGER_free(sno);
10730Sstevel@tonic-gate sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
10740Sstevel@tonic-gate sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
10750Sstevel@tonic-gate if (passin) OPENSSL_free(passin);
10760Sstevel@tonic-gate apps_shutdown();
10770Sstevel@tonic-gate OPENSSL_EXIT(ret);
10780Sstevel@tonic-gate }
10790Sstevel@tonic-gate
x509_load_serial(char * CAfile,char * serialfile,int create)10800Sstevel@tonic-gate static ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile, int create)
10810Sstevel@tonic-gate {
10820Sstevel@tonic-gate char *buf = NULL, *p;
10830Sstevel@tonic-gate ASN1_INTEGER *bs = NULL;
10840Sstevel@tonic-gate BIGNUM *serial = NULL;
10850Sstevel@tonic-gate size_t len;
10860Sstevel@tonic-gate
10870Sstevel@tonic-gate len = ((serialfile == NULL)
10880Sstevel@tonic-gate ?(strlen(CAfile)+strlen(POSTFIX)+1)
10890Sstevel@tonic-gate :(strlen(serialfile)))+1;
10900Sstevel@tonic-gate buf=OPENSSL_malloc(len);
10910Sstevel@tonic-gate if (buf == NULL) { BIO_printf(bio_err,"out of mem\n"); goto end; }
10920Sstevel@tonic-gate if (serialfile == NULL)
10930Sstevel@tonic-gate {
10940Sstevel@tonic-gate BUF_strlcpy(buf,CAfile,len);
10950Sstevel@tonic-gate for (p=buf; *p; p++)
10960Sstevel@tonic-gate if (*p == '.')
10970Sstevel@tonic-gate {
10980Sstevel@tonic-gate *p='\0';
10990Sstevel@tonic-gate break;
11000Sstevel@tonic-gate }
11010Sstevel@tonic-gate BUF_strlcat(buf,POSTFIX,len);
11020Sstevel@tonic-gate }
11030Sstevel@tonic-gate else
11040Sstevel@tonic-gate BUF_strlcpy(buf,serialfile,len);
11050Sstevel@tonic-gate
11060Sstevel@tonic-gate serial = load_serial(buf, create, NULL);
11070Sstevel@tonic-gate if (serial == NULL) goto end;
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate if (!BN_add_word(serial,1))
11100Sstevel@tonic-gate { BIO_printf(bio_err,"add_word failure\n"); goto end; }
11110Sstevel@tonic-gate
11120Sstevel@tonic-gate if (!save_serial(buf, NULL, serial, &bs)) goto end;
11130Sstevel@tonic-gate
11140Sstevel@tonic-gate end:
11150Sstevel@tonic-gate if (buf) OPENSSL_free(buf);
11160Sstevel@tonic-gate BN_free(serial);
11170Sstevel@tonic-gate return bs;
11180Sstevel@tonic-gate }
11190Sstevel@tonic-gate
x509_certify(X509_STORE * ctx,char * CAfile,const EVP_MD * digest,X509 * x,X509 * xca,EVP_PKEY * pkey,char * serialfile,int create,int days,int clrext,CONF * conf,char * section,ASN1_INTEGER * sno)11200Sstevel@tonic-gate static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
11210Sstevel@tonic-gate X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create,
11220Sstevel@tonic-gate int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno)
11230Sstevel@tonic-gate {
11240Sstevel@tonic-gate int ret=0;
11250Sstevel@tonic-gate ASN1_INTEGER *bs=NULL;
11260Sstevel@tonic-gate X509_STORE_CTX xsc;
11270Sstevel@tonic-gate EVP_PKEY *upkey;
11280Sstevel@tonic-gate
11290Sstevel@tonic-gate upkey = X509_get_pubkey(xca);
11300Sstevel@tonic-gate EVP_PKEY_copy_parameters(upkey,pkey);
11310Sstevel@tonic-gate EVP_PKEY_free(upkey);
11320Sstevel@tonic-gate
11330Sstevel@tonic-gate if(!X509_STORE_CTX_init(&xsc,ctx,x,NULL))
11340Sstevel@tonic-gate {
11350Sstevel@tonic-gate BIO_printf(bio_err,"Error initialising X509 store\n");
11360Sstevel@tonic-gate goto end;
11370Sstevel@tonic-gate }
11380Sstevel@tonic-gate if (sno) bs = sno;
11390Sstevel@tonic-gate else if (!(bs = x509_load_serial(CAfile, serialfile, create)))
11400Sstevel@tonic-gate goto end;
11410Sstevel@tonic-gate
11420Sstevel@tonic-gate /* if (!X509_STORE_add_cert(ctx,x)) goto end;*/
11430Sstevel@tonic-gate
11440Sstevel@tonic-gate /* NOTE: this certificate can/should be self signed, unless it was
11450Sstevel@tonic-gate * a certificate request in which case it is not. */
11460Sstevel@tonic-gate X509_STORE_CTX_set_cert(&xsc,x);
1147*8545SJan.Pechanec@Sun.COM if (!reqfile && X509_verify_cert(&xsc) <= 0)
11480Sstevel@tonic-gate goto end;
11490Sstevel@tonic-gate
11500Sstevel@tonic-gate if (!X509_check_private_key(xca,pkey))
11510Sstevel@tonic-gate {
11520Sstevel@tonic-gate BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
11530Sstevel@tonic-gate goto end;
11540Sstevel@tonic-gate }
11550Sstevel@tonic-gate
11560Sstevel@tonic-gate if (!X509_set_issuer_name(x,X509_get_subject_name(xca))) goto end;
11570Sstevel@tonic-gate if (!X509_set_serialNumber(x,bs)) goto end;
11580Sstevel@tonic-gate
11590Sstevel@tonic-gate if (X509_gmtime_adj(X509_get_notBefore(x),0L) == NULL)
11600Sstevel@tonic-gate goto end;
11610Sstevel@tonic-gate
11620Sstevel@tonic-gate /* hardwired expired */
11630Sstevel@tonic-gate if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL)
11640Sstevel@tonic-gate goto end;
11650Sstevel@tonic-gate
11660Sstevel@tonic-gate if (clrext)
11670Sstevel@tonic-gate {
11680Sstevel@tonic-gate while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0);
11690Sstevel@tonic-gate }
11700Sstevel@tonic-gate
11710Sstevel@tonic-gate if (conf)
11720Sstevel@tonic-gate {
11730Sstevel@tonic-gate X509V3_CTX ctx2;
11740Sstevel@tonic-gate X509_set_version(x,2); /* version 3 certificate */
11750Sstevel@tonic-gate X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
11760Sstevel@tonic-gate X509V3_set_nconf(&ctx2, conf);
11770Sstevel@tonic-gate if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end;
11780Sstevel@tonic-gate }
11790Sstevel@tonic-gate
11800Sstevel@tonic-gate if (!X509_sign(x,pkey,digest)) goto end;
11810Sstevel@tonic-gate ret=1;
11820Sstevel@tonic-gate end:
11830Sstevel@tonic-gate X509_STORE_CTX_cleanup(&xsc);
11840Sstevel@tonic-gate if (!ret)
11850Sstevel@tonic-gate ERR_print_errors(bio_err);
11860Sstevel@tonic-gate if (!sno) ASN1_INTEGER_free(bs);
11870Sstevel@tonic-gate return ret;
11880Sstevel@tonic-gate }
11890Sstevel@tonic-gate
callb(int ok,X509_STORE_CTX * ctx)11900Sstevel@tonic-gate static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx)
11910Sstevel@tonic-gate {
11920Sstevel@tonic-gate int err;
11930Sstevel@tonic-gate X509 *err_cert;
11940Sstevel@tonic-gate
11950Sstevel@tonic-gate /* it is ok to use a self signed certificate
11960Sstevel@tonic-gate * This case will catch both the initial ok == 0 and the
11970Sstevel@tonic-gate * final ok == 1 calls to this function */
11980Sstevel@tonic-gate err=X509_STORE_CTX_get_error(ctx);
11990Sstevel@tonic-gate if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
12000Sstevel@tonic-gate return 1;
12010Sstevel@tonic-gate
12020Sstevel@tonic-gate /* BAD we should have gotten an error. Normally if everything
12030Sstevel@tonic-gate * worked X509_STORE_CTX_get_error(ctx) will still be set to
12040Sstevel@tonic-gate * DEPTH_ZERO_SELF_.... */
12050Sstevel@tonic-gate if (ok)
12060Sstevel@tonic-gate {
12070Sstevel@tonic-gate BIO_printf(bio_err,"error with certificate to be certified - should be self signed\n");
12080Sstevel@tonic-gate return 0;
12090Sstevel@tonic-gate }
12100Sstevel@tonic-gate else
12110Sstevel@tonic-gate {
12120Sstevel@tonic-gate err_cert=X509_STORE_CTX_get_current_cert(ctx);
12130Sstevel@tonic-gate print_name(bio_err, NULL, X509_get_subject_name(err_cert),0);
12140Sstevel@tonic-gate BIO_printf(bio_err,"error with certificate - error %d at depth %d\n%s\n",
12150Sstevel@tonic-gate err,X509_STORE_CTX_get_error_depth(ctx),
12160Sstevel@tonic-gate X509_verify_cert_error_string(err));
12170Sstevel@tonic-gate return 1;
12180Sstevel@tonic-gate }
12190Sstevel@tonic-gate }
12200Sstevel@tonic-gate
12210Sstevel@tonic-gate /* self sign */
sign(X509 * x,EVP_PKEY * pkey,int days,int clrext,const EVP_MD * digest,CONF * conf,char * section)12220Sstevel@tonic-gate static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest,
12230Sstevel@tonic-gate CONF *conf, char *section)
12240Sstevel@tonic-gate {
12250Sstevel@tonic-gate
12260Sstevel@tonic-gate EVP_PKEY *pktmp;
12270Sstevel@tonic-gate
12280Sstevel@tonic-gate pktmp = X509_get_pubkey(x);
12290Sstevel@tonic-gate EVP_PKEY_copy_parameters(pktmp,pkey);
12300Sstevel@tonic-gate EVP_PKEY_save_parameters(pktmp,1);
12310Sstevel@tonic-gate EVP_PKEY_free(pktmp);
12320Sstevel@tonic-gate
12330Sstevel@tonic-gate if (!X509_set_issuer_name(x,X509_get_subject_name(x))) goto err;
12340Sstevel@tonic-gate if (X509_gmtime_adj(X509_get_notBefore(x),0) == NULL) goto err;
12350Sstevel@tonic-gate
12360Sstevel@tonic-gate /* Lets just make it 12:00am GMT, Jan 1 1970 */
12370Sstevel@tonic-gate /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
12380Sstevel@tonic-gate /* 28 days to be certified */
12390Sstevel@tonic-gate
12400Sstevel@tonic-gate if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL)
12410Sstevel@tonic-gate goto err;
12420Sstevel@tonic-gate
12430Sstevel@tonic-gate if (!X509_set_pubkey(x,pkey)) goto err;
12440Sstevel@tonic-gate if (clrext)
12450Sstevel@tonic-gate {
12460Sstevel@tonic-gate while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0);
12470Sstevel@tonic-gate }
12480Sstevel@tonic-gate if (conf)
12490Sstevel@tonic-gate {
12500Sstevel@tonic-gate X509V3_CTX ctx;
12510Sstevel@tonic-gate X509_set_version(x,2); /* version 3 certificate */
12520Sstevel@tonic-gate X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
12530Sstevel@tonic-gate X509V3_set_nconf(&ctx, conf);
12540Sstevel@tonic-gate if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) goto err;
12550Sstevel@tonic-gate }
12560Sstevel@tonic-gate if (!X509_sign(x,pkey,digest)) goto err;
12570Sstevel@tonic-gate return 1;
12580Sstevel@tonic-gate err:
12590Sstevel@tonic-gate ERR_print_errors(bio_err);
12600Sstevel@tonic-gate return 0;
12610Sstevel@tonic-gate }
12620Sstevel@tonic-gate
purpose_print(BIO * bio,X509 * cert,X509_PURPOSE * pt)12630Sstevel@tonic-gate static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
12640Sstevel@tonic-gate {
12650Sstevel@tonic-gate int id, i, idret;
12660Sstevel@tonic-gate char *pname;
12670Sstevel@tonic-gate id = X509_PURPOSE_get_id(pt);
12680Sstevel@tonic-gate pname = X509_PURPOSE_get0_name(pt);
12690Sstevel@tonic-gate for (i = 0; i < 2; i++)
12700Sstevel@tonic-gate {
12710Sstevel@tonic-gate idret = X509_check_purpose(cert, id, i);
12720Sstevel@tonic-gate BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
12730Sstevel@tonic-gate if (idret == 1) BIO_printf(bio, "Yes\n");
12740Sstevel@tonic-gate else if (idret == 0) BIO_printf(bio, "No\n");
12750Sstevel@tonic-gate else BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
12760Sstevel@tonic-gate }
12770Sstevel@tonic-gate return 1;
12780Sstevel@tonic-gate }
1279