1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include <stdlib.h> 12e1051a39Sopenharmony_ci#include <string.h> 13e1051a39Sopenharmony_ci#include "apps.h" 14e1051a39Sopenharmony_ci#include "progs.h" 15e1051a39Sopenharmony_ci#include <openssl/bio.h> 16e1051a39Sopenharmony_ci#include <openssl/asn1.h> 17e1051a39Sopenharmony_ci#include <openssl/err.h> 18e1051a39Sopenharmony_ci#include <openssl/bn.h> 19e1051a39Sopenharmony_ci#include <openssl/evp.h> 20e1051a39Sopenharmony_ci#include <openssl/x509.h> 21e1051a39Sopenharmony_ci#include <openssl/x509v3.h> 22e1051a39Sopenharmony_ci#include <openssl/objects.h> 23e1051a39Sopenharmony_ci#include <openssl/pem.h> 24e1051a39Sopenharmony_ci#include <openssl/rsa.h> 25e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA 26e1051a39Sopenharmony_ci# include <openssl/dsa.h> 27e1051a39Sopenharmony_ci#endif 28e1051a39Sopenharmony_ci 29e1051a39Sopenharmony_ci#undef POSTFIX 30e1051a39Sopenharmony_ci#define POSTFIX ".srl" 31e1051a39Sopenharmony_ci#define DEFAULT_DAYS 30 /* default cert validity period in days */ 32e1051a39Sopenharmony_ci#define UNSET_DAYS -2 /* -1 is used for testing expiration checks */ 33e1051a39Sopenharmony_ci#define EXT_COPY_UNSET -1 34e1051a39Sopenharmony_ci 35e1051a39Sopenharmony_cistatic int callb(int ok, X509_STORE_CTX *ctx); 36e1051a39Sopenharmony_cistatic ASN1_INTEGER *x509_load_serial(const char *CAfile, 37e1051a39Sopenharmony_ci const char *serialfile, int create); 38e1051a39Sopenharmony_cistatic int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt); 39e1051a39Sopenharmony_cistatic int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names); 40e1051a39Sopenharmony_ci 41e1051a39Sopenharmony_citypedef enum OPTION_choice { 42e1051a39Sopenharmony_ci OPT_COMMON, 43e1051a39Sopenharmony_ci OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM, 44e1051a39Sopenharmony_ci OPT_CAKEYFORM, OPT_VFYOPT, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE, 45e1051a39Sopenharmony_ci OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_KEY, OPT_SIGNKEY, OPT_CA, OPT_CAKEY, 46e1051a39Sopenharmony_ci OPT_CASERIAL, OPT_SET_SERIAL, OPT_NEW, OPT_FORCE_PUBKEY, OPT_SUBJ, 47e1051a39Sopenharmony_ci OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_DATEOPT, OPT_NAMEOPT, 48e1051a39Sopenharmony_ci OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL, 49e1051a39Sopenharmony_ci OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH, 50e1051a39Sopenharmony_ci OPT_ISSUER_HASH, OPT_SUBJECT, OPT_ISSUER, OPT_FINGERPRINT, OPT_DATES, 51e1051a39Sopenharmony_ci OPT_PURPOSE, OPT_STARTDATE, OPT_ENDDATE, OPT_CHECKEND, OPT_CHECKHOST, 52e1051a39Sopenharmony_ci OPT_CHECKEMAIL, OPT_CHECKIP, OPT_NOOUT, OPT_TRUSTOUT, OPT_CLRTRUST, 53e1051a39Sopenharmony_ci OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID, 54e1051a39Sopenharmony_ci OPT_SUBJECT_HASH_OLD, OPT_ISSUER_HASH_OLD, OPT_COPY_EXTENSIONS, 55e1051a39Sopenharmony_ci OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES, 56e1051a39Sopenharmony_ci OPT_R_ENUM, OPT_PROV_ENUM, OPT_EXT 57e1051a39Sopenharmony_ci} OPTION_CHOICE; 58e1051a39Sopenharmony_ci 59e1051a39Sopenharmony_ciconst OPTIONS x509_options[] = { 60e1051a39Sopenharmony_ci OPT_SECTION("General"), 61e1051a39Sopenharmony_ci {"help", OPT_HELP, '-', "Display this summary"}, 62e1051a39Sopenharmony_ci 63e1051a39Sopenharmony_ci {"in", OPT_IN, '<', 64e1051a39Sopenharmony_ci "Certificate input, or CSR input file with -req (default stdin)"}, 65e1051a39Sopenharmony_ci {"passin", OPT_PASSIN, 's', "Private key and cert file pass-phrase source"}, 66e1051a39Sopenharmony_ci {"new", OPT_NEW, '-', "Generate a certificate from scratch"}, 67e1051a39Sopenharmony_ci {"x509toreq", OPT_X509TOREQ, '-', 68e1051a39Sopenharmony_ci "Output a certification request (rather than a certificate)"}, 69e1051a39Sopenharmony_ci {"req", OPT_REQ, '-', "Input is a CSR file (rather than a certificate)"}, 70e1051a39Sopenharmony_ci {"copy_extensions", OPT_COPY_EXTENSIONS, 's', 71e1051a39Sopenharmony_ci "copy extensions when converting from CSR to x509 or vice versa"}, 72e1051a39Sopenharmony_ci {"inform", OPT_INFORM, 'f', 73e1051a39Sopenharmony_ci "CSR input file format (DER or PEM) - default PEM"}, 74e1051a39Sopenharmony_ci {"vfyopt", OPT_VFYOPT, 's', "CSR verification parameter in n:v form"}, 75e1051a39Sopenharmony_ci {"key", OPT_KEY, 's', 76e1051a39Sopenharmony_ci "Key for signing, and to include unless using -force_pubkey"}, 77e1051a39Sopenharmony_ci {"signkey", OPT_SIGNKEY, 's', 78e1051a39Sopenharmony_ci "Same as -key"}, 79e1051a39Sopenharmony_ci {"keyform", OPT_KEYFORM, 'E', 80e1051a39Sopenharmony_ci "Key input format (ENGINE, other values ignored)"}, 81e1051a39Sopenharmony_ci {"out", OPT_OUT, '>', "Output file - default stdout"}, 82e1051a39Sopenharmony_ci {"outform", OPT_OUTFORM, 'f', 83e1051a39Sopenharmony_ci "Output format (DER or PEM) - default PEM"}, 84e1051a39Sopenharmony_ci {"nocert", OPT_NOCERT, '-', 85e1051a39Sopenharmony_ci "No cert output (except for requested printing)"}, 86e1051a39Sopenharmony_ci {"noout", OPT_NOOUT, '-', "No output (except for requested printing)"}, 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_ci OPT_SECTION("Certificate printing"), 89e1051a39Sopenharmony_ci {"text", OPT_TEXT, '-', "Print the certificate in text form"}, 90e1051a39Sopenharmony_ci {"dateopt", OPT_DATEOPT, 's', "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."}, 91e1051a39Sopenharmony_ci {"certopt", OPT_CERTOPT, 's', "Various certificate text printing options"}, 92e1051a39Sopenharmony_ci {"fingerprint", OPT_FINGERPRINT, '-', "Print the certificate fingerprint"}, 93e1051a39Sopenharmony_ci {"alias", OPT_ALIAS, '-', "Print certificate alias"}, 94e1051a39Sopenharmony_ci {"serial", OPT_SERIAL, '-', "Print serial number value"}, 95e1051a39Sopenharmony_ci {"startdate", OPT_STARTDATE, '-', "Print the notBefore field"}, 96e1051a39Sopenharmony_ci {"enddate", OPT_ENDDATE, '-', "Print the notAfter field"}, 97e1051a39Sopenharmony_ci {"dates", OPT_DATES, '-', "Print both notBefore and notAfter fields"}, 98e1051a39Sopenharmony_ci {"subject", OPT_SUBJECT, '-', "Print subject DN"}, 99e1051a39Sopenharmony_ci {"issuer", OPT_ISSUER, '-', "Print issuer DN"}, 100e1051a39Sopenharmony_ci {"nameopt", OPT_NAMEOPT, 's', 101e1051a39Sopenharmony_ci "Certificate subject/issuer name printing options"}, 102e1051a39Sopenharmony_ci {"email", OPT_EMAIL, '-', "Print email address(es)"}, 103e1051a39Sopenharmony_ci {"hash", OPT_HASH, '-', "Synonym for -subject_hash (for backward compat)"}, 104e1051a39Sopenharmony_ci {"subject_hash", OPT_HASH, '-', "Print subject hash value"}, 105e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_MD5 106e1051a39Sopenharmony_ci {"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-', 107e1051a39Sopenharmony_ci "Print old-style (MD5) subject hash value"}, 108e1051a39Sopenharmony_ci#endif 109e1051a39Sopenharmony_ci {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"}, 110e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_MD5 111e1051a39Sopenharmony_ci {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-', 112e1051a39Sopenharmony_ci "Print old-style (MD5) issuer hash value"}, 113e1051a39Sopenharmony_ci#endif 114e1051a39Sopenharmony_ci {"ext", OPT_EXT, 's', 115e1051a39Sopenharmony_ci "Restrict which X.509 extensions to print and/or copy"}, 116e1051a39Sopenharmony_ci {"ocspid", OPT_OCSPID, '-', 117e1051a39Sopenharmony_ci "Print OCSP hash values for the subject name and public key"}, 118e1051a39Sopenharmony_ci {"ocsp_uri", OPT_OCSP_URI, '-', "Print OCSP Responder URL(s)"}, 119e1051a39Sopenharmony_ci {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"}, 120e1051a39Sopenharmony_ci {"pubkey", OPT_PUBKEY, '-', "Print the public key in PEM format"}, 121e1051a39Sopenharmony_ci {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"}, 122e1051a39Sopenharmony_ci 123e1051a39Sopenharmony_ci OPT_SECTION("Certificate checking"), 124e1051a39Sopenharmony_ci {"checkend", OPT_CHECKEND, 'M', 125e1051a39Sopenharmony_ci "Check whether cert expires in the next arg seconds"}, 126e1051a39Sopenharmony_ci {OPT_MORE_STR, 1, 1, "Exit 1 (failure) if so, 0 if not"}, 127e1051a39Sopenharmony_ci {"checkhost", OPT_CHECKHOST, 's', "Check certificate matches host"}, 128e1051a39Sopenharmony_ci {"checkemail", OPT_CHECKEMAIL, 's', "Check certificate matches email"}, 129e1051a39Sopenharmony_ci {"checkip", OPT_CHECKIP, 's', "Check certificate matches ipaddr"}, 130e1051a39Sopenharmony_ci 131e1051a39Sopenharmony_ci OPT_SECTION("Certificate output"), 132e1051a39Sopenharmony_ci {"set_serial", OPT_SET_SERIAL, 's', 133e1051a39Sopenharmony_ci "Serial number to use, overrides -CAserial"}, 134e1051a39Sopenharmony_ci {"next_serial", OPT_NEXT_SERIAL, '-', 135e1051a39Sopenharmony_ci "Increment current certificate serial number"}, 136e1051a39Sopenharmony_ci {"days", OPT_DAYS, 'n', 137e1051a39Sopenharmony_ci "Number of days until newly generated certificate expires - default 30"}, 138e1051a39Sopenharmony_ci {"preserve_dates", OPT_PRESERVE_DATES, '-', 139e1051a39Sopenharmony_ci "Preserve existing validity dates"}, 140e1051a39Sopenharmony_ci {"subj", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"}, 141e1051a39Sopenharmony_ci {"force_pubkey", OPT_FORCE_PUBKEY, '<', 142e1051a39Sopenharmony_ci "Place the given key in new certificate"}, 143e1051a39Sopenharmony_ci {"clrext", OPT_CLREXT, '-', 144e1051a39Sopenharmony_ci "Do not take over any extensions from the source certificate or request"}, 145e1051a39Sopenharmony_ci {"extfile", OPT_EXTFILE, '<', "Config file with X509V3 extensions to add"}, 146e1051a39Sopenharmony_ci {"extensions", OPT_EXTENSIONS, 's', 147e1051a39Sopenharmony_ci "Section of extfile to use - default: unnamed section"}, 148e1051a39Sopenharmony_ci {"sigopt", OPT_SIGOPT, 's', "Signature parameter, in n:v form"}, 149e1051a39Sopenharmony_ci {"badsig", OPT_BADSIG, '-', 150e1051a39Sopenharmony_ci "Corrupt last byte of certificate signature (for test)"}, 151e1051a39Sopenharmony_ci {"", OPT_MD, '-', "Any supported digest, used for signing and printing"}, 152e1051a39Sopenharmony_ci 153e1051a39Sopenharmony_ci OPT_SECTION("Micro-CA"), 154e1051a39Sopenharmony_ci {"CA", OPT_CA, '<', 155e1051a39Sopenharmony_ci "Use the given CA certificate, conflicts with -key"}, 156e1051a39Sopenharmony_ci {"CAform", OPT_CAFORM, 'F', "CA cert format (PEM/DER/P12); has no effect"}, 157e1051a39Sopenharmony_ci {"CAkey", OPT_CAKEY, 's', "The corresponding CA key; default is -CA arg"}, 158e1051a39Sopenharmony_ci {"CAkeyform", OPT_CAKEYFORM, 'E', 159e1051a39Sopenharmony_ci "CA key format (ENGINE, other values ignored)"}, 160e1051a39Sopenharmony_ci {"CAserial", OPT_CASERIAL, 's', 161e1051a39Sopenharmony_ci "File that keeps track of CA-generated serial number"}, 162e1051a39Sopenharmony_ci {"CAcreateserial", OPT_CACREATESERIAL, '-', 163e1051a39Sopenharmony_ci "Create CA serial number file if it does not exist"}, 164e1051a39Sopenharmony_ci 165e1051a39Sopenharmony_ci OPT_SECTION("Certificate trust output"), 166e1051a39Sopenharmony_ci {"trustout", OPT_TRUSTOUT, '-', "Mark certificate PEM output as trusted"}, 167e1051a39Sopenharmony_ci {"setalias", OPT_SETALIAS, 's', "Set certificate alias (nickname)"}, 168e1051a39Sopenharmony_ci {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"}, 169e1051a39Sopenharmony_ci {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"}, 170e1051a39Sopenharmony_ci {"clrreject", OPT_CLRREJECT, '-', 171e1051a39Sopenharmony_ci "Clears all the prohibited or rejected uses of the certificate"}, 172e1051a39Sopenharmony_ci {"addreject", OPT_ADDREJECT, 's', 173e1051a39Sopenharmony_ci "Reject certificate for a given purpose"}, 174e1051a39Sopenharmony_ci 175e1051a39Sopenharmony_ci OPT_R_OPTIONS, 176e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE 177e1051a39Sopenharmony_ci {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 178e1051a39Sopenharmony_ci#endif 179e1051a39Sopenharmony_ci OPT_PROV_OPTIONS, 180e1051a39Sopenharmony_ci {NULL} 181e1051a39Sopenharmony_ci}; 182e1051a39Sopenharmony_ci 183e1051a39Sopenharmony_cistatic void warn_copying(ASN1_OBJECT *excluded, const char *names) 184e1051a39Sopenharmony_ci{ 185e1051a39Sopenharmony_ci const char *sn = OBJ_nid2sn(OBJ_obj2nid(excluded)); 186e1051a39Sopenharmony_ci 187e1051a39Sopenharmony_ci if (names != NULL && strstr(names, sn) != NULL) 188e1051a39Sopenharmony_ci BIO_printf(bio_err, 189e1051a39Sopenharmony_ci "Warning: -ext should not specify copying %s extension to CSR; ignoring this\n", 190e1051a39Sopenharmony_ci sn); 191e1051a39Sopenharmony_ci} 192e1051a39Sopenharmony_ci 193e1051a39Sopenharmony_cistatic X509_REQ *x509_to_req(X509 *cert, int ext_copy, const char *names) 194e1051a39Sopenharmony_ci{ 195e1051a39Sopenharmony_ci const STACK_OF(X509_EXTENSION) *cert_exts = X509_get0_extensions(cert); 196e1051a39Sopenharmony_ci int i, n = sk_X509_EXTENSION_num(cert_exts /* may be NULL */); 197e1051a39Sopenharmony_ci ASN1_OBJECT *skid = OBJ_nid2obj(NID_subject_key_identifier); 198e1051a39Sopenharmony_ci ASN1_OBJECT *akid = OBJ_nid2obj(NID_authority_key_identifier); 199e1051a39Sopenharmony_ci STACK_OF(X509_EXTENSION) *exts; 200e1051a39Sopenharmony_ci X509_REQ *req = X509_to_X509_REQ(cert, NULL, NULL); 201e1051a39Sopenharmony_ci 202e1051a39Sopenharmony_ci if (req == NULL) 203e1051a39Sopenharmony_ci return NULL; 204e1051a39Sopenharmony_ci 205e1051a39Sopenharmony_ci /* 206e1051a39Sopenharmony_ci * Filter out SKID and AKID extensions, which make no sense in a CSR. 207e1051a39Sopenharmony_ci * If names is not NULL, copy only those extensions listed there. 208e1051a39Sopenharmony_ci */ 209e1051a39Sopenharmony_ci warn_copying(skid, names); 210e1051a39Sopenharmony_ci warn_copying(akid, names); 211e1051a39Sopenharmony_ci if ((exts = sk_X509_EXTENSION_new_reserve(NULL, n)) == NULL) 212e1051a39Sopenharmony_ci goto err; 213e1051a39Sopenharmony_ci for (i = 0; i < n; i++) { 214e1051a39Sopenharmony_ci X509_EXTENSION *ex = sk_X509_EXTENSION_value(cert_exts, i); 215e1051a39Sopenharmony_ci ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex); 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_ci if (OBJ_cmp(obj, skid) != 0 && OBJ_cmp(obj, akid) != 0 218e1051a39Sopenharmony_ci && !sk_X509_EXTENSION_push(exts, ex)) 219e1051a39Sopenharmony_ci goto err; 220e1051a39Sopenharmony_ci } 221e1051a39Sopenharmony_ci 222e1051a39Sopenharmony_ci if (sk_X509_EXTENSION_num(exts) > 0) { 223e1051a39Sopenharmony_ci if (ext_copy != EXT_COPY_UNSET && ext_copy != EXT_COPY_NONE 224e1051a39Sopenharmony_ci && !X509_REQ_add_extensions(req, exts)) { 225e1051a39Sopenharmony_ci BIO_printf(bio_err, "Error copying extensions from certificate\n"); 226e1051a39Sopenharmony_ci goto err; 227e1051a39Sopenharmony_ci } 228e1051a39Sopenharmony_ci } 229e1051a39Sopenharmony_ci sk_X509_EXTENSION_free(exts); 230e1051a39Sopenharmony_ci return req; 231e1051a39Sopenharmony_ci 232e1051a39Sopenharmony_ci err: 233e1051a39Sopenharmony_ci sk_X509_EXTENSION_free(exts); 234e1051a39Sopenharmony_ci X509_REQ_free(req); 235e1051a39Sopenharmony_ci return NULL; 236e1051a39Sopenharmony_ci} 237e1051a39Sopenharmony_ci 238e1051a39Sopenharmony_cistatic int self_signed(X509_STORE *ctx, X509 *cert) 239e1051a39Sopenharmony_ci{ 240e1051a39Sopenharmony_ci X509_STORE_CTX *xsc = X509_STORE_CTX_new(); 241e1051a39Sopenharmony_ci int ret = 0; 242e1051a39Sopenharmony_ci 243e1051a39Sopenharmony_ci if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, cert, NULL)) { 244e1051a39Sopenharmony_ci BIO_printf(bio_err, "Error initialising X509 store\n"); 245e1051a39Sopenharmony_ci } else { 246e1051a39Sopenharmony_ci X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); 247e1051a39Sopenharmony_ci ret = X509_verify_cert(xsc) > 0; 248e1051a39Sopenharmony_ci } 249e1051a39Sopenharmony_ci X509_STORE_CTX_free(xsc); 250e1051a39Sopenharmony_ci return ret; 251e1051a39Sopenharmony_ci} 252e1051a39Sopenharmony_ci 253e1051a39Sopenharmony_ciint x509_main(int argc, char **argv) 254e1051a39Sopenharmony_ci{ 255e1051a39Sopenharmony_ci ASN1_INTEGER *sno = NULL; 256e1051a39Sopenharmony_ci ASN1_OBJECT *objtmp = NULL; 257e1051a39Sopenharmony_ci BIO *out = NULL; 258e1051a39Sopenharmony_ci CONF *extconf = NULL; 259e1051a39Sopenharmony_ci int ext_copy = EXT_COPY_UNSET; 260e1051a39Sopenharmony_ci X509V3_CTX ext_ctx; 261e1051a39Sopenharmony_ci EVP_PKEY *privkey = NULL, *CAkey = NULL, *pubkey = NULL; 262e1051a39Sopenharmony_ci EVP_PKEY *pkey; 263e1051a39Sopenharmony_ci int newcert = 0; 264e1051a39Sopenharmony_ci char *subj = NULL, *digest = NULL; 265e1051a39Sopenharmony_ci X509_NAME *fsubj = NULL; 266e1051a39Sopenharmony_ci const unsigned long chtype = MBSTRING_ASC; 267e1051a39Sopenharmony_ci const int multirdn = 1; 268e1051a39Sopenharmony_ci STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; 269e1051a39Sopenharmony_ci STACK_OF(OPENSSL_STRING) *sigopts = NULL, *vfyopts = NULL; 270e1051a39Sopenharmony_ci X509 *x = NULL, *xca = NULL, *issuer_cert; 271e1051a39Sopenharmony_ci X509_REQ *req = NULL, *rq = NULL; 272e1051a39Sopenharmony_ci X509_STORE *ctx = NULL; 273e1051a39Sopenharmony_ci char *CAkeyfile = NULL, *CAserial = NULL, *pubkeyfile = NULL, *alias = NULL; 274e1051a39Sopenharmony_ci char *checkhost = NULL, *checkemail = NULL, *checkip = NULL; 275e1051a39Sopenharmony_ci char *ext_names = NULL; 276e1051a39Sopenharmony_ci char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL; 277e1051a39Sopenharmony_ci char *infile = NULL, *outfile = NULL, *privkeyfile = NULL, *CAfile = NULL; 278e1051a39Sopenharmony_ci char *prog; 279e1051a39Sopenharmony_ci int days = UNSET_DAYS; /* not explicitly set */ 280e1051a39Sopenharmony_ci int x509toreq = 0, modulus = 0, print_pubkey = 0, pprint = 0; 281e1051a39Sopenharmony_ci int CAformat = FORMAT_UNDEF, CAkeyformat = FORMAT_UNDEF; 282e1051a39Sopenharmony_ci unsigned long dateopt = ASN1_DTFLGS_RFC822; 283e1051a39Sopenharmony_ci int fingerprint = 0, reqfile = 0, checkend = 0; 284e1051a39Sopenharmony_ci int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyformat = FORMAT_UNDEF; 285e1051a39Sopenharmony_ci int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0; 286e1051a39Sopenharmony_ci int noout = 0, CA_createserial = 0, email = 0; 287e1051a39Sopenharmony_ci int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0; 288e1051a39Sopenharmony_ci int ret = 1, i, j, num = 0, badsig = 0, clrext = 0, nocert = 0; 289e1051a39Sopenharmony_ci int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0, ext = 0; 290e1051a39Sopenharmony_ci int enddate = 0; 291e1051a39Sopenharmony_ci time_t checkoffset = 0; 292e1051a39Sopenharmony_ci unsigned long certflag = 0; 293e1051a39Sopenharmony_ci int preserve_dates = 0; 294e1051a39Sopenharmony_ci OPTION_CHOICE o; 295e1051a39Sopenharmony_ci ENGINE *e = NULL; 296e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_MD5 297e1051a39Sopenharmony_ci int subject_hash_old = 0, issuer_hash_old = 0; 298e1051a39Sopenharmony_ci#endif 299e1051a39Sopenharmony_ci 300e1051a39Sopenharmony_ci ctx = X509_STORE_new(); 301e1051a39Sopenharmony_ci if (ctx == NULL) 302e1051a39Sopenharmony_ci goto end; 303e1051a39Sopenharmony_ci X509_STORE_set_verify_cb(ctx, callb); 304e1051a39Sopenharmony_ci 305e1051a39Sopenharmony_ci prog = opt_init(argc, argv, x509_options); 306e1051a39Sopenharmony_ci while ((o = opt_next()) != OPT_EOF) { 307e1051a39Sopenharmony_ci switch (o) { 308e1051a39Sopenharmony_ci case OPT_EOF: 309e1051a39Sopenharmony_ci case OPT_ERR: 310e1051a39Sopenharmony_ci opthelp: 311e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 312e1051a39Sopenharmony_ci goto end; 313e1051a39Sopenharmony_ci case OPT_HELP: 314e1051a39Sopenharmony_ci opt_help(x509_options); 315e1051a39Sopenharmony_ci ret = 0; 316e1051a39Sopenharmony_ci goto end; 317e1051a39Sopenharmony_ci case OPT_INFORM: 318e1051a39Sopenharmony_ci if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) 319e1051a39Sopenharmony_ci goto opthelp; 320e1051a39Sopenharmony_ci break; 321e1051a39Sopenharmony_ci case OPT_IN: 322e1051a39Sopenharmony_ci infile = opt_arg(); 323e1051a39Sopenharmony_ci break; 324e1051a39Sopenharmony_ci case OPT_OUTFORM: 325e1051a39Sopenharmony_ci if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) 326e1051a39Sopenharmony_ci goto opthelp; 327e1051a39Sopenharmony_ci break; 328e1051a39Sopenharmony_ci case OPT_KEYFORM: 329e1051a39Sopenharmony_ci if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat)) 330e1051a39Sopenharmony_ci goto opthelp; 331e1051a39Sopenharmony_ci break; 332e1051a39Sopenharmony_ci case OPT_CAFORM: 333e1051a39Sopenharmony_ci if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAformat)) 334e1051a39Sopenharmony_ci goto opthelp; 335e1051a39Sopenharmony_ci break; 336e1051a39Sopenharmony_ci case OPT_CAKEYFORM: 337e1051a39Sopenharmony_ci if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAkeyformat)) 338e1051a39Sopenharmony_ci goto opthelp; 339e1051a39Sopenharmony_ci break; 340e1051a39Sopenharmony_ci case OPT_OUT: 341e1051a39Sopenharmony_ci outfile = opt_arg(); 342e1051a39Sopenharmony_ci break; 343e1051a39Sopenharmony_ci case OPT_REQ: 344e1051a39Sopenharmony_ci reqfile = 1; 345e1051a39Sopenharmony_ci break; 346e1051a39Sopenharmony_ci 347e1051a39Sopenharmony_ci case OPT_DATEOPT: 348e1051a39Sopenharmony_ci if (!set_dateopt(&dateopt, opt_arg())) { 349e1051a39Sopenharmony_ci BIO_printf(bio_err, 350e1051a39Sopenharmony_ci "Invalid date format: %s\n", opt_arg()); 351e1051a39Sopenharmony_ci goto end; 352e1051a39Sopenharmony_ci } 353e1051a39Sopenharmony_ci break; 354e1051a39Sopenharmony_ci case OPT_COPY_EXTENSIONS: 355e1051a39Sopenharmony_ci if (!set_ext_copy(&ext_copy, opt_arg())) { 356e1051a39Sopenharmony_ci BIO_printf(bio_err, 357e1051a39Sopenharmony_ci "Invalid extension copy option: %s\n", opt_arg()); 358e1051a39Sopenharmony_ci goto end; 359e1051a39Sopenharmony_ci } 360e1051a39Sopenharmony_ci break; 361e1051a39Sopenharmony_ci 362e1051a39Sopenharmony_ci case OPT_SIGOPT: 363e1051a39Sopenharmony_ci if (!sigopts) 364e1051a39Sopenharmony_ci sigopts = sk_OPENSSL_STRING_new_null(); 365e1051a39Sopenharmony_ci if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) 366e1051a39Sopenharmony_ci goto opthelp; 367e1051a39Sopenharmony_ci break; 368e1051a39Sopenharmony_ci case OPT_VFYOPT: 369e1051a39Sopenharmony_ci if (!vfyopts) 370e1051a39Sopenharmony_ci vfyopts = sk_OPENSSL_STRING_new_null(); 371e1051a39Sopenharmony_ci if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg())) 372e1051a39Sopenharmony_ci goto opthelp; 373e1051a39Sopenharmony_ci break; 374e1051a39Sopenharmony_ci case OPT_DAYS: 375e1051a39Sopenharmony_ci days = atoi(opt_arg()); 376e1051a39Sopenharmony_ci if (days < -1) { 377e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n", 378e1051a39Sopenharmony_ci prog); 379e1051a39Sopenharmony_ci goto end; 380e1051a39Sopenharmony_ci } 381e1051a39Sopenharmony_ci break; 382e1051a39Sopenharmony_ci case OPT_PASSIN: 383e1051a39Sopenharmony_ci passinarg = opt_arg(); 384e1051a39Sopenharmony_ci break; 385e1051a39Sopenharmony_ci case OPT_EXTFILE: 386e1051a39Sopenharmony_ci extfile = opt_arg(); 387e1051a39Sopenharmony_ci break; 388e1051a39Sopenharmony_ci case OPT_R_CASES: 389e1051a39Sopenharmony_ci if (!opt_rand(o)) 390e1051a39Sopenharmony_ci goto end; 391e1051a39Sopenharmony_ci break; 392e1051a39Sopenharmony_ci case OPT_PROV_CASES: 393e1051a39Sopenharmony_ci if (!opt_provider(o)) 394e1051a39Sopenharmony_ci goto end; 395e1051a39Sopenharmony_ci break; 396e1051a39Sopenharmony_ci case OPT_EXTENSIONS: 397e1051a39Sopenharmony_ci extsect = opt_arg(); 398e1051a39Sopenharmony_ci break; 399e1051a39Sopenharmony_ci case OPT_KEY: 400e1051a39Sopenharmony_ci case OPT_SIGNKEY: 401e1051a39Sopenharmony_ci privkeyfile = opt_arg(); 402e1051a39Sopenharmony_ci break; 403e1051a39Sopenharmony_ci case OPT_CA: 404e1051a39Sopenharmony_ci CAfile = opt_arg(); 405e1051a39Sopenharmony_ci break; 406e1051a39Sopenharmony_ci case OPT_CAKEY: 407e1051a39Sopenharmony_ci CAkeyfile = opt_arg(); 408e1051a39Sopenharmony_ci break; 409e1051a39Sopenharmony_ci case OPT_CASERIAL: 410e1051a39Sopenharmony_ci CAserial = opt_arg(); 411e1051a39Sopenharmony_ci break; 412e1051a39Sopenharmony_ci case OPT_SET_SERIAL: 413e1051a39Sopenharmony_ci if (sno != NULL) { 414e1051a39Sopenharmony_ci BIO_printf(bio_err, "Serial number supplied twice\n"); 415e1051a39Sopenharmony_ci goto opthelp; 416e1051a39Sopenharmony_ci } 417e1051a39Sopenharmony_ci if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) 418e1051a39Sopenharmony_ci goto opthelp; 419e1051a39Sopenharmony_ci break; 420e1051a39Sopenharmony_ci case OPT_NEW: 421e1051a39Sopenharmony_ci newcert = 1; 422e1051a39Sopenharmony_ci break; 423e1051a39Sopenharmony_ci case OPT_FORCE_PUBKEY: 424e1051a39Sopenharmony_ci pubkeyfile = opt_arg(); 425e1051a39Sopenharmony_ci break; 426e1051a39Sopenharmony_ci case OPT_SUBJ: 427e1051a39Sopenharmony_ci subj = opt_arg(); 428e1051a39Sopenharmony_ci break; 429e1051a39Sopenharmony_ci case OPT_ADDTRUST: 430e1051a39Sopenharmony_ci if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL) 431e1051a39Sopenharmony_ci goto end; 432e1051a39Sopenharmony_ci if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { 433e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: Invalid trust object value %s\n", 434e1051a39Sopenharmony_ci prog, opt_arg()); 435e1051a39Sopenharmony_ci goto opthelp; 436e1051a39Sopenharmony_ci } 437e1051a39Sopenharmony_ci sk_ASN1_OBJECT_push(trust, objtmp); 438e1051a39Sopenharmony_ci trustout = 1; 439e1051a39Sopenharmony_ci break; 440e1051a39Sopenharmony_ci case OPT_ADDREJECT: 441e1051a39Sopenharmony_ci if (reject == NULL && (reject = sk_ASN1_OBJECT_new_null()) == NULL) 442e1051a39Sopenharmony_ci goto end; 443e1051a39Sopenharmony_ci if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { 444e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: Invalid reject object value %s\n", 445e1051a39Sopenharmony_ci prog, opt_arg()); 446e1051a39Sopenharmony_ci goto opthelp; 447e1051a39Sopenharmony_ci } 448e1051a39Sopenharmony_ci sk_ASN1_OBJECT_push(reject, objtmp); 449e1051a39Sopenharmony_ci trustout = 1; 450e1051a39Sopenharmony_ci break; 451e1051a39Sopenharmony_ci case OPT_SETALIAS: 452e1051a39Sopenharmony_ci alias = opt_arg(); 453e1051a39Sopenharmony_ci trustout = 1; 454e1051a39Sopenharmony_ci break; 455e1051a39Sopenharmony_ci case OPT_CERTOPT: 456e1051a39Sopenharmony_ci if (!set_cert_ex(&certflag, opt_arg())) 457e1051a39Sopenharmony_ci goto opthelp; 458e1051a39Sopenharmony_ci break; 459e1051a39Sopenharmony_ci case OPT_NAMEOPT: 460e1051a39Sopenharmony_ci if (!set_nameopt(opt_arg())) 461e1051a39Sopenharmony_ci goto opthelp; 462e1051a39Sopenharmony_ci break; 463e1051a39Sopenharmony_ci case OPT_ENGINE: 464e1051a39Sopenharmony_ci e = setup_engine(opt_arg(), 0); 465e1051a39Sopenharmony_ci break; 466e1051a39Sopenharmony_ci case OPT_EMAIL: 467e1051a39Sopenharmony_ci email = ++num; 468e1051a39Sopenharmony_ci break; 469e1051a39Sopenharmony_ci case OPT_OCSP_URI: 470e1051a39Sopenharmony_ci ocsp_uri = ++num; 471e1051a39Sopenharmony_ci break; 472e1051a39Sopenharmony_ci case OPT_SERIAL: 473e1051a39Sopenharmony_ci serial = ++num; 474e1051a39Sopenharmony_ci break; 475e1051a39Sopenharmony_ci case OPT_NEXT_SERIAL: 476e1051a39Sopenharmony_ci next_serial = ++num; 477e1051a39Sopenharmony_ci break; 478e1051a39Sopenharmony_ci case OPT_MODULUS: 479e1051a39Sopenharmony_ci modulus = ++num; 480e1051a39Sopenharmony_ci break; 481e1051a39Sopenharmony_ci case OPT_PUBKEY: 482e1051a39Sopenharmony_ci print_pubkey = ++num; 483e1051a39Sopenharmony_ci break; 484e1051a39Sopenharmony_ci case OPT_X509TOREQ: 485e1051a39Sopenharmony_ci x509toreq = 1; 486e1051a39Sopenharmony_ci break; 487e1051a39Sopenharmony_ci case OPT_TEXT: 488e1051a39Sopenharmony_ci text = ++num; 489e1051a39Sopenharmony_ci break; 490e1051a39Sopenharmony_ci case OPT_SUBJECT: 491e1051a39Sopenharmony_ci subject = ++num; 492e1051a39Sopenharmony_ci break; 493e1051a39Sopenharmony_ci case OPT_ISSUER: 494e1051a39Sopenharmony_ci issuer = ++num; 495e1051a39Sopenharmony_ci break; 496e1051a39Sopenharmony_ci case OPT_FINGERPRINT: 497e1051a39Sopenharmony_ci fingerprint = ++num; 498e1051a39Sopenharmony_ci break; 499e1051a39Sopenharmony_ci case OPT_HASH: 500e1051a39Sopenharmony_ci subject_hash = ++num; 501e1051a39Sopenharmony_ci break; 502e1051a39Sopenharmony_ci case OPT_ISSUER_HASH: 503e1051a39Sopenharmony_ci issuer_hash = ++num; 504e1051a39Sopenharmony_ci break; 505e1051a39Sopenharmony_ci case OPT_PURPOSE: 506e1051a39Sopenharmony_ci pprint = ++num; 507e1051a39Sopenharmony_ci break; 508e1051a39Sopenharmony_ci case OPT_STARTDATE: 509e1051a39Sopenharmony_ci startdate = ++num; 510e1051a39Sopenharmony_ci break; 511e1051a39Sopenharmony_ci case OPT_ENDDATE: 512e1051a39Sopenharmony_ci enddate = ++num; 513e1051a39Sopenharmony_ci break; 514e1051a39Sopenharmony_ci case OPT_NOOUT: 515e1051a39Sopenharmony_ci noout = ++num; 516e1051a39Sopenharmony_ci break; 517e1051a39Sopenharmony_ci case OPT_EXT: 518e1051a39Sopenharmony_ci ext = ++num; 519e1051a39Sopenharmony_ci ext_names = opt_arg(); 520e1051a39Sopenharmony_ci break; 521e1051a39Sopenharmony_ci case OPT_NOCERT: 522e1051a39Sopenharmony_ci nocert = 1; 523e1051a39Sopenharmony_ci break; 524e1051a39Sopenharmony_ci case OPT_TRUSTOUT: 525e1051a39Sopenharmony_ci trustout = 1; 526e1051a39Sopenharmony_ci break; 527e1051a39Sopenharmony_ci case OPT_CLRTRUST: 528e1051a39Sopenharmony_ci clrtrust = ++num; 529e1051a39Sopenharmony_ci break; 530e1051a39Sopenharmony_ci case OPT_CLRREJECT: 531e1051a39Sopenharmony_ci clrreject = ++num; 532e1051a39Sopenharmony_ci break; 533e1051a39Sopenharmony_ci case OPT_ALIAS: 534e1051a39Sopenharmony_ci aliasout = ++num; 535e1051a39Sopenharmony_ci break; 536e1051a39Sopenharmony_ci case OPT_CACREATESERIAL: 537e1051a39Sopenharmony_ci CA_createserial = 1; 538e1051a39Sopenharmony_ci break; 539e1051a39Sopenharmony_ci case OPT_CLREXT: 540e1051a39Sopenharmony_ci clrext = 1; 541e1051a39Sopenharmony_ci break; 542e1051a39Sopenharmony_ci case OPT_OCSPID: 543e1051a39Sopenharmony_ci ocspid = ++num; 544e1051a39Sopenharmony_ci break; 545e1051a39Sopenharmony_ci case OPT_BADSIG: 546e1051a39Sopenharmony_ci badsig = 1; 547e1051a39Sopenharmony_ci break; 548e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_MD5 549e1051a39Sopenharmony_ci case OPT_SUBJECT_HASH_OLD: 550e1051a39Sopenharmony_ci subject_hash_old = ++num; 551e1051a39Sopenharmony_ci break; 552e1051a39Sopenharmony_ci case OPT_ISSUER_HASH_OLD: 553e1051a39Sopenharmony_ci issuer_hash_old = ++num; 554e1051a39Sopenharmony_ci break; 555e1051a39Sopenharmony_ci#else 556e1051a39Sopenharmony_ci case OPT_SUBJECT_HASH_OLD: 557e1051a39Sopenharmony_ci case OPT_ISSUER_HASH_OLD: 558e1051a39Sopenharmony_ci break; 559e1051a39Sopenharmony_ci#endif 560e1051a39Sopenharmony_ci case OPT_DATES: 561e1051a39Sopenharmony_ci startdate = ++num; 562e1051a39Sopenharmony_ci enddate = ++num; 563e1051a39Sopenharmony_ci break; 564e1051a39Sopenharmony_ci case OPT_CHECKEND: 565e1051a39Sopenharmony_ci checkend = 1; 566e1051a39Sopenharmony_ci { 567e1051a39Sopenharmony_ci ossl_intmax_t temp = 0; 568e1051a39Sopenharmony_ci if (!opt_intmax(opt_arg(), &temp)) 569e1051a39Sopenharmony_ci goto opthelp; 570e1051a39Sopenharmony_ci checkoffset = (time_t)temp; 571e1051a39Sopenharmony_ci if ((ossl_intmax_t)checkoffset != temp) { 572e1051a39Sopenharmony_ci BIO_printf(bio_err, "%s: Checkend time out of range %s\n", 573e1051a39Sopenharmony_ci prog, opt_arg()); 574e1051a39Sopenharmony_ci goto opthelp; 575e1051a39Sopenharmony_ci } 576e1051a39Sopenharmony_ci } 577e1051a39Sopenharmony_ci break; 578e1051a39Sopenharmony_ci case OPT_CHECKHOST: 579e1051a39Sopenharmony_ci checkhost = opt_arg(); 580e1051a39Sopenharmony_ci break; 581e1051a39Sopenharmony_ci case OPT_CHECKEMAIL: 582e1051a39Sopenharmony_ci checkemail = opt_arg(); 583e1051a39Sopenharmony_ci break; 584e1051a39Sopenharmony_ci case OPT_CHECKIP: 585e1051a39Sopenharmony_ci checkip = opt_arg(); 586e1051a39Sopenharmony_ci break; 587e1051a39Sopenharmony_ci case OPT_PRESERVE_DATES: 588e1051a39Sopenharmony_ci preserve_dates = 1; 589e1051a39Sopenharmony_ci break; 590e1051a39Sopenharmony_ci case OPT_MD: 591e1051a39Sopenharmony_ci digest = opt_unknown(); 592e1051a39Sopenharmony_ci break; 593e1051a39Sopenharmony_ci } 594e1051a39Sopenharmony_ci } 595e1051a39Sopenharmony_ci 596e1051a39Sopenharmony_ci /* No extra arguments. */ 597e1051a39Sopenharmony_ci argc = opt_num_rest(); 598e1051a39Sopenharmony_ci if (argc != 0) 599e1051a39Sopenharmony_ci goto opthelp; 600e1051a39Sopenharmony_ci 601e1051a39Sopenharmony_ci if (!app_RAND_load()) 602e1051a39Sopenharmony_ci goto end; 603e1051a39Sopenharmony_ci 604e1051a39Sopenharmony_ci if (preserve_dates && days != UNSET_DAYS) { 605e1051a39Sopenharmony_ci BIO_printf(bio_err, "Cannot use -preserve_dates with -days option\n"); 606e1051a39Sopenharmony_ci goto end; 607e1051a39Sopenharmony_ci } 608e1051a39Sopenharmony_ci if (days == UNSET_DAYS) 609e1051a39Sopenharmony_ci days = DEFAULT_DAYS; 610e1051a39Sopenharmony_ci 611e1051a39Sopenharmony_ci if (!app_passwd(passinarg, NULL, &passin, NULL)) { 612e1051a39Sopenharmony_ci BIO_printf(bio_err, "Error getting password\n"); 613e1051a39Sopenharmony_ci goto end; 614e1051a39Sopenharmony_ci } 615e1051a39Sopenharmony_ci 616e1051a39Sopenharmony_ci if (!X509_STORE_set_default_paths_ex(ctx, app_get0_libctx(), 617e1051a39Sopenharmony_ci app_get0_propq())) 618e1051a39Sopenharmony_ci goto end; 619e1051a39Sopenharmony_ci 620e1051a39Sopenharmony_ci if (newcert && infile != NULL) { 621e1051a39Sopenharmony_ci BIO_printf(bio_err, "The -in option cannot be used with -new\n"); 622e1051a39Sopenharmony_ci goto end; 623e1051a39Sopenharmony_ci } 624e1051a39Sopenharmony_ci if (newcert && reqfile) { 625e1051a39Sopenharmony_ci BIO_printf(bio_err, 626e1051a39Sopenharmony_ci "The -req option cannot be used with -new\n"); 627e1051a39Sopenharmony_ci goto end; 628e1051a39Sopenharmony_ci } 629e1051a39Sopenharmony_ci if (privkeyfile != NULL) { 630e1051a39Sopenharmony_ci privkey = load_key(privkeyfile, keyformat, 0, passin, e, "private key"); 631e1051a39Sopenharmony_ci if (privkey == NULL) 632e1051a39Sopenharmony_ci goto end; 633e1051a39Sopenharmony_ci } 634e1051a39Sopenharmony_ci if (pubkeyfile != NULL) { 635e1051a39Sopenharmony_ci if ((pubkey = load_pubkey(pubkeyfile, keyformat, 0, NULL, e, 636e1051a39Sopenharmony_ci "explicitly set public key")) == NULL) 637e1051a39Sopenharmony_ci goto end; 638e1051a39Sopenharmony_ci } 639e1051a39Sopenharmony_ci 640e1051a39Sopenharmony_ci if (newcert) { 641e1051a39Sopenharmony_ci if (subj == NULL) { 642e1051a39Sopenharmony_ci BIO_printf(bio_err, 643e1051a39Sopenharmony_ci "The -new option requires a subject to be set using -subj\n"); 644e1051a39Sopenharmony_ci goto end; 645e1051a39Sopenharmony_ci } 646e1051a39Sopenharmony_ci if (privkeyfile == NULL && pubkeyfile == NULL) { 647e1051a39Sopenharmony_ci BIO_printf(bio_err, 648e1051a39Sopenharmony_ci "The -new option requires using the -key or -force_pubkey option\n"); 649e1051a39Sopenharmony_ci goto end; 650e1051a39Sopenharmony_ci } 651e1051a39Sopenharmony_ci } 652e1051a39Sopenharmony_ci if (subj != NULL 653e1051a39Sopenharmony_ci && (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL) 654e1051a39Sopenharmony_ci goto end; 655e1051a39Sopenharmony_ci 656e1051a39Sopenharmony_ci if (CAkeyfile == NULL) 657e1051a39Sopenharmony_ci CAkeyfile = CAfile; 658e1051a39Sopenharmony_ci if (CAfile != NULL) { 659e1051a39Sopenharmony_ci if (privkeyfile != NULL) { 660e1051a39Sopenharmony_ci BIO_printf(bio_err, "Cannot use both -key/-signkey and -CA option\n"); 661e1051a39Sopenharmony_ci goto end; 662e1051a39Sopenharmony_ci } 663e1051a39Sopenharmony_ci } else { 664e1051a39Sopenharmony_ci#define WARN_NO_CA(opt) BIO_printf(bio_err, \ 665e1051a39Sopenharmony_ci "Warning: ignoring " opt " option since -CA option is not given\n"); 666e1051a39Sopenharmony_ci if (CAkeyfile != NULL) 667e1051a39Sopenharmony_ci WARN_NO_CA("-CAkey"); 668e1051a39Sopenharmony_ci if (CAkeyformat != FORMAT_UNDEF) 669e1051a39Sopenharmony_ci WARN_NO_CA("-CAkeyform"); 670e1051a39Sopenharmony_ci if (CAformat != FORMAT_UNDEF) 671e1051a39Sopenharmony_ci WARN_NO_CA("-CAform"); 672e1051a39Sopenharmony_ci if (CAserial != NULL) 673e1051a39Sopenharmony_ci WARN_NO_CA("-CAserial"); 674e1051a39Sopenharmony_ci if (CA_createserial) 675e1051a39Sopenharmony_ci WARN_NO_CA("-CAcreateserial"); 676e1051a39Sopenharmony_ci } 677e1051a39Sopenharmony_ci 678e1051a39Sopenharmony_ci if (extfile == NULL) { 679e1051a39Sopenharmony_ci if (extsect != NULL) 680e1051a39Sopenharmony_ci BIO_printf(bio_err, 681e1051a39Sopenharmony_ci "Warning: ignoring -extensions option without -extfile\n"); 682e1051a39Sopenharmony_ci } else { 683e1051a39Sopenharmony_ci X509V3_CTX ctx2; 684e1051a39Sopenharmony_ci 685e1051a39Sopenharmony_ci if ((extconf = app_load_config(extfile)) == NULL) 686e1051a39Sopenharmony_ci goto end; 687e1051a39Sopenharmony_ci if (extsect == NULL) { 688e1051a39Sopenharmony_ci extsect = NCONF_get_string(extconf, "default", "extensions"); 689e1051a39Sopenharmony_ci if (extsect == NULL) { 690e1051a39Sopenharmony_ci ERR_clear_error(); 691e1051a39Sopenharmony_ci extsect = "default"; 692e1051a39Sopenharmony_ci } 693e1051a39Sopenharmony_ci } 694e1051a39Sopenharmony_ci X509V3_set_ctx_test(&ctx2); 695e1051a39Sopenharmony_ci X509V3_set_nconf(&ctx2, extconf); 696e1051a39Sopenharmony_ci if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) { 697e1051a39Sopenharmony_ci BIO_printf(bio_err, 698e1051a39Sopenharmony_ci "Error checking extension section %s\n", extsect); 699e1051a39Sopenharmony_ci goto end; 700e1051a39Sopenharmony_ci } 701e1051a39Sopenharmony_ci } 702e1051a39Sopenharmony_ci 703e1051a39Sopenharmony_ci if (reqfile) { 704e1051a39Sopenharmony_ci req = load_csr(infile, informat, "certificate request input"); 705e1051a39Sopenharmony_ci if (req == NULL) 706e1051a39Sopenharmony_ci goto end; 707e1051a39Sopenharmony_ci 708e1051a39Sopenharmony_ci if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) { 709e1051a39Sopenharmony_ci BIO_printf(bio_err, "Error unpacking public key from CSR\n"); 710e1051a39Sopenharmony_ci goto end; 711e1051a39Sopenharmony_ci } 712e1051a39Sopenharmony_ci i = do_X509_REQ_verify(req, pkey, vfyopts); 713e1051a39Sopenharmony_ci if (i <= 0) { 714e1051a39Sopenharmony_ci BIO_printf(bio_err, i < 0 715e1051a39Sopenharmony_ci ? "Error while verifying certificate request self-signature\n" 716e1051a39Sopenharmony_ci : "Certificate request self-signature did not match the contents\n"); 717e1051a39Sopenharmony_ci goto end; 718e1051a39Sopenharmony_ci } 719e1051a39Sopenharmony_ci BIO_printf(bio_err, "Certificate request self-signature ok\n"); 720e1051a39Sopenharmony_ci 721e1051a39Sopenharmony_ci print_name(bio_err, "subject=", X509_REQ_get_subject_name(req)); 722e1051a39Sopenharmony_ci } else if (!x509toreq && ext_copy != EXT_COPY_UNSET) { 723e1051a39Sopenharmony_ci BIO_printf(bio_err, "Warning: ignoring -copy_extensions since neither -x509toreq nor -req is given\n"); 724e1051a39Sopenharmony_ci } 725e1051a39Sopenharmony_ci 726e1051a39Sopenharmony_ci if (reqfile || newcert) { 727e1051a39Sopenharmony_ci if (preserve_dates) 728e1051a39Sopenharmony_ci BIO_printf(bio_err, 729e1051a39Sopenharmony_ci "Warning: ignoring -preserve_dates option with -req or -new\n"); 730e1051a39Sopenharmony_ci preserve_dates = 0; 731e1051a39Sopenharmony_ci if (privkeyfile == NULL && CAkeyfile == NULL) { 732e1051a39Sopenharmony_ci BIO_printf(bio_err, 733e1051a39Sopenharmony_ci "We need a private key to sign with, use -key or -CAkey or -CA with private key\n"); 734e1051a39Sopenharmony_ci goto end; 735e1051a39Sopenharmony_ci } 736e1051a39Sopenharmony_ci if ((x = X509_new_ex(app_get0_libctx(), app_get0_propq())) == NULL) 737e1051a39Sopenharmony_ci goto end; 738e1051a39Sopenharmony_ci if (CAfile == NULL && sno == NULL) { 739e1051a39Sopenharmony_ci sno = ASN1_INTEGER_new(); 740e1051a39Sopenharmony_ci if (sno == NULL || !rand_serial(NULL, sno)) 741e1051a39Sopenharmony_ci goto end; 742e1051a39Sopenharmony_ci } 743e1051a39Sopenharmony_ci if (req != NULL && ext_copy != EXT_COPY_UNSET) { 744e1051a39Sopenharmony_ci if (clrext && ext_copy != EXT_COPY_NONE) { 745e1051a39Sopenharmony_ci BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n"); 746e1051a39Sopenharmony_ci goto end; 747e1051a39Sopenharmony_ci } else if (!copy_extensions(x, req, ext_copy)) { 748e1051a39Sopenharmony_ci BIO_printf(bio_err, "Error copying extensions from request\n"); 749e1051a39Sopenharmony_ci goto end; 750e1051a39Sopenharmony_ci } 751e1051a39Sopenharmony_ci } 752e1051a39Sopenharmony_ci } else { 753e1051a39Sopenharmony_ci x = load_cert_pass(infile, informat, 1, passin, "certificate"); 754e1051a39Sopenharmony_ci if (x == NULL) 755e1051a39Sopenharmony_ci goto end; 756e1051a39Sopenharmony_ci } 757e1051a39Sopenharmony_ci if ((fsubj != NULL || req != NULL) 758e1051a39Sopenharmony_ci && !X509_set_subject_name(x, fsubj != NULL ? fsubj : 759e1051a39Sopenharmony_ci X509_REQ_get_subject_name(req))) 760e1051a39Sopenharmony_ci goto end; 761e1051a39Sopenharmony_ci if ((pubkey != NULL || privkey != NULL || req != NULL) 762e1051a39Sopenharmony_ci && !X509_set_pubkey(x, pubkey != NULL ? pubkey : 763e1051a39Sopenharmony_ci privkey != NULL ? privkey : 764e1051a39Sopenharmony_ci X509_REQ_get0_pubkey(req))) 765e1051a39Sopenharmony_ci goto end; 766e1051a39Sopenharmony_ci 767e1051a39Sopenharmony_ci if (CAfile != NULL) { 768e1051a39Sopenharmony_ci xca = load_cert_pass(CAfile, CAformat, 1, passin, "CA certificate"); 769e1051a39Sopenharmony_ci if (xca == NULL) 770e1051a39Sopenharmony_ci goto end; 771e1051a39Sopenharmony_ci } 772e1051a39Sopenharmony_ci 773e1051a39Sopenharmony_ci out = bio_open_default(outfile, 'w', outformat); 774e1051a39Sopenharmony_ci if (out == NULL) 775e1051a39Sopenharmony_ci goto end; 776e1051a39Sopenharmony_ci 777e1051a39Sopenharmony_ci if (!noout || text || next_serial) 778e1051a39Sopenharmony_ci OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3"); 779e1051a39Sopenharmony_ci 780e1051a39Sopenharmony_ci if (alias) 781e1051a39Sopenharmony_ci X509_alias_set1(x, (unsigned char *)alias, -1); 782e1051a39Sopenharmony_ci 783e1051a39Sopenharmony_ci if (clrtrust) 784e1051a39Sopenharmony_ci X509_trust_clear(x); 785e1051a39Sopenharmony_ci if (clrreject) 786e1051a39Sopenharmony_ci X509_reject_clear(x); 787e1051a39Sopenharmony_ci 788e1051a39Sopenharmony_ci if (trust != NULL) { 789e1051a39Sopenharmony_ci for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) 790e1051a39Sopenharmony_ci X509_add1_trust_object(x, sk_ASN1_OBJECT_value(trust, i)); 791e1051a39Sopenharmony_ci } 792e1051a39Sopenharmony_ci 793e1051a39Sopenharmony_ci if (reject != NULL) { 794e1051a39Sopenharmony_ci for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) 795e1051a39Sopenharmony_ci X509_add1_reject_object(x, sk_ASN1_OBJECT_value(reject, i)); 796e1051a39Sopenharmony_ci } 797e1051a39Sopenharmony_ci 798e1051a39Sopenharmony_ci if (clrext && ext_names != NULL) 799e1051a39Sopenharmony_ci BIO_printf(bio_err, "Warning: Ignoring -ext since -clrext is given\n"); 800e1051a39Sopenharmony_ci for (i = X509_get_ext_count(x) - 1; i >= 0; i--) { 801e1051a39Sopenharmony_ci X509_EXTENSION *ex = X509_get_ext(x, i); 802e1051a39Sopenharmony_ci const char *sn = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ex))); 803e1051a39Sopenharmony_ci 804e1051a39Sopenharmony_ci if (clrext || (ext_names != NULL && strstr(ext_names, sn) == NULL)) 805e1051a39Sopenharmony_ci X509_EXTENSION_free(X509_delete_ext(x, i)); 806e1051a39Sopenharmony_ci } 807e1051a39Sopenharmony_ci 808e1051a39Sopenharmony_ci issuer_cert = x; 809e1051a39Sopenharmony_ci if (CAfile != NULL) { 810e1051a39Sopenharmony_ci issuer_cert = xca; 811e1051a39Sopenharmony_ci if (sno == NULL) 812e1051a39Sopenharmony_ci sno = x509_load_serial(CAfile, CAserial, CA_createserial); 813e1051a39Sopenharmony_ci if (sno == NULL) 814e1051a39Sopenharmony_ci goto end; 815e1051a39Sopenharmony_ci if (!x509toreq && !reqfile && !newcert && !self_signed(ctx, x)) 816e1051a39Sopenharmony_ci goto end; 817e1051a39Sopenharmony_ci } 818e1051a39Sopenharmony_ci 819e1051a39Sopenharmony_ci if (sno != NULL && !X509_set_serialNumber(x, sno)) 820e1051a39Sopenharmony_ci goto end; 821e1051a39Sopenharmony_ci 822e1051a39Sopenharmony_ci if (reqfile || newcert || privkey != NULL || CAfile != NULL) { 823e1051a39Sopenharmony_ci if (!preserve_dates && !set_cert_times(x, NULL, NULL, days)) 824e1051a39Sopenharmony_ci goto end; 825e1051a39Sopenharmony_ci if (!X509_set_issuer_name(x, X509_get_subject_name(issuer_cert))) 826e1051a39Sopenharmony_ci goto end; 827e1051a39Sopenharmony_ci } 828e1051a39Sopenharmony_ci 829e1051a39Sopenharmony_ci X509V3_set_ctx(&ext_ctx, issuer_cert, x, NULL, NULL, X509V3_CTX_REPLACE); 830e1051a39Sopenharmony_ci /* prepare fallback for AKID, but only if issuer cert equals subject cert */ 831e1051a39Sopenharmony_ci if (CAfile == NULL) { 832e1051a39Sopenharmony_ci if (!X509V3_set_issuer_pkey(&ext_ctx, privkey)) 833e1051a39Sopenharmony_ci goto end; 834e1051a39Sopenharmony_ci } 835e1051a39Sopenharmony_ci if (extconf != NULL && !x509toreq) { 836e1051a39Sopenharmony_ci X509V3_set_nconf(&ext_ctx, extconf); 837e1051a39Sopenharmony_ci if (!X509V3_EXT_add_nconf(extconf, &ext_ctx, extsect, x)) { 838e1051a39Sopenharmony_ci BIO_printf(bio_err, 839e1051a39Sopenharmony_ci "Error adding extensions from section %s\n", extsect); 840e1051a39Sopenharmony_ci goto end; 841e1051a39Sopenharmony_ci } 842e1051a39Sopenharmony_ci } 843e1051a39Sopenharmony_ci 844e1051a39Sopenharmony_ci /* At this point the contents of the certificate x have been finished. */ 845e1051a39Sopenharmony_ci 846e1051a39Sopenharmony_ci pkey = X509_get0_pubkey(x); 847e1051a39Sopenharmony_ci if ((print_pubkey != 0 || modulus != 0) && pkey == NULL) { 848e1051a39Sopenharmony_ci BIO_printf(bio_err, "Error getting public key\n"); 849e1051a39Sopenharmony_ci goto end; 850e1051a39Sopenharmony_ci } 851e1051a39Sopenharmony_ci 852e1051a39Sopenharmony_ci if (x509toreq) { /* also works in conjunction with -req */ 853e1051a39Sopenharmony_ci if (privkey == NULL) { 854e1051a39Sopenharmony_ci BIO_printf(bio_err, "Must specify request signing key using -key\n"); 855e1051a39Sopenharmony_ci goto end; 856e1051a39Sopenharmony_ci } 857e1051a39Sopenharmony_ci if (clrext && ext_copy != EXT_COPY_NONE) { 858e1051a39Sopenharmony_ci BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n"); 859e1051a39Sopenharmony_ci goto end; 860e1051a39Sopenharmony_ci } 861e1051a39Sopenharmony_ci if ((rq = x509_to_req(x, ext_copy, ext_names)) == NULL) 862e1051a39Sopenharmony_ci goto end; 863e1051a39Sopenharmony_ci if (extconf != NULL) { 864e1051a39Sopenharmony_ci X509V3_set_nconf(&ext_ctx, extconf); 865e1051a39Sopenharmony_ci if (!X509V3_EXT_REQ_add_nconf(extconf, &ext_ctx, extsect, rq)) { 866e1051a39Sopenharmony_ci BIO_printf(bio_err, 867e1051a39Sopenharmony_ci "Error adding request extensions from section %s\n", extsect); 868e1051a39Sopenharmony_ci goto end; 869e1051a39Sopenharmony_ci } 870e1051a39Sopenharmony_ci } 871e1051a39Sopenharmony_ci if (!do_X509_REQ_sign(rq, privkey, digest, sigopts)) 872e1051a39Sopenharmony_ci goto end; 873e1051a39Sopenharmony_ci if (!noout) { 874e1051a39Sopenharmony_ci if (outformat == FORMAT_ASN1) { 875e1051a39Sopenharmony_ci X509_REQ_print_ex(out, rq, get_nameopt(), X509_FLAG_COMPAT); 876e1051a39Sopenharmony_ci i = i2d_X509_bio(out, x); 877e1051a39Sopenharmony_ci } else { 878e1051a39Sopenharmony_ci i = PEM_write_bio_X509_REQ(out, rq); 879e1051a39Sopenharmony_ci } 880e1051a39Sopenharmony_ci if (!i) { 881e1051a39Sopenharmony_ci BIO_printf(bio_err, 882e1051a39Sopenharmony_ci "Unable to write certificate request\n"); 883e1051a39Sopenharmony_ci goto end; 884e1051a39Sopenharmony_ci } 885e1051a39Sopenharmony_ci } 886e1051a39Sopenharmony_ci noout = 1; 887e1051a39Sopenharmony_ci } else if (privkey != NULL) { 888e1051a39Sopenharmony_ci if (!do_X509_sign(x, privkey, digest, sigopts, &ext_ctx)) 889e1051a39Sopenharmony_ci goto end; 890e1051a39Sopenharmony_ci } else if (CAfile != NULL) { 891e1051a39Sopenharmony_ci if ((CAkey = load_key(CAkeyfile, CAkeyformat, 892e1051a39Sopenharmony_ci 0, passin, e, "CA private key")) == NULL) 893e1051a39Sopenharmony_ci goto end; 894e1051a39Sopenharmony_ci if (!X509_check_private_key(xca, CAkey)) { 895e1051a39Sopenharmony_ci BIO_printf(bio_err, 896e1051a39Sopenharmony_ci "CA certificate and CA private key do not match\n"); 897e1051a39Sopenharmony_ci goto end; 898e1051a39Sopenharmony_ci } 899e1051a39Sopenharmony_ci 900e1051a39Sopenharmony_ci if (!do_X509_sign(x, CAkey, digest, sigopts, &ext_ctx)) 901e1051a39Sopenharmony_ci goto end; 902e1051a39Sopenharmony_ci } 903e1051a39Sopenharmony_ci if (badsig) { 904e1051a39Sopenharmony_ci const ASN1_BIT_STRING *signature; 905e1051a39Sopenharmony_ci 906e1051a39Sopenharmony_ci X509_get0_signature(&signature, NULL, x); 907e1051a39Sopenharmony_ci corrupt_signature(signature); 908e1051a39Sopenharmony_ci } 909e1051a39Sopenharmony_ci 910e1051a39Sopenharmony_ci /* Process print options in the given order, as indicated by index i */ 911e1051a39Sopenharmony_ci for (i = 1; i <= num; i++) { 912e1051a39Sopenharmony_ci if (i == issuer) { 913e1051a39Sopenharmony_ci print_name(out, "issuer=", X509_get_issuer_name(x)); 914e1051a39Sopenharmony_ci } else if (i == subject) { 915e1051a39Sopenharmony_ci print_name(out, "subject=", X509_get_subject_name(x)); 916e1051a39Sopenharmony_ci } else if (i == serial) { 917e1051a39Sopenharmony_ci BIO_printf(out, "serial="); 918e1051a39Sopenharmony_ci i2a_ASN1_INTEGER(out, X509_get0_serialNumber(x)); 919e1051a39Sopenharmony_ci BIO_printf(out, "\n"); 920e1051a39Sopenharmony_ci } else if (i == next_serial) { 921e1051a39Sopenharmony_ci ASN1_INTEGER *ser; 922e1051a39Sopenharmony_ci BIGNUM *bnser = ASN1_INTEGER_to_BN(X509_get0_serialNumber(x), NULL); 923e1051a39Sopenharmony_ci 924e1051a39Sopenharmony_ci if (bnser == NULL) 925e1051a39Sopenharmony_ci goto end; 926e1051a39Sopenharmony_ci if (!BN_add_word(bnser, 1) 927e1051a39Sopenharmony_ci || (ser = BN_to_ASN1_INTEGER(bnser, NULL)) == NULL) { 928e1051a39Sopenharmony_ci BN_free(bnser); 929e1051a39Sopenharmony_ci goto end; 930e1051a39Sopenharmony_ci } 931e1051a39Sopenharmony_ci BN_free(bnser); 932e1051a39Sopenharmony_ci i2a_ASN1_INTEGER(out, ser); 933e1051a39Sopenharmony_ci ASN1_INTEGER_free(ser); 934e1051a39Sopenharmony_ci BIO_puts(out, "\n"); 935e1051a39Sopenharmony_ci } else if (i == email || i == ocsp_uri) { 936e1051a39Sopenharmony_ci STACK_OF(OPENSSL_STRING) *emlst = 937e1051a39Sopenharmony_ci i == email ? X509_get1_email(x) : X509_get1_ocsp(x); 938e1051a39Sopenharmony_ci 939e1051a39Sopenharmony_ci for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) 940e1051a39Sopenharmony_ci BIO_printf(out, "%s\n", sk_OPENSSL_STRING_value(emlst, j)); 941e1051a39Sopenharmony_ci X509_email_free(emlst); 942e1051a39Sopenharmony_ci } else if (i == aliasout) { 943e1051a39Sopenharmony_ci unsigned char *alstr = X509_alias_get0(x, NULL); 944e1051a39Sopenharmony_ci 945e1051a39Sopenharmony_ci if (alstr) 946e1051a39Sopenharmony_ci BIO_printf(out, "%s\n", alstr); 947e1051a39Sopenharmony_ci else 948e1051a39Sopenharmony_ci BIO_puts(out, "<No Alias>\n"); 949e1051a39Sopenharmony_ci } else if (i == subject_hash) { 950e1051a39Sopenharmony_ci BIO_printf(out, "%08lx\n", X509_subject_name_hash(x)); 951e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_MD5 952e1051a39Sopenharmony_ci } else if (i == subject_hash_old) { 953e1051a39Sopenharmony_ci BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x)); 954e1051a39Sopenharmony_ci#endif 955e1051a39Sopenharmony_ci } else if (i == issuer_hash) { 956e1051a39Sopenharmony_ci BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x)); 957e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_MD5 958e1051a39Sopenharmony_ci } else if (i == issuer_hash_old) { 959e1051a39Sopenharmony_ci BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x)); 960e1051a39Sopenharmony_ci#endif 961e1051a39Sopenharmony_ci } else if (i == pprint) { 962e1051a39Sopenharmony_ci BIO_printf(out, "Certificate purposes:\n"); 963e1051a39Sopenharmony_ci for (j = 0; j < X509_PURPOSE_get_count(); j++) 964e1051a39Sopenharmony_ci purpose_print(out, x, X509_PURPOSE_get0(j)); 965e1051a39Sopenharmony_ci } else if (i == modulus) { 966e1051a39Sopenharmony_ci BIO_printf(out, "Modulus="); 967e1051a39Sopenharmony_ci if (EVP_PKEY_is_a(pkey, "RSA") || EVP_PKEY_is_a(pkey, "RSA-PSS")) { 968e1051a39Sopenharmony_ci BIGNUM *n = NULL; 969e1051a39Sopenharmony_ci 970e1051a39Sopenharmony_ci /* Every RSA key has an 'n' */ 971e1051a39Sopenharmony_ci EVP_PKEY_get_bn_param(pkey, "n", &n); 972e1051a39Sopenharmony_ci BN_print(out, n); 973e1051a39Sopenharmony_ci BN_free(n); 974e1051a39Sopenharmony_ci } else if (EVP_PKEY_is_a(pkey, "DSA")) { 975e1051a39Sopenharmony_ci BIGNUM *dsapub = NULL; 976e1051a39Sopenharmony_ci 977e1051a39Sopenharmony_ci /* Every DSA key has a 'pub' */ 978e1051a39Sopenharmony_ci EVP_PKEY_get_bn_param(pkey, "pub", &dsapub); 979e1051a39Sopenharmony_ci BN_print(out, dsapub); 980e1051a39Sopenharmony_ci BN_free(dsapub); 981e1051a39Sopenharmony_ci } else { 982e1051a39Sopenharmony_ci BIO_printf(out, "No modulus for this public key type"); 983e1051a39Sopenharmony_ci } 984e1051a39Sopenharmony_ci BIO_printf(out, "\n"); 985e1051a39Sopenharmony_ci } else if (i == print_pubkey) { 986e1051a39Sopenharmony_ci PEM_write_bio_PUBKEY(out, pkey); 987e1051a39Sopenharmony_ci } else if (i == text) { 988e1051a39Sopenharmony_ci X509_print_ex(out, x, get_nameopt(), certflag); 989e1051a39Sopenharmony_ci } else if (i == startdate) { 990e1051a39Sopenharmony_ci BIO_puts(out, "notBefore="); 991e1051a39Sopenharmony_ci ASN1_TIME_print_ex(out, X509_get0_notBefore(x), dateopt); 992e1051a39Sopenharmony_ci BIO_puts(out, "\n"); 993e1051a39Sopenharmony_ci } else if (i == enddate) { 994e1051a39Sopenharmony_ci BIO_puts(out, "notAfter="); 995e1051a39Sopenharmony_ci ASN1_TIME_print_ex(out, X509_get0_notAfter(x), dateopt); 996e1051a39Sopenharmony_ci BIO_puts(out, "\n"); 997e1051a39Sopenharmony_ci } else if (i == fingerprint) { 998e1051a39Sopenharmony_ci unsigned int n; 999e1051a39Sopenharmony_ci unsigned char md[EVP_MAX_MD_SIZE]; 1000e1051a39Sopenharmony_ci const char *fdigname = digest; 1001e1051a39Sopenharmony_ci EVP_MD *fdig; 1002e1051a39Sopenharmony_ci int digres; 1003e1051a39Sopenharmony_ci 1004e1051a39Sopenharmony_ci if (fdigname == NULL) 1005e1051a39Sopenharmony_ci fdigname = "SHA1"; 1006e1051a39Sopenharmony_ci 1007e1051a39Sopenharmony_ci if ((fdig = EVP_MD_fetch(app_get0_libctx(), fdigname, 1008e1051a39Sopenharmony_ci app_get0_propq())) == NULL) { 1009e1051a39Sopenharmony_ci BIO_printf(bio_err, "Unknown digest\n"); 1010e1051a39Sopenharmony_ci goto end; 1011e1051a39Sopenharmony_ci } 1012e1051a39Sopenharmony_ci digres = X509_digest(x, fdig, md, &n); 1013e1051a39Sopenharmony_ci EVP_MD_free(fdig); 1014e1051a39Sopenharmony_ci if (!digres) { 1015e1051a39Sopenharmony_ci BIO_printf(bio_err, "Out of memory\n"); 1016e1051a39Sopenharmony_ci goto end; 1017e1051a39Sopenharmony_ci } 1018e1051a39Sopenharmony_ci 1019e1051a39Sopenharmony_ci BIO_printf(out, "%s Fingerprint=", fdigname); 1020e1051a39Sopenharmony_ci for (j = 0; j < (int)n; j++) 1021e1051a39Sopenharmony_ci BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':'); 1022e1051a39Sopenharmony_ci } else if (i == ocspid) { 1023e1051a39Sopenharmony_ci X509_ocspid_print(out, x); 1024e1051a39Sopenharmony_ci } else if (i == ext) { 1025e1051a39Sopenharmony_ci print_x509v3_exts(out, x, ext_names); 1026e1051a39Sopenharmony_ci } 1027e1051a39Sopenharmony_ci } 1028e1051a39Sopenharmony_ci 1029e1051a39Sopenharmony_ci if (checkend) { 1030e1051a39Sopenharmony_ci time_t tcheck = time(NULL) + checkoffset; 1031e1051a39Sopenharmony_ci 1032e1051a39Sopenharmony_ci ret = X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0; 1033e1051a39Sopenharmony_ci if (ret) 1034e1051a39Sopenharmony_ci BIO_printf(out, "Certificate will expire\n"); 1035e1051a39Sopenharmony_ci else 1036e1051a39Sopenharmony_ci BIO_printf(out, "Certificate will not expire\n"); 1037e1051a39Sopenharmony_ci goto end; 1038e1051a39Sopenharmony_ci } 1039e1051a39Sopenharmony_ci 1040e1051a39Sopenharmony_ci print_cert_checks(out, x, checkhost, checkemail, checkip); 1041e1051a39Sopenharmony_ci 1042e1051a39Sopenharmony_ci if (noout || nocert) { 1043e1051a39Sopenharmony_ci ret = 0; 1044e1051a39Sopenharmony_ci goto end; 1045e1051a39Sopenharmony_ci } 1046e1051a39Sopenharmony_ci 1047e1051a39Sopenharmony_ci if (outformat == FORMAT_ASN1) { 1048e1051a39Sopenharmony_ci i = i2d_X509_bio(out, x); 1049e1051a39Sopenharmony_ci } else if (outformat == FORMAT_PEM) { 1050e1051a39Sopenharmony_ci if (trustout) 1051e1051a39Sopenharmony_ci i = PEM_write_bio_X509_AUX(out, x); 1052e1051a39Sopenharmony_ci else 1053e1051a39Sopenharmony_ci i = PEM_write_bio_X509(out, x); 1054e1051a39Sopenharmony_ci } else { 1055e1051a39Sopenharmony_ci BIO_printf(bio_err, "Bad output format specified for outfile\n"); 1056e1051a39Sopenharmony_ci goto end; 1057e1051a39Sopenharmony_ci } 1058e1051a39Sopenharmony_ci if (!i) { 1059e1051a39Sopenharmony_ci BIO_printf(bio_err, "Unable to write certificate\n"); 1060e1051a39Sopenharmony_ci goto end; 1061e1051a39Sopenharmony_ci } 1062e1051a39Sopenharmony_ci ret = 0; 1063e1051a39Sopenharmony_ci 1064e1051a39Sopenharmony_ci end: 1065e1051a39Sopenharmony_ci if (ret != 0) 1066e1051a39Sopenharmony_ci ERR_print_errors(bio_err); 1067e1051a39Sopenharmony_ci NCONF_free(extconf); 1068e1051a39Sopenharmony_ci BIO_free_all(out); 1069e1051a39Sopenharmony_ci X509_STORE_free(ctx); 1070e1051a39Sopenharmony_ci X509_NAME_free(fsubj); 1071e1051a39Sopenharmony_ci X509_REQ_free(req); 1072e1051a39Sopenharmony_ci X509_free(x); 1073e1051a39Sopenharmony_ci X509_free(xca); 1074e1051a39Sopenharmony_ci EVP_PKEY_free(privkey); 1075e1051a39Sopenharmony_ci EVP_PKEY_free(CAkey); 1076e1051a39Sopenharmony_ci EVP_PKEY_free(pubkey); 1077e1051a39Sopenharmony_ci sk_OPENSSL_STRING_free(sigopts); 1078e1051a39Sopenharmony_ci sk_OPENSSL_STRING_free(vfyopts); 1079e1051a39Sopenharmony_ci X509_REQ_free(rq); 1080e1051a39Sopenharmony_ci ASN1_INTEGER_free(sno); 1081e1051a39Sopenharmony_ci sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); 1082e1051a39Sopenharmony_ci sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free); 1083e1051a39Sopenharmony_ci release_engine(e); 1084e1051a39Sopenharmony_ci clear_free(passin); 1085e1051a39Sopenharmony_ci return ret; 1086e1051a39Sopenharmony_ci} 1087e1051a39Sopenharmony_ci 1088e1051a39Sopenharmony_cistatic ASN1_INTEGER *x509_load_serial(const char *CAfile, 1089e1051a39Sopenharmony_ci const char *serialfile, int create) 1090e1051a39Sopenharmony_ci{ 1091e1051a39Sopenharmony_ci char *buf = NULL; 1092e1051a39Sopenharmony_ci ASN1_INTEGER *bs = NULL; 1093e1051a39Sopenharmony_ci BIGNUM *serial = NULL; 1094e1051a39Sopenharmony_ci int defaultfile = 0, file_exists; 1095e1051a39Sopenharmony_ci 1096e1051a39Sopenharmony_ci if (serialfile == NULL) { 1097e1051a39Sopenharmony_ci const char *p = strrchr(CAfile, '.'); 1098e1051a39Sopenharmony_ci size_t len = p != NULL ? (size_t)(p - CAfile) : strlen(CAfile); 1099e1051a39Sopenharmony_ci 1100e1051a39Sopenharmony_ci buf = app_malloc(len + sizeof(POSTFIX), "serial# buffer"); 1101e1051a39Sopenharmony_ci memcpy(buf, CAfile, len); 1102e1051a39Sopenharmony_ci memcpy(buf + len, POSTFIX, sizeof(POSTFIX)); 1103e1051a39Sopenharmony_ci serialfile = buf; 1104e1051a39Sopenharmony_ci defaultfile = 1; 1105e1051a39Sopenharmony_ci } 1106e1051a39Sopenharmony_ci 1107e1051a39Sopenharmony_ci serial = load_serial(serialfile, &file_exists, create || defaultfile, NULL); 1108e1051a39Sopenharmony_ci if (serial == NULL) 1109e1051a39Sopenharmony_ci goto end; 1110e1051a39Sopenharmony_ci 1111e1051a39Sopenharmony_ci if (!BN_add_word(serial, 1)) { 1112e1051a39Sopenharmony_ci BIO_printf(bio_err, "Serial number increment failure\n"); 1113e1051a39Sopenharmony_ci goto end; 1114e1051a39Sopenharmony_ci } 1115e1051a39Sopenharmony_ci 1116e1051a39Sopenharmony_ci if (file_exists || create) 1117e1051a39Sopenharmony_ci save_serial(serialfile, NULL, serial, &bs); 1118e1051a39Sopenharmony_ci else 1119e1051a39Sopenharmony_ci bs = BN_to_ASN1_INTEGER(serial, NULL); 1120e1051a39Sopenharmony_ci 1121e1051a39Sopenharmony_ci end: 1122e1051a39Sopenharmony_ci OPENSSL_free(buf); 1123e1051a39Sopenharmony_ci BN_free(serial); 1124e1051a39Sopenharmony_ci return bs; 1125e1051a39Sopenharmony_ci} 1126e1051a39Sopenharmony_ci 1127e1051a39Sopenharmony_cistatic int callb(int ok, X509_STORE_CTX *ctx) 1128e1051a39Sopenharmony_ci{ 1129e1051a39Sopenharmony_ci int err; 1130e1051a39Sopenharmony_ci X509 *err_cert; 1131e1051a39Sopenharmony_ci 1132e1051a39Sopenharmony_ci /* 1133e1051a39Sopenharmony_ci * It is ok to use a self-signed certificate. This case will catch both 1134e1051a39Sopenharmony_ci * the initial ok == 0 and the final ok == 1 calls to this function. 1135e1051a39Sopenharmony_ci */ 1136e1051a39Sopenharmony_ci err = X509_STORE_CTX_get_error(ctx); 1137e1051a39Sopenharmony_ci if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) 1138e1051a39Sopenharmony_ci return 1; 1139e1051a39Sopenharmony_ci 1140e1051a39Sopenharmony_ci /* 1141e1051a39Sopenharmony_ci * BAD we should have gotten an error. Normally if everything worked 1142e1051a39Sopenharmony_ci * X509_STORE_CTX_get_error(ctx) will still be set to 1143e1051a39Sopenharmony_ci * DEPTH_ZERO_SELF_.... 1144e1051a39Sopenharmony_ci */ 1145e1051a39Sopenharmony_ci if (ok) { 1146e1051a39Sopenharmony_ci BIO_printf(bio_err, 1147e1051a39Sopenharmony_ci "Error with certificate to be certified - should be self-signed\n"); 1148e1051a39Sopenharmony_ci return 0; 1149e1051a39Sopenharmony_ci } else { 1150e1051a39Sopenharmony_ci err_cert = X509_STORE_CTX_get_current_cert(ctx); 1151e1051a39Sopenharmony_ci print_name(bio_err, "subject=", X509_get_subject_name(err_cert)); 1152e1051a39Sopenharmony_ci BIO_printf(bio_err, 1153e1051a39Sopenharmony_ci "Error with certificate - error %d at depth %d\n%s\n", err, 1154e1051a39Sopenharmony_ci X509_STORE_CTX_get_error_depth(ctx), 1155e1051a39Sopenharmony_ci X509_verify_cert_error_string(err)); 1156e1051a39Sopenharmony_ci return 1; 1157e1051a39Sopenharmony_ci } 1158e1051a39Sopenharmony_ci} 1159e1051a39Sopenharmony_ci 1160e1051a39Sopenharmony_cistatic int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt) 1161e1051a39Sopenharmony_ci{ 1162e1051a39Sopenharmony_ci int id, i, idret; 1163e1051a39Sopenharmony_ci const char *pname; 1164e1051a39Sopenharmony_ci id = X509_PURPOSE_get_id(pt); 1165e1051a39Sopenharmony_ci pname = X509_PURPOSE_get0_name(pt); 1166e1051a39Sopenharmony_ci for (i = 0; i < 2; i++) { 1167e1051a39Sopenharmony_ci idret = X509_check_purpose(cert, id, i); 1168e1051a39Sopenharmony_ci BIO_printf(bio, "%s%s : ", pname, i ? " CA" : ""); 1169e1051a39Sopenharmony_ci if (idret == 1) 1170e1051a39Sopenharmony_ci BIO_printf(bio, "Yes\n"); 1171e1051a39Sopenharmony_ci else if (idret == 0) 1172e1051a39Sopenharmony_ci BIO_printf(bio, "No\n"); 1173e1051a39Sopenharmony_ci else 1174e1051a39Sopenharmony_ci BIO_printf(bio, "Yes (WARNING code=%d)\n", idret); 1175e1051a39Sopenharmony_ci } 1176e1051a39Sopenharmony_ci return 1; 1177e1051a39Sopenharmony_ci} 1178e1051a39Sopenharmony_ci 1179e1051a39Sopenharmony_cistatic int parse_ext_names(char *names, const char **result) 1180e1051a39Sopenharmony_ci{ 1181e1051a39Sopenharmony_ci char *p, *q; 1182e1051a39Sopenharmony_ci int cnt = 0, len = 0; 1183e1051a39Sopenharmony_ci 1184e1051a39Sopenharmony_ci p = q = names; 1185e1051a39Sopenharmony_ci len = strlen(names); 1186e1051a39Sopenharmony_ci 1187e1051a39Sopenharmony_ci while (q - names <= len) { 1188e1051a39Sopenharmony_ci if (*q != ',' && *q != '\0') { 1189e1051a39Sopenharmony_ci q++; 1190e1051a39Sopenharmony_ci continue; 1191e1051a39Sopenharmony_ci } 1192e1051a39Sopenharmony_ci if (p != q) { 1193e1051a39Sopenharmony_ci /* found */ 1194e1051a39Sopenharmony_ci if (result != NULL) { 1195e1051a39Sopenharmony_ci result[cnt] = p; 1196e1051a39Sopenharmony_ci *q = '\0'; 1197e1051a39Sopenharmony_ci } 1198e1051a39Sopenharmony_ci cnt++; 1199e1051a39Sopenharmony_ci } 1200e1051a39Sopenharmony_ci p = ++q; 1201e1051a39Sopenharmony_ci } 1202e1051a39Sopenharmony_ci 1203e1051a39Sopenharmony_ci return cnt; 1204e1051a39Sopenharmony_ci} 1205e1051a39Sopenharmony_ci 1206e1051a39Sopenharmony_cistatic int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names) 1207e1051a39Sopenharmony_ci{ 1208e1051a39Sopenharmony_ci const STACK_OF(X509_EXTENSION) *exts = NULL; 1209e1051a39Sopenharmony_ci STACK_OF(X509_EXTENSION) *exts2 = NULL; 1210e1051a39Sopenharmony_ci X509_EXTENSION *ext = NULL; 1211e1051a39Sopenharmony_ci ASN1_OBJECT *obj; 1212e1051a39Sopenharmony_ci int i, j, ret = 0, num, nn = 0; 1213e1051a39Sopenharmony_ci const char *sn, **names = NULL; 1214e1051a39Sopenharmony_ci char *tmp_ext_names = NULL; 1215e1051a39Sopenharmony_ci 1216e1051a39Sopenharmony_ci exts = X509_get0_extensions(x); 1217e1051a39Sopenharmony_ci if ((num = sk_X509_EXTENSION_num(exts)) <= 0) { 1218e1051a39Sopenharmony_ci BIO_printf(bio_err, "No extensions in certificate\n"); 1219e1051a39Sopenharmony_ci ret = 1; 1220e1051a39Sopenharmony_ci goto end; 1221e1051a39Sopenharmony_ci } 1222e1051a39Sopenharmony_ci 1223e1051a39Sopenharmony_ci /* parse comma separated ext name string */ 1224e1051a39Sopenharmony_ci if ((tmp_ext_names = OPENSSL_strdup(ext_names)) == NULL) 1225e1051a39Sopenharmony_ci goto end; 1226e1051a39Sopenharmony_ci if ((nn = parse_ext_names(tmp_ext_names, NULL)) == 0) { 1227e1051a39Sopenharmony_ci BIO_printf(bio, "Invalid extension names: %s\n", ext_names); 1228e1051a39Sopenharmony_ci goto end; 1229e1051a39Sopenharmony_ci } 1230e1051a39Sopenharmony_ci if ((names = OPENSSL_malloc(sizeof(char *) * nn)) == NULL) 1231e1051a39Sopenharmony_ci goto end; 1232e1051a39Sopenharmony_ci parse_ext_names(tmp_ext_names, names); 1233e1051a39Sopenharmony_ci 1234e1051a39Sopenharmony_ci for (i = 0; i < num; i++) { 1235e1051a39Sopenharmony_ci ext = sk_X509_EXTENSION_value(exts, i); 1236e1051a39Sopenharmony_ci 1237e1051a39Sopenharmony_ci /* check if this ext is what we want */ 1238e1051a39Sopenharmony_ci obj = X509_EXTENSION_get_object(ext); 1239e1051a39Sopenharmony_ci sn = OBJ_nid2sn(OBJ_obj2nid(obj)); 1240e1051a39Sopenharmony_ci if (sn == NULL || strcmp(sn, "UNDEF") == 0) 1241e1051a39Sopenharmony_ci continue; 1242e1051a39Sopenharmony_ci 1243e1051a39Sopenharmony_ci for (j = 0; j < nn; j++) { 1244e1051a39Sopenharmony_ci if (strcmp(sn, names[j]) == 0) { 1245e1051a39Sopenharmony_ci /* push the extension into a new stack */ 1246e1051a39Sopenharmony_ci if (exts2 == NULL 1247e1051a39Sopenharmony_ci && (exts2 = sk_X509_EXTENSION_new_null()) == NULL) 1248e1051a39Sopenharmony_ci goto end; 1249e1051a39Sopenharmony_ci if (!sk_X509_EXTENSION_push(exts2, ext)) 1250e1051a39Sopenharmony_ci goto end; 1251e1051a39Sopenharmony_ci } 1252e1051a39Sopenharmony_ci } 1253e1051a39Sopenharmony_ci } 1254e1051a39Sopenharmony_ci 1255e1051a39Sopenharmony_ci if (!sk_X509_EXTENSION_num(exts2)) { 1256e1051a39Sopenharmony_ci BIO_printf(bio, "No extensions matched with %s\n", ext_names); 1257e1051a39Sopenharmony_ci ret = 1; 1258e1051a39Sopenharmony_ci goto end; 1259e1051a39Sopenharmony_ci } 1260e1051a39Sopenharmony_ci 1261e1051a39Sopenharmony_ci ret = X509V3_extensions_print(bio, NULL, exts2, 0, 0); 1262e1051a39Sopenharmony_ci end: 1263e1051a39Sopenharmony_ci sk_X509_EXTENSION_free(exts2); 1264e1051a39Sopenharmony_ci OPENSSL_free(names); 1265e1051a39Sopenharmony_ci OPENSSL_free(tmp_ext_names); 1266e1051a39Sopenharmony_ci return ret; 1267e1051a39Sopenharmony_ci} 1268