1e71b7053SJung-uk Kim /* 2*17f01e99SJung-uk Kim * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. 374664626SKris Kennaway * 4e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 5e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7e71b7053SJung-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" 14e71b7053SJung-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 35e71b7053SJung-uk Kim static int callb(int ok, X509_STORE_CTX *ctx); 36e71b7053SJung-uk Kim static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, 37e71b7053SJung-uk Kim const EVP_MD *digest, CONF *conf, const char *section, 38e71b7053SJung-uk Kim int preserve_dates); 39e71b7053SJung-uk Kim static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest, 40e71b7053SJung-uk Kim X509 *x, X509 *xca, EVP_PKEY *pkey, 41e71b7053SJung-uk Kim STACK_OF(OPENSSL_STRING) *sigopts, const char *serialfile, 42e71b7053SJung-uk Kim int create, int days, int clrext, CONF *conf, 43e71b7053SJung-uk Kim const char *section, ASN1_INTEGER *sno, int reqfile, 44e71b7053SJung-uk Kim int preserve_dates); 45e71b7053SJung-uk Kim static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt); 46e71b7053SJung-uk Kim static int print_x509v3_exts(BIO *bio, X509 *x, const char *exts); 47e71b7053SJung-uk Kim 48e71b7053SJung-uk Kim typedef enum OPTION_choice { 49e71b7053SJung-uk Kim OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 50e71b7053SJung-uk Kim OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM, 51e71b7053SJung-uk Kim OPT_CAKEYFORM, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE, 52e71b7053SJung-uk Kim OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_SIGNKEY, OPT_CA, 53e71b7053SJung-uk Kim OPT_CAKEY, OPT_CASERIAL, OPT_SET_SERIAL, OPT_FORCE_PUBKEY, 54e71b7053SJung-uk Kim OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_NAMEOPT, 55e71b7053SJung-uk Kim OPT_C, OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL, 56e71b7053SJung-uk Kim OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH, 57e71b7053SJung-uk Kim OPT_ISSUER_HASH, OPT_SUBJECT, OPT_ISSUER, OPT_FINGERPRINT, OPT_DATES, 58e71b7053SJung-uk Kim OPT_PURPOSE, OPT_STARTDATE, OPT_ENDDATE, OPT_CHECKEND, OPT_CHECKHOST, 59e71b7053SJung-uk Kim OPT_CHECKEMAIL, OPT_CHECKIP, OPT_NOOUT, OPT_TRUSTOUT, OPT_CLRTRUST, 60e71b7053SJung-uk Kim OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID, 61e71b7053SJung-uk Kim OPT_SUBJECT_HASH_OLD, 62e71b7053SJung-uk Kim OPT_ISSUER_HASH_OLD, 63e71b7053SJung-uk Kim OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES, 64e71b7053SJung-uk Kim OPT_R_ENUM, OPT_EXT 65e71b7053SJung-uk Kim } OPTION_CHOICE; 66e71b7053SJung-uk Kim 67e71b7053SJung-uk Kim const OPTIONS x509_options[] = { 68e71b7053SJung-uk Kim {"help", OPT_HELP, '-', "Display this summary"}, 69e71b7053SJung-uk Kim {"inform", OPT_INFORM, 'f', 70c9cf7b5cSJung-uk Kim "Input format - default PEM (one of DER or PEM)"}, 71e71b7053SJung-uk Kim {"in", OPT_IN, '<', "Input file - default stdin"}, 72e71b7053SJung-uk Kim {"outform", OPT_OUTFORM, 'f', 73c9cf7b5cSJung-uk Kim "Output format - default PEM (one of DER or PEM)"}, 74e71b7053SJung-uk Kim {"out", OPT_OUT, '>', "Output file - default stdout"}, 75*17f01e99SJung-uk Kim {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"}, 76e71b7053SJung-uk Kim {"passin", OPT_PASSIN, 's', "Private key password/pass-phrase source"}, 77e71b7053SJung-uk Kim {"serial", OPT_SERIAL, '-', "Print serial number value"}, 78e71b7053SJung-uk Kim {"subject_hash", OPT_HASH, '-', "Print subject hash value"}, 79e71b7053SJung-uk Kim {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"}, 80e71b7053SJung-uk Kim {"hash", OPT_HASH, '-', "Synonym for -subject_hash"}, 81e71b7053SJung-uk Kim {"subject", OPT_SUBJECT, '-', "Print subject DN"}, 82e71b7053SJung-uk Kim {"issuer", OPT_ISSUER, '-', "Print issuer DN"}, 83e71b7053SJung-uk Kim {"email", OPT_EMAIL, '-', "Print email address(es)"}, 84e71b7053SJung-uk Kim {"startdate", OPT_STARTDATE, '-', "Set notBefore field"}, 85e71b7053SJung-uk Kim {"enddate", OPT_ENDDATE, '-', "Set notAfter field"}, 86e71b7053SJung-uk Kim {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"}, 87e71b7053SJung-uk Kim {"dates", OPT_DATES, '-', "Both Before and After dates"}, 88e71b7053SJung-uk Kim {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"}, 89e71b7053SJung-uk Kim {"pubkey", OPT_PUBKEY, '-', "Output the public key"}, 90e71b7053SJung-uk Kim {"fingerprint", OPT_FINGERPRINT, '-', 91e71b7053SJung-uk Kim "Print the certificate fingerprint"}, 92e71b7053SJung-uk Kim {"alias", OPT_ALIAS, '-', "Output certificate alias"}, 93e71b7053SJung-uk Kim {"noout", OPT_NOOUT, '-', "No output, just status"}, 94e71b7053SJung-uk Kim {"nocert", OPT_NOCERT, '-', "No certificate output"}, 95e71b7053SJung-uk Kim {"ocspid", OPT_OCSPID, '-', 96e71b7053SJung-uk Kim "Print OCSP hash values for the subject name and public key"}, 97e71b7053SJung-uk Kim {"ocsp_uri", OPT_OCSP_URI, '-', "Print OCSP Responder URL(s)"}, 98e71b7053SJung-uk Kim {"trustout", OPT_TRUSTOUT, '-', "Output a trusted certificate"}, 99e71b7053SJung-uk Kim {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"}, 100e71b7053SJung-uk Kim {"clrext", OPT_CLREXT, '-', "Clear all certificate extensions"}, 101e71b7053SJung-uk Kim {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"}, 102e71b7053SJung-uk Kim {"addreject", OPT_ADDREJECT, 's', 103e71b7053SJung-uk Kim "Reject certificate for a given purpose"}, 104e71b7053SJung-uk Kim {"setalias", OPT_SETALIAS, 's', "Set certificate alias"}, 105e71b7053SJung-uk Kim {"days", OPT_DAYS, 'n', 106e71b7053SJung-uk Kim "How long till expiry of a signed certificate - def 30 days"}, 107e71b7053SJung-uk Kim {"checkend", OPT_CHECKEND, 'M', 108e71b7053SJung-uk Kim "Check whether the cert expires in the next arg seconds"}, 109e71b7053SJung-uk Kim {OPT_MORE_STR, 1, 1, "Exit 1 if so, 0 if not"}, 110*17f01e99SJung-uk Kim {"signkey", OPT_SIGNKEY, 's', "Self sign cert with arg"}, 111e71b7053SJung-uk Kim {"x509toreq", OPT_X509TOREQ, '-', 112e71b7053SJung-uk Kim "Output a certification request object"}, 113e71b7053SJung-uk Kim {"req", OPT_REQ, '-', "Input is a certificate request, sign and output"}, 114e71b7053SJung-uk Kim {"CA", OPT_CA, '<', "Set the CA certificate, must be PEM format"}, 115e71b7053SJung-uk Kim {"CAkey", OPT_CAKEY, 's', 116e71b7053SJung-uk Kim "The CA key, must be PEM format; if not in CAfile"}, 117e71b7053SJung-uk Kim {"CAcreateserial", OPT_CACREATESERIAL, '-', 118e71b7053SJung-uk Kim "Create serial number file if it does not exist"}, 119e71b7053SJung-uk Kim {"CAserial", OPT_CASERIAL, 's', "Serial file"}, 120e71b7053SJung-uk Kim {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"}, 121e71b7053SJung-uk Kim {"text", OPT_TEXT, '-', "Print the certificate in text form"}, 122e71b7053SJung-uk Kim {"ext", OPT_EXT, 's', "Print various X509V3 extensions"}, 123e71b7053SJung-uk Kim {"C", OPT_C, '-', "Print out C code forms"}, 124e71b7053SJung-uk Kim {"extfile", OPT_EXTFILE, '<', "File with X509V3 extensions to add"}, 125e71b7053SJung-uk Kim OPT_R_OPTIONS, 126e71b7053SJung-uk Kim {"extensions", OPT_EXTENSIONS, 's', "Section from config file to use"}, 127e71b7053SJung-uk Kim {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, 128e71b7053SJung-uk Kim {"certopt", OPT_CERTOPT, 's', "Various certificate text options"}, 129e71b7053SJung-uk Kim {"checkhost", OPT_CHECKHOST, 's', "Check certificate matches host"}, 130e71b7053SJung-uk Kim {"checkemail", OPT_CHECKEMAIL, 's', "Check certificate matches email"}, 131e71b7053SJung-uk Kim {"checkip", OPT_CHECKIP, 's', "Check certificate matches ipaddr"}, 132e71b7053SJung-uk Kim {"CAform", OPT_CAFORM, 'F', "CA format - default PEM"}, 133*17f01e99SJung-uk Kim {"CAkeyform", OPT_CAKEYFORM, 'E', "CA key format - default PEM"}, 134e71b7053SJung-uk Kim {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, 135e71b7053SJung-uk Kim {"force_pubkey", OPT_FORCE_PUBKEY, '<', "Force the Key to put inside certificate"}, 136e71b7053SJung-uk Kim {"next_serial", OPT_NEXT_SERIAL, '-', "Increment current certificate serial number"}, 137e71b7053SJung-uk Kim {"clrreject", OPT_CLRREJECT, '-', 138e71b7053SJung-uk Kim "Clears all the prohibited or rejected uses of the certificate"}, 139e71b7053SJung-uk Kim {"badsig", OPT_BADSIG, '-', "Corrupt last byte of certificate signature (for test)"}, 140e71b7053SJung-uk Kim {"", OPT_MD, '-', "Any supported digest"}, 1411f13597dSJung-uk Kim #ifndef OPENSSL_NO_MD5 142e71b7053SJung-uk Kim {"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-', 143e71b7053SJung-uk Kim "Print old-style (MD5) issuer hash value"}, 144e71b7053SJung-uk Kim {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-', 145e71b7053SJung-uk Kim "Print old-style (MD5) subject hash value"}, 1461f13597dSJung-uk Kim #endif 147fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_ENGINE 148e71b7053SJung-uk Kim {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 149fceca8a3SJacques Vidrine #endif 150e71b7053SJung-uk Kim {"preserve_dates", OPT_PRESERVE_DATES, '-', "preserve existing dates when signing"}, 151e71b7053SJung-uk Kim {NULL} 15274664626SKris Kennaway }; 15374664626SKris Kennaway 154e71b7053SJung-uk Kim int x509_main(int argc, char **argv) 15574664626SKris Kennaway { 1565c87c606SMark Murray ASN1_INTEGER *sno = NULL; 157e71b7053SJung-uk Kim ASN1_OBJECT *objtmp = NULL; 15874664626SKris Kennaway BIO *out = NULL; 159e71b7053SJung-uk Kim CONF *extconf = NULL; 160e71b7053SJung-uk Kim EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL; 161f579bf8eSKris Kennaway STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; 162e71b7053SJung-uk Kim STACK_OF(OPENSSL_STRING) *sigopts = NULL; 163e71b7053SJung-uk Kim X509 *x = NULL, *xca = NULL; 164e71b7053SJung-uk Kim X509_REQ *req = NULL, *rq = NULL; 165e71b7053SJung-uk Kim X509_STORE *ctx = NULL; 166e71b7053SJung-uk Kim const EVP_MD *digest = NULL; 167e71b7053SJung-uk Kim char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL; 168e71b7053SJung-uk Kim char *checkhost = NULL, *checkemail = NULL, *checkip = NULL, *exts = NULL; 169e71b7053SJung-uk Kim char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL; 17074664626SKris Kennaway char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL; 171e71b7053SJung-uk Kim char *prog; 172e71b7053SJung-uk Kim int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0; 173e71b7053SJung-uk Kim int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM; 174e71b7053SJung-uk Kim int fingerprint = 0, reqfile = 0, checkend = 0; 175e71b7053SJung-uk Kim int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM; 176e71b7053SJung-uk Kim int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0; 177e71b7053SJung-uk Kim int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0; 178e71b7053SJung-uk Kim int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0; 179e71b7053SJung-uk Kim int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0; 180e71b7053SJung-uk Kim int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0, ext = 0; 181e71b7053SJung-uk Kim int enddate = 0; 182e71b7053SJung-uk Kim time_t checkoffset = 0; 183e71b7053SJung-uk Kim unsigned long certflag = 0; 184e71b7053SJung-uk Kim int preserve_dates = 0; 185e71b7053SJung-uk Kim OPTION_CHOICE o; 186e71b7053SJung-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 196e71b7053SJung-uk Kim prog = opt_init(argc, argv, x509_options); 197e71b7053SJung-uk Kim while ((o = opt_next()) != OPT_EOF) { 198e71b7053SJung-uk Kim switch (o) { 199e71b7053SJung-uk Kim case OPT_EOF: 200e71b7053SJung-uk Kim case OPT_ERR: 201e71b7053SJung-uk Kim opthelp: 202e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 203e71b7053SJung-uk Kim goto end; 204e71b7053SJung-uk Kim case OPT_HELP: 205e71b7053SJung-uk Kim opt_help(x509_options); 206e71b7053SJung-uk Kim ret = 0; 207e71b7053SJung-uk Kim goto end; 208e71b7053SJung-uk Kim case OPT_INFORM: 209e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) 210e71b7053SJung-uk Kim goto opthelp; 211e71b7053SJung-uk Kim break; 212e71b7053SJung-uk Kim case OPT_IN: 213e71b7053SJung-uk Kim infile = opt_arg(); 214e71b7053SJung-uk Kim break; 215e71b7053SJung-uk Kim case OPT_OUTFORM: 216e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) 217e71b7053SJung-uk Kim goto opthelp; 218e71b7053SJung-uk Kim break; 219e71b7053SJung-uk Kim case OPT_KEYFORM: 220*17f01e99SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyformat)) 221e71b7053SJung-uk Kim goto opthelp; 222e71b7053SJung-uk Kim break; 223e71b7053SJung-uk Kim case OPT_CAFORM: 224e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat)) 225e71b7053SJung-uk Kim goto opthelp; 226e71b7053SJung-uk Kim break; 227e71b7053SJung-uk Kim case OPT_CAKEYFORM: 228*17f01e99SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PDE, &CAkeyformat)) 229e71b7053SJung-uk Kim goto opthelp; 230e71b7053SJung-uk Kim break; 231e71b7053SJung-uk Kim case OPT_OUT: 232e71b7053SJung-uk Kim outfile = opt_arg(); 233e71b7053SJung-uk Kim break; 234e71b7053SJung-uk Kim case OPT_REQ: 23574664626SKris Kennaway reqfile = 1; 236e71b7053SJung-uk Kim break; 237e71b7053SJung-uk Kim 238e71b7053SJung-uk Kim case OPT_SIGOPT: 2391f13597dSJung-uk Kim if (!sigopts) 2401f13597dSJung-uk Kim sigopts = sk_OPENSSL_STRING_new_null(); 241e71b7053SJung-uk Kim if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) 242e71b7053SJung-uk Kim goto opthelp; 24374664626SKris Kennaway break; 244e71b7053SJung-uk Kim case OPT_DAYS: 245e71b7053SJung-uk Kim if (preserve_dates) 246e71b7053SJung-uk Kim goto opthelp; 247e71b7053SJung-uk Kim days = atoi(opt_arg()); 248e71b7053SJung-uk Kim break; 249e71b7053SJung-uk Kim case OPT_PASSIN: 250e71b7053SJung-uk Kim passinarg = opt_arg(); 251e71b7053SJung-uk Kim break; 252e71b7053SJung-uk Kim case OPT_EXTFILE: 253e71b7053SJung-uk Kim extfile = opt_arg(); 254e71b7053SJung-uk Kim break; 255e71b7053SJung-uk Kim case OPT_R_CASES: 256e71b7053SJung-uk Kim if (!opt_rand(o)) 25774664626SKris Kennaway goto end; 258e71b7053SJung-uk Kim break; 259e71b7053SJung-uk Kim case OPT_EXTENSIONS: 260e71b7053SJung-uk Kim extsect = opt_arg(); 261e71b7053SJung-uk Kim break; 262e71b7053SJung-uk Kim case OPT_SIGNKEY: 263e71b7053SJung-uk Kim keyfile = opt_arg(); 264e71b7053SJung-uk Kim sign_flag = ++num; 265e71b7053SJung-uk Kim break; 266e71b7053SJung-uk Kim case OPT_CA: 267e71b7053SJung-uk Kim CAfile = opt_arg(); 268e71b7053SJung-uk Kim CA_flag = ++num; 269e71b7053SJung-uk Kim break; 270e71b7053SJung-uk Kim case OPT_CAKEY: 271e71b7053SJung-uk Kim CAkeyfile = opt_arg(); 272e71b7053SJung-uk Kim break; 273e71b7053SJung-uk Kim case OPT_CASERIAL: 274e71b7053SJung-uk Kim CAserial = opt_arg(); 275e71b7053SJung-uk Kim break; 276e71b7053SJung-uk Kim case OPT_SET_SERIAL: 277e71b7053SJung-uk Kim if (sno != NULL) { 278e71b7053SJung-uk Kim BIO_printf(bio_err, "Serial number supplied twice\n"); 279e71b7053SJung-uk Kim goto opthelp; 28074664626SKris Kennaway } 281e71b7053SJung-uk Kim if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) 282e71b7053SJung-uk Kim goto opthelp; 283e71b7053SJung-uk Kim break; 284e71b7053SJung-uk Kim case OPT_FORCE_PUBKEY: 285e71b7053SJung-uk Kim fkeyfile = opt_arg(); 286e71b7053SJung-uk Kim break; 287e71b7053SJung-uk Kim case OPT_ADDTRUST: 288e71b7053SJung-uk Kim if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { 289e71b7053SJung-uk Kim BIO_printf(bio_err, 290e71b7053SJung-uk Kim "%s: Invalid trust object value %s\n", 291e71b7053SJung-uk Kim prog, opt_arg()); 292e71b7053SJung-uk Kim goto opthelp; 293e71b7053SJung-uk Kim } 294e71b7053SJung-uk Kim if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL) 295e71b7053SJung-uk Kim goto end; 296e71b7053SJung-uk Kim sk_ASN1_OBJECT_push(trust, objtmp); 297e71b7053SJung-uk Kim objtmp = NULL; 298e71b7053SJung-uk Kim trustout = 1; 299e71b7053SJung-uk Kim break; 300e71b7053SJung-uk Kim case OPT_ADDREJECT: 301e71b7053SJung-uk Kim if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { 302e71b7053SJung-uk Kim BIO_printf(bio_err, 303e71b7053SJung-uk Kim "%s: Invalid reject object value %s\n", 304e71b7053SJung-uk Kim prog, opt_arg()); 305e71b7053SJung-uk Kim goto opthelp; 306e71b7053SJung-uk Kim } 307e71b7053SJung-uk Kim if (reject == NULL 308e71b7053SJung-uk Kim && (reject = sk_ASN1_OBJECT_new_null()) == NULL) 309e71b7053SJung-uk Kim goto end; 310e71b7053SJung-uk Kim sk_ASN1_OBJECT_push(reject, objtmp); 311e71b7053SJung-uk Kim objtmp = NULL; 312e71b7053SJung-uk Kim trustout = 1; 313e71b7053SJung-uk Kim break; 314e71b7053SJung-uk Kim case OPT_SETALIAS: 315e71b7053SJung-uk Kim alias = opt_arg(); 316e71b7053SJung-uk Kim trustout = 1; 317e71b7053SJung-uk Kim break; 318e71b7053SJung-uk Kim case OPT_CERTOPT: 319e71b7053SJung-uk Kim if (!set_cert_ex(&certflag, opt_arg())) 320e71b7053SJung-uk Kim goto opthelp; 321e71b7053SJung-uk Kim break; 322e71b7053SJung-uk Kim case OPT_NAMEOPT: 323e71b7053SJung-uk Kim if (!set_nameopt(opt_arg())) 324e71b7053SJung-uk Kim goto opthelp; 325e71b7053SJung-uk Kim break; 326e71b7053SJung-uk Kim case OPT_ENGINE: 327e71b7053SJung-uk Kim e = setup_engine(opt_arg(), 0); 328e71b7053SJung-uk Kim break; 329e71b7053SJung-uk Kim case OPT_C: 330e71b7053SJung-uk Kim C = ++num; 331e71b7053SJung-uk Kim break; 332e71b7053SJung-uk Kim case OPT_EMAIL: 333e71b7053SJung-uk Kim email = ++num; 334e71b7053SJung-uk Kim break; 335e71b7053SJung-uk Kim case OPT_OCSP_URI: 336e71b7053SJung-uk Kim ocsp_uri = ++num; 337e71b7053SJung-uk Kim break; 338e71b7053SJung-uk Kim case OPT_SERIAL: 339e71b7053SJung-uk Kim serial = ++num; 340e71b7053SJung-uk Kim break; 341e71b7053SJung-uk Kim case OPT_NEXT_SERIAL: 342e71b7053SJung-uk Kim next_serial = ++num; 343e71b7053SJung-uk Kim break; 344e71b7053SJung-uk Kim case OPT_MODULUS: 345e71b7053SJung-uk Kim modulus = ++num; 346e71b7053SJung-uk Kim break; 347e71b7053SJung-uk Kim case OPT_PUBKEY: 348e71b7053SJung-uk Kim pubkey = ++num; 349e71b7053SJung-uk Kim break; 350e71b7053SJung-uk Kim case OPT_X509TOREQ: 351e71b7053SJung-uk Kim x509req = ++num; 352e71b7053SJung-uk Kim break; 353e71b7053SJung-uk Kim case OPT_TEXT: 354e71b7053SJung-uk Kim text = ++num; 355e71b7053SJung-uk Kim break; 356e71b7053SJung-uk Kim case OPT_SUBJECT: 357e71b7053SJung-uk Kim subject = ++num; 358e71b7053SJung-uk Kim break; 359e71b7053SJung-uk Kim case OPT_ISSUER: 360e71b7053SJung-uk Kim issuer = ++num; 361e71b7053SJung-uk Kim break; 362e71b7053SJung-uk Kim case OPT_FINGERPRINT: 363e71b7053SJung-uk Kim fingerprint = ++num; 364e71b7053SJung-uk Kim break; 365e71b7053SJung-uk Kim case OPT_HASH: 366e71b7053SJung-uk Kim subject_hash = ++num; 367e71b7053SJung-uk Kim break; 368e71b7053SJung-uk Kim case OPT_ISSUER_HASH: 369e71b7053SJung-uk Kim issuer_hash = ++num; 370e71b7053SJung-uk Kim break; 371e71b7053SJung-uk Kim case OPT_PURPOSE: 372e71b7053SJung-uk Kim pprint = ++num; 373e71b7053SJung-uk Kim break; 374e71b7053SJung-uk Kim case OPT_STARTDATE: 375e71b7053SJung-uk Kim startdate = ++num; 376e71b7053SJung-uk Kim break; 377e71b7053SJung-uk Kim case OPT_ENDDATE: 378e71b7053SJung-uk Kim enddate = ++num; 379e71b7053SJung-uk Kim break; 380e71b7053SJung-uk Kim case OPT_NOOUT: 381e71b7053SJung-uk Kim noout = ++num; 382e71b7053SJung-uk Kim break; 383e71b7053SJung-uk Kim case OPT_EXT: 384e71b7053SJung-uk Kim ext = ++num; 385e71b7053SJung-uk Kim exts = opt_arg(); 386e71b7053SJung-uk Kim break; 387e71b7053SJung-uk Kim case OPT_NOCERT: 388e71b7053SJung-uk Kim nocert = 1; 389e71b7053SJung-uk Kim break; 390e71b7053SJung-uk Kim case OPT_TRUSTOUT: 391e71b7053SJung-uk Kim trustout = 1; 392e71b7053SJung-uk Kim break; 393e71b7053SJung-uk Kim case OPT_CLRTRUST: 394e71b7053SJung-uk Kim clrtrust = ++num; 395e71b7053SJung-uk Kim break; 396e71b7053SJung-uk Kim case OPT_CLRREJECT: 397e71b7053SJung-uk Kim clrreject = ++num; 398e71b7053SJung-uk Kim break; 399e71b7053SJung-uk Kim case OPT_ALIAS: 400e71b7053SJung-uk Kim aliasout = ++num; 401e71b7053SJung-uk Kim break; 402e71b7053SJung-uk Kim case OPT_CACREATESERIAL: 403e71b7053SJung-uk Kim CA_createserial = ++num; 404e71b7053SJung-uk Kim break; 405e71b7053SJung-uk Kim case OPT_CLREXT: 406e71b7053SJung-uk Kim clrext = 1; 407e71b7053SJung-uk Kim break; 408e71b7053SJung-uk Kim case OPT_OCSPID: 409e71b7053SJung-uk Kim ocspid = ++num; 410e71b7053SJung-uk Kim break; 411e71b7053SJung-uk Kim case OPT_BADSIG: 412e71b7053SJung-uk Kim badsig = 1; 413e71b7053SJung-uk Kim break; 414e71b7053SJung-uk Kim #ifndef OPENSSL_NO_MD5 415e71b7053SJung-uk Kim case OPT_SUBJECT_HASH_OLD: 416e71b7053SJung-uk Kim subject_hash_old = ++num; 417e71b7053SJung-uk Kim break; 418e71b7053SJung-uk Kim case OPT_ISSUER_HASH_OLD: 419e71b7053SJung-uk Kim issuer_hash_old = ++num; 420e71b7053SJung-uk Kim break; 421e71b7053SJung-uk Kim #else 422e71b7053SJung-uk Kim case OPT_SUBJECT_HASH_OLD: 423e71b7053SJung-uk Kim case OPT_ISSUER_HASH_OLD: 424e71b7053SJung-uk Kim break; 425e71b7053SJung-uk Kim #endif 426e71b7053SJung-uk Kim case OPT_DATES: 427e71b7053SJung-uk Kim startdate = ++num; 428e71b7053SJung-uk Kim enddate = ++num; 429e71b7053SJung-uk Kim break; 430e71b7053SJung-uk Kim case OPT_CHECKEND: 431e71b7053SJung-uk Kim checkend = 1; 432e71b7053SJung-uk Kim { 433e71b7053SJung-uk Kim intmax_t temp = 0; 434e71b7053SJung-uk Kim if (!opt_imax(opt_arg(), &temp)) 435e71b7053SJung-uk Kim goto opthelp; 436e71b7053SJung-uk Kim checkoffset = (time_t)temp; 437e71b7053SJung-uk Kim if ((intmax_t)checkoffset != temp) { 438e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: checkend time out of range %s\n", 439e71b7053SJung-uk Kim prog, opt_arg()); 440e71b7053SJung-uk Kim goto opthelp; 441e71b7053SJung-uk Kim } 442e71b7053SJung-uk Kim } 443e71b7053SJung-uk Kim break; 444e71b7053SJung-uk Kim case OPT_CHECKHOST: 445e71b7053SJung-uk Kim checkhost = opt_arg(); 446e71b7053SJung-uk Kim break; 447e71b7053SJung-uk Kim case OPT_CHECKEMAIL: 448e71b7053SJung-uk Kim checkemail = opt_arg(); 449e71b7053SJung-uk Kim break; 450e71b7053SJung-uk Kim case OPT_CHECKIP: 451e71b7053SJung-uk Kim checkip = opt_arg(); 452e71b7053SJung-uk Kim break; 453e71b7053SJung-uk Kim case OPT_PRESERVE_DATES: 454e71b7053SJung-uk Kim if (days != DEF_DAYS) 455e71b7053SJung-uk Kim goto opthelp; 456e71b7053SJung-uk Kim preserve_dates = 1; 457e71b7053SJung-uk Kim break; 458e71b7053SJung-uk Kim case OPT_MD: 459e71b7053SJung-uk Kim if (!opt_md(opt_unknown(), &digest)) 460e71b7053SJung-uk Kim goto opthelp; 461e71b7053SJung-uk Kim } 462e71b7053SJung-uk Kim } 463e71b7053SJung-uk Kim argc = opt_num_rest(); 464e71b7053SJung-uk Kim argv = opt_rest(); 465e71b7053SJung-uk Kim if (argc != 0) { 466e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]); 467e71b7053SJung-uk Kim goto opthelp; 468e71b7053SJung-uk Kim } 4695c87c606SMark Murray 470e71b7053SJung-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 480e71b7053SJung-uk Kim if (fkeyfile != NULL) { 481e71b7053SJung-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 494e71b7053SJung-uk Kim if (extfile != NULL) { 49574664626SKris Kennaway X509V3_CTX ctx2; 496e71b7053SJung-uk Kim if ((extconf = app_load_config(extfile)) == NULL) 49774664626SKris Kennaway goto end; 498e71b7053SJung-uk Kim if (extsect == NULL) { 4995c87c606SMark Murray extsect = NCONF_get_string(extconf, "default", "extensions"); 500e71b7053SJung-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 } 523e71b7053SJung-uk Kim in = bio_open_default(infile, 'r', informat); 524e71b7053SJung-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 534e71b7053SJung-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; 548e71b7053SJung-uk Kim } else { 54974664626SKris Kennaway BIO_printf(bio_err, "Signature ok\n"); 550e71b7053SJung-uk Kim } 55174664626SKris Kennaway 5526f9291ceSJung-uk Kim print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), 553e71b7053SJung-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(); 560e71b7053SJung-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; 566e71b7053SJung-uk Kim } else if (!X509_set_serialNumber(x, sno)) { 5673b4e3dcbSSimon L. B. Nielsen goto end; 5687bded2dbSJung-uk Kim } 569e71b7053SJung-uk Kim 570e71b7053SJung-uk Kim if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req))) 571e71b7053SJung-uk Kim goto end; 572e71b7053SJung-uk Kim if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req))) 573e71b7053SJung-uk Kim goto end; 574e71b7053SJung-uk Kim if (!set_cert_times(x, NULL, NULL, days)) 575e71b7053SJung-uk Kim goto end; 576e71b7053SJung-uk Kim 577e71b7053SJung-uk Kim if (fkey != NULL) { 578e71b7053SJung-uk Kim X509_set_pubkey(x, fkey); 579e71b7053SJung-uk Kim } else { 580e71b7053SJung-uk Kim pkey = X509_REQ_get0_pubkey(req); 581e71b7053SJung-uk Kim X509_set_pubkey(x, pkey); 582e71b7053SJung-uk Kim } 583e71b7053SJung-uk Kim } else { 584e71b7053SJung-uk Kim x = load_cert(infile, informat, "Certificate"); 585e71b7053SJung-uk Kim } 58674664626SKris Kennaway 5876f9291ceSJung-uk Kim if (x == NULL) 5886f9291ceSJung-uk Kim goto end; 5896f9291ceSJung-uk Kim if (CA_flag) { 590e71b7053SJung-uk Kim xca = load_cert(CAfile, CAformat, "CA Certificate"); 5916f9291ceSJung-uk Kim if (xca == NULL) 5926f9291ceSJung-uk Kim goto end; 59374664626SKris Kennaway } 59474664626SKris Kennaway 595e71b7053SJung-uk Kim out = bio_open_default(outfile, 'w', outformat); 596e71b7053SJung-uk Kim if (out == NULL) 597e71b7053SJung-uk Kim goto end; 59874664626SKris Kennaway 599e71b7053SJung-uk Kim if (!noout || text || next_serial) 600e71b7053SJung-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 610e71b7053SJung-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 } 615e71b7053SJung-uk Kim objtmp = NULL; 616f579bf8eSKris Kennaway } 617f579bf8eSKris Kennaway 618e71b7053SJung-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 } 623e71b7053SJung-uk Kim objtmp = NULL; 624e71b7053SJung-uk Kim } 625e71b7053SJung-uk Kim 626e71b7053SJung-uk Kim if (badsig) { 627e71b7053SJung-uk Kim const ASN1_BIT_STRING *signature; 628e71b7053SJung-uk Kim 629e71b7053SJung-uk Kim X509_get0_signature(&signature, NULL, x); 630e71b7053SJung-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) { 636e71b7053SJung-uk Kim print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt()); 6376f9291ceSJung-uk Kim } else if (subject == i) { 638e71b7053SJung-uk Kim print_name(out, "subject=", 639e71b7053SJung-uk Kim X509_get_subject_name(x), get_nameopt()); 6406f9291ceSJung-uk Kim } else if (serial == i) { 641e71b7053SJung-uk Kim BIO_printf(out, "serial="); 642e71b7053SJung-uk Kim i2a_ASN1_INTEGER(out, X509_get_serialNumber(x)); 643e71b7053SJung-uk Kim BIO_printf(out, "\n"); 6446f9291ceSJung-uk Kim } else if (next_serial == i) { 645e71b7053SJung-uk Kim ASN1_INTEGER *ser = X509_get_serialNumber(x); 646e71b7053SJung-uk Kim BIGNUM *bnser = ASN1_INTEGER_to_BN(ser, NULL); 647e71b7053SJung-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++) 667e71b7053SJung-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) 674e71b7053SJung-uk Kim BIO_printf(out, "%s\n", alstr); 6756f9291ceSJung-uk Kim else 676e71b7053SJung-uk Kim BIO_puts(out, "<No Alias>\n"); 6776f9291ceSJung-uk Kim } else if (subject_hash == i) { 678e71b7053SJung-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) { 682e71b7053SJung-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) { 686e71b7053SJung-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) { 690e71b7053SJung-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; 696e71b7053SJung-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); 699e71b7053SJung-uk Kim purpose_print(out, x, ptmp); 700f579bf8eSKris Kennaway } 7016f9291ceSJung-uk Kim } else if (modulus == i) { 70274664626SKris Kennaway EVP_PKEY *pkey; 70374664626SKris Kennaway 704e71b7053SJung-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 } 710e71b7053SJung-uk Kim BIO_printf(out, "Modulus="); 7115c87c606SMark Murray #ifndef OPENSSL_NO_RSA 712e71b7053SJung-uk Kim if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { 713e71b7053SJung-uk Kim const BIGNUM *n; 714e71b7053SJung-uk Kim RSA_get0_key(EVP_PKEY_get0_RSA(pkey), &n, NULL, NULL); 715e71b7053SJung-uk Kim BN_print(out, n); 716e71b7053SJung-uk Kim } else 71774664626SKris Kennaway #endif 7185c87c606SMark Murray #ifndef OPENSSL_NO_DSA 719e71b7053SJung-uk Kim if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) { 720e71b7053SJung-uk Kim const BIGNUM *dsapub = NULL; 721e71b7053SJung-uk Kim DSA_get0_key(EVP_PKEY_get0_DSA(pkey), &dsapub, NULL); 722e71b7053SJung-uk Kim BN_print(out, dsapub); 723e71b7053SJung-uk Kim } else 72474664626SKris Kennaway #endif 725e71b7053SJung-uk Kim { 726e71b7053SJung-uk Kim BIO_printf(out, "Wrong Algorithm type"); 727e71b7053SJung-uk Kim } 728e71b7053SJung-uk Kim BIO_printf(out, "\n"); 7296f9291ceSJung-uk Kim } else if (pubkey == i) { 730f579bf8eSKris Kennaway EVP_PKEY *pkey; 731f579bf8eSKris Kennaway 732e71b7053SJung-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 } 738e71b7053SJung-uk Kim PEM_write_bio_PUBKEY(out, pkey); 7396f9291ceSJung-uk Kim } else if (C == i) { 74074664626SKris Kennaway unsigned char *d; 74174664626SKris Kennaway char *m; 742e71b7053SJung-uk Kim int len; 74374664626SKris Kennaway 744e71b7053SJung-uk Kim print_name(out, "/*\n" 745e71b7053SJung-uk Kim " * Subject: ", X509_get_subject_name(x), get_nameopt()); 746e71b7053SJung-uk Kim print_name(out, " * Issuer: ", X509_get_issuer_name(x), get_nameopt()); 747e71b7053SJung-uk Kim BIO_puts(out, " */\n"); 74874664626SKris Kennaway 749e71b7053SJung-uk Kim len = i2d_X509(x, NULL); 750e71b7053SJung-uk Kim m = app_malloc(len, "x509 name buffer"); 75174664626SKris Kennaway d = (unsigned char *)m; 752e71b7053SJung-uk Kim len = i2d_X509_NAME(X509_get_subject_name(x), &d); 753e71b7053SJung-uk Kim print_array(out, "the_subject_name", len, (unsigned char *)m); 75474664626SKris Kennaway d = (unsigned char *)m; 755e71b7053SJung-uk Kim len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d); 756e71b7053SJung-uk Kim print_array(out, "the_public_key", len, (unsigned char *)m); 75774664626SKris Kennaway d = (unsigned char *)m; 758e71b7053SJung-uk Kim len = i2d_X509(x, &d); 759e71b7053SJung-uk Kim print_array(out, "the_certificate", len, (unsigned char *)m); 760ddd58736SKris Kennaway OPENSSL_free(m); 7616f9291ceSJung-uk Kim } else if (text == i) { 762e71b7053SJung-uk Kim X509_print_ex(out, x, get_nameopt(), certflag); 7636f9291ceSJung-uk Kim } else if (startdate == i) { 764e71b7053SJung-uk Kim BIO_puts(out, "notBefore="); 765e71b7053SJung-uk Kim ASN1_TIME_print(out, X509_get0_notBefore(x)); 766e71b7053SJung-uk Kim BIO_puts(out, "\n"); 7676f9291ceSJung-uk Kim } else if (enddate == i) { 768e71b7053SJung-uk Kim BIO_puts(out, "notAfter="); 769e71b7053SJung-uk Kim ASN1_TIME_print(out, X509_get0_notAfter(x)); 770e71b7053SJung-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 777e71b7053SJung-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 } 784e71b7053SJung-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++) { 787e71b7053SJung-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) { 796e71b7053SJung-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 802e71b7053SJung-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) { 807e71b7053SJung-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, 816e71b7053SJung-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 { 826e71b7053SJung-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) { 841e71b7053SJung-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); 847e71b7053SJung-uk Kim } else if (ext == i) { 848e71b7053SJung-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 856e71b7053SJung-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 866e71b7053SJung-uk Kim print_cert_checks(out, x, checkhost, checkemail, checkip); 8677bded2dbSJung-uk Kim 868e71b7053SJung-uk Kim if (noout || nocert) { 86974664626SKris Kennaway ret = 0; 87074664626SKris Kennaway goto end; 87174664626SKris Kennaway } 87274664626SKris Kennaway 873e71b7053SJung-uk Kim if (outformat == FORMAT_ASN1) { 87474664626SKris Kennaway i = i2d_X509_bio(out, x); 875e71b7053SJung-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); 905e71b7053SJung-uk Kim ASN1_OBJECT_free(objtmp); 9066cf8931aSJung-uk Kim release_engine(e); 9076f9291ceSJung-uk Kim OPENSSL_free(passin); 908e71b7053SJung-uk Kim return ret; 90974664626SKris Kennaway } 91074664626SKris Kennaway 911e71b7053SJung-uk Kim static ASN1_INTEGER *x509_load_serial(const char *CAfile, 912e71b7053SJung-uk Kim const char *serialfile, int create) 91374664626SKris Kennaway { 914e71b7053SJung-uk Kim char *buf = NULL; 915ced566fdSJacques Vidrine ASN1_INTEGER *bs = NULL; 91674664626SKris Kennaway BIGNUM *serial = NULL; 91774664626SKris Kennaway 9186f9291ceSJung-uk Kim if (serialfile == NULL) { 919e71b7053SJung-uk Kim const char *p = strrchr(CAfile, '.'); 920e71b7053SJung-uk Kim size_t len = p != NULL ? (size_t)(p - CAfile) : strlen(CAfile); 92174664626SKris Kennaway 922e71b7053SJung-uk Kim buf = app_malloc(len + sizeof(POSTFIX), "serial# buffer"); 923e71b7053SJung-uk Kim memcpy(buf, CAfile, len); 924e71b7053SJung-uk Kim memcpy(buf + len, POSTFIX, sizeof(POSTFIX)); 925e71b7053SJung-uk Kim serialfile = buf; 926e71b7053SJung-uk Kim } 927e71b7053SJung-uk Kim 928e71b7053SJung-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 937e71b7053SJung-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 946e71b7053SJung-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, 949e71b7053SJung-uk Kim const char *serialfile, int create, 950e71b7053SJung-uk Kim int days, int clrext, CONF *conf, const char *section, 951e71b7053SJung-uk Kim ASN1_INTEGER *sno, int reqfile, int preserve_dates) 9525c87c606SMark Murray { 9535c87c606SMark Murray int ret = 0; 9545c87c606SMark Murray ASN1_INTEGER *bs = NULL; 955e71b7053SJung-uk Kim X509_STORE_CTX *xsc = NULL; 9565c87c606SMark Murray EVP_PKEY *upkey; 9575c87c606SMark Murray 958e71b7053SJung-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 965e71b7053SJung-uk Kim xsc = X509_STORE_CTX_new(); 966e71b7053SJung-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; 972e71b7053SJung-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 */ 979e71b7053SJung-uk Kim X509_STORE_CTX_set_cert(xsc, x); 980e71b7053SJung-uk Kim X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); 981e71b7053SJung-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 995e71b7053SJung-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 1003e71b7053SJung-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 1012e71b7053SJung-uk Kim if (!do_X509_sign(x, pkey, digest, sigopts)) 10131f13597dSJung-uk Kim goto end; 101474664626SKris Kennaway ret = 1; 101574664626SKris Kennaway end: 1016e71b7053SJung-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 1024e71b7053SJung-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, 1059e71b7053SJung-uk Kim const EVP_MD *digest, CONF *conf, const char *section, 1060e71b7053SJung-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; 1065e71b7053SJung-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 } 1073e71b7053SJung-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; 1092e71b7053SJung-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 } 1107e71b7053SJung-uk Kim 1108e71b7053SJung-uk Kim static int parse_ext_names(char *names, const char **result) 1109e71b7053SJung-uk Kim { 1110e71b7053SJung-uk Kim char *p, *q; 1111e71b7053SJung-uk Kim int cnt = 0, len = 0; 1112e71b7053SJung-uk Kim 1113e71b7053SJung-uk Kim p = q = names; 1114e71b7053SJung-uk Kim len = strlen(names); 1115e71b7053SJung-uk Kim 1116e71b7053SJung-uk Kim while (q - names <= len) { 1117e71b7053SJung-uk Kim if (*q != ',' && *q != '\0') { 1118e71b7053SJung-uk Kim q++; 1119e71b7053SJung-uk Kim continue; 1120e71b7053SJung-uk Kim } 1121e71b7053SJung-uk Kim if (p != q) { 1122e71b7053SJung-uk Kim /* found */ 1123e71b7053SJung-uk Kim if (result != NULL) { 1124e71b7053SJung-uk Kim result[cnt] = p; 1125e71b7053SJung-uk Kim *q = '\0'; 1126e71b7053SJung-uk Kim } 1127e71b7053SJung-uk Kim cnt++; 1128e71b7053SJung-uk Kim } 1129e71b7053SJung-uk Kim p = ++q; 1130e71b7053SJung-uk Kim } 1131e71b7053SJung-uk Kim 1132e71b7053SJung-uk Kim return cnt; 1133e71b7053SJung-uk Kim } 1134e71b7053SJung-uk Kim 1135e71b7053SJung-uk Kim static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names) 1136e71b7053SJung-uk Kim { 1137e71b7053SJung-uk Kim const STACK_OF(X509_EXTENSION) *exts = NULL; 1138e71b7053SJung-uk Kim STACK_OF(X509_EXTENSION) *exts2 = NULL; 1139e71b7053SJung-uk Kim X509_EXTENSION *ext = NULL; 1140e71b7053SJung-uk Kim ASN1_OBJECT *obj; 1141e71b7053SJung-uk Kim int i, j, ret = 0, num, nn = 0; 1142e71b7053SJung-uk Kim const char *sn, **names = NULL; 1143e71b7053SJung-uk Kim char *tmp_ext_names = NULL; 1144e71b7053SJung-uk Kim 1145e71b7053SJung-uk Kim exts = X509_get0_extensions(x); 1146e71b7053SJung-uk Kim if ((num = sk_X509_EXTENSION_num(exts)) <= 0) { 1147e71b7053SJung-uk Kim BIO_printf(bio, "No extensions in certificate\n"); 1148e71b7053SJung-uk Kim ret = 1; 1149e71b7053SJung-uk Kim goto end; 1150e71b7053SJung-uk Kim } 1151e71b7053SJung-uk Kim 1152e71b7053SJung-uk Kim /* parse comma separated ext name string */ 1153e71b7053SJung-uk Kim if ((tmp_ext_names = OPENSSL_strdup(ext_names)) == NULL) 1154e71b7053SJung-uk Kim goto end; 1155e71b7053SJung-uk Kim if ((nn = parse_ext_names(tmp_ext_names, NULL)) == 0) { 1156e71b7053SJung-uk Kim BIO_printf(bio, "Invalid extension names: %s\n", ext_names); 1157e71b7053SJung-uk Kim goto end; 1158e71b7053SJung-uk Kim } 1159e71b7053SJung-uk Kim if ((names = OPENSSL_malloc(sizeof(char *) * nn)) == NULL) 1160e71b7053SJung-uk Kim goto end; 1161e71b7053SJung-uk Kim parse_ext_names(tmp_ext_names, names); 1162e71b7053SJung-uk Kim 1163e71b7053SJung-uk Kim for (i = 0; i < num; i++) { 1164e71b7053SJung-uk Kim ext = sk_X509_EXTENSION_value(exts, i); 1165e71b7053SJung-uk Kim 1166e71b7053SJung-uk Kim /* check if this ext is what we want */ 1167e71b7053SJung-uk Kim obj = X509_EXTENSION_get_object(ext); 1168e71b7053SJung-uk Kim sn = OBJ_nid2sn(OBJ_obj2nid(obj)); 1169e71b7053SJung-uk Kim if (sn == NULL || strcmp(sn, "UNDEF") == 0) 1170e71b7053SJung-uk Kim continue; 1171e71b7053SJung-uk Kim 1172e71b7053SJung-uk Kim for (j = 0; j < nn; j++) { 1173e71b7053SJung-uk Kim if (strcmp(sn, names[j]) == 0) { 1174e71b7053SJung-uk Kim /* push the extension into a new stack */ 1175e71b7053SJung-uk Kim if (exts2 == NULL 1176e71b7053SJung-uk Kim && (exts2 = sk_X509_EXTENSION_new_null()) == NULL) 1177e71b7053SJung-uk Kim goto end; 1178e71b7053SJung-uk Kim if (!sk_X509_EXTENSION_push(exts2, ext)) 1179e71b7053SJung-uk Kim goto end; 1180e71b7053SJung-uk Kim } 1181e71b7053SJung-uk Kim } 1182e71b7053SJung-uk Kim } 1183e71b7053SJung-uk Kim 1184e71b7053SJung-uk Kim if (!sk_X509_EXTENSION_num(exts2)) { 1185e71b7053SJung-uk Kim BIO_printf(bio, "No extensions matched with %s\n", ext_names); 1186e71b7053SJung-uk Kim ret = 1; 1187e71b7053SJung-uk Kim goto end; 1188e71b7053SJung-uk Kim } 1189e71b7053SJung-uk Kim 1190e71b7053SJung-uk Kim ret = X509V3_extensions_print(bio, NULL, exts2, 0, 0); 1191e71b7053SJung-uk Kim end: 1192e71b7053SJung-uk Kim sk_X509_EXTENSION_free(exts2); 1193e71b7053SJung-uk Kim OPENSSL_free(names); 1194e71b7053SJung-uk Kim OPENSSL_free(tmp_ext_names); 1195e71b7053SJung-uk Kim return ret; 1196e71b7053SJung-uk Kim } 1197