1*e71b7053SJung-uk Kim /* 2*e71b7053SJung-uk Kim * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. 374664626SKris Kennaway * 4*e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 5*e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6*e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7*e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 874664626SKris Kennaway */ 974664626SKris Kennaway 1074664626SKris Kennaway #include <stdio.h> 1174664626SKris Kennaway #include <stdlib.h> 1274664626SKris Kennaway #include <string.h> 1374664626SKris Kennaway #include "apps.h" 14*e71b7053SJung-uk Kim #include "progs.h" 1574664626SKris Kennaway #include <openssl/bio.h> 1674664626SKris Kennaway #include <openssl/asn1.h> 1774664626SKris Kennaway #include <openssl/err.h> 1874664626SKris Kennaway #include <openssl/bn.h> 1974664626SKris Kennaway #include <openssl/evp.h> 2074664626SKris Kennaway #include <openssl/x509.h> 2174664626SKris Kennaway #include <openssl/x509v3.h> 2274664626SKris Kennaway #include <openssl/objects.h> 2374664626SKris Kennaway #include <openssl/pem.h> 243b4e3dcbSSimon L. B. Nielsen #ifndef OPENSSL_NO_RSA 253b4e3dcbSSimon L. B. Nielsen # include <openssl/rsa.h> 263b4e3dcbSSimon L. B. Nielsen #endif 273b4e3dcbSSimon L. B. Nielsen #ifndef OPENSSL_NO_DSA 283b4e3dcbSSimon L. B. Nielsen # include <openssl/dsa.h> 293b4e3dcbSSimon L. B. Nielsen #endif 3074664626SKris Kennaway 3174664626SKris Kennaway #undef POSTFIX 3274664626SKris Kennaway #define POSTFIX ".srl" 3374664626SKris Kennaway #define DEF_DAYS 30 3474664626SKris Kennaway 35*e71b7053SJung-uk Kim static int callb(int ok, X509_STORE_CTX *ctx); 36*e71b7053SJung-uk Kim static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, 37*e71b7053SJung-uk Kim const EVP_MD *digest, CONF *conf, const char *section, 38*e71b7053SJung-uk Kim int preserve_dates); 39*e71b7053SJung-uk Kim static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest, 40*e71b7053SJung-uk Kim X509 *x, X509 *xca, EVP_PKEY *pkey, 41*e71b7053SJung-uk Kim STACK_OF(OPENSSL_STRING) *sigopts, const char *serialfile, 42*e71b7053SJung-uk Kim int create, int days, int clrext, CONF *conf, 43*e71b7053SJung-uk Kim const char *section, ASN1_INTEGER *sno, int reqfile, 44*e71b7053SJung-uk Kim int preserve_dates); 45*e71b7053SJung-uk Kim static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt); 46*e71b7053SJung-uk Kim static int print_x509v3_exts(BIO *bio, X509 *x, const char *exts); 47*e71b7053SJung-uk Kim 48*e71b7053SJung-uk Kim typedef enum OPTION_choice { 49*e71b7053SJung-uk Kim OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 50*e71b7053SJung-uk Kim OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM, 51*e71b7053SJung-uk Kim OPT_CAKEYFORM, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE, 52*e71b7053SJung-uk Kim OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_SIGNKEY, OPT_CA, 53*e71b7053SJung-uk Kim OPT_CAKEY, OPT_CASERIAL, OPT_SET_SERIAL, OPT_FORCE_PUBKEY, 54*e71b7053SJung-uk Kim OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_NAMEOPT, 55*e71b7053SJung-uk Kim OPT_C, OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL, 56*e71b7053SJung-uk Kim OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH, 57*e71b7053SJung-uk Kim OPT_ISSUER_HASH, OPT_SUBJECT, OPT_ISSUER, OPT_FINGERPRINT, OPT_DATES, 58*e71b7053SJung-uk Kim OPT_PURPOSE, OPT_STARTDATE, OPT_ENDDATE, OPT_CHECKEND, OPT_CHECKHOST, 59*e71b7053SJung-uk Kim OPT_CHECKEMAIL, OPT_CHECKIP, OPT_NOOUT, OPT_TRUSTOUT, OPT_CLRTRUST, 60*e71b7053SJung-uk Kim OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID, 61*e71b7053SJung-uk Kim OPT_SUBJECT_HASH_OLD, 62*e71b7053SJung-uk Kim OPT_ISSUER_HASH_OLD, 63*e71b7053SJung-uk Kim OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES, 64*e71b7053SJung-uk Kim OPT_R_ENUM, OPT_EXT 65*e71b7053SJung-uk Kim } OPTION_CHOICE; 66*e71b7053SJung-uk Kim 67*e71b7053SJung-uk Kim const OPTIONS x509_options[] = { 68*e71b7053SJung-uk Kim {"help", OPT_HELP, '-', "Display this summary"}, 69*e71b7053SJung-uk Kim {"inform", OPT_INFORM, 'f', 70*e71b7053SJung-uk Kim "Input format - default PEM (one of DER, NET or PEM)"}, 71*e71b7053SJung-uk Kim {"in", OPT_IN, '<', "Input file - default stdin"}, 72*e71b7053SJung-uk Kim {"outform", OPT_OUTFORM, 'f', 73*e71b7053SJung-uk Kim "Output format - default PEM (one of DER, NET or PEM)"}, 74*e71b7053SJung-uk Kim {"out", OPT_OUT, '>', "Output file - default stdout"}, 75*e71b7053SJung-uk Kim {"keyform", OPT_KEYFORM, 'F', "Private key format - default PEM"}, 76*e71b7053SJung-uk Kim {"passin", OPT_PASSIN, 's', "Private key password/pass-phrase source"}, 77*e71b7053SJung-uk Kim {"serial", OPT_SERIAL, '-', "Print serial number value"}, 78*e71b7053SJung-uk Kim {"subject_hash", OPT_HASH, '-', "Print subject hash value"}, 79*e71b7053SJung-uk Kim {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"}, 80*e71b7053SJung-uk Kim {"hash", OPT_HASH, '-', "Synonym for -subject_hash"}, 81*e71b7053SJung-uk Kim {"subject", OPT_SUBJECT, '-', "Print subject DN"}, 82*e71b7053SJung-uk Kim {"issuer", OPT_ISSUER, '-', "Print issuer DN"}, 83*e71b7053SJung-uk Kim {"email", OPT_EMAIL, '-', "Print email address(es)"}, 84*e71b7053SJung-uk Kim {"startdate", OPT_STARTDATE, '-', "Set notBefore field"}, 85*e71b7053SJung-uk Kim {"enddate", OPT_ENDDATE, '-', "Set notAfter field"}, 86*e71b7053SJung-uk Kim {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"}, 87*e71b7053SJung-uk Kim {"dates", OPT_DATES, '-', "Both Before and After dates"}, 88*e71b7053SJung-uk Kim {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"}, 89*e71b7053SJung-uk Kim {"pubkey", OPT_PUBKEY, '-', "Output the public key"}, 90*e71b7053SJung-uk Kim {"fingerprint", OPT_FINGERPRINT, '-', 91*e71b7053SJung-uk Kim "Print the certificate fingerprint"}, 92*e71b7053SJung-uk Kim {"alias", OPT_ALIAS, '-', "Output certificate alias"}, 93*e71b7053SJung-uk Kim {"noout", OPT_NOOUT, '-', "No output, just status"}, 94*e71b7053SJung-uk Kim {"nocert", OPT_NOCERT, '-', "No certificate output"}, 95*e71b7053SJung-uk Kim {"ocspid", OPT_OCSPID, '-', 96*e71b7053SJung-uk Kim "Print OCSP hash values for the subject name and public key"}, 97*e71b7053SJung-uk Kim {"ocsp_uri", OPT_OCSP_URI, '-', "Print OCSP Responder URL(s)"}, 98*e71b7053SJung-uk Kim {"trustout", OPT_TRUSTOUT, '-', "Output a trusted certificate"}, 99*e71b7053SJung-uk Kim {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"}, 100*e71b7053SJung-uk Kim {"clrext", OPT_CLREXT, '-', "Clear all certificate extensions"}, 101*e71b7053SJung-uk Kim {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"}, 102*e71b7053SJung-uk Kim {"addreject", OPT_ADDREJECT, 's', 103*e71b7053SJung-uk Kim "Reject certificate for a given purpose"}, 104*e71b7053SJung-uk Kim {"setalias", OPT_SETALIAS, 's', "Set certificate alias"}, 105*e71b7053SJung-uk Kim {"days", OPT_DAYS, 'n', 106*e71b7053SJung-uk Kim "How long till expiry of a signed certificate - def 30 days"}, 107*e71b7053SJung-uk Kim {"checkend", OPT_CHECKEND, 'M', 108*e71b7053SJung-uk Kim "Check whether the cert expires in the next arg seconds"}, 109*e71b7053SJung-uk Kim {OPT_MORE_STR, 1, 1, "Exit 1 if so, 0 if not"}, 110*e71b7053SJung-uk Kim {"signkey", OPT_SIGNKEY, '<', "Self sign cert with arg"}, 111*e71b7053SJung-uk Kim {"x509toreq", OPT_X509TOREQ, '-', 112*e71b7053SJung-uk Kim "Output a certification request object"}, 113*e71b7053SJung-uk Kim {"req", OPT_REQ, '-', "Input is a certificate request, sign and output"}, 114*e71b7053SJung-uk Kim {"CA", OPT_CA, '<', "Set the CA certificate, must be PEM format"}, 115*e71b7053SJung-uk Kim {"CAkey", OPT_CAKEY, 's', 116*e71b7053SJung-uk Kim "The CA key, must be PEM format; if not in CAfile"}, 117*e71b7053SJung-uk Kim {"CAcreateserial", OPT_CACREATESERIAL, '-', 118*e71b7053SJung-uk Kim "Create serial number file if it does not exist"}, 119*e71b7053SJung-uk Kim {"CAserial", OPT_CASERIAL, 's', "Serial file"}, 120*e71b7053SJung-uk Kim {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"}, 121*e71b7053SJung-uk Kim {"text", OPT_TEXT, '-', "Print the certificate in text form"}, 122*e71b7053SJung-uk Kim {"ext", OPT_EXT, 's', "Print various X509V3 extensions"}, 123*e71b7053SJung-uk Kim {"C", OPT_C, '-', "Print out C code forms"}, 124*e71b7053SJung-uk Kim {"extfile", OPT_EXTFILE, '<', "File with X509V3 extensions to add"}, 125*e71b7053SJung-uk Kim OPT_R_OPTIONS, 126*e71b7053SJung-uk Kim {"extensions", OPT_EXTENSIONS, 's', "Section from config file to use"}, 127*e71b7053SJung-uk Kim {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, 128*e71b7053SJung-uk Kim {"certopt", OPT_CERTOPT, 's', "Various certificate text options"}, 129*e71b7053SJung-uk Kim {"checkhost", OPT_CHECKHOST, 's', "Check certificate matches host"}, 130*e71b7053SJung-uk Kim {"checkemail", OPT_CHECKEMAIL, 's', "Check certificate matches email"}, 131*e71b7053SJung-uk Kim {"checkip", OPT_CHECKIP, 's', "Check certificate matches ipaddr"}, 132*e71b7053SJung-uk Kim {"CAform", OPT_CAFORM, 'F', "CA format - default PEM"}, 133*e71b7053SJung-uk Kim {"CAkeyform", OPT_CAKEYFORM, 'f', "CA key format - default PEM"}, 134*e71b7053SJung-uk Kim {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, 135*e71b7053SJung-uk Kim {"force_pubkey", OPT_FORCE_PUBKEY, '<', "Force the Key to put inside certificate"}, 136*e71b7053SJung-uk Kim {"next_serial", OPT_NEXT_SERIAL, '-', "Increment current certificate serial number"}, 137*e71b7053SJung-uk Kim {"clrreject", OPT_CLRREJECT, '-', 138*e71b7053SJung-uk Kim "Clears all the prohibited or rejected uses of the certificate"}, 139*e71b7053SJung-uk Kim {"badsig", OPT_BADSIG, '-', "Corrupt last byte of certificate signature (for test)"}, 140*e71b7053SJung-uk Kim {"", OPT_MD, '-', "Any supported digest"}, 1411f13597dSJung-uk Kim #ifndef OPENSSL_NO_MD5 142*e71b7053SJung-uk Kim {"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-', 143*e71b7053SJung-uk Kim "Print old-style (MD5) issuer hash value"}, 144*e71b7053SJung-uk Kim {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-', 145*e71b7053SJung-uk Kim "Print old-style (MD5) subject hash value"}, 1461f13597dSJung-uk Kim #endif 147fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_ENGINE 148*e71b7053SJung-uk Kim {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 149fceca8a3SJacques Vidrine #endif 150*e71b7053SJung-uk Kim {"preserve_dates", OPT_PRESERVE_DATES, '-', "preserve existing dates when signing"}, 151*e71b7053SJung-uk Kim {NULL} 15274664626SKris Kennaway }; 15374664626SKris Kennaway 154*e71b7053SJung-uk Kim int x509_main(int argc, char **argv) 15574664626SKris Kennaway { 1565c87c606SMark Murray ASN1_INTEGER *sno = NULL; 157*e71b7053SJung-uk Kim ASN1_OBJECT *objtmp = NULL; 15874664626SKris Kennaway BIO *out = NULL; 159*e71b7053SJung-uk Kim CONF *extconf = NULL; 160*e71b7053SJung-uk Kim EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL; 161f579bf8eSKris Kennaway STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; 162*e71b7053SJung-uk Kim STACK_OF(OPENSSL_STRING) *sigopts = NULL; 163*e71b7053SJung-uk Kim X509 *x = NULL, *xca = NULL; 164*e71b7053SJung-uk Kim X509_REQ *req = NULL, *rq = NULL; 165*e71b7053SJung-uk Kim X509_STORE *ctx = NULL; 166*e71b7053SJung-uk Kim const EVP_MD *digest = NULL; 167*e71b7053SJung-uk Kim char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL; 168*e71b7053SJung-uk Kim char *checkhost = NULL, *checkemail = NULL, *checkip = NULL, *exts = NULL; 169*e71b7053SJung-uk Kim char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL; 17074664626SKris Kennaway char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL; 171*e71b7053SJung-uk Kim char *prog; 172*e71b7053SJung-uk Kim int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0; 173*e71b7053SJung-uk Kim int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM; 174*e71b7053SJung-uk Kim int fingerprint = 0, reqfile = 0, checkend = 0; 175*e71b7053SJung-uk Kim int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM; 176*e71b7053SJung-uk Kim int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0; 177*e71b7053SJung-uk Kim int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0; 178*e71b7053SJung-uk Kim int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0; 179*e71b7053SJung-uk Kim int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0; 180*e71b7053SJung-uk Kim int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0, ext = 0; 181*e71b7053SJung-uk Kim int enddate = 0; 182*e71b7053SJung-uk Kim time_t checkoffset = 0; 183*e71b7053SJung-uk Kim unsigned long certflag = 0; 184*e71b7053SJung-uk Kim int preserve_dates = 0; 185*e71b7053SJung-uk Kim OPTION_CHOICE o; 186*e71b7053SJung-uk Kim ENGINE *e = NULL; 1871f13597dSJung-uk Kim #ifndef OPENSSL_NO_MD5 1881f13597dSJung-uk Kim int subject_hash_old = 0, issuer_hash_old = 0; 1891f13597dSJung-uk Kim #endif 19074664626SKris Kennaway 19174664626SKris Kennaway ctx = X509_STORE_new(); 1926f9291ceSJung-uk Kim if (ctx == NULL) 1936f9291ceSJung-uk Kim goto end; 1941f13597dSJung-uk Kim X509_STORE_set_verify_cb(ctx, callb); 19574664626SKris Kennaway 196*e71b7053SJung-uk Kim prog = opt_init(argc, argv, x509_options); 197*e71b7053SJung-uk Kim while ((o = opt_next()) != OPT_EOF) { 198*e71b7053SJung-uk Kim switch (o) { 199*e71b7053SJung-uk Kim case OPT_EOF: 200*e71b7053SJung-uk Kim case OPT_ERR: 201*e71b7053SJung-uk Kim opthelp: 202*e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 203*e71b7053SJung-uk Kim goto end; 204*e71b7053SJung-uk Kim case OPT_HELP: 205*e71b7053SJung-uk Kim opt_help(x509_options); 206*e71b7053SJung-uk Kim ret = 0; 207*e71b7053SJung-uk Kim goto end; 208*e71b7053SJung-uk Kim case OPT_INFORM: 209*e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) 210*e71b7053SJung-uk Kim goto opthelp; 211*e71b7053SJung-uk Kim break; 212*e71b7053SJung-uk Kim case OPT_IN: 213*e71b7053SJung-uk Kim infile = opt_arg(); 214*e71b7053SJung-uk Kim break; 215*e71b7053SJung-uk Kim case OPT_OUTFORM: 216*e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) 217*e71b7053SJung-uk Kim goto opthelp; 218*e71b7053SJung-uk Kim break; 219*e71b7053SJung-uk Kim case OPT_KEYFORM: 220*e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat)) 221*e71b7053SJung-uk Kim goto opthelp; 222*e71b7053SJung-uk Kim break; 223*e71b7053SJung-uk Kim case OPT_CAFORM: 224*e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat)) 225*e71b7053SJung-uk Kim goto opthelp; 226*e71b7053SJung-uk Kim break; 227*e71b7053SJung-uk Kim case OPT_CAKEYFORM: 228*e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAkeyformat)) 229*e71b7053SJung-uk Kim goto opthelp; 230*e71b7053SJung-uk Kim break; 231*e71b7053SJung-uk Kim case OPT_OUT: 232*e71b7053SJung-uk Kim outfile = opt_arg(); 233*e71b7053SJung-uk Kim break; 234*e71b7053SJung-uk Kim case OPT_REQ: 23574664626SKris Kennaway reqfile = 1; 236*e71b7053SJung-uk Kim break; 237*e71b7053SJung-uk Kim 238*e71b7053SJung-uk Kim case OPT_SIGOPT: 2391f13597dSJung-uk Kim if (!sigopts) 2401f13597dSJung-uk Kim sigopts = sk_OPENSSL_STRING_new_null(); 241*e71b7053SJung-uk Kim if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) 242*e71b7053SJung-uk Kim goto opthelp; 24374664626SKris Kennaway break; 244*e71b7053SJung-uk Kim case OPT_DAYS: 245*e71b7053SJung-uk Kim if (preserve_dates) 246*e71b7053SJung-uk Kim goto opthelp; 247*e71b7053SJung-uk Kim days = atoi(opt_arg()); 248*e71b7053SJung-uk Kim break; 249*e71b7053SJung-uk Kim case OPT_PASSIN: 250*e71b7053SJung-uk Kim passinarg = opt_arg(); 251*e71b7053SJung-uk Kim break; 252*e71b7053SJung-uk Kim case OPT_EXTFILE: 253*e71b7053SJung-uk Kim extfile = opt_arg(); 254*e71b7053SJung-uk Kim break; 255*e71b7053SJung-uk Kim case OPT_R_CASES: 256*e71b7053SJung-uk Kim if (!opt_rand(o)) 25774664626SKris Kennaway goto end; 258*e71b7053SJung-uk Kim break; 259*e71b7053SJung-uk Kim case OPT_EXTENSIONS: 260*e71b7053SJung-uk Kim extsect = opt_arg(); 261*e71b7053SJung-uk Kim break; 262*e71b7053SJung-uk Kim case OPT_SIGNKEY: 263*e71b7053SJung-uk Kim keyfile = opt_arg(); 264*e71b7053SJung-uk Kim sign_flag = ++num; 265*e71b7053SJung-uk Kim break; 266*e71b7053SJung-uk Kim case OPT_CA: 267*e71b7053SJung-uk Kim CAfile = opt_arg(); 268*e71b7053SJung-uk Kim CA_flag = ++num; 269*e71b7053SJung-uk Kim break; 270*e71b7053SJung-uk Kim case OPT_CAKEY: 271*e71b7053SJung-uk Kim CAkeyfile = opt_arg(); 272*e71b7053SJung-uk Kim break; 273*e71b7053SJung-uk Kim case OPT_CASERIAL: 274*e71b7053SJung-uk Kim CAserial = opt_arg(); 275*e71b7053SJung-uk Kim break; 276*e71b7053SJung-uk Kim case OPT_SET_SERIAL: 277*e71b7053SJung-uk Kim if (sno != NULL) { 278*e71b7053SJung-uk Kim BIO_printf(bio_err, "Serial number supplied twice\n"); 279*e71b7053SJung-uk Kim goto opthelp; 28074664626SKris Kennaway } 281*e71b7053SJung-uk Kim if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) 282*e71b7053SJung-uk Kim goto opthelp; 283*e71b7053SJung-uk Kim break; 284*e71b7053SJung-uk Kim case OPT_FORCE_PUBKEY: 285*e71b7053SJung-uk Kim fkeyfile = opt_arg(); 286*e71b7053SJung-uk Kim break; 287*e71b7053SJung-uk Kim case OPT_ADDTRUST: 288*e71b7053SJung-uk Kim if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { 289*e71b7053SJung-uk Kim BIO_printf(bio_err, 290*e71b7053SJung-uk Kim "%s: Invalid trust object value %s\n", 291*e71b7053SJung-uk Kim prog, opt_arg()); 292*e71b7053SJung-uk Kim goto opthelp; 293*e71b7053SJung-uk Kim } 294*e71b7053SJung-uk Kim if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL) 295*e71b7053SJung-uk Kim goto end; 296*e71b7053SJung-uk Kim sk_ASN1_OBJECT_push(trust, objtmp); 297*e71b7053SJung-uk Kim objtmp = NULL; 298*e71b7053SJung-uk Kim trustout = 1; 299*e71b7053SJung-uk Kim break; 300*e71b7053SJung-uk Kim case OPT_ADDREJECT: 301*e71b7053SJung-uk Kim if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { 302*e71b7053SJung-uk Kim BIO_printf(bio_err, 303*e71b7053SJung-uk Kim "%s: Invalid reject object value %s\n", 304*e71b7053SJung-uk Kim prog, opt_arg()); 305*e71b7053SJung-uk Kim goto opthelp; 306*e71b7053SJung-uk Kim } 307*e71b7053SJung-uk Kim if (reject == NULL 308*e71b7053SJung-uk Kim && (reject = sk_ASN1_OBJECT_new_null()) == NULL) 309*e71b7053SJung-uk Kim goto end; 310*e71b7053SJung-uk Kim sk_ASN1_OBJECT_push(reject, objtmp); 311*e71b7053SJung-uk Kim objtmp = NULL; 312*e71b7053SJung-uk Kim trustout = 1; 313*e71b7053SJung-uk Kim break; 314*e71b7053SJung-uk Kim case OPT_SETALIAS: 315*e71b7053SJung-uk Kim alias = opt_arg(); 316*e71b7053SJung-uk Kim trustout = 1; 317*e71b7053SJung-uk Kim break; 318*e71b7053SJung-uk Kim case OPT_CERTOPT: 319*e71b7053SJung-uk Kim if (!set_cert_ex(&certflag, opt_arg())) 320*e71b7053SJung-uk Kim goto opthelp; 321*e71b7053SJung-uk Kim break; 322*e71b7053SJung-uk Kim case OPT_NAMEOPT: 323*e71b7053SJung-uk Kim if (!set_nameopt(opt_arg())) 324*e71b7053SJung-uk Kim goto opthelp; 325*e71b7053SJung-uk Kim break; 326*e71b7053SJung-uk Kim case OPT_ENGINE: 327*e71b7053SJung-uk Kim e = setup_engine(opt_arg(), 0); 328*e71b7053SJung-uk Kim break; 329*e71b7053SJung-uk Kim case OPT_C: 330*e71b7053SJung-uk Kim C = ++num; 331*e71b7053SJung-uk Kim break; 332*e71b7053SJung-uk Kim case OPT_EMAIL: 333*e71b7053SJung-uk Kim email = ++num; 334*e71b7053SJung-uk Kim break; 335*e71b7053SJung-uk Kim case OPT_OCSP_URI: 336*e71b7053SJung-uk Kim ocsp_uri = ++num; 337*e71b7053SJung-uk Kim break; 338*e71b7053SJung-uk Kim case OPT_SERIAL: 339*e71b7053SJung-uk Kim serial = ++num; 340*e71b7053SJung-uk Kim break; 341*e71b7053SJung-uk Kim case OPT_NEXT_SERIAL: 342*e71b7053SJung-uk Kim next_serial = ++num; 343*e71b7053SJung-uk Kim break; 344*e71b7053SJung-uk Kim case OPT_MODULUS: 345*e71b7053SJung-uk Kim modulus = ++num; 346*e71b7053SJung-uk Kim break; 347*e71b7053SJung-uk Kim case OPT_PUBKEY: 348*e71b7053SJung-uk Kim pubkey = ++num; 349*e71b7053SJung-uk Kim break; 350*e71b7053SJung-uk Kim case OPT_X509TOREQ: 351*e71b7053SJung-uk Kim x509req = ++num; 352*e71b7053SJung-uk Kim break; 353*e71b7053SJung-uk Kim case OPT_TEXT: 354*e71b7053SJung-uk Kim text = ++num; 355*e71b7053SJung-uk Kim break; 356*e71b7053SJung-uk Kim case OPT_SUBJECT: 357*e71b7053SJung-uk Kim subject = ++num; 358*e71b7053SJung-uk Kim break; 359*e71b7053SJung-uk Kim case OPT_ISSUER: 360*e71b7053SJung-uk Kim issuer = ++num; 361*e71b7053SJung-uk Kim break; 362*e71b7053SJung-uk Kim case OPT_FINGERPRINT: 363*e71b7053SJung-uk Kim fingerprint = ++num; 364*e71b7053SJung-uk Kim break; 365*e71b7053SJung-uk Kim case OPT_HASH: 366*e71b7053SJung-uk Kim subject_hash = ++num; 367*e71b7053SJung-uk Kim break; 368*e71b7053SJung-uk Kim case OPT_ISSUER_HASH: 369*e71b7053SJung-uk Kim issuer_hash = ++num; 370*e71b7053SJung-uk Kim break; 371*e71b7053SJung-uk Kim case OPT_PURPOSE: 372*e71b7053SJung-uk Kim pprint = ++num; 373*e71b7053SJung-uk Kim break; 374*e71b7053SJung-uk Kim case OPT_STARTDATE: 375*e71b7053SJung-uk Kim startdate = ++num; 376*e71b7053SJung-uk Kim break; 377*e71b7053SJung-uk Kim case OPT_ENDDATE: 378*e71b7053SJung-uk Kim enddate = ++num; 379*e71b7053SJung-uk Kim break; 380*e71b7053SJung-uk Kim case OPT_NOOUT: 381*e71b7053SJung-uk Kim noout = ++num; 382*e71b7053SJung-uk Kim break; 383*e71b7053SJung-uk Kim case OPT_EXT: 384*e71b7053SJung-uk Kim ext = ++num; 385*e71b7053SJung-uk Kim exts = opt_arg(); 386*e71b7053SJung-uk Kim break; 387*e71b7053SJung-uk Kim case OPT_NOCERT: 388*e71b7053SJung-uk Kim nocert = 1; 389*e71b7053SJung-uk Kim break; 390*e71b7053SJung-uk Kim case OPT_TRUSTOUT: 391*e71b7053SJung-uk Kim trustout = 1; 392*e71b7053SJung-uk Kim break; 393*e71b7053SJung-uk Kim case OPT_CLRTRUST: 394*e71b7053SJung-uk Kim clrtrust = ++num; 395*e71b7053SJung-uk Kim break; 396*e71b7053SJung-uk Kim case OPT_CLRREJECT: 397*e71b7053SJung-uk Kim clrreject = ++num; 398*e71b7053SJung-uk Kim break; 399*e71b7053SJung-uk Kim case OPT_ALIAS: 400*e71b7053SJung-uk Kim aliasout = ++num; 401*e71b7053SJung-uk Kim break; 402*e71b7053SJung-uk Kim case OPT_CACREATESERIAL: 403*e71b7053SJung-uk Kim CA_createserial = ++num; 404*e71b7053SJung-uk Kim break; 405*e71b7053SJung-uk Kim case OPT_CLREXT: 406*e71b7053SJung-uk Kim clrext = 1; 407*e71b7053SJung-uk Kim break; 408*e71b7053SJung-uk Kim case OPT_OCSPID: 409*e71b7053SJung-uk Kim ocspid = ++num; 410*e71b7053SJung-uk Kim break; 411*e71b7053SJung-uk Kim case OPT_BADSIG: 412*e71b7053SJung-uk Kim badsig = 1; 413*e71b7053SJung-uk Kim break; 414*e71b7053SJung-uk Kim #ifndef OPENSSL_NO_MD5 415*e71b7053SJung-uk Kim case OPT_SUBJECT_HASH_OLD: 416*e71b7053SJung-uk Kim subject_hash_old = ++num; 417*e71b7053SJung-uk Kim break; 418*e71b7053SJung-uk Kim case OPT_ISSUER_HASH_OLD: 419*e71b7053SJung-uk Kim issuer_hash_old = ++num; 420*e71b7053SJung-uk Kim break; 421*e71b7053SJung-uk Kim #else 422*e71b7053SJung-uk Kim case OPT_SUBJECT_HASH_OLD: 423*e71b7053SJung-uk Kim case OPT_ISSUER_HASH_OLD: 424*e71b7053SJung-uk Kim break; 425*e71b7053SJung-uk Kim #endif 426*e71b7053SJung-uk Kim case OPT_DATES: 427*e71b7053SJung-uk Kim startdate = ++num; 428*e71b7053SJung-uk Kim enddate = ++num; 429*e71b7053SJung-uk Kim break; 430*e71b7053SJung-uk Kim case OPT_CHECKEND: 431*e71b7053SJung-uk Kim checkend = 1; 432*e71b7053SJung-uk Kim { 433*e71b7053SJung-uk Kim intmax_t temp = 0; 434*e71b7053SJung-uk Kim if (!opt_imax(opt_arg(), &temp)) 435*e71b7053SJung-uk Kim goto opthelp; 436*e71b7053SJung-uk Kim checkoffset = (time_t)temp; 437*e71b7053SJung-uk Kim if ((intmax_t)checkoffset != temp) { 438*e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: checkend time out of range %s\n", 439*e71b7053SJung-uk Kim prog, opt_arg()); 440*e71b7053SJung-uk Kim goto opthelp; 441*e71b7053SJung-uk Kim } 442*e71b7053SJung-uk Kim } 443*e71b7053SJung-uk Kim break; 444*e71b7053SJung-uk Kim case OPT_CHECKHOST: 445*e71b7053SJung-uk Kim checkhost = opt_arg(); 446*e71b7053SJung-uk Kim break; 447*e71b7053SJung-uk Kim case OPT_CHECKEMAIL: 448*e71b7053SJung-uk Kim checkemail = opt_arg(); 449*e71b7053SJung-uk Kim break; 450*e71b7053SJung-uk Kim case OPT_CHECKIP: 451*e71b7053SJung-uk Kim checkip = opt_arg(); 452*e71b7053SJung-uk Kim break; 453*e71b7053SJung-uk Kim case OPT_PRESERVE_DATES: 454*e71b7053SJung-uk Kim if (days != DEF_DAYS) 455*e71b7053SJung-uk Kim goto opthelp; 456*e71b7053SJung-uk Kim preserve_dates = 1; 457*e71b7053SJung-uk Kim break; 458*e71b7053SJung-uk Kim case OPT_MD: 459*e71b7053SJung-uk Kim if (!opt_md(opt_unknown(), &digest)) 460*e71b7053SJung-uk Kim goto opthelp; 461*e71b7053SJung-uk Kim } 462*e71b7053SJung-uk Kim } 463*e71b7053SJung-uk Kim argc = opt_num_rest(); 464*e71b7053SJung-uk Kim argv = opt_rest(); 465*e71b7053SJung-uk Kim if (argc != 0) { 466*e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]); 467*e71b7053SJung-uk Kim goto opthelp; 468*e71b7053SJung-uk Kim } 4695c87c606SMark Murray 470*e71b7053SJung-uk Kim if (!app_passwd(passinarg, NULL, &passin, NULL)) { 471f579bf8eSKris Kennaway BIO_printf(bio_err, "Error getting password\n"); 472f579bf8eSKris Kennaway goto end; 473f579bf8eSKris Kennaway } 47474664626SKris Kennaway 4756f9291ceSJung-uk Kim if (!X509_STORE_set_default_paths(ctx)) { 47674664626SKris Kennaway ERR_print_errors(bio_err); 47774664626SKris Kennaway goto end; 47874664626SKris Kennaway } 47974664626SKris Kennaway 480*e71b7053SJung-uk Kim if (fkeyfile != NULL) { 481*e71b7053SJung-uk Kim fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key"); 4827bded2dbSJung-uk Kim if (fkey == NULL) 4837bded2dbSJung-uk Kim goto end; 4847bded2dbSJung-uk Kim } 4857bded2dbSJung-uk Kim 4866f9291ceSJung-uk Kim if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) { 4876f9291ceSJung-uk Kim CAkeyfile = CAfile; 4886f9291ceSJung-uk Kim } else if ((CA_flag) && (CAkeyfile == NULL)) { 4896f9291ceSJung-uk Kim BIO_printf(bio_err, 4906f9291ceSJung-uk Kim "need to specify a CAkey if using the CA command\n"); 49174664626SKris Kennaway goto end; 49274664626SKris Kennaway } 49374664626SKris Kennaway 494*e71b7053SJung-uk Kim if (extfile != NULL) { 49574664626SKris Kennaway X509V3_CTX ctx2; 496*e71b7053SJung-uk Kim if ((extconf = app_load_config(extfile)) == NULL) 49774664626SKris Kennaway goto end; 498*e71b7053SJung-uk Kim if (extsect == NULL) { 4995c87c606SMark Murray extsect = NCONF_get_string(extconf, "default", "extensions"); 500*e71b7053SJung-uk Kim if (extsect == NULL) { 5015c87c606SMark Murray ERR_clear_error(); 5025c87c606SMark Murray extsect = "default"; 5035c87c606SMark Murray } 5045c87c606SMark Murray } 50574664626SKris Kennaway X509V3_set_ctx_test(&ctx2); 5065c87c606SMark Murray X509V3_set_nconf(&ctx2, extconf); 5076f9291ceSJung-uk Kim if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) { 50874664626SKris Kennaway BIO_printf(bio_err, 5096f9291ceSJung-uk Kim "Error Loading extension section %s\n", extsect); 51074664626SKris Kennaway ERR_print_errors(bio_err); 51174664626SKris Kennaway goto end; 51274664626SKris Kennaway } 51374664626SKris Kennaway } 51474664626SKris Kennaway 5156f9291ceSJung-uk Kim if (reqfile) { 51674664626SKris Kennaway EVP_PKEY *pkey; 51774664626SKris Kennaway BIO *in; 51874664626SKris Kennaway 5196f9291ceSJung-uk Kim if (!sign_flag && !CA_flag) { 52074664626SKris Kennaway BIO_printf(bio_err, "We need a private key to sign with\n"); 52174664626SKris Kennaway goto end; 52274664626SKris Kennaway } 523*e71b7053SJung-uk Kim in = bio_open_default(infile, 'r', informat); 524*e71b7053SJung-uk Kim if (in == NULL) 52574664626SKris Kennaway goto end; 52674664626SKris Kennaway req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); 52774664626SKris Kennaway BIO_free(in); 52874664626SKris Kennaway 5296f9291ceSJung-uk Kim if (req == NULL) { 530ddd58736SKris Kennaway ERR_print_errors(bio_err); 531ddd58736SKris Kennaway goto end; 532ddd58736SKris Kennaway } 53374664626SKris Kennaway 534*e71b7053SJung-uk Kim if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) { 53574664626SKris Kennaway BIO_printf(bio_err, "error unpacking public key\n"); 53674664626SKris Kennaway goto end; 53774664626SKris Kennaway } 53874664626SKris Kennaway i = X509_REQ_verify(req, pkey); 5396f9291ceSJung-uk Kim if (i < 0) { 54074664626SKris Kennaway BIO_printf(bio_err, "Signature verification error\n"); 54174664626SKris Kennaway ERR_print_errors(bio_err); 54274664626SKris Kennaway goto end; 54374664626SKris Kennaway } 5446f9291ceSJung-uk Kim if (i == 0) { 5456f9291ceSJung-uk Kim BIO_printf(bio_err, 5466f9291ceSJung-uk Kim "Signature did not match the certificate request\n"); 54774664626SKris Kennaway goto end; 548*e71b7053SJung-uk Kim } else { 54974664626SKris Kennaway BIO_printf(bio_err, "Signature ok\n"); 550*e71b7053SJung-uk Kim } 55174664626SKris Kennaway 5526f9291ceSJung-uk Kim print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), 553*e71b7053SJung-uk Kim get_nameopt()); 55474664626SKris Kennaway 5556f9291ceSJung-uk Kim if ((x = X509_new()) == NULL) 5566f9291ceSJung-uk Kim goto end; 55774664626SKris Kennaway 5586f9291ceSJung-uk Kim if (sno == NULL) { 5596be8ae07SJacques Vidrine sno = ASN1_INTEGER_new(); 560*e71b7053SJung-uk Kim if (sno == NULL || !rand_serial(NULL, sno)) 5615c87c606SMark Murray goto end; 5626be8ae07SJacques Vidrine if (!X509_set_serialNumber(x, sno)) 5636be8ae07SJacques Vidrine goto end; 5643b4e3dcbSSimon L. B. Nielsen ASN1_INTEGER_free(sno); 5653b4e3dcbSSimon L. B. Nielsen sno = NULL; 566*e71b7053SJung-uk Kim } else if (!X509_set_serialNumber(x, sno)) { 5673b4e3dcbSSimon L. B. Nielsen goto end; 5687bded2dbSJung-uk Kim } 569*e71b7053SJung-uk Kim 570*e71b7053SJung-uk Kim if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req))) 571*e71b7053SJung-uk Kim goto end; 572*e71b7053SJung-uk Kim if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req))) 573*e71b7053SJung-uk Kim goto end; 574*e71b7053SJung-uk Kim if (!set_cert_times(x, NULL, NULL, days)) 575*e71b7053SJung-uk Kim goto end; 576*e71b7053SJung-uk Kim 577*e71b7053SJung-uk Kim if (fkey != NULL) { 578*e71b7053SJung-uk Kim X509_set_pubkey(x, fkey); 579*e71b7053SJung-uk Kim } else { 580*e71b7053SJung-uk Kim pkey = X509_REQ_get0_pubkey(req); 581*e71b7053SJung-uk Kim X509_set_pubkey(x, pkey); 582*e71b7053SJung-uk Kim } 583*e71b7053SJung-uk Kim } else { 584*e71b7053SJung-uk Kim x = load_cert(infile, informat, "Certificate"); 585*e71b7053SJung-uk Kim } 58674664626SKris Kennaway 5876f9291ceSJung-uk Kim if (x == NULL) 5886f9291ceSJung-uk Kim goto end; 5896f9291ceSJung-uk Kim if (CA_flag) { 590*e71b7053SJung-uk Kim xca = load_cert(CAfile, CAformat, "CA Certificate"); 5916f9291ceSJung-uk Kim if (xca == NULL) 5926f9291ceSJung-uk Kim goto end; 59374664626SKris Kennaway } 59474664626SKris Kennaway 595*e71b7053SJung-uk Kim out = bio_open_default(outfile, 'w', outformat); 596*e71b7053SJung-uk Kim if (out == NULL) 597*e71b7053SJung-uk Kim goto end; 59874664626SKris Kennaway 599*e71b7053SJung-uk Kim if (!noout || text || next_serial) 600*e71b7053SJung-uk Kim OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3"); 60174664626SKris Kennaway 6026f9291ceSJung-uk Kim if (alias) 6036f9291ceSJung-uk Kim X509_alias_set1(x, (unsigned char *)alias, -1); 604f579bf8eSKris Kennaway 6056f9291ceSJung-uk Kim if (clrtrust) 6066f9291ceSJung-uk Kim X509_trust_clear(x); 6076f9291ceSJung-uk Kim if (clrreject) 6086f9291ceSJung-uk Kim X509_reject_clear(x); 609f579bf8eSKris Kennaway 610*e71b7053SJung-uk Kim if (trust != NULL) { 6116f9291ceSJung-uk Kim for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) { 612f579bf8eSKris Kennaway objtmp = sk_ASN1_OBJECT_value(trust, i); 613f579bf8eSKris Kennaway X509_add1_trust_object(x, objtmp); 614f579bf8eSKris Kennaway } 615*e71b7053SJung-uk Kim objtmp = NULL; 616f579bf8eSKris Kennaway } 617f579bf8eSKris Kennaway 618*e71b7053SJung-uk Kim if (reject != NULL) { 6196f9291ceSJung-uk Kim for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) { 620f579bf8eSKris Kennaway objtmp = sk_ASN1_OBJECT_value(reject, i); 621f579bf8eSKris Kennaway X509_add1_reject_object(x, objtmp); 622f579bf8eSKris Kennaway } 623*e71b7053SJung-uk Kim objtmp = NULL; 624*e71b7053SJung-uk Kim } 625*e71b7053SJung-uk Kim 626*e71b7053SJung-uk Kim if (badsig) { 627*e71b7053SJung-uk Kim const ASN1_BIT_STRING *signature; 628*e71b7053SJung-uk Kim 629*e71b7053SJung-uk Kim X509_get0_signature(&signature, NULL, x); 630*e71b7053SJung-uk Kim corrupt_signature(signature); 631f579bf8eSKris Kennaway } 632f579bf8eSKris Kennaway 6336f9291ceSJung-uk Kim if (num) { 6346f9291ceSJung-uk Kim for (i = 1; i <= num; i++) { 6356f9291ceSJung-uk Kim if (issuer == i) { 636*e71b7053SJung-uk Kim print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt()); 6376f9291ceSJung-uk Kim } else if (subject == i) { 638*e71b7053SJung-uk Kim print_name(out, "subject=", 639*e71b7053SJung-uk Kim X509_get_subject_name(x), get_nameopt()); 6406f9291ceSJung-uk Kim } else if (serial == i) { 641*e71b7053SJung-uk Kim BIO_printf(out, "serial="); 642*e71b7053SJung-uk Kim i2a_ASN1_INTEGER(out, X509_get_serialNumber(x)); 643*e71b7053SJung-uk Kim BIO_printf(out, "\n"); 6446f9291ceSJung-uk Kim } else if (next_serial == i) { 645*e71b7053SJung-uk Kim ASN1_INTEGER *ser = X509_get_serialNumber(x); 646*e71b7053SJung-uk Kim BIGNUM *bnser = ASN1_INTEGER_to_BN(ser, NULL); 647*e71b7053SJung-uk Kim 6486be8ae07SJacques Vidrine if (!bnser) 6496be8ae07SJacques Vidrine goto end; 6506be8ae07SJacques Vidrine if (!BN_add_word(bnser, 1)) 6516be8ae07SJacques Vidrine goto end; 6526be8ae07SJacques Vidrine ser = BN_to_ASN1_INTEGER(bnser, NULL); 6536be8ae07SJacques Vidrine if (!ser) 6546be8ae07SJacques Vidrine goto end; 6556be8ae07SJacques Vidrine BN_free(bnser); 6566be8ae07SJacques Vidrine i2a_ASN1_INTEGER(out, ser); 6576be8ae07SJacques Vidrine ASN1_INTEGER_free(ser); 6586be8ae07SJacques Vidrine BIO_puts(out, "\n"); 6596f9291ceSJung-uk Kim } else if ((email == i) || (ocsp_uri == i)) { 660ddd58736SKris Kennaway int j; 6611f13597dSJung-uk Kim STACK_OF(OPENSSL_STRING) *emlst; 662db522d3aSSimon L. B. Nielsen if (email == i) 663ddd58736SKris Kennaway emlst = X509_get1_email(x); 664db522d3aSSimon L. B. Nielsen else 665db522d3aSSimon L. B. Nielsen emlst = X509_get1_ocsp(x); 6661f13597dSJung-uk Kim for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) 667*e71b7053SJung-uk Kim BIO_printf(out, "%s\n", 6681f13597dSJung-uk Kim sk_OPENSSL_STRING_value(emlst, j)); 669ddd58736SKris Kennaway X509_email_free(emlst); 6706f9291ceSJung-uk Kim } else if (aliasout == i) { 671f579bf8eSKris Kennaway unsigned char *alstr; 672f579bf8eSKris Kennaway alstr = X509_alias_get0(x, NULL); 6736f9291ceSJung-uk Kim if (alstr) 674*e71b7053SJung-uk Kim BIO_printf(out, "%s\n", alstr); 6756f9291ceSJung-uk Kim else 676*e71b7053SJung-uk Kim BIO_puts(out, "<No Alias>\n"); 6776f9291ceSJung-uk Kim } else if (subject_hash == i) { 678*e71b7053SJung-uk Kim BIO_printf(out, "%08lx\n", X509_subject_name_hash(x)); 67974664626SKris Kennaway } 6801f13597dSJung-uk Kim #ifndef OPENSSL_NO_MD5 6816f9291ceSJung-uk Kim else if (subject_hash_old == i) { 682*e71b7053SJung-uk Kim BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x)); 6831f13597dSJung-uk Kim } 6841f13597dSJung-uk Kim #endif 6856f9291ceSJung-uk Kim else if (issuer_hash == i) { 686*e71b7053SJung-uk Kim BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x)); 6873b4e3dcbSSimon L. B. Nielsen } 6881f13597dSJung-uk Kim #ifndef OPENSSL_NO_MD5 6896f9291ceSJung-uk Kim else if (issuer_hash_old == i) { 690*e71b7053SJung-uk Kim BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x)); 6911f13597dSJung-uk Kim } 6921f13597dSJung-uk Kim #endif 6936f9291ceSJung-uk Kim else if (pprint == i) { 694f579bf8eSKris Kennaway X509_PURPOSE *ptmp; 695f579bf8eSKris Kennaway int j; 696*e71b7053SJung-uk Kim BIO_printf(out, "Certificate purposes:\n"); 6976f9291ceSJung-uk Kim for (j = 0; j < X509_PURPOSE_get_count(); j++) { 698f579bf8eSKris Kennaway ptmp = X509_PURPOSE_get0(j); 699*e71b7053SJung-uk Kim purpose_print(out, x, ptmp); 700f579bf8eSKris Kennaway } 7016f9291ceSJung-uk Kim } else if (modulus == i) { 70274664626SKris Kennaway EVP_PKEY *pkey; 70374664626SKris Kennaway 704*e71b7053SJung-uk Kim pkey = X509_get0_pubkey(x); 7056f9291ceSJung-uk Kim if (pkey == NULL) { 70674664626SKris Kennaway BIO_printf(bio_err, "Modulus=unavailable\n"); 70774664626SKris Kennaway ERR_print_errors(bio_err); 70874664626SKris Kennaway goto end; 70974664626SKris Kennaway } 710*e71b7053SJung-uk Kim BIO_printf(out, "Modulus="); 7115c87c606SMark Murray #ifndef OPENSSL_NO_RSA 712*e71b7053SJung-uk Kim if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { 713*e71b7053SJung-uk Kim const BIGNUM *n; 714*e71b7053SJung-uk Kim RSA_get0_key(EVP_PKEY_get0_RSA(pkey), &n, NULL, NULL); 715*e71b7053SJung-uk Kim BN_print(out, n); 716*e71b7053SJung-uk Kim } else 71774664626SKris Kennaway #endif 7185c87c606SMark Murray #ifndef OPENSSL_NO_DSA 719*e71b7053SJung-uk Kim if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) { 720*e71b7053SJung-uk Kim const BIGNUM *dsapub = NULL; 721*e71b7053SJung-uk Kim DSA_get0_key(EVP_PKEY_get0_DSA(pkey), &dsapub, NULL); 722*e71b7053SJung-uk Kim BN_print(out, dsapub); 723*e71b7053SJung-uk Kim } else 72474664626SKris Kennaway #endif 725*e71b7053SJung-uk Kim { 726*e71b7053SJung-uk Kim BIO_printf(out, "Wrong Algorithm type"); 727*e71b7053SJung-uk Kim } 728*e71b7053SJung-uk Kim BIO_printf(out, "\n"); 7296f9291ceSJung-uk Kim } else if (pubkey == i) { 730f579bf8eSKris Kennaway EVP_PKEY *pkey; 731f579bf8eSKris Kennaway 732*e71b7053SJung-uk Kim pkey = X509_get0_pubkey(x); 7336f9291ceSJung-uk Kim if (pkey == NULL) { 734f579bf8eSKris Kennaway BIO_printf(bio_err, "Error getting public key\n"); 735f579bf8eSKris Kennaway ERR_print_errors(bio_err); 736f579bf8eSKris Kennaway goto end; 737f579bf8eSKris Kennaway } 738*e71b7053SJung-uk Kim PEM_write_bio_PUBKEY(out, pkey); 7396f9291ceSJung-uk Kim } else if (C == i) { 74074664626SKris Kennaway unsigned char *d; 74174664626SKris Kennaway char *m; 742*e71b7053SJung-uk Kim int len; 74374664626SKris Kennaway 744*e71b7053SJung-uk Kim print_name(out, "/*\n" 745*e71b7053SJung-uk Kim " * Subject: ", X509_get_subject_name(x), get_nameopt()); 746*e71b7053SJung-uk Kim print_name(out, " * Issuer: ", X509_get_issuer_name(x), get_nameopt()); 747*e71b7053SJung-uk Kim BIO_puts(out, " */\n"); 74874664626SKris Kennaway 749*e71b7053SJung-uk Kim len = i2d_X509(x, NULL); 750*e71b7053SJung-uk Kim m = app_malloc(len, "x509 name buffer"); 75174664626SKris Kennaway d = (unsigned char *)m; 752*e71b7053SJung-uk Kim len = i2d_X509_NAME(X509_get_subject_name(x), &d); 753*e71b7053SJung-uk Kim print_array(out, "the_subject_name", len, (unsigned char *)m); 75474664626SKris Kennaway d = (unsigned char *)m; 755*e71b7053SJung-uk Kim len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d); 756*e71b7053SJung-uk Kim print_array(out, "the_public_key", len, (unsigned char *)m); 75774664626SKris Kennaway d = (unsigned char *)m; 758*e71b7053SJung-uk Kim len = i2d_X509(x, &d); 759*e71b7053SJung-uk Kim print_array(out, "the_certificate", len, (unsigned char *)m); 760ddd58736SKris Kennaway OPENSSL_free(m); 7616f9291ceSJung-uk Kim } else if (text == i) { 762*e71b7053SJung-uk Kim X509_print_ex(out, x, get_nameopt(), certflag); 7636f9291ceSJung-uk Kim } else if (startdate == i) { 764*e71b7053SJung-uk Kim BIO_puts(out, "notBefore="); 765*e71b7053SJung-uk Kim ASN1_TIME_print(out, X509_get0_notBefore(x)); 766*e71b7053SJung-uk Kim BIO_puts(out, "\n"); 7676f9291ceSJung-uk Kim } else if (enddate == i) { 768*e71b7053SJung-uk Kim BIO_puts(out, "notAfter="); 769*e71b7053SJung-uk Kim ASN1_TIME_print(out, X509_get0_notAfter(x)); 770*e71b7053SJung-uk Kim BIO_puts(out, "\n"); 7716f9291ceSJung-uk Kim } else if (fingerprint == i) { 77274664626SKris Kennaway int j; 77374664626SKris Kennaway unsigned int n; 77474664626SKris Kennaway unsigned char md[EVP_MAX_MD_SIZE]; 7751f13597dSJung-uk Kim const EVP_MD *fdig = digest; 77674664626SKris Kennaway 777*e71b7053SJung-uk Kim if (fdig == NULL) 7781f13597dSJung-uk Kim fdig = EVP_sha1(); 7791f13597dSJung-uk Kim 7806f9291ceSJung-uk Kim if (!X509_digest(x, fdig, md, &n)) { 78174664626SKris Kennaway BIO_printf(bio_err, "out of memory\n"); 78274664626SKris Kennaway goto end; 78374664626SKris Kennaway } 784*e71b7053SJung-uk Kim BIO_printf(out, "%s Fingerprint=", 7851f13597dSJung-uk Kim OBJ_nid2sn(EVP_MD_type(fdig))); 7866f9291ceSJung-uk Kim for (j = 0; j < (int)n; j++) { 787*e71b7053SJung-uk Kim BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n) 78874664626SKris Kennaway ? '\n' : ':'); 78974664626SKris Kennaway } 79074664626SKris Kennaway } 79174664626SKris Kennaway 79274664626SKris Kennaway /* should be in the library */ 7936f9291ceSJung-uk Kim else if ((sign_flag == i) && (x509req == 0)) { 79474664626SKris Kennaway BIO_printf(bio_err, "Getting Private key\n"); 7956f9291ceSJung-uk Kim if (Upkey == NULL) { 796*e71b7053SJung-uk Kim Upkey = load_key(keyfile, keyformat, 0, 7975c87c606SMark Murray passin, e, "Private key"); 7986f9291ceSJung-uk Kim if (Upkey == NULL) 7996f9291ceSJung-uk Kim goto end; 80074664626SKris Kennaway } 80174664626SKris Kennaway 802*e71b7053SJung-uk Kim if (!sign(x, Upkey, days, clrext, digest, extconf, extsect, preserve_dates)) 8036f9291ceSJung-uk Kim goto end; 8046f9291ceSJung-uk Kim } else if (CA_flag == i) { 80574664626SKris Kennaway BIO_printf(bio_err, "Getting CA Private Key\n"); 8066f9291ceSJung-uk Kim if (CAkeyfile != NULL) { 807*e71b7053SJung-uk Kim CApkey = load_key(CAkeyfile, CAkeyformat, 8086f9291ceSJung-uk Kim 0, passin, e, "CA Private Key"); 8096f9291ceSJung-uk Kim if (CApkey == NULL) 8106f9291ceSJung-uk Kim goto end; 81174664626SKris Kennaway } 81274664626SKris Kennaway 81374664626SKris Kennaway if (!x509_certify(ctx, CAfile, digest, x, xca, 8141f13597dSJung-uk Kim CApkey, sigopts, 8151f13597dSJung-uk Kim CAserial, CA_createserial, days, clrext, 816*e71b7053SJung-uk Kim extconf, extsect, sno, reqfile, preserve_dates)) 81774664626SKris Kennaway goto end; 8186f9291ceSJung-uk Kim } else if (x509req == i) { 81974664626SKris Kennaway EVP_PKEY *pk; 82074664626SKris Kennaway 82174664626SKris Kennaway BIO_printf(bio_err, "Getting request Private Key\n"); 8226f9291ceSJung-uk Kim if (keyfile == NULL) { 82374664626SKris Kennaway BIO_printf(bio_err, "no request key file specified\n"); 82474664626SKris Kennaway goto end; 8256f9291ceSJung-uk Kim } else { 826*e71b7053SJung-uk Kim pk = load_key(keyfile, keyformat, 0, 8275c87c606SMark Murray passin, e, "request key"); 8286f9291ceSJung-uk Kim if (pk == NULL) 8296f9291ceSJung-uk Kim goto end; 83074664626SKris Kennaway } 83174664626SKris Kennaway 83274664626SKris Kennaway BIO_printf(bio_err, "Generating certificate request\n"); 83374664626SKris Kennaway 834f579bf8eSKris Kennaway rq = X509_to_X509_REQ(x, pk, digest); 83574664626SKris Kennaway EVP_PKEY_free(pk); 8366f9291ceSJung-uk Kim if (rq == NULL) { 83774664626SKris Kennaway ERR_print_errors(bio_err); 83874664626SKris Kennaway goto end; 83974664626SKris Kennaway } 8406f9291ceSJung-uk Kim if (!noout) { 841*e71b7053SJung-uk Kim X509_REQ_print_ex(out, rq, get_nameopt(), X509_FLAG_COMPAT); 84274664626SKris Kennaway PEM_write_bio_X509_REQ(out, rq); 84374664626SKris Kennaway } 84474664626SKris Kennaway noout = 1; 8456f9291ceSJung-uk Kim } else if (ocspid == i) { 8465c87c606SMark Murray X509_ocspid_print(out, x); 847*e71b7053SJung-uk Kim } else if (ext == i) { 848*e71b7053SJung-uk Kim print_x509v3_exts(out, x, exts); 8495c87c606SMark Murray } 85074664626SKris Kennaway } 85174664626SKris Kennaway } 85274664626SKris Kennaway 8536f9291ceSJung-uk Kim if (checkend) { 8543b4e3dcbSSimon L. B. Nielsen time_t tcheck = time(NULL) + checkoffset; 855ddd58736SKris Kennaway 856*e71b7053SJung-uk Kim if (X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0) { 857ddd58736SKris Kennaway BIO_printf(out, "Certificate will expire\n"); 858ddd58736SKris Kennaway ret = 1; 8596f9291ceSJung-uk Kim } else { 860ddd58736SKris Kennaway BIO_printf(out, "Certificate will not expire\n"); 861ddd58736SKris Kennaway ret = 0; 862ddd58736SKris Kennaway } 863ddd58736SKris Kennaway goto end; 864ddd58736SKris Kennaway } 865ddd58736SKris Kennaway 866*e71b7053SJung-uk Kim print_cert_checks(out, x, checkhost, checkemail, checkip); 8677bded2dbSJung-uk Kim 868*e71b7053SJung-uk Kim if (noout || nocert) { 86974664626SKris Kennaway ret = 0; 87074664626SKris Kennaway goto end; 87174664626SKris Kennaway } 87274664626SKris Kennaway 873*e71b7053SJung-uk Kim if (outformat == FORMAT_ASN1) { 87474664626SKris Kennaway i = i2d_X509_bio(out, x); 875*e71b7053SJung-uk Kim } else if (outformat == FORMAT_PEM) { 8766f9291ceSJung-uk Kim if (trustout) 8776f9291ceSJung-uk Kim i = PEM_write_bio_X509_AUX(out, x); 8786f9291ceSJung-uk Kim else 8796f9291ceSJung-uk Kim i = PEM_write_bio_X509(out, x); 8806f9291ceSJung-uk Kim } else { 88174664626SKris Kennaway BIO_printf(bio_err, "bad output format specified for outfile\n"); 88274664626SKris Kennaway goto end; 88374664626SKris Kennaway } 8846f9291ceSJung-uk Kim if (!i) { 88574664626SKris Kennaway BIO_printf(bio_err, "unable to write certificate\n"); 88674664626SKris Kennaway ERR_print_errors(bio_err); 88774664626SKris Kennaway goto end; 88874664626SKris Kennaway } 88974664626SKris Kennaway ret = 0; 89074664626SKris Kennaway end: 8915c87c606SMark Murray NCONF_free(extconf); 892ddd58736SKris Kennaway BIO_free_all(out); 89374664626SKris Kennaway X509_STORE_free(ctx); 89474664626SKris Kennaway X509_REQ_free(req); 89574664626SKris Kennaway X509_free(x); 89674664626SKris Kennaway X509_free(xca); 89774664626SKris Kennaway EVP_PKEY_free(Upkey); 89874664626SKris Kennaway EVP_PKEY_free(CApkey); 8997bded2dbSJung-uk Kim EVP_PKEY_free(fkey); 9001f13597dSJung-uk Kim sk_OPENSSL_STRING_free(sigopts); 90174664626SKris Kennaway X509_REQ_free(rq); 9025c87c606SMark Murray ASN1_INTEGER_free(sno); 903f579bf8eSKris Kennaway sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); 904f579bf8eSKris Kennaway sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free); 905*e71b7053SJung-uk Kim ASN1_OBJECT_free(objtmp); 9066cf8931aSJung-uk Kim release_engine(e); 9076f9291ceSJung-uk Kim OPENSSL_free(passin); 908*e71b7053SJung-uk Kim return ret; 90974664626SKris Kennaway } 91074664626SKris Kennaway 911*e71b7053SJung-uk Kim static ASN1_INTEGER *x509_load_serial(const char *CAfile, 912*e71b7053SJung-uk Kim const char *serialfile, int create) 91374664626SKris Kennaway { 914*e71b7053SJung-uk Kim char *buf = NULL; 915ced566fdSJacques Vidrine ASN1_INTEGER *bs = NULL; 91674664626SKris Kennaway BIGNUM *serial = NULL; 91774664626SKris Kennaway 9186f9291ceSJung-uk Kim if (serialfile == NULL) { 919*e71b7053SJung-uk Kim const char *p = strrchr(CAfile, '.'); 920*e71b7053SJung-uk Kim size_t len = p != NULL ? (size_t)(p - CAfile) : strlen(CAfile); 92174664626SKris Kennaway 922*e71b7053SJung-uk Kim buf = app_malloc(len + sizeof(POSTFIX), "serial# buffer"); 923*e71b7053SJung-uk Kim memcpy(buf, CAfile, len); 924*e71b7053SJung-uk Kim memcpy(buf + len, POSTFIX, sizeof(POSTFIX)); 925*e71b7053SJung-uk Kim serialfile = buf; 926*e71b7053SJung-uk Kim } 927*e71b7053SJung-uk Kim 928*e71b7053SJung-uk Kim serial = load_serial(serialfile, create, NULL); 9296f9291ceSJung-uk Kim if (serial == NULL) 9306f9291ceSJung-uk Kim goto end; 93174664626SKris Kennaway 9326f9291ceSJung-uk Kim if (!BN_add_word(serial, 1)) { 9336f9291ceSJung-uk Kim BIO_printf(bio_err, "add_word failure\n"); 9346f9291ceSJung-uk Kim goto end; 9356f9291ceSJung-uk Kim } 9365c87c606SMark Murray 937*e71b7053SJung-uk Kim if (!save_serial(serialfile, NULL, serial, &bs)) 9386f9291ceSJung-uk Kim goto end; 9395c87c606SMark Murray 9405c87c606SMark Murray end: 9416f9291ceSJung-uk Kim OPENSSL_free(buf); 9425c87c606SMark Murray BN_free(serial); 943ced566fdSJacques Vidrine return bs; 9445c87c606SMark Murray } 9455c87c606SMark Murray 946*e71b7053SJung-uk Kim static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest, 9471f13597dSJung-uk Kim X509 *x, X509 *xca, EVP_PKEY *pkey, 9481f13597dSJung-uk Kim STACK_OF(OPENSSL_STRING) *sigopts, 949*e71b7053SJung-uk Kim const char *serialfile, int create, 950*e71b7053SJung-uk Kim int days, int clrext, CONF *conf, const char *section, 951*e71b7053SJung-uk Kim ASN1_INTEGER *sno, int reqfile, int preserve_dates) 9525c87c606SMark Murray { 9535c87c606SMark Murray int ret = 0; 9545c87c606SMark Murray ASN1_INTEGER *bs = NULL; 955*e71b7053SJung-uk Kim X509_STORE_CTX *xsc = NULL; 9565c87c606SMark Murray EVP_PKEY *upkey; 9575c87c606SMark Murray 958*e71b7053SJung-uk Kim upkey = X509_get0_pubkey(xca); 959aeb5019cSJung-uk Kim if (upkey == NULL) { 960aeb5019cSJung-uk Kim BIO_printf(bio_err, "Error obtaining CA X509 public key\n"); 961aeb5019cSJung-uk Kim goto end; 962aeb5019cSJung-uk Kim } 9635c87c606SMark Murray EVP_PKEY_copy_parameters(upkey, pkey); 9645c87c606SMark Murray 965*e71b7053SJung-uk Kim xsc = X509_STORE_CTX_new(); 966*e71b7053SJung-uk Kim if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, x, NULL)) { 9675c87c606SMark Murray BIO_printf(bio_err, "Error initialising X509 store\n"); 9685c87c606SMark Murray goto end; 9695c87c606SMark Murray } 9706f9291ceSJung-uk Kim if (sno) 9716f9291ceSJung-uk Kim bs = sno; 972*e71b7053SJung-uk Kim else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL) 9735c87c606SMark Murray goto end; 97474664626SKris Kennaway 9756f9291ceSJung-uk Kim /* 9766f9291ceSJung-uk Kim * NOTE: this certificate can/should be self signed, unless it was a 9776f9291ceSJung-uk Kim * certificate request in which case it is not. 9786f9291ceSJung-uk Kim */ 979*e71b7053SJung-uk Kim X509_STORE_CTX_set_cert(xsc, x); 980*e71b7053SJung-uk Kim X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); 981*e71b7053SJung-uk Kim if (!reqfile && X509_verify_cert(xsc) <= 0) 98274664626SKris Kennaway goto end; 98374664626SKris Kennaway 9846f9291ceSJung-uk Kim if (!X509_check_private_key(xca, pkey)) { 9856f9291ceSJung-uk Kim BIO_printf(bio_err, 9866f9291ceSJung-uk Kim "CA certificate and CA private key do not match\n"); 98774664626SKris Kennaway goto end; 98874664626SKris Kennaway } 98974664626SKris Kennaway 9906f9291ceSJung-uk Kim if (!X509_set_issuer_name(x, X509_get_subject_name(xca))) 9916f9291ceSJung-uk Kim goto end; 9926f9291ceSJung-uk Kim if (!X509_set_serialNumber(x, bs)) 9936f9291ceSJung-uk Kim goto end; 99474664626SKris Kennaway 995*e71b7053SJung-uk Kim if (!preserve_dates && !set_cert_times(x, NULL, NULL, days)) 99674664626SKris Kennaway goto end; 99774664626SKris Kennaway 9986f9291ceSJung-uk Kim if (clrext) { 9996f9291ceSJung-uk Kim while (X509_get_ext_count(x) > 0) 10006f9291ceSJung-uk Kim X509_delete_ext(x, 0); 1001f579bf8eSKris Kennaway } 1002f579bf8eSKris Kennaway 1003*e71b7053SJung-uk Kim if (conf != NULL) { 100474664626SKris Kennaway X509V3_CTX ctx2; 100574664626SKris Kennaway X509_set_version(x, 2); /* version 3 certificate */ 100674664626SKris Kennaway X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0); 10075c87c606SMark Murray X509V3_set_nconf(&ctx2, conf); 10086f9291ceSJung-uk Kim if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) 10096f9291ceSJung-uk Kim goto end; 101074664626SKris Kennaway } 101174664626SKris Kennaway 1012*e71b7053SJung-uk Kim if (!do_X509_sign(x, pkey, digest, sigopts)) 10131f13597dSJung-uk Kim goto end; 101474664626SKris Kennaway ret = 1; 101574664626SKris Kennaway end: 1016*e71b7053SJung-uk Kim X509_STORE_CTX_free(xsc); 101774664626SKris Kennaway if (!ret) 101874664626SKris Kennaway ERR_print_errors(bio_err); 10196f9291ceSJung-uk Kim if (!sno) 10206f9291ceSJung-uk Kim ASN1_INTEGER_free(bs); 1021ddd58736SKris Kennaway return ret; 102274664626SKris Kennaway } 102374664626SKris Kennaway 1024*e71b7053SJung-uk Kim static int callb(int ok, X509_STORE_CTX *ctx) 102574664626SKris Kennaway { 102674664626SKris Kennaway int err; 102774664626SKris Kennaway X509 *err_cert; 102874664626SKris Kennaway 10296f9291ceSJung-uk Kim /* 10306f9291ceSJung-uk Kim * it is ok to use a self signed certificate This case will catch both 10316f9291ceSJung-uk Kim * the initial ok == 0 and the final ok == 1 calls to this function 10326f9291ceSJung-uk Kim */ 103374664626SKris Kennaway err = X509_STORE_CTX_get_error(ctx); 103474664626SKris Kennaway if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) 1035ddd58736SKris Kennaway return 1; 103674664626SKris Kennaway 10376f9291ceSJung-uk Kim /* 10386f9291ceSJung-uk Kim * BAD we should have gotten an error. Normally if everything worked 10396f9291ceSJung-uk Kim * X509_STORE_CTX_get_error(ctx) will still be set to 10406f9291ceSJung-uk Kim * DEPTH_ZERO_SELF_.... 10416f9291ceSJung-uk Kim */ 10426f9291ceSJung-uk Kim if (ok) { 10436f9291ceSJung-uk Kim BIO_printf(bio_err, 10446f9291ceSJung-uk Kim "error with certificate to be certified - should be self signed\n"); 1045ddd58736SKris Kennaway return 0; 10466f9291ceSJung-uk Kim } else { 104774664626SKris Kennaway err_cert = X509_STORE_CTX_get_current_cert(ctx); 1048ddd58736SKris Kennaway print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0); 10496f9291ceSJung-uk Kim BIO_printf(bio_err, 10506f9291ceSJung-uk Kim "error with certificate - error %d at depth %d\n%s\n", err, 10516f9291ceSJung-uk Kim X509_STORE_CTX_get_error_depth(ctx), 105274664626SKris Kennaway X509_verify_cert_error_string(err)); 1053ddd58736SKris Kennaway return 1; 105474664626SKris Kennaway } 105574664626SKris Kennaway } 105674664626SKris Kennaway 105774664626SKris Kennaway /* self sign */ 10586f9291ceSJung-uk Kim static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, 1059*e71b7053SJung-uk Kim const EVP_MD *digest, CONF *conf, const char *section, 1060*e71b7053SJung-uk Kim int preserve_dates) 106174664626SKris Kennaway { 106274664626SKris Kennaway 10636f9291ceSJung-uk Kim if (!X509_set_issuer_name(x, X509_get_subject_name(x))) 10646f9291ceSJung-uk Kim goto err; 1065*e71b7053SJung-uk Kim if (!preserve_dates && !set_cert_times(x, NULL, NULL, days)) 10666f9291ceSJung-uk Kim goto err; 10676f9291ceSJung-uk Kim if (!X509_set_pubkey(x, pkey)) 10686f9291ceSJung-uk Kim goto err; 10696f9291ceSJung-uk Kim if (clrext) { 10706f9291ceSJung-uk Kim while (X509_get_ext_count(x) > 0) 10716f9291ceSJung-uk Kim X509_delete_ext(x, 0); 1072f579bf8eSKris Kennaway } 1073*e71b7053SJung-uk Kim if (conf != NULL) { 107474664626SKris Kennaway X509V3_CTX ctx; 107574664626SKris Kennaway X509_set_version(x, 2); /* version 3 certificate */ 107674664626SKris Kennaway X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0); 10775c87c606SMark Murray X509V3_set_nconf(&ctx, conf); 10786f9291ceSJung-uk Kim if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) 10796f9291ceSJung-uk Kim goto err; 108074664626SKris Kennaway } 10816f9291ceSJung-uk Kim if (!X509_sign(x, pkey, digest)) 10826f9291ceSJung-uk Kim goto err; 1083ddd58736SKris Kennaway return 1; 108474664626SKris Kennaway err: 108574664626SKris Kennaway ERR_print_errors(bio_err); 1086ddd58736SKris Kennaway return 0; 108774664626SKris Kennaway } 1088f579bf8eSKris Kennaway 1089f579bf8eSKris Kennaway static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt) 1090f579bf8eSKris Kennaway { 1091f579bf8eSKris Kennaway int id, i, idret; 1092*e71b7053SJung-uk Kim const char *pname; 1093f579bf8eSKris Kennaway id = X509_PURPOSE_get_id(pt); 1094f579bf8eSKris Kennaway pname = X509_PURPOSE_get0_name(pt); 10956f9291ceSJung-uk Kim for (i = 0; i < 2; i++) { 1096f579bf8eSKris Kennaway idret = X509_check_purpose(cert, id, i); 1097f579bf8eSKris Kennaway BIO_printf(bio, "%s%s : ", pname, i ? " CA" : ""); 10986f9291ceSJung-uk Kim if (idret == 1) 10996f9291ceSJung-uk Kim BIO_printf(bio, "Yes\n"); 11006f9291ceSJung-uk Kim else if (idret == 0) 11016f9291ceSJung-uk Kim BIO_printf(bio, "No\n"); 11026f9291ceSJung-uk Kim else 11036f9291ceSJung-uk Kim BIO_printf(bio, "Yes (WARNING code=%d)\n", idret); 1104f579bf8eSKris Kennaway } 1105f579bf8eSKris Kennaway return 1; 1106f579bf8eSKris Kennaway } 1107*e71b7053SJung-uk Kim 1108*e71b7053SJung-uk Kim static int parse_ext_names(char *names, const char **result) 1109*e71b7053SJung-uk Kim { 1110*e71b7053SJung-uk Kim char *p, *q; 1111*e71b7053SJung-uk Kim int cnt = 0, len = 0; 1112*e71b7053SJung-uk Kim 1113*e71b7053SJung-uk Kim p = q = names; 1114*e71b7053SJung-uk Kim len = strlen(names); 1115*e71b7053SJung-uk Kim 1116*e71b7053SJung-uk Kim while (q - names <= len) { 1117*e71b7053SJung-uk Kim if (*q != ',' && *q != '\0') { 1118*e71b7053SJung-uk Kim q++; 1119*e71b7053SJung-uk Kim continue; 1120*e71b7053SJung-uk Kim } 1121*e71b7053SJung-uk Kim if (p != q) { 1122*e71b7053SJung-uk Kim /* found */ 1123*e71b7053SJung-uk Kim if (result != NULL) { 1124*e71b7053SJung-uk Kim result[cnt] = p; 1125*e71b7053SJung-uk Kim *q = '\0'; 1126*e71b7053SJung-uk Kim } 1127*e71b7053SJung-uk Kim cnt++; 1128*e71b7053SJung-uk Kim } 1129*e71b7053SJung-uk Kim p = ++q; 1130*e71b7053SJung-uk Kim } 1131*e71b7053SJung-uk Kim 1132*e71b7053SJung-uk Kim return cnt; 1133*e71b7053SJung-uk Kim } 1134*e71b7053SJung-uk Kim 1135*e71b7053SJung-uk Kim static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names) 1136*e71b7053SJung-uk Kim { 1137*e71b7053SJung-uk Kim const STACK_OF(X509_EXTENSION) *exts = NULL; 1138*e71b7053SJung-uk Kim STACK_OF(X509_EXTENSION) *exts2 = NULL; 1139*e71b7053SJung-uk Kim X509_EXTENSION *ext = NULL; 1140*e71b7053SJung-uk Kim ASN1_OBJECT *obj; 1141*e71b7053SJung-uk Kim int i, j, ret = 0, num, nn = 0; 1142*e71b7053SJung-uk Kim const char *sn, **names = NULL; 1143*e71b7053SJung-uk Kim char *tmp_ext_names = NULL; 1144*e71b7053SJung-uk Kim 1145*e71b7053SJung-uk Kim exts = X509_get0_extensions(x); 1146*e71b7053SJung-uk Kim if ((num = sk_X509_EXTENSION_num(exts)) <= 0) { 1147*e71b7053SJung-uk Kim BIO_printf(bio, "No extensions in certificate\n"); 1148*e71b7053SJung-uk Kim ret = 1; 1149*e71b7053SJung-uk Kim goto end; 1150*e71b7053SJung-uk Kim } 1151*e71b7053SJung-uk Kim 1152*e71b7053SJung-uk Kim /* parse comma separated ext name string */ 1153*e71b7053SJung-uk Kim if ((tmp_ext_names = OPENSSL_strdup(ext_names)) == NULL) 1154*e71b7053SJung-uk Kim goto end; 1155*e71b7053SJung-uk Kim if ((nn = parse_ext_names(tmp_ext_names, NULL)) == 0) { 1156*e71b7053SJung-uk Kim BIO_printf(bio, "Invalid extension names: %s\n", ext_names); 1157*e71b7053SJung-uk Kim goto end; 1158*e71b7053SJung-uk Kim } 1159*e71b7053SJung-uk Kim if ((names = OPENSSL_malloc(sizeof(char *) * nn)) == NULL) 1160*e71b7053SJung-uk Kim goto end; 1161*e71b7053SJung-uk Kim parse_ext_names(tmp_ext_names, names); 1162*e71b7053SJung-uk Kim 1163*e71b7053SJung-uk Kim for (i = 0; i < num; i++) { 1164*e71b7053SJung-uk Kim ext = sk_X509_EXTENSION_value(exts, i); 1165*e71b7053SJung-uk Kim 1166*e71b7053SJung-uk Kim /* check if this ext is what we want */ 1167*e71b7053SJung-uk Kim obj = X509_EXTENSION_get_object(ext); 1168*e71b7053SJung-uk Kim sn = OBJ_nid2sn(OBJ_obj2nid(obj)); 1169*e71b7053SJung-uk Kim if (sn == NULL || strcmp(sn, "UNDEF") == 0) 1170*e71b7053SJung-uk Kim continue; 1171*e71b7053SJung-uk Kim 1172*e71b7053SJung-uk Kim for (j = 0; j < nn; j++) { 1173*e71b7053SJung-uk Kim if (strcmp(sn, names[j]) == 0) { 1174*e71b7053SJung-uk Kim /* push the extension into a new stack */ 1175*e71b7053SJung-uk Kim if (exts2 == NULL 1176*e71b7053SJung-uk Kim && (exts2 = sk_X509_EXTENSION_new_null()) == NULL) 1177*e71b7053SJung-uk Kim goto end; 1178*e71b7053SJung-uk Kim if (!sk_X509_EXTENSION_push(exts2, ext)) 1179*e71b7053SJung-uk Kim goto end; 1180*e71b7053SJung-uk Kim } 1181*e71b7053SJung-uk Kim } 1182*e71b7053SJung-uk Kim } 1183*e71b7053SJung-uk Kim 1184*e71b7053SJung-uk Kim if (!sk_X509_EXTENSION_num(exts2)) { 1185*e71b7053SJung-uk Kim BIO_printf(bio, "No extensions matched with %s\n", ext_names); 1186*e71b7053SJung-uk Kim ret = 1; 1187*e71b7053SJung-uk Kim goto end; 1188*e71b7053SJung-uk Kim } 1189*e71b7053SJung-uk Kim 1190*e71b7053SJung-uk Kim ret = X509V3_extensions_print(bio, NULL, exts2, 0, 0); 1191*e71b7053SJung-uk Kim end: 1192*e71b7053SJung-uk Kim sk_X509_EXTENSION_free(exts2); 1193*e71b7053SJung-uk Kim OPENSSL_free(names); 1194*e71b7053SJung-uk Kim OPENSSL_free(tmp_ext_names); 1195*e71b7053SJung-uk Kim return ret; 1196*e71b7053SJung-uk Kim } 1197