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