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. 8280304Sjkim * 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). 15280304Sjkim * 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. 22280304Sjkim * 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 :-). 37280304Sjkim * 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)" 40280304Sjkim * 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. 52280304Sjkim * 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 64280304Sjkim# 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 77280304Sjkim# include <openssl/rsa.h> 78160814Ssimon#endif 79160814Ssimon#ifndef OPENSSL_NO_DSA 80280304Sjkim# include <openssl/dsa.h> 81160814Ssimon#endif 8255714Skris 8355714Skris#undef PROG 8455714Skris#define PROG x509_main 8555714Skris 8655714Skris#undef POSTFIX 87280304Sjkim#define POSTFIX ".srl" 88280304Sjkim#define DEF_DAYS 30 8955714Skris 90280304Sjkimstatic const char *x509_usage[] = { 91280304Sjkim "usage: x509 args\n", 92280304Sjkim " -inform arg - input format - default PEM (one of DER, NET or PEM)\n", 93280304Sjkim " -outform arg - output format - default PEM (one of DER, NET or PEM)\n", 94280304Sjkim " -keyform arg - private key format - default PEM\n", 95280304Sjkim " -CAform arg - CA format - default PEM\n", 96280304Sjkim " -CAkeyform arg - CA key format - default PEM\n", 97280304Sjkim " -in arg - input file - default stdin\n", 98280304Sjkim " -out arg - output file - default stdout\n", 99280304Sjkim " -passin arg - private key password source\n", 100280304Sjkim " -serial - print serial number value\n", 101280304Sjkim " -subject_hash - print subject hash value\n", 102238405Sjkim#ifndef OPENSSL_NO_MD5 103280304Sjkim " -subject_hash_old - print old-style (MD5) subject hash value\n", 104238405Sjkim#endif 105280304Sjkim " -issuer_hash - print issuer hash value\n", 106238405Sjkim#ifndef OPENSSL_NO_MD5 107280304Sjkim " -issuer_hash_old - print old-style (MD5) issuer hash value\n", 108238405Sjkim#endif 109280304Sjkim " -hash - synonym for -subject_hash\n", 110280304Sjkim " -subject - print subject DN\n", 111280304Sjkim " -issuer - print issuer DN\n", 112280304Sjkim " -email - print email address(es)\n", 113280304Sjkim " -startdate - notBefore field\n", 114280304Sjkim " -enddate - notAfter field\n", 115280304Sjkim " -purpose - print out certificate purposes\n", 116280304Sjkim " -dates - both Before and After dates\n", 117280304Sjkim " -modulus - print the RSA key modulus\n", 118280304Sjkim " -pubkey - output the public key\n", 119280304Sjkim " -fingerprint - print the certificate fingerprint\n", 120280304Sjkim " -alias - output certificate alias\n", 121280304Sjkim " -noout - no certificate output\n", 122280304Sjkim " -ocspid - print OCSP hash values for the subject name and public key\n", 123280304Sjkim " -ocsp_uri - print OCSP Responder URL(s)\n", 124280304Sjkim " -trustout - output a \"trusted\" certificate\n", 125280304Sjkim " -clrtrust - clear all trusted purposes\n", 126280304Sjkim " -clrreject - clear all rejected purposes\n", 127280304Sjkim " -addtrust arg - trust certificate for a given purpose\n", 128280304Sjkim " -addreject arg - reject certificate for a given purpose\n", 129280304Sjkim " -setalias arg - set certificate alias\n", 130280304Sjkim " -days arg - How long till expiry of a signed certificate - def 30 days\n", 131280304Sjkim " -checkend arg - check whether the cert expires in the next arg seconds\n", 132280304Sjkim " exit 1 if so, 0 if not\n", 133280304Sjkim " -signkey arg - self sign cert with arg\n", 134280304Sjkim " -x509toreq - output a certification request object\n", 135280304Sjkim " -req - input is a certificate request, sign and output.\n", 136280304Sjkim " -CA arg - set the CA certificate, must be PEM format.\n", 137280304Sjkim " -CAkey arg - set the CA key, must be PEM format\n", 138280304Sjkim " missing, it is assumed to be in the CA file.\n", 139280304Sjkim " -CAcreateserial - create serial number file if it does not exist\n", 140280304Sjkim " -CAserial arg - serial file\n", 141280304Sjkim " -set_serial - serial number to use\n", 142280304Sjkim " -text - print the certificate in text form\n", 143280304Sjkim " -C - print out C code forms\n", 144280304Sjkim " -md2/-md5/-sha1/-mdc2 - digest to use\n", 145280304Sjkim " -extfile - configuration file with X509V3 extensions to add\n", 146280304Sjkim " -extensions - section from config file with X509V3 extensions to add\n", 147280304Sjkim " -clrext - delete extensions before signing and input certificate\n", 148280304Sjkim " -nameopt arg - various certificate name options\n", 149111147Snectar#ifndef OPENSSL_NO_ENGINE 150280304Sjkim " -engine e - use engine e, possibly a hardware device.\n", 151111147Snectar#endif 152280304Sjkim " -certopt arg - various certificate text options\n", 153280304Sjkim NULL 15455714Skris}; 15555714Skris 15655714Skrisstatic int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx); 157280304Sjkimstatic int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, 158280304Sjkim const EVP_MD *digest, CONF *conf, char *section); 159280304Sjkimstatic int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, 160280304Sjkim X509 *x, X509 *xca, EVP_PKEY *pkey, 161280304Sjkim STACK_OF(OPENSSL_STRING) *sigopts, char *serial, 162280304Sjkim int create, int days, int clrext, CONF *conf, 163280304Sjkim char *section, ASN1_INTEGER *sno); 16459191Skrisstatic int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt); 165280304Sjkimstatic int reqfile = 0; 16655714Skris 16759191Skrisint MAIN(int, char **); 16859191Skris 16955714Skrisint MAIN(int argc, char **argv) 170280304Sjkim{ 171280304Sjkim ENGINE *e = NULL; 172280304Sjkim int ret = 1; 173280304Sjkim X509_REQ *req = NULL; 174280304Sjkim X509 *x = NULL, *xca = NULL; 175280304Sjkim ASN1_OBJECT *objtmp; 176280304Sjkim STACK_OF(OPENSSL_STRING) *sigopts = NULL; 177280304Sjkim EVP_PKEY *Upkey = NULL, *CApkey = NULL; 178280304Sjkim ASN1_INTEGER *sno = NULL; 179280304Sjkim int i, num, badops = 0; 180280304Sjkim BIO *out = NULL; 181280304Sjkim BIO *STDout = NULL; 182280304Sjkim STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; 183280304Sjkim int informat, outformat, keyformat, CAformat, CAkeyformat; 184280304Sjkim char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL; 185280304Sjkim char *CAkeyfile = NULL, *CAserial = NULL; 186280304Sjkim char *alias = NULL; 187280304Sjkim int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 188280304Sjkim 0, enddate = 0; 189280304Sjkim int next_serial = 0; 190280304Sjkim int subject_hash = 0, issuer_hash = 0, ocspid = 0; 191238405Sjkim#ifndef OPENSSL_NO_MD5 192280304Sjkim int subject_hash_old = 0, issuer_hash_old = 0; 193238405Sjkim#endif 194280304Sjkim int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0; 195280304Sjkim int ocsp_uri = 0; 196280304Sjkim int trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0, clrext = 0; 197280304Sjkim int C = 0; 198280304Sjkim int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0; 199280304Sjkim int pprint = 0; 200280304Sjkim const char **pp; 201280304Sjkim X509_STORE *ctx = NULL; 202280304Sjkim X509_REQ *rq = NULL; 203280304Sjkim int fingerprint = 0; 204280304Sjkim char buf[256]; 205280304Sjkim const EVP_MD *md_alg, *digest = NULL; 206280304Sjkim CONF *extconf = NULL; 207280304Sjkim char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL; 208280304Sjkim int need_rand = 0; 209280304Sjkim int checkend = 0, checkoffset = 0; 210280304Sjkim unsigned long nmflag = 0, certflag = 0; 211111147Snectar#ifndef OPENSSL_NO_ENGINE 212280304Sjkim char *engine = NULL; 213111147Snectar#endif 21455714Skris 215280304Sjkim reqfile = 0; 21655714Skris 217280304Sjkim apps_startup(); 21855714Skris 219280304Sjkim if (bio_err == NULL) 220280304Sjkim bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 221109998Smarkm 222280304Sjkim if (!load_config(bio_err, NULL)) 223280304Sjkim goto end; 224280304Sjkim STDout = BIO_new_fp(stdout, BIO_NOCLOSE); 225109998Smarkm#ifdef OPENSSL_SYS_VMS 226280304Sjkim { 227280304Sjkim BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 228280304Sjkim STDout = BIO_push(tmpbio, STDout); 229280304Sjkim } 23068651Skris#endif 23155714Skris 232280304Sjkim informat = FORMAT_PEM; 233280304Sjkim outformat = FORMAT_PEM; 234280304Sjkim keyformat = FORMAT_PEM; 235280304Sjkim CAformat = FORMAT_PEM; 236280304Sjkim CAkeyformat = FORMAT_PEM; 23755714Skris 238280304Sjkim ctx = X509_STORE_new(); 239280304Sjkim if (ctx == NULL) 240280304Sjkim goto end; 241280304Sjkim X509_STORE_set_verify_cb(ctx, callb); 24255714Skris 243280304Sjkim argc--; 244280304Sjkim argv++; 245280304Sjkim num = 0; 246280304Sjkim while (argc >= 1) { 247280304Sjkim if (strcmp(*argv, "-inform") == 0) { 248280304Sjkim if (--argc < 1) 249280304Sjkim goto bad; 250280304Sjkim informat = str2fmt(*(++argv)); 251280304Sjkim } else if (strcmp(*argv, "-outform") == 0) { 252280304Sjkim if (--argc < 1) 253280304Sjkim goto bad; 254280304Sjkim outformat = str2fmt(*(++argv)); 255280304Sjkim } else if (strcmp(*argv, "-keyform") == 0) { 256280304Sjkim if (--argc < 1) 257280304Sjkim goto bad; 258280304Sjkim keyformat = str2fmt(*(++argv)); 259280304Sjkim } else if (strcmp(*argv, "-req") == 0) { 260280304Sjkim reqfile = 1; 261280304Sjkim need_rand = 1; 262280304Sjkim } else if (strcmp(*argv, "-CAform") == 0) { 263280304Sjkim if (--argc < 1) 264280304Sjkim goto bad; 265280304Sjkim CAformat = str2fmt(*(++argv)); 266280304Sjkim } else if (strcmp(*argv, "-CAkeyform") == 0) { 267280304Sjkim if (--argc < 1) 268280304Sjkim goto bad; 269280304Sjkim CAkeyformat = str2fmt(*(++argv)); 270280304Sjkim } else if (strcmp(*argv, "-sigopt") == 0) { 271280304Sjkim if (--argc < 1) 272280304Sjkim goto bad; 273280304Sjkim if (!sigopts) 274280304Sjkim sigopts = sk_OPENSSL_STRING_new_null(); 275280304Sjkim if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv))) 276280304Sjkim goto bad; 277280304Sjkim } else if (strcmp(*argv, "-days") == 0) { 278280304Sjkim if (--argc < 1) 279280304Sjkim goto bad; 280280304Sjkim days = atoi(*(++argv)); 281280304Sjkim if (days == 0) { 282280304Sjkim BIO_printf(bio_err, "bad number of days\n"); 283280304Sjkim goto bad; 284280304Sjkim } 285280304Sjkim } else if (strcmp(*argv, "-passin") == 0) { 286280304Sjkim if (--argc < 1) 287280304Sjkim goto bad; 288280304Sjkim passargin = *(++argv); 289280304Sjkim } else if (strcmp(*argv, "-extfile") == 0) { 290280304Sjkim if (--argc < 1) 291280304Sjkim goto bad; 292280304Sjkim extfile = *(++argv); 293280304Sjkim } else if (strcmp(*argv, "-extensions") == 0) { 294280304Sjkim if (--argc < 1) 295280304Sjkim goto bad; 296280304Sjkim extsect = *(++argv); 297280304Sjkim } else if (strcmp(*argv, "-in") == 0) { 298280304Sjkim if (--argc < 1) 299280304Sjkim goto bad; 300280304Sjkim infile = *(++argv); 301280304Sjkim } else if (strcmp(*argv, "-out") == 0) { 302280304Sjkim if (--argc < 1) 303280304Sjkim goto bad; 304280304Sjkim outfile = *(++argv); 305280304Sjkim } else if (strcmp(*argv, "-signkey") == 0) { 306280304Sjkim if (--argc < 1) 307280304Sjkim goto bad; 308280304Sjkim keyfile = *(++argv); 309280304Sjkim sign_flag = ++num; 310280304Sjkim need_rand = 1; 311280304Sjkim } else if (strcmp(*argv, "-CA") == 0) { 312280304Sjkim if (--argc < 1) 313280304Sjkim goto bad; 314280304Sjkim CAfile = *(++argv); 315280304Sjkim CA_flag = ++num; 316280304Sjkim need_rand = 1; 317280304Sjkim } else if (strcmp(*argv, "-CAkey") == 0) { 318280304Sjkim if (--argc < 1) 319280304Sjkim goto bad; 320280304Sjkim CAkeyfile = *(++argv); 321280304Sjkim } else if (strcmp(*argv, "-CAserial") == 0) { 322280304Sjkim if (--argc < 1) 323280304Sjkim goto bad; 324280304Sjkim CAserial = *(++argv); 325280304Sjkim } else if (strcmp(*argv, "-set_serial") == 0) { 326280304Sjkim if (--argc < 1) 327280304Sjkim goto bad; 328280304Sjkim if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv)))) 329280304Sjkim goto bad; 330280304Sjkim } else if (strcmp(*argv, "-addtrust") == 0) { 331280304Sjkim if (--argc < 1) 332280304Sjkim goto bad; 333280304Sjkim if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) { 334280304Sjkim BIO_printf(bio_err, "Invalid trust object value %s\n", *argv); 335280304Sjkim goto bad; 336280304Sjkim } 337280304Sjkim if (!trust) 338280304Sjkim trust = sk_ASN1_OBJECT_new_null(); 339280304Sjkim sk_ASN1_OBJECT_push(trust, objtmp); 340280304Sjkim trustout = 1; 341280304Sjkim } else if (strcmp(*argv, "-addreject") == 0) { 342280304Sjkim if (--argc < 1) 343280304Sjkim goto bad; 344280304Sjkim if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) { 345280304Sjkim BIO_printf(bio_err, 346280304Sjkim "Invalid reject object value %s\n", *argv); 347280304Sjkim goto bad; 348280304Sjkim } 349280304Sjkim if (!reject) 350280304Sjkim reject = sk_ASN1_OBJECT_new_null(); 351280304Sjkim sk_ASN1_OBJECT_push(reject, objtmp); 352280304Sjkim trustout = 1; 353280304Sjkim } else if (strcmp(*argv, "-setalias") == 0) { 354280304Sjkim if (--argc < 1) 355280304Sjkim goto bad; 356280304Sjkim alias = *(++argv); 357280304Sjkim trustout = 1; 358280304Sjkim } else if (strcmp(*argv, "-certopt") == 0) { 359280304Sjkim if (--argc < 1) 360280304Sjkim goto bad; 361280304Sjkim if (!set_cert_ex(&certflag, *(++argv))) 362280304Sjkim goto bad; 363280304Sjkim } else if (strcmp(*argv, "-nameopt") == 0) { 364280304Sjkim if (--argc < 1) 365280304Sjkim goto bad; 366280304Sjkim if (!set_name_ex(&nmflag, *(++argv))) 367280304Sjkim goto bad; 368280304Sjkim } 369111147Snectar#ifndef OPENSSL_NO_ENGINE 370280304Sjkim else if (strcmp(*argv, "-engine") == 0) { 371280304Sjkim if (--argc < 1) 372280304Sjkim goto bad; 373280304Sjkim engine = *(++argv); 374280304Sjkim } 375111147Snectar#endif 376280304Sjkim else if (strcmp(*argv, "-C") == 0) 377280304Sjkim C = ++num; 378280304Sjkim else if (strcmp(*argv, "-email") == 0) 379280304Sjkim email = ++num; 380280304Sjkim else if (strcmp(*argv, "-ocsp_uri") == 0) 381280304Sjkim ocsp_uri = ++num; 382280304Sjkim else if (strcmp(*argv, "-serial") == 0) 383280304Sjkim serial = ++num; 384280304Sjkim else if (strcmp(*argv, "-next_serial") == 0) 385280304Sjkim next_serial = ++num; 386280304Sjkim else if (strcmp(*argv, "-modulus") == 0) 387280304Sjkim modulus = ++num; 388280304Sjkim else if (strcmp(*argv, "-pubkey") == 0) 389280304Sjkim pubkey = ++num; 390280304Sjkim else if (strcmp(*argv, "-x509toreq") == 0) 391280304Sjkim x509req = ++num; 392280304Sjkim else if (strcmp(*argv, "-text") == 0) 393280304Sjkim text = ++num; 394280304Sjkim else if (strcmp(*argv, "-hash") == 0 395280304Sjkim || strcmp(*argv, "-subject_hash") == 0) 396280304Sjkim subject_hash = ++num; 397238405Sjkim#ifndef OPENSSL_NO_MD5 398280304Sjkim else if (strcmp(*argv, "-subject_hash_old") == 0) 399280304Sjkim subject_hash_old = ++num; 400238405Sjkim#endif 401280304Sjkim else if (strcmp(*argv, "-issuer_hash") == 0) 402280304Sjkim issuer_hash = ++num; 403238405Sjkim#ifndef OPENSSL_NO_MD5 404280304Sjkim else if (strcmp(*argv, "-issuer_hash_old") == 0) 405280304Sjkim issuer_hash_old = ++num; 406238405Sjkim#endif 407280304Sjkim else if (strcmp(*argv, "-subject") == 0) 408280304Sjkim subject = ++num; 409280304Sjkim else if (strcmp(*argv, "-issuer") == 0) 410280304Sjkim issuer = ++num; 411280304Sjkim else if (strcmp(*argv, "-fingerprint") == 0) 412280304Sjkim fingerprint = ++num; 413280304Sjkim else if (strcmp(*argv, "-dates") == 0) { 414280304Sjkim startdate = ++num; 415280304Sjkim enddate = ++num; 416280304Sjkim } else if (strcmp(*argv, "-purpose") == 0) 417280304Sjkim pprint = ++num; 418280304Sjkim else if (strcmp(*argv, "-startdate") == 0) 419280304Sjkim startdate = ++num; 420280304Sjkim else if (strcmp(*argv, "-enddate") == 0) 421280304Sjkim enddate = ++num; 422280304Sjkim else if (strcmp(*argv, "-checkend") == 0) { 423280304Sjkim if (--argc < 1) 424280304Sjkim goto bad; 425280304Sjkim checkoffset = atoi(*(++argv)); 426280304Sjkim checkend = 1; 427280304Sjkim } else if (strcmp(*argv, "-noout") == 0) 428280304Sjkim noout = ++num; 429280304Sjkim else if (strcmp(*argv, "-trustout") == 0) 430280304Sjkim trustout = 1; 431280304Sjkim else if (strcmp(*argv, "-clrtrust") == 0) 432280304Sjkim clrtrust = ++num; 433280304Sjkim else if (strcmp(*argv, "-clrreject") == 0) 434280304Sjkim clrreject = ++num; 435280304Sjkim else if (strcmp(*argv, "-alias") == 0) 436280304Sjkim aliasout = ++num; 437280304Sjkim else if (strcmp(*argv, "-CAcreateserial") == 0) 438280304Sjkim CA_createserial = ++num; 439280304Sjkim else if (strcmp(*argv, "-clrext") == 0) 440280304Sjkim clrext = 1; 441280304Sjkim#if 1 /* stay backwards-compatible with 0.9.5; this 442280304Sjkim * should go away soon */ 443280304Sjkim else if (strcmp(*argv, "-crlext") == 0) { 444280304Sjkim BIO_printf(bio_err, "use -clrext instead of -crlext\n"); 445280304Sjkim clrext = 1; 446280304Sjkim } 44759191Skris#endif 448280304Sjkim else if (strcmp(*argv, "-ocspid") == 0) 449280304Sjkim ocspid = ++num; 450280304Sjkim else if ((md_alg = EVP_get_digestbyname(*argv + 1))) { 451280304Sjkim /* ok */ 452280304Sjkim digest = md_alg; 453280304Sjkim } else { 454280304Sjkim BIO_printf(bio_err, "unknown option %s\n", *argv); 455280304Sjkim badops = 1; 456280304Sjkim break; 457280304Sjkim } 458280304Sjkim argc--; 459280304Sjkim argv++; 460280304Sjkim } 46155714Skris 462280304Sjkim if (badops) { 463280304Sjkim bad: 464280304Sjkim for (pp = x509_usage; (*pp != NULL); pp++) 465280304Sjkim BIO_printf(bio_err, "%s", *pp); 466280304Sjkim goto end; 467280304Sjkim } 468111147Snectar#ifndef OPENSSL_NO_ENGINE 469280304Sjkim e = setup_engine(bio_err, engine, 0); 470111147Snectar#endif 471109998Smarkm 472280304Sjkim if (need_rand) 473280304Sjkim app_RAND_load_file(NULL, bio_err, 0); 47459191Skris 475280304Sjkim ERR_load_crypto_strings(); 47655714Skris 477280304Sjkim if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { 478280304Sjkim BIO_printf(bio_err, "Error getting password\n"); 479280304Sjkim goto end; 480280304Sjkim } 48159191Skris 482280304Sjkim if (!X509_STORE_set_default_paths(ctx)) { 483280304Sjkim ERR_print_errors(bio_err); 484280304Sjkim goto end; 485280304Sjkim } 48655714Skris 487280304Sjkim if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) { 488280304Sjkim CAkeyfile = CAfile; 489280304Sjkim } else if ((CA_flag) && (CAkeyfile == NULL)) { 490280304Sjkim BIO_printf(bio_err, 491280304Sjkim "need to specify a CAkey if using the CA command\n"); 492280304Sjkim goto end; 493280304Sjkim } 49455714Skris 495280304Sjkim if (extfile) { 496280304Sjkim long errorline = -1; 497280304Sjkim X509V3_CTX ctx2; 498280304Sjkim extconf = NCONF_new(NULL); 499280304Sjkim if (!NCONF_load(extconf, extfile, &errorline)) { 500280304Sjkim if (errorline <= 0) 501280304Sjkim BIO_printf(bio_err, 502280304Sjkim "error loading the config file '%s'\n", extfile); 503280304Sjkim else 504280304Sjkim BIO_printf(bio_err, 505280304Sjkim "error on line %ld of config file '%s'\n", 506280304Sjkim errorline, extfile); 507280304Sjkim goto end; 508280304Sjkim } 509280304Sjkim if (!extsect) { 510280304Sjkim extsect = NCONF_get_string(extconf, "default", "extensions"); 511280304Sjkim if (!extsect) { 512280304Sjkim ERR_clear_error(); 513280304Sjkim extsect = "default"; 514280304Sjkim } 515280304Sjkim } 516280304Sjkim X509V3_set_ctx_test(&ctx2); 517280304Sjkim X509V3_set_nconf(&ctx2, extconf); 518280304Sjkim if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) { 519280304Sjkim BIO_printf(bio_err, 520280304Sjkim "Error Loading extension section %s\n", extsect); 521280304Sjkim ERR_print_errors(bio_err); 522280304Sjkim goto end; 523280304Sjkim } 524280304Sjkim } 52555714Skris 526280304Sjkim if (reqfile) { 527280304Sjkim EVP_PKEY *pkey; 528280304Sjkim BIO *in; 52955714Skris 530280304Sjkim if (!sign_flag && !CA_flag) { 531280304Sjkim BIO_printf(bio_err, "We need a private key to sign with\n"); 532280304Sjkim goto end; 533280304Sjkim } 534280304Sjkim in = BIO_new(BIO_s_file()); 535280304Sjkim if (in == NULL) { 536280304Sjkim ERR_print_errors(bio_err); 537280304Sjkim goto end; 538280304Sjkim } 53955714Skris 540280304Sjkim if (infile == NULL) 541280304Sjkim BIO_set_fp(in, stdin, BIO_NOCLOSE | BIO_FP_TEXT); 542280304Sjkim else { 543280304Sjkim if (BIO_read_filename(in, infile) <= 0) { 544280304Sjkim perror(infile); 545280304Sjkim BIO_free(in); 546280304Sjkim goto end; 547280304Sjkim } 548280304Sjkim } 549280304Sjkim req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); 550280304Sjkim BIO_free(in); 55155714Skris 552280304Sjkim if (req == NULL) { 553280304Sjkim ERR_print_errors(bio_err); 554280304Sjkim goto end; 555280304Sjkim } 55655714Skris 557280304Sjkim if ((req->req_info == NULL) || 558280304Sjkim (req->req_info->pubkey == NULL) || 559280304Sjkim (req->req_info->pubkey->public_key == NULL) || 560280304Sjkim (req->req_info->pubkey->public_key->data == NULL)) { 561280304Sjkim BIO_printf(bio_err, 562280304Sjkim "The certificate request appears to corrupted\n"); 563280304Sjkim BIO_printf(bio_err, "It does not contain a public key\n"); 564280304Sjkim goto end; 565280304Sjkim } 566280304Sjkim if ((pkey = X509_REQ_get_pubkey(req)) == NULL) { 567280304Sjkim BIO_printf(bio_err, "error unpacking public key\n"); 568280304Sjkim goto end; 569280304Sjkim } 570280304Sjkim i = X509_REQ_verify(req, pkey); 571280304Sjkim EVP_PKEY_free(pkey); 572280304Sjkim if (i < 0) { 573280304Sjkim BIO_printf(bio_err, "Signature verification error\n"); 574280304Sjkim ERR_print_errors(bio_err); 575280304Sjkim goto end; 576280304Sjkim } 577280304Sjkim if (i == 0) { 578280304Sjkim BIO_printf(bio_err, 579280304Sjkim "Signature did not match the certificate request\n"); 580280304Sjkim goto end; 581280304Sjkim } else 582280304Sjkim BIO_printf(bio_err, "Signature ok\n"); 58355714Skris 584280304Sjkim print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), 585280304Sjkim nmflag); 58655714Skris 587280304Sjkim if ((x = X509_new()) == NULL) 588280304Sjkim goto end; 58968651Skris 590280304Sjkim if (sno == NULL) { 591280304Sjkim sno = ASN1_INTEGER_new(); 592280304Sjkim if (!sno || !rand_serial(NULL, sno)) 593280304Sjkim goto end; 594280304Sjkim if (!X509_set_serialNumber(x, sno)) 595280304Sjkim goto end; 596280304Sjkim ASN1_INTEGER_free(sno); 597280304Sjkim sno = NULL; 598280304Sjkim } else if (!X509_set_serialNumber(x, sno)) 599280304Sjkim goto end; 60055714Skris 601280304Sjkim if (!X509_set_issuer_name(x, req->req_info->subject)) 602280304Sjkim goto end; 603280304Sjkim if (!X509_set_subject_name(x, req->req_info->subject)) 604280304Sjkim goto end; 605142425Snectar 606280304Sjkim X509_gmtime_adj(X509_get_notBefore(x), 0); 607280304Sjkim X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL); 60855714Skris 609280304Sjkim pkey = X509_REQ_get_pubkey(req); 610280304Sjkim X509_set_pubkey(x, pkey); 611280304Sjkim EVP_PKEY_free(pkey); 612280304Sjkim } else 613280304Sjkim x = load_cert(bio_err, infile, informat, NULL, e, "Certificate"); 61455714Skris 615280304Sjkim if (x == NULL) 616280304Sjkim goto end; 617280304Sjkim if (CA_flag) { 618280304Sjkim xca = load_cert(bio_err, CAfile, CAformat, NULL, e, "CA Certificate"); 619280304Sjkim if (xca == NULL) 620280304Sjkim goto end; 621280304Sjkim } 62255714Skris 623280304Sjkim if (!noout || text || next_serial) { 624280304Sjkim OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3"); 62555714Skris 626280304Sjkim out = BIO_new(BIO_s_file()); 627280304Sjkim if (out == NULL) { 628280304Sjkim ERR_print_errors(bio_err); 629280304Sjkim goto end; 630280304Sjkim } 631280304Sjkim if (outfile == NULL) { 632280304Sjkim BIO_set_fp(out, stdout, BIO_NOCLOSE); 633109998Smarkm#ifdef OPENSSL_SYS_VMS 634280304Sjkim { 635280304Sjkim BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 636280304Sjkim out = BIO_push(tmpbio, out); 637280304Sjkim } 63868651Skris#endif 639280304Sjkim } else { 640280304Sjkim if (BIO_write_filename(out, outfile) <= 0) { 641280304Sjkim perror(outfile); 642280304Sjkim goto end; 643280304Sjkim } 644280304Sjkim } 645280304Sjkim } 64655714Skris 647280304Sjkim if (alias) 648280304Sjkim X509_alias_set1(x, (unsigned char *)alias, -1); 64959191Skris 650280304Sjkim if (clrtrust) 651280304Sjkim X509_trust_clear(x); 652280304Sjkim if (clrreject) 653280304Sjkim X509_reject_clear(x); 65459191Skris 655280304Sjkim if (trust) { 656280304Sjkim for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) { 657280304Sjkim objtmp = sk_ASN1_OBJECT_value(trust, i); 658280304Sjkim X509_add1_trust_object(x, objtmp); 659280304Sjkim } 660280304Sjkim } 66159191Skris 662280304Sjkim if (reject) { 663280304Sjkim for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) { 664280304Sjkim objtmp = sk_ASN1_OBJECT_value(reject, i); 665280304Sjkim X509_add1_reject_object(x, objtmp); 666280304Sjkim } 667280304Sjkim } 66859191Skris 669280304Sjkim if (num) { 670280304Sjkim for (i = 1; i <= num; i++) { 671280304Sjkim if (issuer == i) { 672280304Sjkim print_name(STDout, "issuer= ", 673280304Sjkim X509_get_issuer_name(x), nmflag); 674280304Sjkim } else if (subject == i) { 675280304Sjkim print_name(STDout, "subject= ", 676280304Sjkim X509_get_subject_name(x), nmflag); 677280304Sjkim } else if (serial == i) { 678280304Sjkim BIO_printf(STDout, "serial="); 679280304Sjkim i2a_ASN1_INTEGER(STDout, X509_get_serialNumber(x)); 680280304Sjkim BIO_printf(STDout, "\n"); 681280304Sjkim } else if (next_serial == i) { 682280304Sjkim BIGNUM *bnser; 683280304Sjkim ASN1_INTEGER *ser; 684280304Sjkim ser = X509_get_serialNumber(x); 685280304Sjkim bnser = ASN1_INTEGER_to_BN(ser, NULL); 686280304Sjkim if (!bnser) 687280304Sjkim goto end; 688280304Sjkim if (!BN_add_word(bnser, 1)) 689280304Sjkim goto end; 690280304Sjkim ser = BN_to_ASN1_INTEGER(bnser, NULL); 691280304Sjkim if (!ser) 692280304Sjkim goto end; 693280304Sjkim BN_free(bnser); 694280304Sjkim i2a_ASN1_INTEGER(out, ser); 695280304Sjkim ASN1_INTEGER_free(ser); 696280304Sjkim BIO_puts(out, "\n"); 697280304Sjkim } else if ((email == i) || (ocsp_uri == i)) { 698280304Sjkim int j; 699280304Sjkim STACK_OF(OPENSSL_STRING) *emlst; 700280304Sjkim if (email == i) 701280304Sjkim emlst = X509_get1_email(x); 702280304Sjkim else 703280304Sjkim emlst = X509_get1_ocsp(x); 704280304Sjkim for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) 705280304Sjkim BIO_printf(STDout, "%s\n", 706280304Sjkim sk_OPENSSL_STRING_value(emlst, j)); 707280304Sjkim X509_email_free(emlst); 708280304Sjkim } else if (aliasout == i) { 709280304Sjkim unsigned char *alstr; 710280304Sjkim alstr = X509_alias_get0(x, NULL); 711280304Sjkim if (alstr) 712280304Sjkim BIO_printf(STDout, "%s\n", alstr); 713280304Sjkim else 714280304Sjkim BIO_puts(STDout, "<No Alias>\n"); 715280304Sjkim } else if (subject_hash == i) { 716280304Sjkim BIO_printf(STDout, "%08lx\n", X509_subject_name_hash(x)); 717280304Sjkim } 718238405Sjkim#ifndef OPENSSL_NO_MD5 719280304Sjkim else if (subject_hash_old == i) { 720280304Sjkim BIO_printf(STDout, "%08lx\n", X509_subject_name_hash_old(x)); 721280304Sjkim } 722238405Sjkim#endif 723280304Sjkim else if (issuer_hash == i) { 724280304Sjkim BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash(x)); 725280304Sjkim } 726238405Sjkim#ifndef OPENSSL_NO_MD5 727280304Sjkim else if (issuer_hash_old == i) { 728280304Sjkim BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash_old(x)); 729280304Sjkim } 730238405Sjkim#endif 731280304Sjkim else if (pprint == i) { 732280304Sjkim X509_PURPOSE *ptmp; 733280304Sjkim int j; 734280304Sjkim BIO_printf(STDout, "Certificate purposes:\n"); 735280304Sjkim for (j = 0; j < X509_PURPOSE_get_count(); j++) { 736280304Sjkim ptmp = X509_PURPOSE_get0(j); 737280304Sjkim purpose_print(STDout, x, ptmp); 738280304Sjkim } 739280304Sjkim } else if (modulus == i) { 740280304Sjkim EVP_PKEY *pkey; 74155714Skris 742280304Sjkim pkey = X509_get_pubkey(x); 743280304Sjkim if (pkey == NULL) { 744280304Sjkim BIO_printf(bio_err, "Modulus=unavailable\n"); 745280304Sjkim ERR_print_errors(bio_err); 746280304Sjkim goto end; 747280304Sjkim } 748280304Sjkim BIO_printf(STDout, "Modulus="); 749109998Smarkm#ifndef OPENSSL_NO_RSA 750280304Sjkim if (pkey->type == EVP_PKEY_RSA) 751280304Sjkim BN_print(STDout, pkey->pkey.rsa->n); 752280304Sjkim else 75355714Skris#endif 754109998Smarkm#ifndef OPENSSL_NO_DSA 755280304Sjkim if (pkey->type == EVP_PKEY_DSA) 756280304Sjkim BN_print(STDout, pkey->pkey.dsa->pub_key); 757280304Sjkim else 75855714Skris#endif 759280304Sjkim BIO_printf(STDout, "Wrong Algorithm type"); 760280304Sjkim BIO_printf(STDout, "\n"); 761280304Sjkim EVP_PKEY_free(pkey); 762280304Sjkim } else if (pubkey == i) { 763280304Sjkim EVP_PKEY *pkey; 76459191Skris 765280304Sjkim pkey = X509_get_pubkey(x); 766280304Sjkim if (pkey == NULL) { 767280304Sjkim BIO_printf(bio_err, "Error getting public key\n"); 768280304Sjkim ERR_print_errors(bio_err); 769280304Sjkim goto end; 770280304Sjkim } 771280304Sjkim PEM_write_bio_PUBKEY(STDout, pkey); 772280304Sjkim EVP_PKEY_free(pkey); 773280304Sjkim } else if (C == i) { 774280304Sjkim unsigned char *d; 775280304Sjkim char *m; 776280304Sjkim int y, z; 77755714Skris 778280304Sjkim X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof buf); 779280304Sjkim BIO_printf(STDout, "/* subject:%s */\n", buf); 780280304Sjkim m = X509_NAME_oneline(X509_get_issuer_name(x), buf, 781280304Sjkim sizeof buf); 782280304Sjkim BIO_printf(STDout, "/* issuer :%s */\n", buf); 78355714Skris 784280304Sjkim z = i2d_X509(x, NULL); 785280304Sjkim m = OPENSSL_malloc(z); 786280304Sjkim if (!m) { 787280304Sjkim BIO_printf(bio_err, "Out of memory\n"); 788280304Sjkim ERR_print_errors(bio_err); 789280304Sjkim goto end; 790280304Sjkim } 79155714Skris 792280304Sjkim d = (unsigned char *)m; 793280304Sjkim z = i2d_X509_NAME(X509_get_subject_name(x), &d); 794280304Sjkim BIO_printf(STDout, "unsigned char XXX_subject_name[%d]={\n", 795280304Sjkim z); 796280304Sjkim d = (unsigned char *)m; 797280304Sjkim for (y = 0; y < z; y++) { 798280304Sjkim BIO_printf(STDout, "0x%02X,", d[y]); 799280304Sjkim if ((y & 0x0f) == 0x0f) 800280304Sjkim BIO_printf(STDout, "\n"); 801280304Sjkim } 802280304Sjkim if (y % 16 != 0) 803280304Sjkim BIO_printf(STDout, "\n"); 804280304Sjkim BIO_printf(STDout, "};\n"); 80555714Skris 806280304Sjkim z = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d); 807280304Sjkim BIO_printf(STDout, "unsigned char XXX_public_key[%d]={\n", z); 808280304Sjkim d = (unsigned char *)m; 809280304Sjkim for (y = 0; y < z; y++) { 810280304Sjkim BIO_printf(STDout, "0x%02X,", d[y]); 811280304Sjkim if ((y & 0x0f) == 0x0f) 812280304Sjkim BIO_printf(STDout, "\n"); 813280304Sjkim } 814280304Sjkim if (y % 16 != 0) 815280304Sjkim BIO_printf(STDout, "\n"); 816280304Sjkim BIO_printf(STDout, "};\n"); 81755714Skris 818280304Sjkim z = i2d_X509(x, &d); 819280304Sjkim BIO_printf(STDout, "unsigned char XXX_certificate[%d]={\n", 820280304Sjkim z); 821280304Sjkim d = (unsigned char *)m; 822280304Sjkim for (y = 0; y < z; y++) { 823280304Sjkim BIO_printf(STDout, "0x%02X,", d[y]); 824280304Sjkim if ((y & 0x0f) == 0x0f) 825280304Sjkim BIO_printf(STDout, "\n"); 826280304Sjkim } 827280304Sjkim if (y % 16 != 0) 828280304Sjkim BIO_printf(STDout, "\n"); 829280304Sjkim BIO_printf(STDout, "};\n"); 83055714Skris 831280304Sjkim OPENSSL_free(m); 832280304Sjkim } else if (text == i) { 833280304Sjkim X509_print_ex(STDout, x, nmflag, certflag); 834280304Sjkim } else if (startdate == i) { 835280304Sjkim BIO_puts(STDout, "notBefore="); 836280304Sjkim ASN1_TIME_print(STDout, X509_get_notBefore(x)); 837280304Sjkim BIO_puts(STDout, "\n"); 838280304Sjkim } else if (enddate == i) { 839280304Sjkim BIO_puts(STDout, "notAfter="); 840280304Sjkim ASN1_TIME_print(STDout, X509_get_notAfter(x)); 841280304Sjkim BIO_puts(STDout, "\n"); 842280304Sjkim } else if (fingerprint == i) { 843280304Sjkim int j; 844280304Sjkim unsigned int n; 845280304Sjkim unsigned char md[EVP_MAX_MD_SIZE]; 846280304Sjkim const EVP_MD *fdig = digest; 84755714Skris 848280304Sjkim if (!fdig) 849280304Sjkim fdig = EVP_sha1(); 850238405Sjkim 851280304Sjkim if (!X509_digest(x, fdig, md, &n)) { 852280304Sjkim BIO_printf(bio_err, "out of memory\n"); 853280304Sjkim goto end; 854280304Sjkim } 855280304Sjkim BIO_printf(STDout, "%s Fingerprint=", 856280304Sjkim OBJ_nid2sn(EVP_MD_type(fdig))); 857280304Sjkim for (j = 0; j < (int)n; j++) { 858280304Sjkim BIO_printf(STDout, "%02X%c", md[j], (j + 1 == (int)n) 859280304Sjkim ? '\n' : ':'); 860280304Sjkim } 861280304Sjkim } 86255714Skris 863280304Sjkim /* should be in the library */ 864280304Sjkim else if ((sign_flag == i) && (x509req == 0)) { 865280304Sjkim BIO_printf(bio_err, "Getting Private key\n"); 866280304Sjkim if (Upkey == NULL) { 867280304Sjkim Upkey = load_key(bio_err, 868280304Sjkim keyfile, keyformat, 0, 869280304Sjkim passin, e, "Private key"); 870280304Sjkim if (Upkey == NULL) 871280304Sjkim goto end; 872280304Sjkim } 87355714Skris 874280304Sjkim assert(need_rand); 875280304Sjkim if (!sign(x, Upkey, days, clrext, digest, extconf, extsect)) 876280304Sjkim goto end; 877280304Sjkim } else if (CA_flag == i) { 878280304Sjkim BIO_printf(bio_err, "Getting CA Private Key\n"); 879280304Sjkim if (CAkeyfile != NULL) { 880280304Sjkim CApkey = load_key(bio_err, 881280304Sjkim CAkeyfile, CAkeyformat, 882280304Sjkim 0, passin, e, "CA Private Key"); 883280304Sjkim if (CApkey == NULL) 884280304Sjkim goto end; 885280304Sjkim } 88655714Skris 887280304Sjkim assert(need_rand); 888280304Sjkim if (!x509_certify(ctx, CAfile, digest, x, xca, 889280304Sjkim CApkey, sigopts, 890280304Sjkim CAserial, CA_createserial, days, clrext, 891280304Sjkim extconf, extsect, sno)) 892280304Sjkim goto end; 893280304Sjkim } else if (x509req == i) { 894280304Sjkim EVP_PKEY *pk; 89555714Skris 896280304Sjkim BIO_printf(bio_err, "Getting request Private Key\n"); 897280304Sjkim if (keyfile == NULL) { 898280304Sjkim BIO_printf(bio_err, "no request key file specified\n"); 899280304Sjkim goto end; 900280304Sjkim } else { 901280304Sjkim pk = load_key(bio_err, 902280304Sjkim keyfile, keyformat, 0, 903280304Sjkim passin, e, "request key"); 904280304Sjkim if (pk == NULL) 905280304Sjkim goto end; 906280304Sjkim } 90755714Skris 908280304Sjkim BIO_printf(bio_err, "Generating certificate request\n"); 90955714Skris 910280304Sjkim rq = X509_to_X509_REQ(x, pk, digest); 911280304Sjkim EVP_PKEY_free(pk); 912280304Sjkim if (rq == NULL) { 913280304Sjkim ERR_print_errors(bio_err); 914280304Sjkim goto end; 915280304Sjkim } 916280304Sjkim if (!noout) { 917280304Sjkim X509_REQ_print(out, rq); 918280304Sjkim PEM_write_bio_X509_REQ(out, rq); 919280304Sjkim } 920280304Sjkim noout = 1; 921280304Sjkim } else if (ocspid == i) { 922280304Sjkim X509_ocspid_print(out, x); 923280304Sjkim } 924280304Sjkim } 925280304Sjkim } 92668651Skris 927280304Sjkim if (checkend) { 928280304Sjkim time_t tcheck = time(NULL) + checkoffset; 92968651Skris 930280304Sjkim if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) { 931280304Sjkim BIO_printf(out, "Certificate will expire\n"); 932280304Sjkim ret = 1; 933280304Sjkim } else { 934280304Sjkim BIO_printf(out, "Certificate will not expire\n"); 935280304Sjkim ret = 0; 936280304Sjkim } 937280304Sjkim goto end; 938280304Sjkim } 93955714Skris 940280304Sjkim if (noout) { 941280304Sjkim ret = 0; 942280304Sjkim goto end; 943280304Sjkim } 94455714Skris 945280304Sjkim if (outformat == FORMAT_ASN1) 946280304Sjkim i = i2d_X509_bio(out, x); 947280304Sjkim else if (outformat == FORMAT_PEM) { 948280304Sjkim if (trustout) 949280304Sjkim i = PEM_write_bio_X509_AUX(out, x); 950280304Sjkim else 951280304Sjkim i = PEM_write_bio_X509(out, x); 952280304Sjkim } else if (outformat == FORMAT_NETSCAPE) { 953280304Sjkim NETSCAPE_X509 nx; 954280304Sjkim ASN1_OCTET_STRING hdr; 95555714Skris 956280304Sjkim hdr.data = (unsigned char *)NETSCAPE_CERT_HDR; 957280304Sjkim hdr.length = strlen(NETSCAPE_CERT_HDR); 958280304Sjkim nx.header = &hdr; 959280304Sjkim nx.cert = x; 96055714Skris 961280304Sjkim i = ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509), out, &nx); 962280304Sjkim } else { 963280304Sjkim BIO_printf(bio_err, "bad output format specified for outfile\n"); 964280304Sjkim goto end; 965280304Sjkim } 966280304Sjkim if (!i) { 967280304Sjkim BIO_printf(bio_err, "unable to write certificate\n"); 968280304Sjkim ERR_print_errors(bio_err); 969280304Sjkim goto end; 970280304Sjkim } 971280304Sjkim ret = 0; 972280304Sjkim end: 973280304Sjkim if (need_rand) 974280304Sjkim app_RAND_write_file(NULL, bio_err); 975280304Sjkim OBJ_cleanup(); 976280304Sjkim NCONF_free(extconf); 977280304Sjkim BIO_free_all(out); 978280304Sjkim BIO_free_all(STDout); 979280304Sjkim X509_STORE_free(ctx); 980280304Sjkim X509_REQ_free(req); 981280304Sjkim X509_free(x); 982280304Sjkim X509_free(xca); 983280304Sjkim EVP_PKEY_free(Upkey); 984280304Sjkim EVP_PKEY_free(CApkey); 985280304Sjkim if (sigopts) 986280304Sjkim sk_OPENSSL_STRING_free(sigopts); 987280304Sjkim X509_REQ_free(rq); 988280304Sjkim ASN1_INTEGER_free(sno); 989280304Sjkim sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); 990280304Sjkim sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free); 991280304Sjkim if (passin) 992280304Sjkim OPENSSL_free(passin); 993280304Sjkim apps_shutdown(); 994280304Sjkim OPENSSL_EXIT(ret); 995280304Sjkim} 99655714Skris 997280304Sjkimstatic ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile, 998280304Sjkim int create) 999280304Sjkim{ 1000280304Sjkim char *buf = NULL, *p; 1001280304Sjkim ASN1_INTEGER *bs = NULL; 1002280304Sjkim BIGNUM *serial = NULL; 1003280304Sjkim size_t len; 100455714Skris 1005280304Sjkim len = ((serialfile == NULL) 1006280304Sjkim ? (strlen(CAfile) + strlen(POSTFIX) + 1) 1007280304Sjkim : (strlen(serialfile))) + 1; 1008280304Sjkim buf = OPENSSL_malloc(len); 1009280304Sjkim if (buf == NULL) { 1010280304Sjkim BIO_printf(bio_err, "out of mem\n"); 1011280304Sjkim goto end; 1012280304Sjkim } 1013280304Sjkim if (serialfile == NULL) { 1014280304Sjkim BUF_strlcpy(buf, CAfile, len); 1015280304Sjkim for (p = buf; *p; p++) 1016280304Sjkim if (*p == '.') { 1017280304Sjkim *p = '\0'; 1018280304Sjkim break; 1019280304Sjkim } 1020280304Sjkim BUF_strlcat(buf, POSTFIX, len); 1021280304Sjkim } else 1022280304Sjkim BUF_strlcpy(buf, serialfile, len); 102355714Skris 1024280304Sjkim serial = load_serial(buf, create, NULL); 1025280304Sjkim if (serial == NULL) 1026280304Sjkim goto end; 1027109998Smarkm 1028280304Sjkim if (!BN_add_word(serial, 1)) { 1029280304Sjkim BIO_printf(bio_err, "add_word failure\n"); 1030280304Sjkim goto end; 1031280304Sjkim } 1032127128Snectar 1033280304Sjkim if (!save_serial(buf, NULL, serial, &bs)) 1034280304Sjkim goto end; 1035280304Sjkim 1036127128Snectar end: 1037280304Sjkim if (buf) 1038280304Sjkim OPENSSL_free(buf); 1039280304Sjkim BN_free(serial); 1040280304Sjkim return bs; 1041280304Sjkim} 1042109998Smarkm 1043109998Smarkmstatic int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, 1044280304Sjkim X509 *x, X509 *xca, EVP_PKEY *pkey, 1045280304Sjkim STACK_OF(OPENSSL_STRING) *sigopts, 1046280304Sjkim char *serialfile, int create, 1047280304Sjkim int days, int clrext, CONF *conf, char *section, 1048280304Sjkim ASN1_INTEGER *sno) 1049280304Sjkim{ 1050280304Sjkim int ret = 0; 1051280304Sjkim ASN1_INTEGER *bs = NULL; 1052280304Sjkim X509_STORE_CTX xsc; 1053280304Sjkim EVP_PKEY *upkey; 1054109998Smarkm 1055280304Sjkim upkey = X509_get_pubkey(xca); 1056306196Sjkim if (upkey == NULL) { 1057306196Sjkim BIO_printf(bio_err, "Error obtaining CA X509 public key\n"); 1058306196Sjkim goto end; 1059306196Sjkim } 1060280304Sjkim EVP_PKEY_copy_parameters(upkey, pkey); 1061280304Sjkim EVP_PKEY_free(upkey); 1062109998Smarkm 1063280304Sjkim if (!X509_STORE_CTX_init(&xsc, ctx, x, NULL)) { 1064280304Sjkim BIO_printf(bio_err, "Error initialising X509 store\n"); 1065280304Sjkim goto end; 1066280304Sjkim } 1067280304Sjkim if (sno) 1068280304Sjkim bs = sno; 1069280304Sjkim else if (!(bs = x509_load_serial(CAfile, serialfile, create))) 1070280304Sjkim goto end; 1071109998Smarkm 1072280304Sjkim/* if (!X509_STORE_add_cert(ctx,x)) goto end;*/ 107355714Skris 1074280304Sjkim /* 1075280304Sjkim * NOTE: this certificate can/should be self signed, unless it was a 1076280304Sjkim * certificate request in which case it is not. 1077280304Sjkim */ 1078280304Sjkim X509_STORE_CTX_set_cert(&xsc, x); 1079280304Sjkim X509_STORE_CTX_set_flags(&xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); 1080280304Sjkim if (!reqfile && X509_verify_cert(&xsc) <= 0) 1081280304Sjkim goto end; 108255714Skris 1083280304Sjkim if (!X509_check_private_key(xca, pkey)) { 1084280304Sjkim BIO_printf(bio_err, 1085280304Sjkim "CA certificate and CA private key do not match\n"); 1086280304Sjkim goto end; 1087280304Sjkim } 108855714Skris 1089280304Sjkim if (!X509_set_issuer_name(x, X509_get_subject_name(xca))) 1090280304Sjkim goto end; 1091280304Sjkim if (!X509_set_serialNumber(x, bs)) 1092280304Sjkim goto end; 109355714Skris 1094280304Sjkim if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL) 1095280304Sjkim goto end; 109655714Skris 1097280304Sjkim /* hardwired expired */ 1098280304Sjkim if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL) 1099280304Sjkim goto end; 110055714Skris 1101280304Sjkim if (clrext) { 1102280304Sjkim while (X509_get_ext_count(x) > 0) 1103280304Sjkim X509_delete_ext(x, 0); 1104280304Sjkim } 110559191Skris 1106280304Sjkim if (conf) { 1107280304Sjkim X509V3_CTX ctx2; 1108280304Sjkim X509_set_version(x, 2); /* version 3 certificate */ 1109280304Sjkim X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0); 1110280304Sjkim X509V3_set_nconf(&ctx2, conf); 1111280304Sjkim if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) 1112280304Sjkim goto end; 1113280304Sjkim } 111455714Skris 1115280304Sjkim if (!do_X509_sign(bio_err, x, pkey, digest, sigopts)) 1116280304Sjkim goto end; 1117280304Sjkim ret = 1; 1118280304Sjkim end: 1119280304Sjkim X509_STORE_CTX_cleanup(&xsc); 1120280304Sjkim if (!ret) 1121280304Sjkim ERR_print_errors(bio_err); 1122280304Sjkim if (!sno) 1123280304Sjkim ASN1_INTEGER_free(bs); 1124280304Sjkim return ret; 1125280304Sjkim} 112655714Skris 112755714Skrisstatic int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx) 1128280304Sjkim{ 1129280304Sjkim int err; 1130280304Sjkim X509 *err_cert; 113155714Skris 1132280304Sjkim /* 1133280304Sjkim * it is ok to use a self signed certificate This case will catch both 1134280304Sjkim * the initial ok == 0 and the final ok == 1 calls to this function 1135280304Sjkim */ 1136280304Sjkim err = X509_STORE_CTX_get_error(ctx); 1137280304Sjkim if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) 1138280304Sjkim return 1; 113955714Skris 1140280304Sjkim /* 1141280304Sjkim * BAD we should have gotten an error. Normally if everything worked 1142280304Sjkim * X509_STORE_CTX_get_error(ctx) will still be set to 1143280304Sjkim * DEPTH_ZERO_SELF_.... 1144280304Sjkim */ 1145280304Sjkim if (ok) { 1146280304Sjkim BIO_printf(bio_err, 1147280304Sjkim "error with certificate to be certified - should be self signed\n"); 1148280304Sjkim return 0; 1149280304Sjkim } else { 1150280304Sjkim err_cert = X509_STORE_CTX_get_current_cert(ctx); 1151280304Sjkim print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0); 1152280304Sjkim BIO_printf(bio_err, 1153280304Sjkim "error with certificate - error %d at depth %d\n%s\n", err, 1154280304Sjkim X509_STORE_CTX_get_error_depth(ctx), 1155280304Sjkim X509_verify_cert_error_string(err)); 1156280304Sjkim return 1; 1157280304Sjkim } 1158280304Sjkim} 115955714Skris 116055714Skris/* self sign */ 1161280304Sjkimstatic int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, 1162280304Sjkim const EVP_MD *digest, CONF *conf, char *section) 1163280304Sjkim{ 116455714Skris 1165280304Sjkim EVP_PKEY *pktmp; 116655714Skris 1167280304Sjkim pktmp = X509_get_pubkey(x); 1168306196Sjkim if (pktmp == NULL) 1169306196Sjkim goto err; 1170280304Sjkim EVP_PKEY_copy_parameters(pktmp, pkey); 1171280304Sjkim EVP_PKEY_save_parameters(pktmp, 1); 1172280304Sjkim EVP_PKEY_free(pktmp); 117355714Skris 1174280304Sjkim if (!X509_set_issuer_name(x, X509_get_subject_name(x))) 1175280304Sjkim goto err; 1176280304Sjkim if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL) 1177280304Sjkim goto err; 117855714Skris 1179295016Sjkim if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL) 1180280304Sjkim goto err; 118155714Skris 1182280304Sjkim if (!X509_set_pubkey(x, pkey)) 1183280304Sjkim goto err; 1184280304Sjkim if (clrext) { 1185280304Sjkim while (X509_get_ext_count(x) > 0) 1186280304Sjkim X509_delete_ext(x, 0); 1187280304Sjkim } 1188280304Sjkim if (conf) { 1189280304Sjkim X509V3_CTX ctx; 1190280304Sjkim X509_set_version(x, 2); /* version 3 certificate */ 1191280304Sjkim X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0); 1192280304Sjkim X509V3_set_nconf(&ctx, conf); 1193280304Sjkim if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) 1194280304Sjkim goto err; 1195280304Sjkim } 1196280304Sjkim if (!X509_sign(x, pkey, digest)) 1197280304Sjkim goto err; 1198280304Sjkim return 1; 1199280304Sjkim err: 1200280304Sjkim ERR_print_errors(bio_err); 1201280304Sjkim return 0; 1202280304Sjkim} 120359191Skris 120459191Skrisstatic int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt) 120559191Skris{ 1206280304Sjkim int id, i, idret; 1207280304Sjkim char *pname; 1208280304Sjkim id = X509_PURPOSE_get_id(pt); 1209280304Sjkim pname = X509_PURPOSE_get0_name(pt); 1210280304Sjkim for (i = 0; i < 2; i++) { 1211280304Sjkim idret = X509_check_purpose(cert, id, i); 1212280304Sjkim BIO_printf(bio, "%s%s : ", pname, i ? " CA" : ""); 1213280304Sjkim if (idret == 1) 1214280304Sjkim BIO_printf(bio, "Yes\n"); 1215280304Sjkim else if (idret == 0) 1216280304Sjkim BIO_printf(bio, "No\n"); 1217280304Sjkim else 1218280304Sjkim BIO_printf(bio, "Yes (WARNING code=%d)\n", idret); 1219280304Sjkim } 1220280304Sjkim return 1; 122159191Skris} 1222