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. 8296341Sdelphij * 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). 15296341Sdelphij * 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. 22296341Sdelphij * 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 :-). 37296341Sdelphij * 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)" 40296341Sdelphij * 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. 52296341Sdelphij * 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 64296341Sdelphij# 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 77296341Sdelphij# include <openssl/rsa.h> 78160814Ssimon#endif 79160814Ssimon#ifndef OPENSSL_NO_DSA 80296341Sdelphij# include <openssl/dsa.h> 81160814Ssimon#endif 8255714Skris 8355714Skris#undef PROG 8455714Skris#define PROG x509_main 8555714Skris 8655714Skris#undef POSTFIX 87296341Sdelphij#define POSTFIX ".srl" 88296341Sdelphij#define DEF_DAYS 30 8955714Skris 90296341Sdelphijstatic const char *x509_usage[] = { 91296341Sdelphij "usage: x509 args\n", 92296341Sdelphij " -inform arg - input format - default PEM (one of DER, NET or PEM)\n", 93296341Sdelphij " -outform arg - output format - default PEM (one of DER, NET or PEM)\n", 94296341Sdelphij " -keyform arg - private key format - default PEM\n", 95296341Sdelphij " -CAform arg - CA format - default PEM\n", 96296341Sdelphij " -CAkeyform arg - CA key format - default PEM\n", 97296341Sdelphij " -in arg - input file - default stdin\n", 98296341Sdelphij " -out arg - output file - default stdout\n", 99296341Sdelphij " -passin arg - private key password source\n", 100296341Sdelphij " -serial - print serial number value\n", 101296341Sdelphij " -subject_hash - print subject hash value\n", 102238405Sjkim#ifndef OPENSSL_NO_MD5 103296341Sdelphij " -subject_hash_old - print old-style (MD5) subject hash value\n", 104238405Sjkim#endif 105296341Sdelphij " -issuer_hash - print issuer hash value\n", 106238405Sjkim#ifndef OPENSSL_NO_MD5 107296341Sdelphij " -issuer_hash_old - print old-style (MD5) issuer hash value\n", 108238405Sjkim#endif 109296341Sdelphij " -hash - synonym for -subject_hash\n", 110296341Sdelphij " -subject - print subject DN\n", 111296341Sdelphij " -issuer - print issuer DN\n", 112296341Sdelphij " -email - print email address(es)\n", 113296341Sdelphij " -startdate - notBefore field\n", 114296341Sdelphij " -enddate - notAfter field\n", 115296341Sdelphij " -purpose - print out certificate purposes\n", 116296341Sdelphij " -dates - both Before and After dates\n", 117296341Sdelphij " -modulus - print the RSA key modulus\n", 118296341Sdelphij " -pubkey - output the public key\n", 119296341Sdelphij " -fingerprint - print the certificate fingerprint\n", 120296341Sdelphij " -alias - output certificate alias\n", 121296341Sdelphij " -noout - no certificate output\n", 122296341Sdelphij " -ocspid - print OCSP hash values for the subject name and public key\n", 123296341Sdelphij " -ocsp_uri - print OCSP Responder URL(s)\n", 124296341Sdelphij " -trustout - output a \"trusted\" certificate\n", 125296341Sdelphij " -clrtrust - clear all trusted purposes\n", 126296341Sdelphij " -clrreject - clear all rejected purposes\n", 127296341Sdelphij " -addtrust arg - trust certificate for a given purpose\n", 128296341Sdelphij " -addreject arg - reject certificate for a given purpose\n", 129296341Sdelphij " -setalias arg - set certificate alias\n", 130296341Sdelphij " -days arg - How long till expiry of a signed certificate - def 30 days\n", 131296341Sdelphij " -checkend arg - check whether the cert expires in the next arg seconds\n", 132296341Sdelphij " exit 1 if so, 0 if not\n", 133296341Sdelphij " -signkey arg - self sign cert with arg\n", 134296341Sdelphij " -x509toreq - output a certification request object\n", 135296341Sdelphij " -req - input is a certificate request, sign and output.\n", 136296341Sdelphij " -CA arg - set the CA certificate, must be PEM format.\n", 137296341Sdelphij " -CAkey arg - set the CA key, must be PEM format\n", 138296341Sdelphij " missing, it is assumed to be in the CA file.\n", 139296341Sdelphij " -CAcreateserial - create serial number file if it does not exist\n", 140296341Sdelphij " -CAserial arg - serial file\n", 141296341Sdelphij " -set_serial - serial number to use\n", 142296341Sdelphij " -text - print the certificate in text form\n", 143296341Sdelphij " -C - print out C code forms\n", 144296341Sdelphij " -md2/-md5/-sha1/-mdc2 - digest to use\n", 145296341Sdelphij " -extfile - configuration file with X509V3 extensions to add\n", 146296341Sdelphij " -extensions - section from config file with X509V3 extensions to add\n", 147296341Sdelphij " -clrext - delete extensions before signing and input certificate\n", 148296341Sdelphij " -nameopt arg - various certificate name options\n", 149111147Snectar#ifndef OPENSSL_NO_ENGINE 150296341Sdelphij " -engine e - use engine e, possibly a hardware device.\n", 151111147Snectar#endif 152296341Sdelphij " -certopt arg - various certificate text options\n", 153296341Sdelphij NULL 15455714Skris}; 15555714Skris 15655714Skrisstatic int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx); 157296341Sdelphijstatic int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, 158296341Sdelphij const EVP_MD *digest, CONF *conf, char *section); 159296341Sdelphijstatic int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, 160296341Sdelphij X509 *x, X509 *xca, EVP_PKEY *pkey, 161296341Sdelphij STACK_OF(OPENSSL_STRING) *sigopts, char *serial, 162296341Sdelphij int create, int days, int clrext, CONF *conf, 163296341Sdelphij char *section, ASN1_INTEGER *sno); 16459191Skrisstatic int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt); 165296341Sdelphijstatic int reqfile = 0; 16655714Skris 16759191Skrisint MAIN(int, char **); 16859191Skris 16955714Skrisint MAIN(int argc, char **argv) 170296341Sdelphij{ 171296341Sdelphij ENGINE *e = NULL; 172296341Sdelphij int ret = 1; 173296341Sdelphij X509_REQ *req = NULL; 174296341Sdelphij X509 *x = NULL, *xca = NULL; 175296341Sdelphij ASN1_OBJECT *objtmp; 176296341Sdelphij STACK_OF(OPENSSL_STRING) *sigopts = NULL; 177296341Sdelphij EVP_PKEY *Upkey = NULL, *CApkey = NULL; 178296341Sdelphij ASN1_INTEGER *sno = NULL; 179296341Sdelphij int i, num, badops = 0; 180296341Sdelphij BIO *out = NULL; 181296341Sdelphij BIO *STDout = NULL; 182296341Sdelphij STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; 183296341Sdelphij int informat, outformat, keyformat, CAformat, CAkeyformat; 184296341Sdelphij char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL; 185296341Sdelphij char *CAkeyfile = NULL, *CAserial = NULL; 186296341Sdelphij char *alias = NULL; 187296341Sdelphij int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 188296341Sdelphij 0, enddate = 0; 189296341Sdelphij int next_serial = 0; 190296341Sdelphij int subject_hash = 0, issuer_hash = 0, ocspid = 0; 191238405Sjkim#ifndef OPENSSL_NO_MD5 192296341Sdelphij int subject_hash_old = 0, issuer_hash_old = 0; 193238405Sjkim#endif 194296341Sdelphij int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0; 195296341Sdelphij int ocsp_uri = 0; 196296341Sdelphij int trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0, clrext = 0; 197296341Sdelphij int C = 0; 198296341Sdelphij int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0; 199296341Sdelphij int pprint = 0; 200296341Sdelphij const char **pp; 201296341Sdelphij X509_STORE *ctx = NULL; 202296341Sdelphij X509_REQ *rq = NULL; 203296341Sdelphij int fingerprint = 0; 204296341Sdelphij char buf[256]; 205296341Sdelphij const EVP_MD *md_alg, *digest = NULL; 206296341Sdelphij CONF *extconf = NULL; 207296341Sdelphij char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL; 208296341Sdelphij int need_rand = 0; 209296341Sdelphij int checkend = 0, checkoffset = 0; 210296341Sdelphij unsigned long nmflag = 0, certflag = 0; 211111147Snectar#ifndef OPENSSL_NO_ENGINE 212296341Sdelphij char *engine = NULL; 213111147Snectar#endif 21455714Skris 215296341Sdelphij reqfile = 0; 21655714Skris 217296341Sdelphij apps_startup(); 21855714Skris 219296341Sdelphij if (bio_err == NULL) 220296341Sdelphij bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 221109998Smarkm 222296341Sdelphij if (!load_config(bio_err, NULL)) 223296341Sdelphij goto end; 224296341Sdelphij STDout = BIO_new_fp(stdout, BIO_NOCLOSE); 225109998Smarkm#ifdef OPENSSL_SYS_VMS 226296341Sdelphij { 227296341Sdelphij BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 228296341Sdelphij STDout = BIO_push(tmpbio, STDout); 229296341Sdelphij } 23068651Skris#endif 23155714Skris 232296341Sdelphij informat = FORMAT_PEM; 233296341Sdelphij outformat = FORMAT_PEM; 234296341Sdelphij keyformat = FORMAT_PEM; 235296341Sdelphij CAformat = FORMAT_PEM; 236296341Sdelphij CAkeyformat = FORMAT_PEM; 23755714Skris 238296341Sdelphij ctx = X509_STORE_new(); 239296341Sdelphij if (ctx == NULL) 240296341Sdelphij goto end; 241296341Sdelphij X509_STORE_set_verify_cb(ctx, callb); 24255714Skris 243296341Sdelphij argc--; 244296341Sdelphij argv++; 245296341Sdelphij num = 0; 246296341Sdelphij while (argc >= 1) { 247296341Sdelphij if (strcmp(*argv, "-inform") == 0) { 248296341Sdelphij if (--argc < 1) 249296341Sdelphij goto bad; 250296341Sdelphij informat = str2fmt(*(++argv)); 251296341Sdelphij } else if (strcmp(*argv, "-outform") == 0) { 252296341Sdelphij if (--argc < 1) 253296341Sdelphij goto bad; 254296341Sdelphij outformat = str2fmt(*(++argv)); 255296341Sdelphij } else if (strcmp(*argv, "-keyform") == 0) { 256296341Sdelphij if (--argc < 1) 257296341Sdelphij goto bad; 258296341Sdelphij keyformat = str2fmt(*(++argv)); 259296341Sdelphij } else if (strcmp(*argv, "-req") == 0) { 260296341Sdelphij reqfile = 1; 261296341Sdelphij need_rand = 1; 262296341Sdelphij } else if (strcmp(*argv, "-CAform") == 0) { 263296341Sdelphij if (--argc < 1) 264296341Sdelphij goto bad; 265296341Sdelphij CAformat = str2fmt(*(++argv)); 266296341Sdelphij } else if (strcmp(*argv, "-CAkeyform") == 0) { 267296341Sdelphij if (--argc < 1) 268296341Sdelphij goto bad; 269296341Sdelphij CAkeyformat = str2fmt(*(++argv)); 270296341Sdelphij } else if (strcmp(*argv, "-sigopt") == 0) { 271296341Sdelphij if (--argc < 1) 272296341Sdelphij goto bad; 273296341Sdelphij if (!sigopts) 274296341Sdelphij sigopts = sk_OPENSSL_STRING_new_null(); 275296341Sdelphij if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv))) 276296341Sdelphij goto bad; 277296341Sdelphij } else if (strcmp(*argv, "-days") == 0) { 278296341Sdelphij if (--argc < 1) 279296341Sdelphij goto bad; 280296341Sdelphij days = atoi(*(++argv)); 281296341Sdelphij if (days == 0) { 282296341Sdelphij BIO_printf(bio_err, "bad number of days\n"); 283296341Sdelphij goto bad; 284296341Sdelphij } 285296341Sdelphij } else if (strcmp(*argv, "-passin") == 0) { 286296341Sdelphij if (--argc < 1) 287296341Sdelphij goto bad; 288296341Sdelphij passargin = *(++argv); 289296341Sdelphij } else if (strcmp(*argv, "-extfile") == 0) { 290296341Sdelphij if (--argc < 1) 291296341Sdelphij goto bad; 292296341Sdelphij extfile = *(++argv); 293296341Sdelphij } else if (strcmp(*argv, "-extensions") == 0) { 294296341Sdelphij if (--argc < 1) 295296341Sdelphij goto bad; 296296341Sdelphij extsect = *(++argv); 297296341Sdelphij } else if (strcmp(*argv, "-in") == 0) { 298296341Sdelphij if (--argc < 1) 299296341Sdelphij goto bad; 300296341Sdelphij infile = *(++argv); 301296341Sdelphij } else if (strcmp(*argv, "-out") == 0) { 302296341Sdelphij if (--argc < 1) 303296341Sdelphij goto bad; 304296341Sdelphij outfile = *(++argv); 305296341Sdelphij } else if (strcmp(*argv, "-signkey") == 0) { 306296341Sdelphij if (--argc < 1) 307296341Sdelphij goto bad; 308296341Sdelphij keyfile = *(++argv); 309296341Sdelphij sign_flag = ++num; 310296341Sdelphij need_rand = 1; 311296341Sdelphij } else if (strcmp(*argv, "-CA") == 0) { 312296341Sdelphij if (--argc < 1) 313296341Sdelphij goto bad; 314296341Sdelphij CAfile = *(++argv); 315296341Sdelphij CA_flag = ++num; 316296341Sdelphij need_rand = 1; 317296341Sdelphij } else if (strcmp(*argv, "-CAkey") == 0) { 318296341Sdelphij if (--argc < 1) 319296341Sdelphij goto bad; 320296341Sdelphij CAkeyfile = *(++argv); 321296341Sdelphij } else if (strcmp(*argv, "-CAserial") == 0) { 322296341Sdelphij if (--argc < 1) 323296341Sdelphij goto bad; 324296341Sdelphij CAserial = *(++argv); 325296341Sdelphij } else if (strcmp(*argv, "-set_serial") == 0) { 326296341Sdelphij if (--argc < 1) 327296341Sdelphij goto bad; 328296341Sdelphij if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv)))) 329296341Sdelphij goto bad; 330296341Sdelphij } else if (strcmp(*argv, "-addtrust") == 0) { 331296341Sdelphij if (--argc < 1) 332296341Sdelphij goto bad; 333296341Sdelphij if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) { 334296341Sdelphij BIO_printf(bio_err, "Invalid trust object value %s\n", *argv); 335296341Sdelphij goto bad; 336296341Sdelphij } 337296341Sdelphij if (!trust) 338296341Sdelphij trust = sk_ASN1_OBJECT_new_null(); 339296341Sdelphij sk_ASN1_OBJECT_push(trust, objtmp); 340296341Sdelphij trustout = 1; 341296341Sdelphij } else if (strcmp(*argv, "-addreject") == 0) { 342296341Sdelphij if (--argc < 1) 343296341Sdelphij goto bad; 344296341Sdelphij if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) { 345296341Sdelphij BIO_printf(bio_err, 346296341Sdelphij "Invalid reject object value %s\n", *argv); 347296341Sdelphij goto bad; 348296341Sdelphij } 349296341Sdelphij if (!reject) 350296341Sdelphij reject = sk_ASN1_OBJECT_new_null(); 351296341Sdelphij sk_ASN1_OBJECT_push(reject, objtmp); 352296341Sdelphij trustout = 1; 353296341Sdelphij } else if (strcmp(*argv, "-setalias") == 0) { 354296341Sdelphij if (--argc < 1) 355296341Sdelphij goto bad; 356296341Sdelphij alias = *(++argv); 357296341Sdelphij trustout = 1; 358296341Sdelphij } else if (strcmp(*argv, "-certopt") == 0) { 359296341Sdelphij if (--argc < 1) 360296341Sdelphij goto bad; 361296341Sdelphij if (!set_cert_ex(&certflag, *(++argv))) 362296341Sdelphij goto bad; 363296341Sdelphij } else if (strcmp(*argv, "-nameopt") == 0) { 364296341Sdelphij if (--argc < 1) 365296341Sdelphij goto bad; 366296341Sdelphij if (!set_name_ex(&nmflag, *(++argv))) 367296341Sdelphij goto bad; 368296341Sdelphij } 369111147Snectar#ifndef OPENSSL_NO_ENGINE 370296341Sdelphij else if (strcmp(*argv, "-engine") == 0) { 371296341Sdelphij if (--argc < 1) 372296341Sdelphij goto bad; 373296341Sdelphij engine = *(++argv); 374296341Sdelphij } 375111147Snectar#endif 376296341Sdelphij else if (strcmp(*argv, "-C") == 0) 377296341Sdelphij C = ++num; 378296341Sdelphij else if (strcmp(*argv, "-email") == 0) 379296341Sdelphij email = ++num; 380296341Sdelphij else if (strcmp(*argv, "-ocsp_uri") == 0) 381296341Sdelphij ocsp_uri = ++num; 382296341Sdelphij else if (strcmp(*argv, "-serial") == 0) 383296341Sdelphij serial = ++num; 384296341Sdelphij else if (strcmp(*argv, "-next_serial") == 0) 385296341Sdelphij next_serial = ++num; 386296341Sdelphij else if (strcmp(*argv, "-modulus") == 0) 387296341Sdelphij modulus = ++num; 388296341Sdelphij else if (strcmp(*argv, "-pubkey") == 0) 389296341Sdelphij pubkey = ++num; 390296341Sdelphij else if (strcmp(*argv, "-x509toreq") == 0) 391296341Sdelphij x509req = ++num; 392296341Sdelphij else if (strcmp(*argv, "-text") == 0) 393296341Sdelphij text = ++num; 394296341Sdelphij else if (strcmp(*argv, "-hash") == 0 395296341Sdelphij || strcmp(*argv, "-subject_hash") == 0) 396296341Sdelphij subject_hash = ++num; 397238405Sjkim#ifndef OPENSSL_NO_MD5 398296341Sdelphij else if (strcmp(*argv, "-subject_hash_old") == 0) 399296341Sdelphij subject_hash_old = ++num; 400238405Sjkim#endif 401296341Sdelphij else if (strcmp(*argv, "-issuer_hash") == 0) 402296341Sdelphij issuer_hash = ++num; 403238405Sjkim#ifndef OPENSSL_NO_MD5 404296341Sdelphij else if (strcmp(*argv, "-issuer_hash_old") == 0) 405296341Sdelphij issuer_hash_old = ++num; 406238405Sjkim#endif 407296341Sdelphij else if (strcmp(*argv, "-subject") == 0) 408296341Sdelphij subject = ++num; 409296341Sdelphij else if (strcmp(*argv, "-issuer") == 0) 410296341Sdelphij issuer = ++num; 411296341Sdelphij else if (strcmp(*argv, "-fingerprint") == 0) 412296341Sdelphij fingerprint = ++num; 413296341Sdelphij else if (strcmp(*argv, "-dates") == 0) { 414296341Sdelphij startdate = ++num; 415296341Sdelphij enddate = ++num; 416296341Sdelphij } else if (strcmp(*argv, "-purpose") == 0) 417296341Sdelphij pprint = ++num; 418296341Sdelphij else if (strcmp(*argv, "-startdate") == 0) 419296341Sdelphij startdate = ++num; 420296341Sdelphij else if (strcmp(*argv, "-enddate") == 0) 421296341Sdelphij enddate = ++num; 422296341Sdelphij else if (strcmp(*argv, "-checkend") == 0) { 423296341Sdelphij if (--argc < 1) 424296341Sdelphij goto bad; 425296341Sdelphij checkoffset = atoi(*(++argv)); 426296341Sdelphij checkend = 1; 427296341Sdelphij } else if (strcmp(*argv, "-noout") == 0) 428296341Sdelphij noout = ++num; 429296341Sdelphij else if (strcmp(*argv, "-trustout") == 0) 430296341Sdelphij trustout = 1; 431296341Sdelphij else if (strcmp(*argv, "-clrtrust") == 0) 432296341Sdelphij clrtrust = ++num; 433296341Sdelphij else if (strcmp(*argv, "-clrreject") == 0) 434296341Sdelphij clrreject = ++num; 435296341Sdelphij else if (strcmp(*argv, "-alias") == 0) 436296341Sdelphij aliasout = ++num; 437296341Sdelphij else if (strcmp(*argv, "-CAcreateserial") == 0) 438296341Sdelphij CA_createserial = ++num; 439296341Sdelphij else if (strcmp(*argv, "-clrext") == 0) 440296341Sdelphij clrext = 1; 441296341Sdelphij#if 1 /* stay backwards-compatible with 0.9.5; this 442296341Sdelphij * should go away soon */ 443296341Sdelphij else if (strcmp(*argv, "-crlext") == 0) { 444296341Sdelphij BIO_printf(bio_err, "use -clrext instead of -crlext\n"); 445296341Sdelphij clrext = 1; 446296341Sdelphij } 44759191Skris#endif 448296341Sdelphij else if (strcmp(*argv, "-ocspid") == 0) 449296341Sdelphij ocspid = ++num; 450296341Sdelphij else if ((md_alg = EVP_get_digestbyname(*argv + 1))) { 451296341Sdelphij /* ok */ 452296341Sdelphij digest = md_alg; 453296341Sdelphij } else { 454296341Sdelphij BIO_printf(bio_err, "unknown option %s\n", *argv); 455296341Sdelphij badops = 1; 456296341Sdelphij break; 457296341Sdelphij } 458296341Sdelphij argc--; 459296341Sdelphij argv++; 460296341Sdelphij } 46155714Skris 462296341Sdelphij if (badops) { 463296341Sdelphij bad: 464296341Sdelphij for (pp = x509_usage; (*pp != NULL); pp++) 465296341Sdelphij BIO_printf(bio_err, "%s", *pp); 466296341Sdelphij goto end; 467296341Sdelphij } 468111147Snectar#ifndef OPENSSL_NO_ENGINE 469296341Sdelphij e = setup_engine(bio_err, engine, 0); 470111147Snectar#endif 471109998Smarkm 472296341Sdelphij if (need_rand) 473296341Sdelphij app_RAND_load_file(NULL, bio_err, 0); 47459191Skris 475296341Sdelphij ERR_load_crypto_strings(); 47655714Skris 477296341Sdelphij if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { 478296341Sdelphij BIO_printf(bio_err, "Error getting password\n"); 479296341Sdelphij goto end; 480296341Sdelphij } 48159191Skris 482296341Sdelphij if (!X509_STORE_set_default_paths(ctx)) { 483296341Sdelphij ERR_print_errors(bio_err); 484296341Sdelphij goto end; 485296341Sdelphij } 48655714Skris 487296341Sdelphij if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) { 488296341Sdelphij CAkeyfile = CAfile; 489296341Sdelphij } else if ((CA_flag) && (CAkeyfile == NULL)) { 490296341Sdelphij BIO_printf(bio_err, 491296341Sdelphij "need to specify a CAkey if using the CA command\n"); 492296341Sdelphij goto end; 493296341Sdelphij } 49455714Skris 495296341Sdelphij if (extfile) { 496296341Sdelphij long errorline = -1; 497296341Sdelphij X509V3_CTX ctx2; 498296341Sdelphij extconf = NCONF_new(NULL); 499296341Sdelphij if (!NCONF_load(extconf, extfile, &errorline)) { 500296341Sdelphij if (errorline <= 0) 501296341Sdelphij BIO_printf(bio_err, 502296341Sdelphij "error loading the config file '%s'\n", extfile); 503296341Sdelphij else 504296341Sdelphij BIO_printf(bio_err, 505296341Sdelphij "error on line %ld of config file '%s'\n", 506296341Sdelphij errorline, extfile); 507296341Sdelphij goto end; 508296341Sdelphij } 509296341Sdelphij if (!extsect) { 510296341Sdelphij extsect = NCONF_get_string(extconf, "default", "extensions"); 511296341Sdelphij if (!extsect) { 512296341Sdelphij ERR_clear_error(); 513296341Sdelphij extsect = "default"; 514296341Sdelphij } 515296341Sdelphij } 516296341Sdelphij X509V3_set_ctx_test(&ctx2); 517296341Sdelphij X509V3_set_nconf(&ctx2, extconf); 518296341Sdelphij if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) { 519296341Sdelphij BIO_printf(bio_err, 520296341Sdelphij "Error Loading extension section %s\n", extsect); 521296341Sdelphij ERR_print_errors(bio_err); 522296341Sdelphij goto end; 523296341Sdelphij } 524296341Sdelphij } 52555714Skris 526296341Sdelphij if (reqfile) { 527296341Sdelphij EVP_PKEY *pkey; 528296341Sdelphij BIO *in; 52955714Skris 530296341Sdelphij if (!sign_flag && !CA_flag) { 531296341Sdelphij BIO_printf(bio_err, "We need a private key to sign with\n"); 532296341Sdelphij goto end; 533296341Sdelphij } 534296341Sdelphij in = BIO_new(BIO_s_file()); 535296341Sdelphij if (in == NULL) { 536296341Sdelphij ERR_print_errors(bio_err); 537296341Sdelphij goto end; 538296341Sdelphij } 53955714Skris 540296341Sdelphij if (infile == NULL) 541296341Sdelphij BIO_set_fp(in, stdin, BIO_NOCLOSE | BIO_FP_TEXT); 542296341Sdelphij else { 543296341Sdelphij if (BIO_read_filename(in, infile) <= 0) { 544296341Sdelphij perror(infile); 545296341Sdelphij BIO_free(in); 546296341Sdelphij goto end; 547296341Sdelphij } 548296341Sdelphij } 549296341Sdelphij req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); 550296341Sdelphij BIO_free(in); 55155714Skris 552296341Sdelphij if (req == NULL) { 553296341Sdelphij ERR_print_errors(bio_err); 554296341Sdelphij goto end; 555296341Sdelphij } 55655714Skris 557296341Sdelphij if ((req->req_info == NULL) || 558296341Sdelphij (req->req_info->pubkey == NULL) || 559296341Sdelphij (req->req_info->pubkey->public_key == NULL) || 560296341Sdelphij (req->req_info->pubkey->public_key->data == NULL)) { 561296341Sdelphij BIO_printf(bio_err, 562296341Sdelphij "The certificate request appears to corrupted\n"); 563296341Sdelphij BIO_printf(bio_err, "It does not contain a public key\n"); 564296341Sdelphij goto end; 565296341Sdelphij } 566296341Sdelphij if ((pkey = X509_REQ_get_pubkey(req)) == NULL) { 567296341Sdelphij BIO_printf(bio_err, "error unpacking public key\n"); 568296341Sdelphij goto end; 569296341Sdelphij } 570296341Sdelphij i = X509_REQ_verify(req, pkey); 571296341Sdelphij EVP_PKEY_free(pkey); 572296341Sdelphij if (i < 0) { 573296341Sdelphij BIO_printf(bio_err, "Signature verification error\n"); 574296341Sdelphij ERR_print_errors(bio_err); 575296341Sdelphij goto end; 576296341Sdelphij } 577296341Sdelphij if (i == 0) { 578296341Sdelphij BIO_printf(bio_err, 579296341Sdelphij "Signature did not match the certificate request\n"); 580296341Sdelphij goto end; 581296341Sdelphij } else 582296341Sdelphij BIO_printf(bio_err, "Signature ok\n"); 58355714Skris 584296341Sdelphij print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), 585296341Sdelphij nmflag); 58655714Skris 587296341Sdelphij if ((x = X509_new()) == NULL) 588296341Sdelphij goto end; 58968651Skris 590296341Sdelphij if (sno == NULL) { 591296341Sdelphij sno = ASN1_INTEGER_new(); 592296341Sdelphij if (!sno || !rand_serial(NULL, sno)) 593296341Sdelphij goto end; 594296341Sdelphij if (!X509_set_serialNumber(x, sno)) 595296341Sdelphij goto end; 596296341Sdelphij ASN1_INTEGER_free(sno); 597296341Sdelphij sno = NULL; 598296341Sdelphij } else if (!X509_set_serialNumber(x, sno)) 599296341Sdelphij goto end; 60055714Skris 601296341Sdelphij if (!X509_set_issuer_name(x, req->req_info->subject)) 602296341Sdelphij goto end; 603296341Sdelphij if (!X509_set_subject_name(x, req->req_info->subject)) 604296341Sdelphij goto end; 605142425Snectar 606296341Sdelphij X509_gmtime_adj(X509_get_notBefore(x), 0); 607296341Sdelphij X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL); 60855714Skris 609296341Sdelphij pkey = X509_REQ_get_pubkey(req); 610296341Sdelphij X509_set_pubkey(x, pkey); 611296341Sdelphij EVP_PKEY_free(pkey); 612296341Sdelphij } else 613296341Sdelphij x = load_cert(bio_err, infile, informat, NULL, e, "Certificate"); 61455714Skris 615296341Sdelphij if (x == NULL) 616296341Sdelphij goto end; 617296341Sdelphij if (CA_flag) { 618296341Sdelphij xca = load_cert(bio_err, CAfile, CAformat, NULL, e, "CA Certificate"); 619296341Sdelphij if (xca == NULL) 620296341Sdelphij goto end; 621296341Sdelphij } 62255714Skris 623296341Sdelphij if (!noout || text || next_serial) { 624296341Sdelphij OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3"); 62555714Skris 626296341Sdelphij out = BIO_new(BIO_s_file()); 627296341Sdelphij if (out == NULL) { 628296341Sdelphij ERR_print_errors(bio_err); 629296341Sdelphij goto end; 630296341Sdelphij } 631296341Sdelphij if (outfile == NULL) { 632296341Sdelphij BIO_set_fp(out, stdout, BIO_NOCLOSE); 633109998Smarkm#ifdef OPENSSL_SYS_VMS 634296341Sdelphij { 635296341Sdelphij BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 636296341Sdelphij out = BIO_push(tmpbio, out); 637296341Sdelphij } 63868651Skris#endif 639296341Sdelphij } else { 640296341Sdelphij if (BIO_write_filename(out, outfile) <= 0) { 641296341Sdelphij perror(outfile); 642296341Sdelphij goto end; 643296341Sdelphij } 644296341Sdelphij } 645296341Sdelphij } 64655714Skris 647296341Sdelphij if (alias) 648296341Sdelphij X509_alias_set1(x, (unsigned char *)alias, -1); 64959191Skris 650296341Sdelphij if (clrtrust) 651296341Sdelphij X509_trust_clear(x); 652296341Sdelphij if (clrreject) 653296341Sdelphij X509_reject_clear(x); 65459191Skris 655296341Sdelphij if (trust) { 656296341Sdelphij for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) { 657296341Sdelphij objtmp = sk_ASN1_OBJECT_value(trust, i); 658296341Sdelphij X509_add1_trust_object(x, objtmp); 659296341Sdelphij } 660296341Sdelphij } 66159191Skris 662296341Sdelphij if (reject) { 663296341Sdelphij for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) { 664296341Sdelphij objtmp = sk_ASN1_OBJECT_value(reject, i); 665296341Sdelphij X509_add1_reject_object(x, objtmp); 666296341Sdelphij } 667296341Sdelphij } 66859191Skris 669296341Sdelphij if (num) { 670296341Sdelphij for (i = 1; i <= num; i++) { 671296341Sdelphij if (issuer == i) { 672296341Sdelphij print_name(STDout, "issuer= ", 673296341Sdelphij X509_get_issuer_name(x), nmflag); 674296341Sdelphij } else if (subject == i) { 675296341Sdelphij print_name(STDout, "subject= ", 676296341Sdelphij X509_get_subject_name(x), nmflag); 677296341Sdelphij } else if (serial == i) { 678296341Sdelphij BIO_printf(STDout, "serial="); 679296341Sdelphij i2a_ASN1_INTEGER(STDout, X509_get_serialNumber(x)); 680296341Sdelphij BIO_printf(STDout, "\n"); 681296341Sdelphij } else if (next_serial == i) { 682296341Sdelphij BIGNUM *bnser; 683296341Sdelphij ASN1_INTEGER *ser; 684296341Sdelphij ser = X509_get_serialNumber(x); 685296341Sdelphij bnser = ASN1_INTEGER_to_BN(ser, NULL); 686296341Sdelphij if (!bnser) 687296341Sdelphij goto end; 688296341Sdelphij if (!BN_add_word(bnser, 1)) 689296341Sdelphij goto end; 690296341Sdelphij ser = BN_to_ASN1_INTEGER(bnser, NULL); 691296341Sdelphij if (!ser) 692296341Sdelphij goto end; 693296341Sdelphij BN_free(bnser); 694296341Sdelphij i2a_ASN1_INTEGER(out, ser); 695296341Sdelphij ASN1_INTEGER_free(ser); 696296341Sdelphij BIO_puts(out, "\n"); 697296341Sdelphij } else if ((email == i) || (ocsp_uri == i)) { 698296341Sdelphij int j; 699296341Sdelphij STACK_OF(OPENSSL_STRING) *emlst; 700296341Sdelphij if (email == i) 701296341Sdelphij emlst = X509_get1_email(x); 702296341Sdelphij else 703296341Sdelphij emlst = X509_get1_ocsp(x); 704296341Sdelphij for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) 705296341Sdelphij BIO_printf(STDout, "%s\n", 706296341Sdelphij sk_OPENSSL_STRING_value(emlst, j)); 707296341Sdelphij X509_email_free(emlst); 708296341Sdelphij } else if (aliasout == i) { 709296341Sdelphij unsigned char *alstr; 710296341Sdelphij alstr = X509_alias_get0(x, NULL); 711296341Sdelphij if (alstr) 712296341Sdelphij BIO_printf(STDout, "%s\n", alstr); 713296341Sdelphij else 714296341Sdelphij BIO_puts(STDout, "<No Alias>\n"); 715296341Sdelphij } else if (subject_hash == i) { 716296341Sdelphij BIO_printf(STDout, "%08lx\n", X509_subject_name_hash(x)); 717296341Sdelphij } 718238405Sjkim#ifndef OPENSSL_NO_MD5 719296341Sdelphij else if (subject_hash_old == i) { 720296341Sdelphij BIO_printf(STDout, "%08lx\n", X509_subject_name_hash_old(x)); 721296341Sdelphij } 722238405Sjkim#endif 723296341Sdelphij else if (issuer_hash == i) { 724296341Sdelphij BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash(x)); 725296341Sdelphij } 726238405Sjkim#ifndef OPENSSL_NO_MD5 727296341Sdelphij else if (issuer_hash_old == i) { 728296341Sdelphij BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash_old(x)); 729296341Sdelphij } 730238405Sjkim#endif 731296341Sdelphij else if (pprint == i) { 732296341Sdelphij X509_PURPOSE *ptmp; 733296341Sdelphij int j; 734296341Sdelphij BIO_printf(STDout, "Certificate purposes:\n"); 735296341Sdelphij for (j = 0; j < X509_PURPOSE_get_count(); j++) { 736296341Sdelphij ptmp = X509_PURPOSE_get0(j); 737296341Sdelphij purpose_print(STDout, x, ptmp); 738296341Sdelphij } 739296341Sdelphij } else if (modulus == i) { 740296341Sdelphij EVP_PKEY *pkey; 74155714Skris 742296341Sdelphij pkey = X509_get_pubkey(x); 743296341Sdelphij if (pkey == NULL) { 744296341Sdelphij BIO_printf(bio_err, "Modulus=unavailable\n"); 745296341Sdelphij ERR_print_errors(bio_err); 746296341Sdelphij goto end; 747296341Sdelphij } 748296341Sdelphij BIO_printf(STDout, "Modulus="); 749109998Smarkm#ifndef OPENSSL_NO_RSA 750296341Sdelphij if (pkey->type == EVP_PKEY_RSA) 751296341Sdelphij BN_print(STDout, pkey->pkey.rsa->n); 752296341Sdelphij else 75355714Skris#endif 754109998Smarkm#ifndef OPENSSL_NO_DSA 755296341Sdelphij if (pkey->type == EVP_PKEY_DSA) 756296341Sdelphij BN_print(STDout, pkey->pkey.dsa->pub_key); 757296341Sdelphij else 75855714Skris#endif 759296341Sdelphij BIO_printf(STDout, "Wrong Algorithm type"); 760296341Sdelphij BIO_printf(STDout, "\n"); 761296341Sdelphij EVP_PKEY_free(pkey); 762296341Sdelphij } else if (pubkey == i) { 763296341Sdelphij EVP_PKEY *pkey; 76459191Skris 765296341Sdelphij pkey = X509_get_pubkey(x); 766296341Sdelphij if (pkey == NULL) { 767296341Sdelphij BIO_printf(bio_err, "Error getting public key\n"); 768296341Sdelphij ERR_print_errors(bio_err); 769296341Sdelphij goto end; 770296341Sdelphij } 771296341Sdelphij PEM_write_bio_PUBKEY(STDout, pkey); 772296341Sdelphij EVP_PKEY_free(pkey); 773296341Sdelphij } else if (C == i) { 774296341Sdelphij unsigned char *d; 775296341Sdelphij char *m; 776296341Sdelphij int y, z; 77755714Skris 778296341Sdelphij X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof buf); 779296341Sdelphij BIO_printf(STDout, "/* subject:%s */\n", buf); 780296341Sdelphij m = X509_NAME_oneline(X509_get_issuer_name(x), buf, 781296341Sdelphij sizeof buf); 782296341Sdelphij BIO_printf(STDout, "/* issuer :%s */\n", buf); 78355714Skris 784296341Sdelphij z = i2d_X509(x, NULL); 785296341Sdelphij m = OPENSSL_malloc(z); 786296341Sdelphij if (!m) { 787296341Sdelphij BIO_printf(bio_err, "Out of memory\n"); 788296341Sdelphij ERR_print_errors(bio_err); 789296341Sdelphij goto end; 790296341Sdelphij } 79155714Skris 792296341Sdelphij d = (unsigned char *)m; 793296341Sdelphij z = i2d_X509_NAME(X509_get_subject_name(x), &d); 794296341Sdelphij BIO_printf(STDout, "unsigned char XXX_subject_name[%d]={\n", 795296341Sdelphij z); 796296341Sdelphij d = (unsigned char *)m; 797296341Sdelphij for (y = 0; y < z; y++) { 798296341Sdelphij BIO_printf(STDout, "0x%02X,", d[y]); 799296341Sdelphij if ((y & 0x0f) == 0x0f) 800296341Sdelphij BIO_printf(STDout, "\n"); 801296341Sdelphij } 802296341Sdelphij if (y % 16 != 0) 803296341Sdelphij BIO_printf(STDout, "\n"); 804296341Sdelphij BIO_printf(STDout, "};\n"); 80555714Skris 806296341Sdelphij z = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d); 807296341Sdelphij BIO_printf(STDout, "unsigned char XXX_public_key[%d]={\n", z); 808296341Sdelphij d = (unsigned char *)m; 809296341Sdelphij for (y = 0; y < z; y++) { 810296341Sdelphij BIO_printf(STDout, "0x%02X,", d[y]); 811296341Sdelphij if ((y & 0x0f) == 0x0f) 812296341Sdelphij BIO_printf(STDout, "\n"); 813296341Sdelphij } 814296341Sdelphij if (y % 16 != 0) 815296341Sdelphij BIO_printf(STDout, "\n"); 816296341Sdelphij BIO_printf(STDout, "};\n"); 81755714Skris 818296341Sdelphij z = i2d_X509(x, &d); 819296341Sdelphij BIO_printf(STDout, "unsigned char XXX_certificate[%d]={\n", 820296341Sdelphij z); 821296341Sdelphij d = (unsigned char *)m; 822296341Sdelphij for (y = 0; y < z; y++) { 823296341Sdelphij BIO_printf(STDout, "0x%02X,", d[y]); 824296341Sdelphij if ((y & 0x0f) == 0x0f) 825296341Sdelphij BIO_printf(STDout, "\n"); 826296341Sdelphij } 827296341Sdelphij if (y % 16 != 0) 828296341Sdelphij BIO_printf(STDout, "\n"); 829296341Sdelphij BIO_printf(STDout, "};\n"); 83055714Skris 831296341Sdelphij OPENSSL_free(m); 832296341Sdelphij } else if (text == i) { 833296341Sdelphij X509_print_ex(STDout, x, nmflag, certflag); 834296341Sdelphij } else if (startdate == i) { 835296341Sdelphij BIO_puts(STDout, "notBefore="); 836296341Sdelphij ASN1_TIME_print(STDout, X509_get_notBefore(x)); 837296341Sdelphij BIO_puts(STDout, "\n"); 838296341Sdelphij } else if (enddate == i) { 839296341Sdelphij BIO_puts(STDout, "notAfter="); 840296341Sdelphij ASN1_TIME_print(STDout, X509_get_notAfter(x)); 841296341Sdelphij BIO_puts(STDout, "\n"); 842296341Sdelphij } else if (fingerprint == i) { 843296341Sdelphij int j; 844296341Sdelphij unsigned int n; 845296341Sdelphij unsigned char md[EVP_MAX_MD_SIZE]; 846296341Sdelphij const EVP_MD *fdig = digest; 84755714Skris 848296341Sdelphij if (!fdig) 849296341Sdelphij fdig = EVP_sha1(); 850238405Sjkim 851296341Sdelphij if (!X509_digest(x, fdig, md, &n)) { 852296341Sdelphij BIO_printf(bio_err, "out of memory\n"); 853296341Sdelphij goto end; 854296341Sdelphij } 855296341Sdelphij BIO_printf(STDout, "%s Fingerprint=", 856296341Sdelphij OBJ_nid2sn(EVP_MD_type(fdig))); 857296341Sdelphij for (j = 0; j < (int)n; j++) { 858296341Sdelphij BIO_printf(STDout, "%02X%c", md[j], (j + 1 == (int)n) 859296341Sdelphij ? '\n' : ':'); 860296341Sdelphij } 861296341Sdelphij } 86255714Skris 863296341Sdelphij /* should be in the library */ 864296341Sdelphij else if ((sign_flag == i) && (x509req == 0)) { 865296341Sdelphij BIO_printf(bio_err, "Getting Private key\n"); 866296341Sdelphij if (Upkey == NULL) { 867296341Sdelphij Upkey = load_key(bio_err, 868296341Sdelphij keyfile, keyformat, 0, 869296341Sdelphij passin, e, "Private key"); 870296341Sdelphij if (Upkey == NULL) 871296341Sdelphij goto end; 872296341Sdelphij } 87355714Skris 874296341Sdelphij assert(need_rand); 875296341Sdelphij if (!sign(x, Upkey, days, clrext, digest, extconf, extsect)) 876296341Sdelphij goto end; 877296341Sdelphij } else if (CA_flag == i) { 878296341Sdelphij BIO_printf(bio_err, "Getting CA Private Key\n"); 879296341Sdelphij if (CAkeyfile != NULL) { 880296341Sdelphij CApkey = load_key(bio_err, 881296341Sdelphij CAkeyfile, CAkeyformat, 882296341Sdelphij 0, passin, e, "CA Private Key"); 883296341Sdelphij if (CApkey == NULL) 884296341Sdelphij goto end; 885296341Sdelphij } 88655714Skris 887296341Sdelphij assert(need_rand); 888296341Sdelphij if (!x509_certify(ctx, CAfile, digest, x, xca, 889296341Sdelphij CApkey, sigopts, 890296341Sdelphij CAserial, CA_createserial, days, clrext, 891296341Sdelphij extconf, extsect, sno)) 892296341Sdelphij goto end; 893296341Sdelphij } else if (x509req == i) { 894296341Sdelphij EVP_PKEY *pk; 89555714Skris 896296341Sdelphij BIO_printf(bio_err, "Getting request Private Key\n"); 897296341Sdelphij if (keyfile == NULL) { 898296341Sdelphij BIO_printf(bio_err, "no request key file specified\n"); 899296341Sdelphij goto end; 900296341Sdelphij } else { 901296341Sdelphij pk = load_key(bio_err, 902296341Sdelphij keyfile, keyformat, 0, 903296341Sdelphij passin, e, "request key"); 904296341Sdelphij if (pk == NULL) 905296341Sdelphij goto end; 906296341Sdelphij } 90755714Skris 908296341Sdelphij BIO_printf(bio_err, "Generating certificate request\n"); 90955714Skris 910296341Sdelphij rq = X509_to_X509_REQ(x, pk, digest); 911296341Sdelphij EVP_PKEY_free(pk); 912296341Sdelphij if (rq == NULL) { 913296341Sdelphij ERR_print_errors(bio_err); 914296341Sdelphij goto end; 915296341Sdelphij } 916296341Sdelphij if (!noout) { 917296341Sdelphij X509_REQ_print(out, rq); 918296341Sdelphij PEM_write_bio_X509_REQ(out, rq); 919296341Sdelphij } 920296341Sdelphij noout = 1; 921296341Sdelphij } else if (ocspid == i) { 922296341Sdelphij X509_ocspid_print(out, x); 923296341Sdelphij } 924296341Sdelphij } 925296341Sdelphij } 92668651Skris 927296341Sdelphij if (checkend) { 928296341Sdelphij time_t tcheck = time(NULL) + checkoffset; 92968651Skris 930296341Sdelphij if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) { 931296341Sdelphij BIO_printf(out, "Certificate will expire\n"); 932296341Sdelphij ret = 1; 933296341Sdelphij } else { 934296341Sdelphij BIO_printf(out, "Certificate will not expire\n"); 935296341Sdelphij ret = 0; 936296341Sdelphij } 937296341Sdelphij goto end; 938296341Sdelphij } 93955714Skris 940296341Sdelphij if (noout) { 941296341Sdelphij ret = 0; 942296341Sdelphij goto end; 943296341Sdelphij } 94455714Skris 945296341Sdelphij if (outformat == FORMAT_ASN1) 946296341Sdelphij i = i2d_X509_bio(out, x); 947296341Sdelphij else if (outformat == FORMAT_PEM) { 948296341Sdelphij if (trustout) 949296341Sdelphij i = PEM_write_bio_X509_AUX(out, x); 950296341Sdelphij else 951296341Sdelphij i = PEM_write_bio_X509(out, x); 952296341Sdelphij } else if (outformat == FORMAT_NETSCAPE) { 953296341Sdelphij NETSCAPE_X509 nx; 954296341Sdelphij ASN1_OCTET_STRING hdr; 95555714Skris 956296341Sdelphij hdr.data = (unsigned char *)NETSCAPE_CERT_HDR; 957296341Sdelphij hdr.length = strlen(NETSCAPE_CERT_HDR); 958296341Sdelphij nx.header = &hdr; 959296341Sdelphij nx.cert = x; 96055714Skris 961296341Sdelphij i = ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509), out, &nx); 962296341Sdelphij } else { 963296341Sdelphij BIO_printf(bio_err, "bad output format specified for outfile\n"); 964296341Sdelphij goto end; 965296341Sdelphij } 966296341Sdelphij if (!i) { 967296341Sdelphij BIO_printf(bio_err, "unable to write certificate\n"); 968296341Sdelphij ERR_print_errors(bio_err); 969296341Sdelphij goto end; 970296341Sdelphij } 971296341Sdelphij ret = 0; 972296341Sdelphij end: 973296341Sdelphij if (need_rand) 974296341Sdelphij app_RAND_write_file(NULL, bio_err); 975296341Sdelphij OBJ_cleanup(); 976296341Sdelphij NCONF_free(extconf); 977296341Sdelphij BIO_free_all(out); 978296341Sdelphij BIO_free_all(STDout); 979296341Sdelphij X509_STORE_free(ctx); 980296341Sdelphij X509_REQ_free(req); 981296341Sdelphij X509_free(x); 982296341Sdelphij X509_free(xca); 983296341Sdelphij EVP_PKEY_free(Upkey); 984296341Sdelphij EVP_PKEY_free(CApkey); 985296341Sdelphij if (sigopts) 986296341Sdelphij sk_OPENSSL_STRING_free(sigopts); 987296341Sdelphij X509_REQ_free(rq); 988296341Sdelphij ASN1_INTEGER_free(sno); 989296341Sdelphij sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); 990296341Sdelphij sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free); 991296341Sdelphij if (passin) 992296341Sdelphij OPENSSL_free(passin); 993296341Sdelphij apps_shutdown(); 994296341Sdelphij OPENSSL_EXIT(ret); 995296341Sdelphij} 99655714Skris 997296341Sdelphijstatic ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile, 998296341Sdelphij int create) 999296341Sdelphij{ 1000296341Sdelphij char *buf = NULL, *p; 1001296341Sdelphij ASN1_INTEGER *bs = NULL; 1002296341Sdelphij BIGNUM *serial = NULL; 1003296341Sdelphij size_t len; 100455714Skris 1005296341Sdelphij len = ((serialfile == NULL) 1006296341Sdelphij ? (strlen(CAfile) + strlen(POSTFIX) + 1) 1007296341Sdelphij : (strlen(serialfile))) + 1; 1008296341Sdelphij buf = OPENSSL_malloc(len); 1009296341Sdelphij if (buf == NULL) { 1010296341Sdelphij BIO_printf(bio_err, "out of mem\n"); 1011296341Sdelphij goto end; 1012296341Sdelphij } 1013296341Sdelphij if (serialfile == NULL) { 1014296341Sdelphij BUF_strlcpy(buf, CAfile, len); 1015296341Sdelphij for (p = buf; *p; p++) 1016296341Sdelphij if (*p == '.') { 1017296341Sdelphij *p = '\0'; 1018296341Sdelphij break; 1019296341Sdelphij } 1020296341Sdelphij BUF_strlcat(buf, POSTFIX, len); 1021296341Sdelphij } else 1022296341Sdelphij BUF_strlcpy(buf, serialfile, len); 102355714Skris 1024296341Sdelphij serial = load_serial(buf, create, NULL); 1025296341Sdelphij if (serial == NULL) 1026296341Sdelphij goto end; 1027109998Smarkm 1028296341Sdelphij if (!BN_add_word(serial, 1)) { 1029296341Sdelphij BIO_printf(bio_err, "add_word failure\n"); 1030296341Sdelphij goto end; 1031296341Sdelphij } 1032127128Snectar 1033296341Sdelphij if (!save_serial(buf, NULL, serial, &bs)) 1034296341Sdelphij goto end; 1035296341Sdelphij 1036127128Snectar end: 1037296341Sdelphij if (buf) 1038296341Sdelphij OPENSSL_free(buf); 1039296341Sdelphij BN_free(serial); 1040296341Sdelphij return bs; 1041296341Sdelphij} 1042109998Smarkm 1043109998Smarkmstatic int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, 1044296341Sdelphij X509 *x, X509 *xca, EVP_PKEY *pkey, 1045296341Sdelphij STACK_OF(OPENSSL_STRING) *sigopts, 1046296341Sdelphij char *serialfile, int create, 1047296341Sdelphij int days, int clrext, CONF *conf, char *section, 1048296341Sdelphij ASN1_INTEGER *sno) 1049296341Sdelphij{ 1050296341Sdelphij int ret = 0; 1051296341Sdelphij ASN1_INTEGER *bs = NULL; 1052296341Sdelphij X509_STORE_CTX xsc; 1053296341Sdelphij EVP_PKEY *upkey; 1054109998Smarkm 1055296341Sdelphij upkey = X509_get_pubkey(xca); 1056296341Sdelphij EVP_PKEY_copy_parameters(upkey, pkey); 1057296341Sdelphij EVP_PKEY_free(upkey); 1058109998Smarkm 1059296341Sdelphij if (!X509_STORE_CTX_init(&xsc, ctx, x, NULL)) { 1060296341Sdelphij BIO_printf(bio_err, "Error initialising X509 store\n"); 1061296341Sdelphij goto end; 1062296341Sdelphij } 1063296341Sdelphij if (sno) 1064296341Sdelphij bs = sno; 1065296341Sdelphij else if (!(bs = x509_load_serial(CAfile, serialfile, create))) 1066296341Sdelphij goto end; 1067109998Smarkm 1068296341Sdelphij/* if (!X509_STORE_add_cert(ctx,x)) goto end;*/ 106955714Skris 1070296341Sdelphij /* 1071296341Sdelphij * NOTE: this certificate can/should be self signed, unless it was a 1072296341Sdelphij * certificate request in which case it is not. 1073296341Sdelphij */ 1074296341Sdelphij X509_STORE_CTX_set_cert(&xsc, x); 1075296341Sdelphij X509_STORE_CTX_set_flags(&xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); 1076296341Sdelphij if (!reqfile && X509_verify_cert(&xsc) <= 0) 1077296341Sdelphij goto end; 107855714Skris 1079296341Sdelphij if (!X509_check_private_key(xca, pkey)) { 1080296341Sdelphij BIO_printf(bio_err, 1081296341Sdelphij "CA certificate and CA private key do not match\n"); 1082296341Sdelphij goto end; 1083296341Sdelphij } 108455714Skris 1085296341Sdelphij if (!X509_set_issuer_name(x, X509_get_subject_name(xca))) 1086296341Sdelphij goto end; 1087296341Sdelphij if (!X509_set_serialNumber(x, bs)) 1088296341Sdelphij goto end; 108955714Skris 1090296341Sdelphij if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL) 1091296341Sdelphij goto end; 109255714Skris 1093296341Sdelphij /* hardwired expired */ 1094296341Sdelphij if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL) 1095296341Sdelphij goto end; 109655714Skris 1097296341Sdelphij if (clrext) { 1098296341Sdelphij while (X509_get_ext_count(x) > 0) 1099296341Sdelphij X509_delete_ext(x, 0); 1100296341Sdelphij } 110159191Skris 1102296341Sdelphij if (conf) { 1103296341Sdelphij X509V3_CTX ctx2; 1104296341Sdelphij X509_set_version(x, 2); /* version 3 certificate */ 1105296341Sdelphij X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0); 1106296341Sdelphij X509V3_set_nconf(&ctx2, conf); 1107296341Sdelphij if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) 1108296341Sdelphij goto end; 1109296341Sdelphij } 111055714Skris 1111296341Sdelphij if (!do_X509_sign(bio_err, x, pkey, digest, sigopts)) 1112296341Sdelphij goto end; 1113296341Sdelphij ret = 1; 1114296341Sdelphij end: 1115296341Sdelphij X509_STORE_CTX_cleanup(&xsc); 1116296341Sdelphij if (!ret) 1117296341Sdelphij ERR_print_errors(bio_err); 1118296341Sdelphij if (!sno) 1119296341Sdelphij ASN1_INTEGER_free(bs); 1120296341Sdelphij return ret; 1121296341Sdelphij} 112255714Skris 112355714Skrisstatic int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx) 1124296341Sdelphij{ 1125296341Sdelphij int err; 1126296341Sdelphij X509 *err_cert; 112755714Skris 1128296341Sdelphij /* 1129296341Sdelphij * it is ok to use a self signed certificate This case will catch both 1130296341Sdelphij * the initial ok == 0 and the final ok == 1 calls to this function 1131296341Sdelphij */ 1132296341Sdelphij err = X509_STORE_CTX_get_error(ctx); 1133296341Sdelphij if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) 1134296341Sdelphij return 1; 113555714Skris 1136296341Sdelphij /* 1137296341Sdelphij * BAD we should have gotten an error. Normally if everything worked 1138296341Sdelphij * X509_STORE_CTX_get_error(ctx) will still be set to 1139296341Sdelphij * DEPTH_ZERO_SELF_.... 1140296341Sdelphij */ 1141296341Sdelphij if (ok) { 1142296341Sdelphij BIO_printf(bio_err, 1143296341Sdelphij "error with certificate to be certified - should be self signed\n"); 1144296341Sdelphij return 0; 1145296341Sdelphij } else { 1146296341Sdelphij err_cert = X509_STORE_CTX_get_current_cert(ctx); 1147296341Sdelphij print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0); 1148296341Sdelphij BIO_printf(bio_err, 1149296341Sdelphij "error with certificate - error %d at depth %d\n%s\n", err, 1150296341Sdelphij X509_STORE_CTX_get_error_depth(ctx), 1151296341Sdelphij X509_verify_cert_error_string(err)); 1152296341Sdelphij return 1; 1153296341Sdelphij } 1154296341Sdelphij} 115555714Skris 115655714Skris/* self sign */ 1157296341Sdelphijstatic int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, 1158296341Sdelphij const EVP_MD *digest, CONF *conf, char *section) 1159296341Sdelphij{ 116055714Skris 1161296341Sdelphij EVP_PKEY *pktmp; 116255714Skris 1163296341Sdelphij pktmp = X509_get_pubkey(x); 1164296341Sdelphij EVP_PKEY_copy_parameters(pktmp, pkey); 1165296341Sdelphij EVP_PKEY_save_parameters(pktmp, 1); 1166296341Sdelphij EVP_PKEY_free(pktmp); 116755714Skris 1168296341Sdelphij if (!X509_set_issuer_name(x, X509_get_subject_name(x))) 1169296341Sdelphij goto err; 1170296341Sdelphij if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL) 1171296341Sdelphij goto err; 117255714Skris 1173296341Sdelphij /* Lets just make it 12:00am GMT, Jan 1 1970 */ 1174296341Sdelphij /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */ 1175296341Sdelphij /* 28 days to be certified */ 117655714Skris 1177296341Sdelphij if (X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * days) == 1178296341Sdelphij NULL) 1179296341Sdelphij goto err; 118055714Skris 1181296341Sdelphij if (!X509_set_pubkey(x, pkey)) 1182296341Sdelphij goto err; 1183296341Sdelphij if (clrext) { 1184296341Sdelphij while (X509_get_ext_count(x) > 0) 1185296341Sdelphij X509_delete_ext(x, 0); 1186296341Sdelphij } 1187296341Sdelphij if (conf) { 1188296341Sdelphij X509V3_CTX ctx; 1189296341Sdelphij X509_set_version(x, 2); /* version 3 certificate */ 1190296341Sdelphij X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0); 1191296341Sdelphij X509V3_set_nconf(&ctx, conf); 1192296341Sdelphij if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) 1193296341Sdelphij goto err; 1194296341Sdelphij } 1195296341Sdelphij if (!X509_sign(x, pkey, digest)) 1196296341Sdelphij goto err; 1197296341Sdelphij return 1; 1198296341Sdelphij err: 1199296341Sdelphij ERR_print_errors(bio_err); 1200296341Sdelphij return 0; 1201296341Sdelphij} 120259191Skris 120359191Skrisstatic int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt) 120459191Skris{ 1205296341Sdelphij int id, i, idret; 1206296341Sdelphij char *pname; 1207296341Sdelphij id = X509_PURPOSE_get_id(pt); 1208296341Sdelphij pname = X509_PURPOSE_get0_name(pt); 1209296341Sdelphij for (i = 0; i < 2; i++) { 1210296341Sdelphij idret = X509_check_purpose(cert, id, i); 1211296341Sdelphij BIO_printf(bio, "%s%s : ", pname, i ? " CA" : ""); 1212296341Sdelphij if (idret == 1) 1213296341Sdelphij BIO_printf(bio, "Yes\n"); 1214296341Sdelphij else if (idret == 0) 1215296341Sdelphij BIO_printf(bio, "No\n"); 1216296341Sdelphij else 1217296341Sdelphij BIO_printf(bio, "Yes (WARNING code=%d)\n", idret); 1218296341Sdelphij } 1219296341Sdelphij return 1; 122059191Skris} 1221