[openssl] master update

dev at ddvo.net dev at ddvo.net
Wed Jan 20 15:01:13 UTC 2021


The branch master has been updated
       via  d8ab30be9cc4d4e77008d4037e696bc41ce293f8 (commit)
       via  05458fdb73dcca30edace5ad727a15d6d919e215 (commit)
       via  b9fbacaa7bdce2083186211b3cdf8511ad4cb91d (commit)
       via  1d1d23128f2bfc24d98a973e48e4eb1555d24880 (commit)
       via  03f4e3ded67ed4eacf0849f05c73222a56d4f8ef (commit)
       via  2367238ced66d5da07e104aa9d8ab1e1eae64ec4 (commit)
       via  db6a47b10d3daad512fc08950d8329891209a4f4 (commit)
       via  743975c7e5e7a6bd5fafba2fc09c5942a833bfe3 (commit)
       via  b24cfd6bf4d68ffe2b8526b5375861e89c5b9414 (commit)
       via  7c5237e1d7947e68bb100a2e170518ed0d74a20a (commit)
       via  49b36afb0b4bcd7ba2dde511f20095e15130aba6 (commit)
       via  abc4439c925bbc867180ba024c42583e6836aaeb (commit)
       via  8cadc51706e1383febe2c1a5965b19c5b86e05a6 (commit)
      from  63162e3d55e38aff51e243212bc73aa27bed8c4c (commit)


- Log -----------------------------------------------------------------
commit d8ab30be9cc4d4e77008d4037e696bc41ce293f8
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Fri Jan 8 23:18:19 2021 +0100

    X509v3_get_ext_by_NID.pod: Add warning on counter-intuitive behavior of X509v3_delete_ext() etc.
    
    Also simplify two uses of these functions.
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13711)

commit 05458fdb73dcca30edace5ad727a15d6d919e215
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Fri Jan 8 17:43:13 2021 +0100

    apps/x509.c: Make -x509toreq respect -clrext, -sigopt, and -extfile options
    
    Also prevent copying SKID and AKID extension, which make no sense in CSRs
    and extend the use -ext to select with extensions are copied.
    Further simplifiy the overall structure of the code.
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13711)

commit b9fbacaa7bdce2083186211b3cdf8511ad4cb91d
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Wed Jan 6 14:44:03 2021 +0100

    apps/x509.c: Add -copy_extensions option, used when transforming x509 <-> req
    
    Fixes #3638
    Fixes #6481
    Fixes #10458
    Partly fixes #13708
    Supersedes #9449
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13711)

commit 1d1d23128f2bfc24d98a973e48e4eb1555d24880
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Wed Jan 6 14:32:21 2021 +0100

    80-test_ssl_old.t: Minor corrections: update name of test dir etc.
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13711)

commit 03f4e3ded67ed4eacf0849f05c73222a56d4f8ef
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Wed Jan 6 12:57:27 2021 +0100

    apps.c: Clean up copy_extensions()
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13711)

commit 2367238ced66d5da07e104aa9d8ab1e1eae64ec4
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Wed Jan 6 11:49:36 2021 +0100

    X509_REQ_print_ex(): Correct indentation of extensions, which are attributes
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13711)

commit db6a47b10d3daad512fc08950d8329891209a4f4
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Wed Jan 6 11:27:55 2021 +0100

    X509_REQ_print_ex(): Replace weird 'a0:00' output on empty attributes by '(none)'
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13711)

commit 743975c7e5e7a6bd5fafba2fc09c5942a833bfe3
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Tue Jan 5 23:07:07 2021 +0100

    constify X509_REQ_add_extensions() and X509_REQ_add_extensions_nid()
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13711)

commit b24cfd6bf4d68ffe2b8526b5375861e89c5b9414
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Sat Dec 19 17:42:51 2020 +0100

    apps/x509.c: Major code, user guidance, and documentation cleanup
    
    This brings the options in help output and doc in reasonable order
    and fixes various corner cases of option use combinations
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13711)

commit 7c5237e1d7947e68bb100a2e170518ed0d74a20a
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Thu Dec 10 17:31:10 2020 +0100

    apps/x509.c: Take the -signkey arg as default pubkey with -new
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13711)

commit 49b36afb0b4bcd7ba2dde511f20095e15130aba6
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Thu Dec 10 17:01:45 2020 +0100

    25-test_x509.t: Make test case w.r.t. self-issued cert run also without EC enabled
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13711)

commit abc4439c925bbc867180ba024c42583e6836aaeb
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Thu Dec 10 16:41:03 2020 +0100

    25-test_x509.t: Minor update: factor out path for test input files
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13711)

commit 8cadc51706e1383febe2c1a5965b19c5b86e05a6
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Thu Dec 10 16:32:13 2020 +0100

    25-test_x509.t: Minor update: do not anymore unlink test output files
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13711)

-----------------------------------------------------------------------

Summary of changes:
 CHANGES.md                         |  24 +-
 apps/lib/apps.c                    |  27 +-
 apps/x509.c                        | 703 ++++++++++++++++++++-----------------
 crypto/ct/ct_sct_ctx.c             |   5 +-
 crypto/x509/t_req.c                |  10 +-
 crypto/x509/v3_conf.c              |   8 +-
 crypto/x509/x509_req.c             |  10 +-
 doc/man1/openssl-x509.pod.in       | 676 ++++++++++++++++++-----------------
 doc/man3/X509v3_get_ext_by_NID.pod |  11 +-
 include/openssl/x509.h.in          |   6 +-
 test/recipes/25-test_x509.t        |  69 ++--
 test/recipes/80-test_ssl_old.t     |   8 +-
 12 files changed, 825 insertions(+), 732 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index cd093491be..8ae1c7470a 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -929,19 +929,25 @@ OpenSSL 3.0
 
    *Richard Levitte*
 
- * Added the `<-copy_extensions` option to the `req` command for use with `-x509`.
-   When given with the `copy` or `copyall` argument,
-   any extensions present in the certification request are copied to the certificate.
+ * Added the `-copy_extensions` option to the `x509` command for use with
+   `-req` and `-x509toreq`. When given with the `copy` or `copyall` argument,
+   all extensions in the request are copied to the certificate or vice versa.
+
+   *David von Oheimb*, *Kirill Stefanenkov <kirill_stefanenkov at rambler.ru>*
+
+ * Added the `-copy_extensions` option to the `req` command for use with
+   `-x509`. When given with the `copy` or `copyall` argument,
+   all extensions in the certification request are copied to the certificate.
 
    *David von Oheimb*
 
- * The `x509`, `req`, and `ca` commands now make sure that certificates they
-   generate are RFC 5280 compliant by default: For X.509 version 3 certs they ensure that
-   a subjectKeyIdentifier extension is included containing a hash value of the public key
-   and an authorityKeyIdentifier extension is included for not self-signed certs
-   containing a keyIdentifier field with the hash value identifying the signing key.
+ * The `x509`, `req`, and `ca` commands now make sure that X.509v3 certificates
+   they generate are by default RFC 5280 compliant in the following sense:
+   There is a subjectKeyIdentifier extension with a hash value of the public key
+   and for not self-signed certs there is an authorityKeyIdentifier extension
+   with a keyIdentifier field or issuer information identifying the signing key.
    This is done unless some configuration overrides the new default behavior,
-   e.g. `authorityKeyIdentifier = none`.
+   such as `subjectKeyIdentifier = none` and `authorityKeyIdentifier = none`.
 
    *David von Oheimb*
 
diff --git a/apps/lib/apps.c b/apps/lib/apps.c
index d5654d9dc9..30d026bdef 100644
--- a/apps/lib/apps.c
+++ b/apps/lib/apps.c
@@ -968,41 +968,38 @@ int set_ext_copy(int *copy_type, const char *arg)
 
 int copy_extensions(X509 *x, X509_REQ *req, int copy_type)
 {
-    STACK_OF(X509_EXTENSION) *exts = NULL;
-    X509_EXTENSION *ext, *tmpext;
-    ASN1_OBJECT *obj;
-    int i, idx, ret = 0;
-    if (!x || !req || (copy_type == EXT_COPY_NONE))
+    STACK_OF(X509_EXTENSION) *exts;
+    int i, ret = 0;
+
+    if (x == NULL || req == NULL)
+        return 0;
+    if (copy_type == EXT_COPY_NONE)
         return 1;
     exts = X509_REQ_get_extensions(req);
 
     for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
-        ext = sk_X509_EXTENSION_value(exts, i);
-        obj = X509_EXTENSION_get_object(ext);
-        idx = X509_get_ext_by_OBJ(x, obj, -1);
-        /* Does extension exist? */
+        X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
+        ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext);
+        int idx = X509_get_ext_by_OBJ(x, obj, -1);
+
+        /* Does extension exist in target? */
         if (idx != -1) {
             /* If normal copy don't override existing extension */
             if (copy_type == EXT_COPY_ADD)
                 continue;
             /* Delete all extensions of same type */
             do {
-                tmpext = X509_get_ext(x, idx);
-                X509_delete_ext(x, idx);
-                X509_EXTENSION_free(tmpext);
+                X509_EXTENSION_free(X509_delete_ext(x, idx));
                 idx = X509_get_ext_by_OBJ(x, obj, -1);
             } while (idx != -1);
         }
         if (!X509_add_ext(x, ext, -1))
             goto end;
     }
-
     ret = 1;
 
  end:
-
     sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
-
     return ret;
 }
 
diff --git a/apps/x509.c b/apps/x509.c
index 5769f5f982..7ffcc121af 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -28,22 +28,15 @@
 
 #undef POSTFIX
 #define POSTFIX ".srl"
-#define DEF_DAYS        30
+#define DEFAULT_DAYS    30 /* default cert validity period in days */
+#define UNSET_DAYS      -2 /* -1 is used for testing expiration checks */
+#define EXT_COPY_UNSET     -1
 
 static int callb(int ok, X509_STORE_CTX *ctx);
-static int sign(X509 *x, EVP_PKEY *pkey, X509 *issuer,
-                STACK_OF(OPENSSL_STRING) *sigopts,
-                int days, int clrext,
-                const EVP_MD *digest, CONF *conf, const char *section,
-                int preserve_dates);
-static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest,
-                        X509 *x, X509 *xca, EVP_PKEY *pkey,
-                        STACK_OF(OPENSSL_STRING) *sigopts, const char *serialfile,
-                        int create, int days, int clrext, CONF *conf,
-                        const char *section, ASN1_INTEGER *sno, int reqfile,
-                        int preserve_dates);
+static ASN1_INTEGER *x509_load_serial(const char *CAfile,
+                                      const char *serialfile, int create);
 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
-static int print_x509v3_exts(BIO *bio, X509 *x, const char *exts);
+static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names);
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
@@ -58,8 +51,7 @@ typedef enum OPTION_choice {
     OPT_PURPOSE, OPT_STARTDATE, OPT_ENDDATE, OPT_CHECKEND, OPT_CHECKHOST,
     OPT_CHECKEMAIL, OPT_CHECKIP, OPT_NOOUT, OPT_TRUSTOUT, OPT_CLRTRUST,
     OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID,
-    OPT_SUBJECT_HASH_OLD,
-    OPT_ISSUER_HASH_OLD,
+    OPT_SUBJECT_HASH_OLD, OPT_ISSUER_HASH_OLD, OPT_COPY_EXTENSIONS,
     OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES,
     OPT_R_ENUM, OPT_PROV_ENUM, OPT_EXT
 } OPTION_CHOICE;
@@ -67,107 +59,192 @@ typedef enum OPTION_choice {
 const OPTIONS x509_options[] = {
     OPT_SECTION("General"),
     {"help", OPT_HELP, '-', "Display this summary"},
-#ifndef OPENSSL_NO_ENGINE
-    {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
-#endif
 
-    {"inform", OPT_INFORM, 'f',
-     "CSR input format (DER or PEM) - default PEM"},
-    {"in", OPT_IN, '<', "Input file - default stdin"},
+    {"in", OPT_IN, '<',
+     "Certificate input (default stdin), or CSR input file with -req"},
     {"passin", OPT_PASSIN, 's', "Private key and cert file pass-phrase source"},
+    {"new", OPT_NEW, '-', "Generate a certificate from scratch"},
+    {"x509toreq", OPT_X509TOREQ, '-',
+     "Output a certification request (rather than a certificate)"},
+    {"req", OPT_REQ, '-', "Input is a CSR file (rather than a certificate)"},
+    {"copy_extensions", OPT_COPY_EXTENSIONS, 's',
+     "copy extensions when converting from CSR to x509 or vice versa"},
+    {"inform", OPT_INFORM, 'f',
+     "CSR input file format (DER or PEM) - default PEM"},
+    {"vfyopt", OPT_VFYOPT, 's', "CSR verification parameter in n:v form"},
+    {"signkey", OPT_SIGNKEY, 's',
+     "Key used to self-sign certificate or cert request"},
+    {"keyform", OPT_KEYFORM, 'E',
+     "Key input format (ENGINE, other values ignored)"},
+    {"out", OPT_OUT, '>', "Output file - default stdout"},
     {"outform", OPT_OUTFORM, 'f',
      "Output format (DER or PEM) - default PEM"},
-    {"out", OPT_OUT, '>', "Output file - default stdout"},
-    {"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"},
-    {"req", OPT_REQ, '-', "Input is a certificate request, sign and output"},
-    {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"},
+    {"nocert", OPT_NOCERT, '-',
+     "No cert output (except for requested printing)"},
+    {"noout", OPT_NOOUT, '-', "No output (except for requested printing)"},
 
-    OPT_SECTION("Output"),
+    OPT_SECTION("Certificate printing"),
+    {"text", OPT_TEXT, '-', "Print the certificate in text form"},
+    {"certopt", OPT_CERTOPT, 's', "Various certificate text printing options"},
+    {"fingerprint", OPT_FINGERPRINT, '-', "Print the certificate fingerprint"},
+    {"alias", OPT_ALIAS, '-', "Print certificate alias"},
     {"serial", OPT_SERIAL, '-', "Print serial number value"},
-    {"subject_hash", OPT_HASH, '-', "Print subject hash value"},
-    {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"},
-    {"hash", OPT_HASH, '-', "Synonym for -subject_hash"},
+    {"startdate", OPT_STARTDATE, '-', "Print the notBefore field"},
+    {"enddate", OPT_ENDDATE, '-', "Print the notAfter field"},
+    {"dates", OPT_DATES, '-', "Print both notBefore and notAfter fields"},
     {"subject", OPT_SUBJECT, '-', "Print subject DN"},
     {"issuer", OPT_ISSUER, '-', "Print issuer DN"},
+    {"nameopt", OPT_NAMEOPT, 's',
+     "Certificate subject/issuer name printing options"},
     {"email", OPT_EMAIL, '-', "Print email address(es)"},
-    {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"},
-    {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"},
-    {"pubkey", OPT_PUBKEY, '-', "Output the public key"},
-    {"fingerprint", OPT_FINGERPRINT, '-', "Print the certificate fingerprint"},
-    {"alias", OPT_ALIAS, '-', "Output certificate alias"},
-    {"noout", OPT_NOOUT, '-', "No output, just status"},
-    {"ocspid", OPT_OCSPID, '-',
-     "Print OCSP hash values for the subject name and public key"},
-    {"ocsp_uri", OPT_OCSP_URI, '-', "Print OCSP Responder URL(s)"},
-    {"nocert", OPT_NOCERT, '-', "No certificate output"},
-    {"trustout", OPT_TRUSTOUT, '-', "Output a trusted certificate"},
-    {"x509toreq", OPT_X509TOREQ, '-',
-     "Output a certification request object"},
-    {"checkend", OPT_CHECKEND, 'M',
-     "Check whether the cert expires in the next arg seconds"},
-    {OPT_MORE_STR, 1, 1, "Exit 1 if so, 0 if not"},
-    {"text", OPT_TEXT, '-', "Print the certificate in text form"},
-    {"ext", OPT_EXT, 's', "Print various X509V3 extensions"},
+    {"hash", OPT_HASH, '-', "Synonym for -subject_hash (for backward compat)"},
+    {"subject_hash", OPT_HASH, '-', "Print subject hash value"},
 #ifndef OPENSSL_NO_MD5
     {"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-',
      "Print old-style (MD5) subject hash value"},
+#endif
+    {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"},
+#ifndef OPENSSL_NO_MD5
     {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-',
      "Print old-style (MD5) issuer hash value"},
 #endif
-    {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
+    {"ext", OPT_EXT, 's',
+     "Restrict which X.509 extensions to print and/or copy"},
+    {"ocspid", OPT_OCSPID, '-',
+     "Print OCSP hash values for the subject name and public key"},
+    {"ocsp_uri", OPT_OCSP_URI, '-', "Print OCSP Responder URL(s)"},
+    {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"},
+    {"pubkey", OPT_PUBKEY, '-', "Print the public key in PEM format"},
+    {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"},
 
-    OPT_SECTION("Certificate"),
-    {"startdate", OPT_STARTDATE, '-', "Set notBefore field"},
-    {"enddate", OPT_ENDDATE, '-', "Set notAfter field"},
-    {"dates", OPT_DATES, '-', "Both Before and After dates"},
-    {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"},
-    {"clrext", OPT_CLREXT, '-', "Clear all certificate extensions"},
-    {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"},
-    {"addreject", OPT_ADDREJECT, 's',
-     "Reject certificate for a given purpose"},
-    {"setalias", OPT_SETALIAS, 's', "Set certificate alias"},
-    {"days", OPT_DAYS, 'n',
-     "How long till expiry of a signed certificate - def 30 days"},
-    {"signkey", OPT_SIGNKEY, 's', "Self-sign cert with arg"},
-    {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"},
-    {"extensions", OPT_EXTENSIONS, 's', "Section from config file to use"},
-    {"certopt", OPT_CERTOPT, 's', "Various certificate text options"},
+    OPT_SECTION("Certificate checking"),
+    {"checkend", OPT_CHECKEND, 'M',
+     "Check whether cert expires in the next arg seconds"},
+    {OPT_MORE_STR, 1, 1, "Exit 1 (failure) if so, 0 if not"},
     {"checkhost", OPT_CHECKHOST, 's', "Check certificate matches host"},
     {"checkemail", OPT_CHECKEMAIL, 's', "Check certificate matches email"},
     {"checkip", OPT_CHECKIP, 's', "Check certificate matches ipaddr"},
-    {"force_pubkey", OPT_FORCE_PUBKEY, '<', "Force the key to put inside certificate"},
-    {"subj", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"},
 
-    OPT_SECTION("CA"),
-    {"CA", OPT_CA, '<', "Set the CA certificate, must be PEM format"},
-    {"CAkey", OPT_CAKEY, 's',
-     "The CA key, must be PEM format; if not in CAfile"},
-    {"extfile", OPT_EXTFILE, '<', "File with X509V3 extensions to add"},
-    OPT_R_OPTIONS,
-    OPT_PROV_OPTIONS,
+    OPT_SECTION("Certificate output"),
+    {"set_serial", OPT_SET_SERIAL, 's',
+     "Serial number to use, overrides -CAserial"},
+    {"next_serial", OPT_NEXT_SERIAL, '-',
+     "Increment current certificate serial number"},
+    {"days", OPT_DAYS, 'n',
+     "Number of days until newly generated certificate expires - default 30"},
+    {"preserve_dates", OPT_PRESERVE_DATES, '-',
+     "Preserve existing validity dates"},
+    {"subj", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"},
+    {"force_pubkey", OPT_FORCE_PUBKEY, '<',
+     "Place the given key in new certificate"},
+    {"clrext", OPT_CLREXT, '-',
+     "Do not take over any extensions from the source certificate or request"},
+    {"extfile", OPT_EXTFILE, '<', "Config file with X509V3 extensions to add"},
+    {"extensions", OPT_EXTENSIONS, 's',
+     "Section of extfile to use - default: unnamed section"},
+    {"sigopt", OPT_SIGOPT, 's', "Signature parameter, in n:v form"},
+    {"badsig", OPT_BADSIG, '-',
+     "Corrupt last byte of certificate signature (for test)"},
+    {"", OPT_MD, '-', "Any supported digest, used for signing and printing"},
+
+    OPT_SECTION("Micro-CA"),
+    {"CA", OPT_CA, '<',
+     "Use the given CA certificate, conflicts with -signkey"},
     {"CAform", OPT_CAFORM, 'F', "CA cert format (PEM/DER/P12); has no effect"},
-    {"CAkeyform", OPT_CAKEYFORM, 'E', "CA key format (ENGINE, other values ignored)"},
-    {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
+    {"CAkey", OPT_CAKEY, 's', "The corresponding CA key; default is -CA arg"},
+    {"CAkeyform", OPT_CAKEYFORM, 'E',
+     "CA key format (ENGINE, other values ignored)"},
+    {"CAserial", OPT_CASERIAL, 's',
+     "File that keeps track of CA-generated serial number"},
     {"CAcreateserial", OPT_CACREATESERIAL, '-',
-     "Create serial number file if it does not exist"},
-    {"CAserial", OPT_CASERIAL, 's', "Serial file"},
-    {"new", OPT_NEW, '-', "Generate a certificate from scratch"},
-    {"next_serial", OPT_NEXT_SERIAL, '-', "Increment current certificate serial number"},
+     "Create CA serial number file if it does not exist"},
+
+    OPT_SECTION("Certificate trust output"),
+    {"trustout", OPT_TRUSTOUT, '-', "Mark certificate PEM output as trusted"},
+    {"setalias", OPT_SETALIAS, 's', "Set certificate alias (nickname)"},
+    {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"},
+    {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"},
     {"clrreject", OPT_CLRREJECT, '-',
      "Clears all the prohibited or rejected uses of the certificate"},
-    {"badsig", OPT_BADSIG, '-', "Corrupt last byte of certificate signature (for test)"},
-    {"", OPT_MD, '-', "Any supported digest"},
-    {"preserve_dates", OPT_PRESERVE_DATES, '-', "preserve existing dates when signing"},
+    {"addreject", OPT_ADDREJECT, 's',
+     "Reject certificate for a given purpose"},
+
+    OPT_R_OPTIONS,
+#ifndef OPENSSL_NO_ENGINE
+    {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
+#endif
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
+static void warn_copying(ASN1_OBJECT *excluded, const char *names)
+{
+    const char *sn = OBJ_nid2sn(OBJ_obj2nid(excluded));
+
+    if (names != NULL && strstr(names, sn) != NULL)
+        BIO_printf(bio_err,
+                   "Warning: -ext should not specify copying %s extension to CSR; ignoring this\n",
+                   sn);
+}
+
+static X509_REQ *x509_to_req(X509 *cert, EVP_PKEY *pkey, const EVP_MD *digest,
+                             STACK_OF(OPENSSL_STRING) *sigopts,
+                             int ext_copy, const char *names)
+{
+    const STACK_OF(X509_EXTENSION) *cert_exts = X509_get0_extensions(cert);
+    int i, n = sk_X509_EXTENSION_num(cert_exts /* may be NULL */);
+    ASN1_OBJECT *skid = OBJ_nid2obj(NID_subject_key_identifier);
+    ASN1_OBJECT *akid = OBJ_nid2obj(NID_authority_key_identifier);
+    STACK_OF(X509_EXTENSION) *exts;
+    X509_REQ *req = X509_to_X509_REQ(cert, NULL, NULL);
+
+    if (req == NULL)
+        return NULL;
+
+    /*
+     * Filter out SKID and AKID extensions, which make no sense in a CSR.
+     * If names is not NULL, copy only those extensions listed there.
+     */
+    warn_copying(skid, names);
+    warn_copying(akid, names);
+    if ((exts = sk_X509_EXTENSION_new_reserve(NULL, n)) == NULL)
+        goto err;
+    for (i = 0; i < n; i++) {
+        X509_EXTENSION *ex = sk_X509_EXTENSION_value(cert_exts, i);
+        ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex);
+
+        if (OBJ_cmp(obj, skid) != 0 && OBJ_cmp(obj, akid) != 0
+                && !sk_X509_EXTENSION_push(exts, ex))
+            goto err;
+    }
+
+    if (sk_X509_EXTENSION_num(exts) > 0) {
+        if (ext_copy != EXT_COPY_UNSET && ext_copy != EXT_COPY_NONE
+                && !X509_REQ_add_extensions(req, exts)) {
+            BIO_printf(bio_err, "Error copying extensions from certificate\n");
+            goto err;
+        }
+    }
+    if (!do_X509_REQ_sign(req, pkey, digest, sigopts))
+        goto err;
+    sk_X509_EXTENSION_free(exts);
+    return req;
+
+ err:
+    sk_X509_EXTENSION_free(exts);
+    X509_REQ_free(req);
+    return NULL;
+}
+
 int x509_main(int argc, char **argv)
 {
     ASN1_INTEGER *sno = NULL;
     ASN1_OBJECT *objtmp = NULL;
     BIO *out = NULL;
     CONF *extconf = NULL;
-    EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL;
+    int ext_copy = EXT_COPY_UNSET;
+    X509V3_CTX ext_ctx;
+    EVP_PKEY *signkey = NULL, *CAkey = NULL, *pubkey = NULL;
     int newcert = 0;
     char *subj = NULL;
     X509_NAME *fsubj = NULL;
@@ -175,21 +252,23 @@ int x509_main(int argc, char **argv)
     const int multirdn = 1;
     STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
     STACK_OF(OPENSSL_STRING) *sigopts = NULL, *vfyopts = NULL;
-    X509 *x = NULL, *xca = NULL;
+    X509 *x = NULL, *xca = NULL, *issuer_cert;
     X509_REQ *req = NULL, *rq = NULL;
     X509_STORE *ctx = NULL;
     const EVP_MD *digest = NULL;
-    char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL;
-    char *checkhost = NULL, *checkemail = NULL, *checkip = NULL, *exts = NULL;
+    char *CAkeyfile = NULL, *CAserial = NULL, *pubkeyfile = NULL, *alias = NULL;
+    char *checkhost = NULL, *checkemail = NULL, *checkip = NULL;
+    char *ext_names = NULL;
     char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL;
-    char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
+    char *infile = NULL, *outfile = NULL, *signkeyfile = NULL, *CAfile = NULL;
     char *prog;
-    int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0;
+    int days = UNSET_DAYS; /* not explicitly set */
+    int x509toreq = 0, modulus = 0, print_pubkey = 0, pprint = 0;
     int CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM;
     int fingerprint = 0, reqfile = 0, checkend = 0;
     int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
     int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0;
-    int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0;
+    int noout = 0, CA_createserial = 0, email = 0;
     int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0;
     int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0;
     int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0, ext = 0;
@@ -249,6 +328,13 @@ int x509_main(int argc, char **argv)
         case OPT_REQ:
             reqfile = 1;
             break;
+        case OPT_COPY_EXTENSIONS:
+            if (!set_ext_copy(&ext_copy, opt_arg())) {
+                BIO_printf(bio_err,
+                           "Invalid extension copy option: %s\n", opt_arg());
+                goto end;
+            }
+            break;
 
         case OPT_SIGOPT:
             if (!sigopts)
@@ -263,9 +349,12 @@ int x509_main(int argc, char **argv)
                 goto opthelp;
             break;
         case OPT_DAYS:
-            if (preserve_dates)
-                goto opthelp;
             days = atoi(opt_arg());
+            if (days < -1) {
+                BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n",
+                           prog);
+                goto end;
+            }
             break;
         case OPT_PASSIN:
             passinarg = opt_arg();
@@ -285,12 +374,10 @@ int x509_main(int argc, char **argv)
             extsect = opt_arg();
             break;
         case OPT_SIGNKEY:
-            keyfile = opt_arg();
-            sign_flag = ++num;
+            signkeyfile = opt_arg();
             break;
         case OPT_CA:
             CAfile = opt_arg();
-            CA_flag = ++num;
             break;
         case OPT_CAKEY:
             CAkeyfile = opt_arg();
@@ -310,7 +397,7 @@ int x509_main(int argc, char **argv)
             newcert = 1;
             break;
         case OPT_FORCE_PUBKEY:
-            fkeyfile = opt_arg();
+            pubkeyfile = opt_arg();
             break;
         case OPT_SUBJ:
             subj = opt_arg();
@@ -373,10 +460,10 @@ int x509_main(int argc, char **argv)
             modulus = ++num;
             break;
         case OPT_PUBKEY:
-            pubkey = ++num;
+            print_pubkey = ++num;
             break;
         case OPT_X509TOREQ:
-            x509req = ++num;
+            x509toreq = 1;
             break;
         case OPT_TEXT:
             text = ++num;
@@ -410,7 +497,7 @@ int x509_main(int argc, char **argv)
             break;
         case OPT_EXT:
             ext = ++num;
-            exts = opt_arg();
+            ext_names = opt_arg();
             break;
         case OPT_NOCERT:
             nocert = 1;
@@ -479,8 +566,6 @@ int x509_main(int argc, char **argv)
             checkip = opt_arg();
             break;
         case OPT_PRESERVE_DATES:
-            if (days != DEF_DAYS)
-                goto opthelp;
             preserve_dates = 1;
             break;
         case OPT_MD:
@@ -494,54 +579,77 @@ int x509_main(int argc, char **argv)
     if (argc != 0)
         goto opthelp;
 
+    if (preserve_dates && days != UNSET_DAYS) {
+        BIO_printf(bio_err, "Cannot use -preserve_dates with -days option\n");
+        goto end;
+    }
+    if (days == UNSET_DAYS)
+        days = DEFAULT_DAYS;
+
     if (!app_passwd(passinarg, NULL, &passin, NULL)) {
         BIO_printf(bio_err, "Error getting password\n");
         goto end;
     }
 
     if (!X509_STORE_set_default_paths_ex(ctx, app_get0_libctx(),
-                                         app_get0_propq())) {
-        ERR_print_errors(bio_err);
+                                         app_get0_propq()))
         goto end;
-    }
 
     if (newcert && infile != NULL) {
-        BIO_printf(bio_err, "The -in option must not be used since -new is set\n");
+        BIO_printf(bio_err, "The -in option cannot be used with -new\n");
         goto end;
     }
-    if (newcert && fkeyfile == NULL) {
+    if (newcert && reqfile) {
         BIO_printf(bio_err,
-                   "The -new option requires a public key to be set using -force_pubkey\n");
+                   "The -req option cannot be used with -new\n");
         goto end;
     }
-    if (fkeyfile != NULL) {
-        fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "forced key");
-        if (fkey == NULL)
+    if (signkeyfile != NULL) {
+        signkey = load_key(signkeyfile, keyformat, 0, passin, e, "private key");
+        if (signkey == NULL)
+            goto end;
+    }
+    if (pubkeyfile != NULL) {
+        if ((pubkey = load_pubkey(pubkeyfile, keyformat, 0, NULL, e,
+                                  "explicitly set public key")) == NULL)
             goto end;
     }
 
-    if (newcert && subj == NULL) {
-        BIO_printf(bio_err,
-                   "The -new option requires a subject to be set using -subj\n");
-        goto end;
+    if (newcert) {
+        if (subj == NULL) {
+            BIO_printf(bio_err,
+                       "The -new option requires a subject to be set using -subj\n");
+            goto end;
+        }
+        if (signkeyfile == NULL && pubkeyfile == NULL) {
+            BIO_printf(bio_err,
+                       "The -new option without -signkey requires using -force_pubkey\n");
+            goto end;
+        }
     }
     if (subj != NULL
             && (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL)
         goto end;
 
-    if (CAkeyfile == NULL && CA_flag && CAformat == FORMAT_PEM) {
+    if (CAkeyfile == NULL)
         CAkeyfile = CAfile;
-    } else if (CA_flag && CAkeyfile == NULL) {
-        BIO_printf(bio_err,
-                   "Need to specify a CAkey if using the CA command\n");
-        goto end;
-    } else if (!CA_flag && CAkeyfile != NULL) {
+    if (CAfile != NULL) {
+        if (signkeyfile != NULL) {
+            BIO_printf(bio_err, "Cannot use both -signkey and -CA option\n");
+            goto end;
+        }
+    } else if (CAkeyfile != NULL) {
         BIO_printf(bio_err,
-                   "Ignoring -CAkey option since no -CA option is given\n");
+                   "Warning: ignoring -CAkey option since no -CA option is given\n");
     }
 
-    if (extfile != NULL) {
+    if (extfile == NULL) {
+        if (extsect != NULL)
+            BIO_printf(bio_err,
+                       "Warning: ignoring -extensions option without -extfile\n");
+    } else {
         X509V3_CTX ctx2;
+
         if ((extconf = app_load_config(extfile)) == NULL)
             goto end;
         if (extsect == NULL) {
@@ -556,7 +664,6 @@ int x509_main(int argc, char **argv)
         if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
             BIO_printf(bio_err,
                        "Error checking extension section %s\n", extsect);
-            ERR_print_errors(bio_err);
             goto end;
         }
     }
@@ -574,64 +681,66 @@ int x509_main(int argc, char **argv)
         }
         i = do_X509_REQ_verify(req, pkey, vfyopts);
         if (i < 0) {
-            BIO_printf(bio_err, "Request self-signature verification error\n");
-            ERR_print_errors(bio_err);
+            BIO_printf(bio_err,
+                       "Error while verifying certificate request self-signature\n");
             goto end;
         }
         if (i == 0) {
             BIO_printf(bio_err,
-                       "Request self-signature did not match the certificate request\n");
+                       "Certificate request self-signature did not match the contents\n");
             goto end;
         } else {
-            BIO_printf(bio_err, "Request self-signature ok\n");
+            BIO_printf(bio_err, "Certificate request self-signature ok\n");
         }
 
         print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
                    get_nameopt());
+    } else if (!x509toreq && ext_copy != EXT_COPY_UNSET) {
+        BIO_printf(bio_err, "Warning: ignoring -copy_extensions since neither -x509toreq nor -req is given\n");
     }
 
     if (reqfile || newcert) {
-        X509_NAME *n;
-
-        if (!sign_flag && CAkeyfile == NULL) {
+        if (preserve_dates)
+            BIO_printf(bio_err,
+                       "Warning: ignoring -preserve_dates option with -req or -new\n");
+        preserve_dates = 0;
+        if (signkeyfile == NULL && CAkeyfile == NULL) {
             BIO_printf(bio_err,
-                       "We need a private key to sign with, use -signkey or -CAkey or -CA <file> with private key\n");
+                       "We need a private key to sign with, use -signkey or -CAkey or -CA with private key\n");
             goto end;
         }
         if ((x = X509_new_ex(app_get0_libctx(), app_get0_propq())) == NULL)
             goto end;
-
         if (sno == NULL) {
             sno = ASN1_INTEGER_new();
             if (sno == NULL || !rand_serial(NULL, sno))
                 goto end;
-            if (!X509_set_serialNumber(x, sno))
+        }
+        if (req != NULL && ext_copy != EXT_COPY_UNSET) {
+            if (clrext && ext_copy != EXT_COPY_NONE) {
+                BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n");
                 goto end;
-            ASN1_INTEGER_free(sno);
-            sno = NULL;
-        } else if (!X509_set_serialNumber(x, sno)) {
-            goto end;
+            } else if (!copy_extensions(x, req, ext_copy)) {
+                BIO_printf(bio_err, "Error copying extensions from request\n");
+                goto end;
+            }
         }
-
-        n = req == NULL ? fsubj : X509_REQ_get_subject_name(req);
-        if (!X509_set_issuer_name(x, n) || !X509_set_subject_name(x, n))
-            goto end;
-        if (!set_cert_times(x, NULL, NULL, days))
-            goto end;
-
-        if (!X509_set_pubkey(x, fkey != NULL ? fkey : X509_REQ_get0_pubkey(req)))
-            goto end;
     } else {
         x = load_cert_pass(infile, 1, passin, "certificate");
         if (x == NULL)
             goto end;
-        if (fkey != NULL && !X509_set_pubkey(x, fkey))
-            goto end;
-        if (fsubj != NULL && !X509_set_subject_name(x, fsubj))
-            goto end;
     }
+    if ((fsubj != NULL || req != NULL)
+        && !X509_set_subject_name(x, fsubj != NULL ? fsubj :
+                                  X509_REQ_get_subject_name(req)))
+        goto end;
+    if ((pubkey != NULL || signkey != NULL || req != NULL)
+        && !X509_set_pubkey(x, pubkey != NULL ? pubkey :
+                            signkey != NULL ? signkey :
+                            X509_REQ_get0_pubkey(req)))
+        goto end;
 
-    if (CA_flag) {
+    if (CAfile != NULL) {
         xca = load_cert_pass(CAfile, 1, passin, "CA certificate");
         if (xca == NULL)
             goto end;
@@ -643,6 +752,7 @@ int x509_main(int argc, char **argv)
 
     if (!noout || text || next_serial)
         OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");
+    /* TODO: why is this strange object created (and no error checked)? */
 
     if (alias)
         X509_alias_set1(x, (unsigned char *)alias, -1);
@@ -668,6 +778,104 @@ int x509_main(int argc, char **argv)
         objtmp = NULL;
     }
 
+    if (clrext && ext_names != NULL)
+        BIO_printf(bio_err, "Warning: Ignoring -ext since -clrext is given\n");
+    for (i = X509_get_ext_count(x) - 1; i >= 0; i--) {
+        X509_EXTENSION *ex = X509_get_ext(x, i);
+        const char *sn = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ex)));
+
+        if (clrext || (ext_names != NULL && strstr(ext_names, sn) == NULL))
+            X509_EXTENSION_free(X509_delete_ext(x, i));
+    }
+
+    if ((reqfile || newcert || signkey != NULL || CAfile != NULL)
+            && !preserve_dates && !set_cert_times(x, NULL, NULL, days))
+        goto end;
+
+    issuer_cert = x;
+    if (CAfile != NULL) {
+        issuer_cert = xca;
+        if (sno == NULL)
+            sno = x509_load_serial(CAfile, CAserial, CA_createserial);
+        if (sno == NULL)
+            goto end;
+    }
+
+    if (sno != NULL && !X509_set_serialNumber(x, sno))
+        goto end;
+
+    if (!X509_set_issuer_name(x, X509_get_subject_name(issuer_cert)))
+        goto end;
+
+    X509V3_set_ctx(&ext_ctx, issuer_cert, x, req, NULL, X509V3_CTX_REPLACE);
+    if (extconf != NULL) {
+        X509V3_set_nconf(&ext_ctx, extconf);
+        if (!X509V3_EXT_add_nconf(extconf, &ext_ctx, extsect, x)) {
+            BIO_printf(bio_err,
+                       "Error adding extensions from section %s\n", extsect);
+            goto end;
+        }
+    }
+
+    /* At this point the contents of the certificate x have been finished. */
+
+    if (x509toreq) { /* also works in conjunction with -req */
+        if (signkey == NULL) {
+            BIO_printf(bio_err, "Must specify request key using -signkey\n");
+            goto end;
+        }
+        if (clrext && ext_copy != EXT_COPY_NONE) {
+            BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n");
+            goto end;
+        }
+        if ((rq = x509_to_req(x, signkey, digest, sigopts,
+                              ext_copy, ext_names)) == NULL)
+            goto end;
+        if (!noout) {
+            if (outformat == FORMAT_ASN1) {
+                X509_REQ_print_ex(out, rq, get_nameopt(), X509_FLAG_COMPAT);
+                i = i2d_X509_bio(out, x);
+            } else {
+                i = PEM_write_bio_X509_REQ(out, rq);
+            }
+            if (!i) {
+                BIO_printf(bio_err,
+                           "Unable to write certificate request\n");
+                goto end;
+            }
+        }
+        noout = 1;
+    } else if (signkey != NULL) {
+        if (!do_X509_sign(x, signkey, digest, sigopts, &ext_ctx))
+            goto end;
+    } else if (CAfile != NULL) {
+        if (!reqfile && !newcert) { /* certificate should be self-signed */
+            X509_STORE_CTX *xsc = X509_STORE_CTX_new();
+
+            if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, x, NULL)) {
+                BIO_printf(bio_err, "Error initialising X509 store\n");
+                X509_STORE_CTX_free(xsc);
+                goto end;
+            }
+            X509_STORE_CTX_set_cert(xsc, x);
+            X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
+            i = X509_verify_cert(xsc);
+            X509_STORE_CTX_free(xsc);
+            if (i <= 0)
+                goto end;
+        }
+        if ((CAkey = load_key(CAkeyfile, CAkeyformat,
+                              0, passin, e, "CA private key")) == NULL)
+            goto end;
+        if (!X509_check_private_key(xca, CAkey)) {
+            BIO_printf(bio_err,
+                       "CA certificate and CA private key do not match\n");
+            goto end;
+        }
+
+        if (!do_X509_sign(x, CAkey, digest, sigopts, &ext_ctx))
+            goto end;
+    }
     if (badsig) {
         const ASN1_BIT_STRING *signature;
 
@@ -675,10 +883,12 @@ int x509_main(int argc, char **argv)
         corrupt_signature(signature);
     }
 
-    if (num) {
+    if (num) { /* TODO remove this needless guard and extra indentation below */
+        /* Process print options in the given order, as indicated by index i */
         for (i = 1; i <= num; i++) {
             if (issuer == i) {
-                print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt());
+                print_name(out, "issuer=", X509_get_issuer_name(x),
+                           get_nameopt());
             } else if (subject == i) {
                 print_name(out, "subject=",
                            X509_get_subject_name(x), get_nameopt());
@@ -702,8 +912,9 @@ int x509_main(int argc, char **argv)
                 ASN1_INTEGER_free(ser);
                 BIO_puts(out, "\n");
             } else if (email == i || ocsp_uri == i) {
-                int j;
                 STACK_OF(OPENSSL_STRING) *emlst;
+                int j;
+
                 if (email == i)
                     emlst = X509_get1_email(x);
                 else
@@ -714,6 +925,7 @@ int x509_main(int argc, char **argv)
                 X509_email_free(emlst);
             } else if (aliasout == i) {
                 unsigned char *alstr;
+
                 alstr = X509_alias_get0(x, NULL);
                 if (alstr)
                     BIO_printf(out, "%s\n", alstr);
@@ -721,23 +933,20 @@ int x509_main(int argc, char **argv)
                     BIO_puts(out, "<No Alias>\n");
             } else if (subject_hash == i) {
                 BIO_printf(out, "%08lx\n", X509_subject_name_hash(x));
-            }
 #ifndef OPENSSL_NO_MD5
-            else if (subject_hash_old == i) {
+            } else if (subject_hash_old == i) {
                 BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x));
-            }
 #endif
-            else if (issuer_hash == i) {
+            } else if (issuer_hash == i) {
                 BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x));
-            }
 #ifndef OPENSSL_NO_MD5
-            else if (issuer_hash_old == i) {
+            } else if (issuer_hash_old == i) {
                 BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x));
-            }
 #endif
-            else if (pprint == i) {
+            } else if (pprint == i) {
                 X509_PURPOSE *ptmp;
                 int j;
+
                 BIO_printf(out, "Certificate purposes:\n");
                 for (j = 0; j < X509_PURPOSE_get_count(); j++) {
                     ptmp = X509_PURPOSE_get0(j);
@@ -748,8 +957,8 @@ int x509_main(int argc, char **argv)
 
                 pkey = X509_get0_pubkey(x);
                 if (pkey == NULL) {
-                    BIO_printf(bio_err, "Modulus=unavailable\n");
-                    ERR_print_errors(bio_err);
+                    BIO_printf(bio_err,
+                               "Modulus unavailable: cannot get key\n");
                     goto end;
                 }
                 BIO_printf(out, "Modulus=");
@@ -768,16 +977,15 @@ int x509_main(int argc, char **argv)
                     BN_print(out, dsapub);
                     BN_free(dsapub);
                 } else {
-                    BIO_printf(out, "Wrong Algorithm type");
+                    BIO_printf(out, "No modulus for this public key type");
                 }
                 BIO_printf(out, "\n");
-            } else if (pubkey == i) {
+            } else if (print_pubkey == i) {
                 EVP_PKEY *pkey;
 
                 pkey = X509_get0_pubkey(x);
                 if (pkey == NULL) {
                     BIO_printf(bio_err, "Error getting public key\n");
-                    ERR_print_errors(bio_err);
                     goto end;
                 }
                 PEM_write_bio_PUBKEY(out, pkey);
@@ -810,64 +1018,10 @@ int x509_main(int argc, char **argv)
                     BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n)
                                ? '\n' : ':');
                 }
-            }
-
-            /* should be in the library */
-            else if (sign_flag == i && x509req == 0) {
-                if (Upkey == NULL) {
-                    Upkey = load_key(keyfile, keyformat, 0,
-                                     passin, e, "private key");
-                    if (Upkey == NULL)
-                        goto end;
-                }
-                if (fkey == NULL && !X509_set_pubkey(x, Upkey))
-                    goto end;
-                if (!sign(x, Upkey, x /* self-issuing */, sigopts, days, clrext,
-                          digest, extconf, extsect, preserve_dates)) {
-                    ERR_print_errors(bio_err);
-                    goto end;
-                }
-            } else if (CA_flag == i) {
-                if (CAkeyfile != NULL) {
-                    CApkey = load_key(CAkeyfile, CAkeyformat,
-                                      0, passin, e, "CA private key");
-                    if (CApkey == NULL)
-                        goto end;
-                }
-
-                if (!x509_certify(ctx, CAfile, digest, x, xca,
-                                  CApkey, sigopts,
-                                  CAserial, CA_createserial, days, clrext,
-                                  extconf, extsect, sno, reqfile, preserve_dates))
-                    goto end;
-            } else if (x509req == i) {
-                EVP_PKEY *pk;
-
-                if (keyfile == NULL) {
-                    BIO_printf(bio_err, "No request key file specified\n");
-                    goto end;
-                } else {
-                    pk = load_key(keyfile, keyformat, 0,
-                                  passin, e, "request key");
-                    if (pk == NULL)
-                        goto end;
-                }
-
-                rq = X509_to_X509_REQ(x, pk, digest);
-                EVP_PKEY_free(pk);
-                if (rq == NULL) {
-                    ERR_print_errors(bio_err);
-                    goto end;
-                }
-                if (!noout) {
-                    X509_REQ_print_ex(out, rq, get_nameopt(), X509_FLAG_COMPAT);
-                    PEM_write_bio_X509_REQ(out, rq);
-                }
-                noout = 1;
             } else if (ocspid == i) {
                 X509_ocspid_print(out, x);
             } else if (ext == i) {
-                print_x509v3_exts(out, x, exts);
+                print_x509v3_exts(out, x, ext_names);
             }
         }
     }
@@ -905,11 +1059,13 @@ int x509_main(int argc, char **argv)
     }
     if (!i) {
         BIO_printf(bio_err, "Unable to write certificate\n");
-        ERR_print_errors(bio_err);
         goto end;
     }
     ret = 0;
+
  end:
+    if (ret != 0)
+        ERR_print_errors(bio_err);
     NCONF_free(extconf);
     BIO_free_all(out);
     X509_STORE_free(ctx);
@@ -917,9 +1073,9 @@ int x509_main(int argc, char **argv)
     X509_REQ_free(req);
     X509_free(x);
     X509_free(xca);
-    EVP_PKEY_free(Upkey);
-    EVP_PKEY_free(CApkey);
-    EVP_PKEY_free(fkey);
+    EVP_PKEY_free(signkey);
+    EVP_PKEY_free(CAkey);
+    EVP_PKEY_free(pubkey);
     sk_OPENSSL_STRING_free(sigopts);
     sk_OPENSSL_STRING_free(vfyopts);
     X509_REQ_free(rq);
@@ -967,67 +1123,6 @@ static ASN1_INTEGER *x509_load_serial(const char *CAfile,
     return bs;
 }
 
-static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest,
-                        X509 *x, X509 *xca, EVP_PKEY *pkey,
-                        STACK_OF(OPENSSL_STRING) *sigopts,
-                        const char *serialfile, int create,
-                        int days, int clrext, CONF *conf, const char *section,
-                        ASN1_INTEGER *sno, int reqfile, int preserve_dates)
-{
-    int ret = 0;
-    ASN1_INTEGER *bs = NULL;
-    X509_STORE_CTX *xsc = NULL;
-    EVP_PKEY *upkey;
-
-    upkey = X509_get0_pubkey(xca);
-    if (upkey == NULL) {
-        BIO_printf(bio_err, "Error obtaining CA X509 public key\n");
-        goto end;
-    }
-    EVP_PKEY_copy_parameters(upkey, pkey);
-
-    xsc = X509_STORE_CTX_new();
-    if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, x, NULL)) {
-        BIO_printf(bio_err, "Error initialising X509 store\n");
-        goto end;
-    }
-    if (sno)
-        bs = sno;
-    else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL)
-        goto end;
-
-    /*
-     * NOTE: this certificate can/should be self-signed, unless it was a
-     * certificate request in which case it is not.
-     */
-    X509_STORE_CTX_set_cert(xsc, x);
-    X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
-    if (!reqfile && X509_verify_cert(xsc) <= 0)
-        goto end;
-
-    if (!X509_check_private_key(xca, pkey)) {
-        BIO_printf(bio_err,
-                   "CA certificate and CA private key do not match\n");
-        goto end;
-    }
-
-    if (!X509_set_serialNumber(x, bs))
-        goto end;
-
-    if (!sign(x, pkey, xca, sigopts, days, clrext, digest,
-              conf, section, preserve_dates))
-        goto end;
-
-    ret = 1;
- end:
-    X509_STORE_CTX_free(xsc);
-    if (!ret)
-        ERR_print_errors(bio_err);
-    if (!sno)
-        ASN1_INTEGER_free(bs);
-    return ret;
-}
-
 static int callb(int ok, X509_STORE_CTX *ctx)
 {
     int err;
@@ -1061,42 +1156,6 @@ static int callb(int ok, X509_STORE_CTX *ctx)
     }
 }
 
-static int sign(X509 *x, EVP_PKEY *pkey, X509 *issuer,
-                STACK_OF(OPENSSL_STRING) *sigopts,
-                int days, int clrext,
-                const EVP_MD *digest, CONF *conf, const char *section,
-                int preserve_dates)
-{
-    X509V3_CTX ext_ctx;
-
-    if (!X509_set_issuer_name(x, X509_get_subject_name(issuer)))
-        return 0;
-
-    if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
-        return 0;
-
-    if (clrext) {
-        while (X509_get_ext_count(x) > 0)
-            X509_delete_ext(x, 0);
-    }
-
-    X509V3_set_ctx(&ext_ctx, issuer, x, NULL, NULL, X509V3_CTX_REPLACE);
-    if (issuer == x
-        /* prepare the correct AKID of self-issued, possibly self-signed cert */
-            && !X509V3_set_issuer_pkey(&ext_ctx, pkey))
-        return 0;
-
-    if (conf != NULL) {
-        X509V3_set_nconf(&ext_ctx, conf);
-        if (!X509V3_EXT_add_nconf(conf, &ext_ctx, section, x)) {
-            BIO_printf(bio_err,
-                       "Error adding extensions from section %s\n", section);
-            return 0;
-        }
-    }
-    return do_X509_sign(x, pkey, digest, sigopts, &ext_ctx);
-}
-
 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
 {
     int id, i, idret;
diff --git a/crypto/ct/ct_sct_ctx.c b/crypto/ct/ct_sct_ctx.c
index a84c476caf..353b5a7f0e 100644
--- a/crypto/ct/ct_sct_ctx.c
+++ b/crypto/ct/ct_sct_ctx.c
@@ -168,15 +168,12 @@ int SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner)
      * SCT.
      */
     if (idx >= 0) {
-        X509_EXTENSION *ext;
-
         /* Take a copy of certificate so we don't modify passed version */
         pretmp = X509_dup(cert);
         if (pretmp == NULL)
             goto err;
 
-        ext = X509_delete_ext(pretmp, idx);
-        X509_EXTENSION_free(ext);
+        X509_EXTENSION_free(X509_delete_ext(pretmp, idx));
 
         if (!ct_x509_cert_fixup(pretmp, presigner))
             goto err;
diff --git a/crypto/x509/t_req.c b/crypto/x509/t_req.c
index 1f50a0a1e2..5e26db9c4e 100644
--- a/crypto/x509/t_req.c
+++ b/crypto/x509/t_req.c
@@ -108,7 +108,7 @@ int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
             goto err;
 
         if (X509_REQ_get_attr_count(x) == 0) {
-            if (BIO_printf(bp, "%12sa0:00\n", "") <= 0)
+            if (BIO_printf(bp, "%12s(none)\n", "") <= 0)
                 goto err;
         } else {
             for (i = 0; i < X509_REQ_get_attr_count(x); i++) {
@@ -166,14 +166,14 @@ int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
     if (!(cflag & X509_FLAG_NO_EXTENSIONS)) {
         exts = X509_REQ_get_extensions(x);
         if (exts) {
-            if (BIO_printf(bp, "%8sRequested Extensions:\n", "") <= 0)
+            if (BIO_printf(bp, "%12sRequested Extensions:\n", "") <= 0)
                 goto err;
             for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
                 ASN1_OBJECT *obj;
                 X509_EXTENSION *ex;
                 int critical;
                 ex = sk_X509_EXTENSION_value(exts, i);
-                if (BIO_printf(bp, "%12s", "") <= 0)
+                if (BIO_printf(bp, "%16s", "") <= 0)
                     goto err;
                 obj = X509_EXTENSION_get_object(ex);
                 if (i2a_ASN1_OBJECT(bp, obj) <= 0)
@@ -181,8 +181,8 @@ int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
                 critical = X509_EXTENSION_get_critical(ex);
                 if (BIO_printf(bp, ": %s\n", critical ? "critical" : "") <= 0)
                     goto err;
-                if (!X509V3_EXT_print(bp, ex, cflag, 16)) {
-                    if (BIO_printf(bp, "%16s", "") <= 0
+                if (!X509V3_EXT_print(bp, ex, cflag, 20)) {
+                    if (BIO_printf(bp, "%20s", "") <= 0
                         || ASN1_STRING_print(bp,
                                              X509_EXTENSION_get_data(ex)) <= 0)
                         goto err;
diff --git a/crypto/x509/v3_conf.c b/crypto/x509/v3_conf.c
index 740108fefd..9eda71348c 100644
--- a/crypto/x509/v3_conf.c
+++ b/crypto/x509/v3_conf.c
@@ -295,12 +295,8 @@ static void delete_ext(STACK_OF(X509_EXTENSION) *sk, X509_EXTENSION *dext)
     ASN1_OBJECT *obj;
 
     obj = X509_EXTENSION_get_object(dext);
-    while ((idx = X509v3_get_ext_by_OBJ(sk, obj, -1)) >= 0) {
-        X509_EXTENSION *tmpext = X509v3_get_ext(sk, idx);
-
-        X509v3_delete_ext(sk, idx);
-        X509_EXTENSION_free(tmpext);
-    }
+    while ((idx = X509v3_get_ext_by_OBJ(sk, obj, -1)) >= 0)
+        X509_EXTENSION_free(X509v3_delete_ext(sk, idx));
 }
 
 /*
diff --git a/crypto/x509/x509_req.c b/crypto/x509/x509_req.c
index f3764e4179..4f4319a30c 100644
--- a/crypto/x509/x509_req.c
+++ b/crypto/x509/x509_req.c
@@ -164,15 +164,15 @@ STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req)
  * Add a STACK_OF extensions to a certificate request: allow alternative OIDs
  * in case we want to create a non standard one.
  */
-
-int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
-                                int nid)
+int X509_REQ_add_extensions_nid(X509_REQ *req,
+                                const STACK_OF(X509_EXTENSION) *exts, int nid)
 {
     int extlen;
     int rv = 0;
     unsigned char *ext = NULL;
+
     /* Generate encoding of extensions */
-    extlen = ASN1_item_i2d((ASN1_VALUE *)exts, &ext,
+    extlen = ASN1_item_i2d((const ASN1_VALUE *)exts, &ext,
                            ASN1_ITEM_rptr(X509_EXTENSIONS));
     if (extlen <= 0)
         return 0;
@@ -182,7 +182,7 @@ int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
 }
 
 /* This is the normal usage: use the "official" OID */
-int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts)
+int X509_REQ_add_extensions(X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts)
 {
     return X509_REQ_add_extensions_nid(req, exts, NID_ext_req);
 }
diff --git a/doc/man1/openssl-x509.pod.in b/doc/man1/openssl-x509.pod.in
index 0c0fc7e414..f90c8b3e3a 100644
--- a/doc/man1/openssl-x509.pod.in
+++ b/doc/man1/openssl-x509.pod.in
@@ -9,70 +9,71 @@ openssl-x509 - Certificate display and signing command
 
 B<openssl> B<x509>
 [B<-help>]
+[B<-in> I<filename>|I<uri>]
+[B<-passin> I<arg>]
+[B<-new>]
+[B<-x509toreq>]
+[B<-req>]
+[B<-copy_extensions> I<arg>]
 [B<-inform> B<DER>|B<PEM>]
-[B<-outform> B<DER>|B<PEM>]
+[B<-vfyopt> I<nm>:I<v>]
+[B<-signkey> I<filename>|I<uri>]
 [B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
-[B<-CAform> B<DER>|B<PEM>|B<P12>]
-[B<-CAkeyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
-[B<-in> I<filename>]
 [B<-out> I<filename>]
+[B<-outform> B<DER>|B<PEM>]
+[B<-nocert>]
+[B<-noout>]
+[B<-text>]
+[B<-certopt> I<option>]
+[B<-fingerprint>]
+[B<-alias>]
 [B<-serial>]
+[B<-startdate>]
+[B<-enddate>]
+[B<-dates>]
+[B<-subject>]
+[B<-issuer>]
+{- $OpenSSL::safe::opt_name_synopsis -}
+[B<-email>]
 [B<-hash>]
 [B<-subject_hash>]
 [B<-subject_hash_old>]
 [B<-issuer_hash>]
 [B<-issuer_hash_old>]
+[B<-ext> I<extensions>]
 [B<-ocspid>]
-[B<-subject>]
-[B<-issuer>]
-[B<-email>]
 [B<-ocsp_uri>]
-[B<-startdate>]
-[B<-enddate>]
 [B<-purpose>]
-[B<-dates>]
-[B<-checkend> I<num>]
-[B<-modulus>]
 [B<-pubkey>]
-[B<-fingerprint>]
-[B<-alias>]
-[B<-noout>]
-[B<-trustout>]
-[B<-clrtrust>]
-[B<-clrreject>]
-[B<-addtrust> I<arg>]
-[B<-addreject> I<arg>]
-[B<-setalias> I<arg>]
-[B<-days> I<arg>]
-[B<-set_serial> I<n>]
-[B<-signkey> I<filename>|I<uri>]
-[B<-badsig>]
-[B<-passin> I<arg>]
-[B<-x509toreq>]
-[B<-req>]
-[B<-CA> I<filename>]
-[B<-CAkey> I<filename>|I<uri>]
-[B<-CAcreateserial>]
-[B<-CAserial> I<filename>]
-[B<-new>]
-[B<-next_serial>]
-[B<-nocert>]
-[B<-force_pubkey> I<filename>]
-[B<-subj> I<arg>]
-[B<-text>]
-[B<-ext> I<extensions>]
-[B<-certopt> I<option>]
+[B<-modulus>]
+[B<-checkend> I<num>]
 [B<-checkhost> I<host>]
 [B<-checkemail> I<host>]
 [B<-checkip> I<ipaddr>]
-[B<-I<digest>>]
+[B<-set_serial> I<n>]
+[B<-next_serial>]
+[B<-days> I<arg>]
+[B<-preserve_dates>]
+[B<-subj> I<arg>]
+[B<-force_pubkey> I<filename>]
 [B<-clrext>]
 [B<-extfile> I<filename>]
 [B<-extensions> I<section>]
 [B<-sigopt> I<nm>:I<v>]
-[B<-vfyopt> I<nm>:I<v>]
-[B<-preserve_dates>]
-{- $OpenSSL::safe::opt_name_synopsis -}
+[B<-badsig>]
+[B<-I<digest>>]
+[B<-CA> I<filename>|I<uri>]
+[B<-CAform> B<DER>|B<PEM>|B<P12>]
+[B<-CAkey> I<filename>|I<uri>]
+[B<-CAkeyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>]
+[B<-CAserial> I<filename>]
+[B<-CAcreateserial>]
+[B<-trustout>]
+[B<-setalias> I<arg>]
+[B<-clrtrust>]
+[B<-addtrust> I<arg>]
+[B<-clrreject>]
+[B<-addreject> I<arg>]
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
 
@@ -80,10 +81,11 @@ B<openssl> B<x509>
 
 =head1 DESCRIPTION
 
-This command is a multi-purposes certificate command. It can
-be used to display certificate information, convert certificates to
-various forms, sign certificate requests like a "mini CA" or edit
-certificate trust settings.
+This command is a multi-purposes certificate handling command.
+It can be used to print certificate information,
+convert certificates to various forms, edit certificate trust settings,
+generate certificates from scratch or from certificating requests
+and then self-signing them or signing them like a "micro CA".
 
 Since there are a large number of options they will split up into
 various sections.
@@ -98,356 +100,384 @@ various sections.
 
 Print out a usage message.
 
+=item B<-in> I<filename>|I<uri>
+
+If the B<-req> option is not used this specifies the input
+to read a certificate from or standard input if this option is not specified.
+With the B<-req> option this specifies a certificate request file.
+
+=item B<-passin> I<arg>
+
+The key and certificate file password source.
+For more information about the format of I<arg>
+see L<openssl-passphrase-options(1)>.
+
+=item B<-new>
+
+Generate a certificate from scratch, not using an input certificate
+or certificate request. So the B<-in> option must not be used in this case.
+Instead, the B<-subj> option needs to be given.
+The public key to include can be given with the B<-force_pubkey> option
+and defaults to the key given with the B<-signkey> option,
+which implies self-signature.
+
+=item B<-x509toreq>
+
+Output a PKCS#10 certificate request (rather than a certificate).
+The B<-signkey> option must be used to provide the private key for self-signing;
+the corresponding public key is placed in the subjectPKInfo field.
+
+X.509 extensions included in a certificate input are not copied by default.
+X.509 extensions to be added can be specified using the B<-extfile> option.
+
+=item B<-req>
+
+By default a certificate is expected on input.
+With this option a PKCS#10 certificate request is expected instead,
+which must be correctly self-signed.
+
+X.509 extensions included in the request are not copied by default.
+X.509 extensions to be added can be specified using the B<-extfile> option.
+
+=item B<-copy_extensions> I<arg>
+
+Determines how to handle X.509 extensions
+when converting from a certificate to a request using the B<-x509toreq> option
+or converting from a request to a certificate using the B<-req> option.
+If I<arg> is B<none> or this option is not present then extensions are ignored.
+If I<arg> is B<copy> or B<copyall> then all extensions are copied,
+except that subject identifier and authority key identifier extensions
+are not taken over when producing a certificate request.
+
+The B<-ext> option can be used to further restrict which extensions to copy.
+
 =item B<-inform> B<DER>|B<PEM>
 
-The CSR input format; the default is B<PEM>.
+The CSR input file format; the default is B<PEM>.
 See L<openssl-format-options(1)> for details.
 
-The input is normally an X.509 certificate file of any format,
-but this can change if other options such as B<-req> are used.
+=item B<-vfyopt> I<nm>:I<v>
 
-B<-outform> B<DER>|B<PEM>
+Pass options to the signature algorithm during verify operations.
+Names and values of these options are algorithm-specific.
 
-The output format; the default is B<PEM>.
-See L<openssl-format-options(1)> for details.
+=item B<-signkey> I<filename>|I<uri>
 
-=item B<-in> I<filename>
+This option causes the new certificate or certificate request
+to be self-signed using the supplied private key.
+This cannot be used in conjunction with the B<-CA> option.
 
-This specifies the input filename to read a certificate from or standard input
-if this option is not specified.
+It sets the issuer name to the subject name (i.e., makes it self-issued)
+and changes the public key to the supplied value (unless overridden
+by B<-force_pubkey>).
+Unless the B<-preserve_dates> option is supplied,
+it sets the validity start date to the current time
+and the end date to a value determined by the B<-days> option.
 
-=item B<-out> I<filename>
+=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
 
-This specifies the output filename to write to or standard output by
-default.
+The key input format; the default is B<PEM>.
+The only value with effect is B<ENGINE>; all others have become obsolete.
+See L<openssl-format-options(1)> for details.
 
-=item B<-I<digest>>
+=item B<-out> I<filename>
 
-The digest to use.
-This affects any signing or display option that uses a message
-digest, such as the B<-fingerprint>, B<-signkey> and B<-CA> options.
-Any digest supported by the L<openssl-dgst(1)> command can be used.
-If not specified then SHA1 is used with B<-fingerprint> or
-the default digest for the signing algorithm is used, typically SHA256.
+This specifies the output filename to write to or standard output by default.
 
-=item B<-preserve_dates>
+=item B<-outform> B<DER>|B<PEM>
 
-When signing a certificate, preserve the "notBefore" and "notAfter" dates
-instead of adjusting them to current time and duration.
-Cannot be used with the B<-days> option.
+The output format; the default is B<PEM>.
+See L<openssl-format-options(1)> for details.
 
-{- $OpenSSL::safe::opt_r_synopsis -}
+=item B<-nocert>
 
-{- $OpenSSL::safe::opt_engine_item -}
+Do not output a certificate (except for printing as requested by below options).
 
-{- $OpenSSL::safe::opt_provider_item -}
+=item B<-noout>
+
+This option prevents output except for printing as requested by below options.
 
 =back
 
-=head2 Display Options
+=head2 Certificate Printing Options
 
-Note: the B<-alias> and B<-purpose> options are also display options
+Note: the B<-alias> and B<-purpose> options are also printing options
 but are described in the L</Trust Settings> section.
 
 =over 4
 
 =item B<-text>
 
-Prints out the certificate in text form. Full details are output including the
+Prints out the certificate in text form. Full details are printed including the
 public key, signature algorithms, issuer and subject names, serial number
 any extensions present and any trust settings.
 
-=item B<-ext> I<extensions>
-
-Prints out the certificate extensions in text form. Extensions are specified
-with a comma separated string, e.g., "subjectAltName,subjectKeyIdentifier".
-See the L<x509v3_config(5)> manual page for the extension names.
-
 =item B<-certopt> I<option>
 
-Customise the output format used with B<-text>. The I<option> argument
-can be a single option or multiple options separated by commas. The
-B<-certopt> switch may be also be used more than once to set multiple
-options. See the L</Text Options> section for more information.
+Customise the print format used with B<-text>. The I<option> argument
+can be a single option or multiple options separated by commas.
+The B<-certopt> switch may be also be used more than once to set multiple
+options. See the L</Text Printing Flags> section for more information.
 
-=item B<-checkhost> I<host>
-
-Check that the certificate matches the specified host.
+=item B<-fingerprint>
 
-=item B<-checkemail> I<email>
+Calculates and prints the digest of the DER encoded version of the entire
+certificate (see digest options).
+This is commonly called a "fingerprint". Because of the nature of message
+digests, the fingerprint of a certificate is unique to that certificate and
+two certificates with the same fingerprint can be considered to be the same.
 
-Check that the certificate matches the specified email address.
+=item B<-alias>
 
-=item B<-checkip> I<ipaddr>
+Prints the certificate "alias" (nickname), if any.
 
-Check that the certificate matches the specified IP address.
+=item B<-serial>
 
-=item B<-noout>
+Prints the certificate serial number.
 
-This option prevents output of the encoded version of the certificate.
+=item B<-startdate>
 
-=item B<-pubkey>
+Prints out the start date of the certificate, that is the notBefore date.
 
-Outputs the certificate's SubjectPublicKeyInfo block in PEM format.
+=item B<-enddate>
 
-=item B<-modulus>
+Prints out the expiry date of the certificate, that is the notAfter date.
 
-This option prints out the value of the modulus of the public key
-contained in the certificate.
+=item B<-dates>
 
-=item B<-serial>
+Prints out the start and expiry dates of a certificate.
 
-Outputs the certificate serial number.
+=item B<-subject>
 
-=item B<-subject_hash>
+Prints the subject name.
 
-Outputs the "hash" of the certificate subject name. This is used in OpenSSL to
-form an index to allow certificates in a directory to be looked up by subject
-name.
+=item B<-issuer>
 
-=item B<-issuer_hash>
+Prints the issuer name.
 
-Outputs the "hash" of the certificate issuer name.
+{- $OpenSSL::safe::opt_name_item -}
 
-=item B<-ocspid>
+=item B<-email>
 
-Outputs the OCSP hash values for the subject name and public key.
+Prints the email address(es) if any.
 
 =item B<-hash>
 
 Synonym for "-subject_hash" for backward compatibility reasons.
 
+=item B<-subject_hash>
+
+Prints the "hash" of the certificate subject name. This is used in OpenSSL to
+form an index to allow certificates in a directory to be looked up by subject
+name.
+
 =item B<-subject_hash_old>
 
-Outputs the "hash" of the certificate subject name using the older algorithm
+Prints the "hash" of the certificate subject name using the older algorithm
 as used by OpenSSL before version 1.0.0.
 
+=item B<-issuer_hash>
+
+Prints the "hash" of the certificate issuer name.
+
 =item B<-issuer_hash_old>
 
-Outputs the "hash" of the certificate issuer name using the older algorithm
+Prints the "hash" of the certificate issuer name using the older algorithm
 as used by OpenSSL before version 1.0.0.
 
-=item B<-subject>
+=item B<-ext> I<extensions>
 
-Outputs the subject name.
+Prints out the certificate extensions in text form.
+Can also be used to restrict which extensions to copy.
+Extensions are specified
+with a comma separated string, e.g., "subjectAltName,subjectKeyIdentifier".
+See the L<x509v3_config(5)> manual page for the extension names.
 
-=item B<-issuer>
+=item B<-ocspid>
 
-Outputs the issuer name.
+Prints the OCSP hash values for the subject name and public key.
 
-{- $OpenSSL::safe::opt_name_item -}
+=item B<-ocsp_uri>
 
-=item B<-email>
+Prints the OCSP responder address(es) if any.
 
-Outputs the email address(es) if any.
+=item B<-purpose>
 
-=item B<-ocsp_uri>
+This option performs tests on the certificate extensions and prints
+the results. For a more complete description see the
+L</CERTIFICATE EXTENSIONS> section.
 
-Outputs the OCSP responder address(es) if any.
+=item B<-pubkey>
 
-=item B<-startdate>
+Prints the certificate's SubjectPublicKeyInfo block in PEM format.
 
-Prints out the start date of the certificate, that is the notBefore date.
+=item B<-modulus>
 
-=item B<-enddate>
+This option prints out the value of the modulus of the public key
+contained in the certificate.
 
-Prints out the expiry date of the certificate, that is the notAfter date.
+=back
 
-=item B<-dates>
+=head2 Certificate Checking Options
 
-Prints out the start and expiry dates of a certificate.
+=over 4
 
 =item B<-checkend> I<arg>
 
 Checks if the certificate expires within the next I<arg> seconds and exits
 nonzero if yes it will expire or zero if not.
 
-=item B<-fingerprint>
+=item B<-checkhost> I<host>
 
-Calculates and outputs the digest of the DER encoded version of the entire
-certificate (see digest options).
-This is commonly called a "fingerprint". Because of the nature of message
-digests, the fingerprint of a certificate is unique to that certificate and
-two certificates with the same fingerprint can be considered to be the same.
+Check that the certificate matches the specified host.
 
-=back
+=item B<-checkemail> I<email>
 
-=head2 Trust Settings
+Check that the certificate matches the specified email address.
 
-A B<trusted certificate> is an ordinary certificate which has several
-additional pieces of information attached to it such as the permitted
-and prohibited uses of the certificate and an "alias".
+=item B<-checkip> I<ipaddr>
 
-Normally when a certificate is being verified at least one certificate
-must be "trusted". By default a trusted certificate must be stored
-locally and must be a root CA: any certificate chain ending in this CA
-is then usable for any purpose.
+Check that the certificate matches the specified IP address.
 
-Trust settings currently are only used with a root CA. They allow a finer
-control over the purposes the root CA can be used for. For example a CA
-may be trusted for SSL client but not SSL server use.
+=back
 
-See the description in L<openssl-verify(1)> for more information
-on the meaning of trust settings.
+=head2 Certificate Output Options
 
-Future versions of OpenSSL will recognize trust settings on any
-certificate: not just root CAs.
+=over 4
 
+=item B<-set_serial> I<n>
 
-=over 4
+Specifies the serial number to use. This option can be used with either
+the B<-signkey> or B<-CA> options. If used in conjunction with the B<-CA> option
+the serial number file (as specified by the B<-CAserial> option) is not used.
 
-=item B<-trustout>
+The serial number can be decimal or hex (if preceded by C<0x>).
 
-Output a B<trusted> certificate rather than an ordinary. An ordinary
-or trusted certificate can be input but by default an ordinary
-certificate is output and any trust settings are discarded. With the
-B<-trustout> option a trusted certificate is output. A trusted
-certificate is automatically output if any trust settings are modified.
+=item B<-next_serial>
 
-=item B<-setalias> I<arg>
+Set the serial to be one more than the number in the certificate.
 
-Sets the alias of the certificate. This will allow the certificate
-to be referred to using a nickname for example "Steve's Certificate".
+=item B<-days> I<arg>
 
-=item B<-alias>
+Specifies the number of days until a newly generated certificate expires.
+The default is 30.
+Cannot be used together with the B<-preserve_dates> option.
 
-Outputs the certificate alias, if any.
+=item B<-preserve_dates>
 
-=item B<-clrtrust>
+When signing a certificate, preserve "notBefore" and "notAfter" dates of any
+input certificate instead of adjusting them to current time and duration.
+Cannot be used together with the B<-days> option.
 
-Clears all the permitted or trusted uses of the certificate.
+=item B<-subj> I<arg>
 
-=item B<-clrreject>
+When a certificate is created set its subject name to the given value.
+When the certificate is self-signed the issuer name is set to the same value.
 
-Clears all the prohibited or rejected uses of the certificate.
+The arg must be formatted as C</type0=value0/type1=value1/type2=...>.
+Special characters may be escaped by C<\> (backslash), whitespace is retained.
+Empty values are permitted, but the corresponding type will not be included
+in the certificate.
+Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
+Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
+between the AttributeValueAssertions (AVAs) that specify the members of the set.
+Example:
 
-=item B<-addtrust> I<arg>
+C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
 
-Adds a trusted certificate use.
-Any object name can be used here but currently only B<clientAuth> (SSL client
-use), B<serverAuth> (SSL server use), B<emailProtection> (S/MIME email) and
-B<anyExtendedKeyUsage> are used.
-As of OpenSSL 1.1.0, the last of these blocks all purposes when rejected or
-enables all purposes when trusted.
-Other OpenSSL applications may define additional uses.
+This option can be used in conjunction with the B<-force_pubkey> option
+to create a certificate even without providing an input certificate
+or certificate request.
 
-=item B<-addreject> I<arg>
+=item B<-force_pubkey> I<filename>
 
-Adds a prohibited use. It accepts the same values as the B<-addtrust>
-option.
+When a certificate is created set its public key to the key in I<filename>
+instead of the key contained in the input or given with the B<-signkey> option.
 
-=item B<-purpose>
+This option is useful for creating self-issued certificates that are not
+self-signed, for instance when the key cannot be used for signing, such as DH.
+It can also be used in conjunction with b<-new> and B<-subj> to directly
+generate a certificate containing any desired public key.
 
-This option performs tests on the certificate extensions and outputs
-the results. For a more complete description see the
-L</CERTIFICATE EXTENSIONS> section.
+=item B<-clrext>
 
-=back
+When transforming a certificate to a new certificate
+by default all certificate extensions are retained.
 
-=head2 Signing Options
+When transforming a certificate or certificate request,
+the B<-clrext> option prevents taking over any extensions from the source.
+In any case, when producing a certificate request,
+neither subject identifier nor authority key identifier extensions are included.
 
-This command can be used to sign certificates and requests: it
-can thus behave like a "mini CA".
+=item B<-extfile> I<filename>
 
-=over 4
+Configuration file containing certificate and request X.509 extensions to add.
 
-=item B<-signkey> I<filename>|I<uri>
+=item B<-extensions> I<section>
 
-This option causes the input file to be self signed using the supplied
-private key.
+The section in the extfile to add X.509 extensions from.
+If this option is not
+specified then the extensions should either be contained in the unnamed
+(default) section or the default section should contain a variable called
+"extensions" which contains the section to use.
+See the L<x509v3_config(5)> manual page for details of the
+extension section format.
 
-It sets the issuer name to the subject name (i.e., makes it self-issued)
-and changes the public key to the supplied value (unless overridden by
-B<-force_pubkey>). It sets the validity start date to the current time
-and the end date to a value determined by the B<-days> option.
-It retains any certificate extensions unless the B<-clrext> option is supplied;
-this includes, for example, any existing key identifier extensions.
+=item B<-sigopt> I<nm>:I<v>
+
+Pass options to the signature algorithm during sign operations.
+This option may be given multiple times.
+Names and values provided using this option are algorithm-specific.
 
 =item B<-badsig>
 
 Corrupt the signature before writing it; this can be useful
 for testing.
 
-=item B<-sigopt> I<nm>:I<v>
-
-Pass options to the signature algorithm during sign operations.
-Names and values of these options are algorithm-specific.
-
-=item B<-vfyopt> I<nm>:I<v>
+=item B<-I<digest>>
 
-Pass options to the signature algorithm during verify operations.
-Names and values of these options are algorithm-specific.
+The digest to use.
+This affects any signing or printing option that uses a message
+digest, such as the B<-fingerprint>, B<-signkey> and B<-CA> options.
+Any digest supported by the L<openssl-dgst(1)> command can be used.
+If not specified then SHA1 is used with B<-fingerprint> or
+the default digest for the signing algorithm is used, typically SHA256.
 
-=item B<-passin> I<arg>
+=back
 
-The key and certificate file password source.
-For more information about the format of I<arg>
-see L<openssl-passphrase-options(1)>.
+=head2 Micro-CA Options
 
-=item B<-clrext>
+=over 4
 
-Delete any extensions from a certificate. This option is used when a
-certificate is being created from another certificate (for example with
-the B<-signkey> or the B<-CA> options). Normally all extensions are
-retained.
+=item B<-CA> I<filename>|I<uri>
 
-=item B<-keyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
+Specifies the "CA" certificate to be used for signing.
+When present, this behaves like a "micro CA" as follows:
+The subject name of the "CA" certificate is placed as issuer name in the new
+certificate, which is then signed using the "CA" key given as detailed below.
 
-The key format; the default is B<PEM>.
-The only value with effect is B<ENGINE>; all others have become obsolete.
-See L<openssl-format-options(1)> for details.
+This option cannot be used in conjunction with the B<-signkey> option.
+This option is normally combined with the B<-req> option referencing a CSR.
+Without the B<-req> option the input must be a self-signed certificate
+unless the B<-new> option is given, which generates a certificate from scratch.
 
 =item B<-CAform> B<DER>|B<PEM>|B<P12>,
 
 The format for the CA certificate.
 This option has no effect and is retained for backward compatibility.
 
+=item B<-CAkey> I<filename>|I<uri>
+
+Sets the CA private key to sign a certificate with.
+The private key must match the public key of the certificate given with B<-CA>.
+If this option is not provided then the key must be present in the B<-CA> input.
+
 =item B<-CAkeyform> B<DER>|B<PEM>|B<P12>|B<ENGINE>
 
 The format for the CA key; the default is B<PEM>.
 The only value with effect is B<ENGINE>; all others have become obsolete.
 See L<openssl-format-options(1)> for details.
 
-=item B<-days> I<arg>
-
-Specifies the number of days to make a certificate valid for. The default
-is 30 days. Cannot be used with the B<-preserve_dates> option.
-
-=item B<-x509toreq>
-
-Converts a certificate into a certificate request. The B<-signkey> option
-is used to pass the required private key.
-
-=item B<-req>
-
-By default a certificate is expected on input. With this option a
-certificate request is expected instead.
-
-=item B<-set_serial> I<n>
-
-Specifies the serial number to use. This option can be used with either
-the B<-signkey> or B<-CA> options. If used in conjunction with the B<-CA>
-option the serial number file (as specified by the B<-CAserial> or
-B<-CAcreateserial> options) is not used.
-
-The serial number can be decimal or hex (if preceded by C<0x>).
-
-=item B<-CA> I<filename>
-
-Specifies the CA certificate to be used for signing. When this option is
-present, this command behaves like a "mini CA". The input file is signed by
-this CA using this option: that is its issuer name is set to the subject name
-of the CA and it is digitally signed using the CAs private key.
-
-This option is normally combined with the B<-req> option. Without the
-B<-req> option the input is a certificate which must be self signed.
-
-=item B<-CAkey> I<filename>|I<uri>
-
-Sets the CA private key to sign a certificate with. If this option is
-not specified then it is assumed that the CA private key is present in
-the CA certificate file.
-
 =item B<-CAserial> I<filename>
 
 Sets the CA serial number file to use.
@@ -470,78 +500,92 @@ have the 1 as its serial number. If the B<-CA> option is specified
 and the serial number file does not exist a random number is generated;
 this is the recommended practice.
 
-=item B<-extfile> I<filename>
+=back
 
-File containing certificate extensions to use. If not specified then
-no extensions are added to the certificate.
+=head2 Trust Settings
 
-=item B<-extensions> I<section>
+A B<trusted certificate> is an ordinary certificate which has several
+additional pieces of information attached to it such as the permitted
+and prohibited uses of the certificate and possibly an "alias" (nickname).
 
-The section to add certificate extensions from. If this option is not
-specified then the extensions should either be contained in the unnamed
-(default) section or the default section should contain a variable called
-"extensions" which contains the section to use. See the
-L<x509v3_config(5)> manual page for details of the
-extension section format.
+Normally when a certificate is being verified at least one certificate
+must be "trusted". By default a trusted certificate must be stored
+locally and must be a root CA: any certificate chain ending in this CA
+is then usable for any purpose.
 
-=item B<-new>
+Trust settings currently are only used with a root CA.
+They allow a finer control over the purposes the root CA can be used for.
+For example, a CA may be trusted for SSL client but not SSL server use.
 
-Generate a certificate from scratch, not using an input certificate
-or certificate request. So the B<-in> option must not be used in this case.
-Instead, the B<-subj> and <-force_pubkey> options need to be given.
+See the description in L<openssl-verify(1)> for more information
+on the meaning of trust settings.
 
-=item B<-next_serial>
+Future versions of OpenSSL will recognize trust settings on any
+certificate: not just root CAs.
 
-Set the serial to be one more than the number in the certificate.
+=over 4
 
-=item B<-nocert>
+=item B<-trustout>
 
-Do not generate or output a certificate.
+Mark any certificate PEM output as <trusted> certificate rather than ordinary.
+An ordinary or trusted certificate can be input but by default an ordinary
+certificate is output and any trust settings are discarded.
+With the B<-trustout> option a trusted certificate is output. A trusted
+certificate is automatically output if any trust settings are modified.
 
-=item B<-force_pubkey> I<filename>
+=item B<-setalias> I<arg>
 
-When a certificate is created set its public key to the key in I<filename>
-instead of the key contained in the input or given with the B<-signkey> option.
+Sets the "alias" of the certificate. This will allow the certificate
+to be referred to using a nickname for example "Steve's Certificate".
 
-This option is useful for creating self-issued certificates that are not
-self-signed, for instance when the key cannot be used for signing, such as DH.
-It can also be used in conjunction with b<-new> and B<-subj> to directly
-generate a certificate containing any desired public key.
+=item B<-clrtrust>
 
-=item B<-subj> I<arg>
+Clears all the permitted or trusted uses of the certificate.
 
-When a certificate is created set its subject name to the given value.
+=item B<-addtrust> I<arg>
 
-The arg must be formatted as C</type0=value0/type1=value1/type2=...>.
-Special characters may be escaped by C<\> (backslash), whitespace is retained.
-Empty values are permitted, but the corresponding type will not be included
-in the certificate.
-Giving a single C</> will lead to an empty sequence of RDNs (a NULL-DN).
-Multi-valued RDNs can be formed by placing a C<+> character instead of a C</>
-between the AttributeValueAssertions (AVAs) that specify the members of the set.
-Example:
+Adds a trusted certificate use.
+Any object name can be used here but currently only B<clientAuth> (SSL client
+use), B<serverAuth> (SSL server use), B<emailProtection> (S/MIME email)
+and B<anyExtendedKeyUsage> are used.
+As of OpenSSL 1.1.0, the last of these blocks all purposes when rejected or
+enables all purposes when trusted.
+Other OpenSSL applications may define additional uses.
 
-C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
+=item B<-clrreject>
 
-Unless the B<-CA> option is given the issuer is set to the same value.
+Clears all the prohibited or rejected uses of the certificate.
 
-This option can be used in conjunction with the B<-force_pubkey> option
-to create a certificate even without providing an input certificate
-or certificate request.
+=item B<-addreject> I<arg>
+
+Adds a prohibited use.
+It accepts the same values as the B<-addtrust> option.
 
 =back
 
-=head2 Text Options
+=head2 Generic options
+
+=over 4
+
+{- $OpenSSL::safe::opt_r_item -}
 
-As well as customising the name output format, it is also possible to
-customise the actual fields printed using the B<certopt> options when
+{- $OpenSSL::safe::opt_engine_item -}
+
+{- $OpenSSL::safe::opt_provider_item -}
+
+=back
+
+=head2 Text Printing Flags
+
+As well as customising the name printing format, it is also possible to
+customise the actual fields printed using the B<certopt> option when
 the B<text> option is present. The default behaviour is to print all fields.
 
 =over 4
 
 =item B<compatible>
 
-Use the old format. This is equivalent to specifying no output options at all.
+Use the old format. This is equivalent to specifying no printing options at all.
 
 =item B<no_header>
 
@@ -617,36 +661,36 @@ B<no_header>, and B<no_version>.
 Note: in these examples the '\' means the example should be all on one
 line.
 
-Display the contents of a certificate:
+Print the contents of a certificate:
 
  openssl x509 -in cert.pem -noout -text
 
-Display the "Subject Alternative Name" extension of a certificate:
+Print the "Subject Alternative Name" extension of a certificate:
 
  openssl x509 -in cert.pem -noout -ext subjectAltName
 
-Display more extensions of a certificate:
+Print more extensions of a certificate:
 
  openssl x509 -in cert.pem -noout -ext subjectAltName,nsCertType
 
-Display the certificate serial number:
+Print the certificate serial number:
 
  openssl x509 -in cert.pem -noout -serial
 
-Display the certificate subject name:
+Print the certificate subject name:
 
  openssl x509 -in cert.pem -noout -subject
 
-Display the certificate subject name in RFC2253 form:
+Print the certificate subject name in RFC2253 form:
 
  openssl x509 -in cert.pem -noout -subject -nameopt RFC2253
 
-Display the certificate subject name in oneline form on a terminal
+Print the certificate subject name in oneline form on a terminal
 supporting UTF8:
 
  openssl x509 -in cert.pem -noout -subject -nameopt oneline,-esc_msb
 
-Display the certificate SHA1 fingerprint:
+Print the certificate SHA1 fingerprint:
 
  openssl x509 -sha1 -in cert.pem -noout -fingerprint
 
@@ -658,7 +702,7 @@ Convert a certificate to a certificate request:
 
  openssl x509 -x509toreq -in cert.pem -out req.pem -signkey key.pem
 
-Convert a certificate request into a self signed certificate using
+Convert a certificate request into a self-signed certificate using
 extensions for a CA:
 
  openssl x509 -req -in careq.pem -extfile openssl.cnf -extensions v3_ca \
@@ -670,7 +714,6 @@ certificate extensions:
  openssl x509 -req -in req.pem -extfile openssl.cnf -extensions v3_usr \
         -CA cacert.pem -CAkey key.pem -CAcreateserial
 
-
 Set a certificate to be trusted for SSL client use and change set its alias to
 "Steve's Class 1 CA"
 
@@ -682,7 +725,7 @@ Set a certificate to be trusted for SSL client use and change set its alias to
 The conversion to UTF8 format used with the name options assumes that
 T61Strings use the ISO8859-1 character set. This is wrong but Netscape
 and MSIE do this as do many certificates. So although this is incorrect
-it is more likely to display the majority of certificates correctly.
+it is more likely to print the majority of certificates correctly.
 
 The B<-email> option searches the subject name and the subject alternative
 name extension. Only unique email addresses will be printed out: it will
@@ -710,9 +753,9 @@ because the certificate should really not be regarded as a CA: however
 it is allowed to be a CA to work around some broken software.
 
 If the certificate is a V1 certificate (and thus has no extensions) and
-it is self signed it is also assumed to be a CA but a warning is again
+it is self-signed it is also assumed to be a CA but a warning is again
 given: this is to work around the problem of Verisign roots which are V1
-self signed certificates.
+self-signed certificates.
 
 If the keyUsage extension is present then additional restraints are
 made on the uses of the certificate. A CA certificate B<must> have the
@@ -803,12 +846,9 @@ must be present.
 
 =head1 BUGS
 
-Extensions in certificates are not transferred to certificate requests and
-vice versa.
-
 It is possible to produce invalid certificates or requests by specifying the
-wrong private key or using inconsistent options in some cases: these should
-be checked.
+wrong private key, using unsuitable X.509 extensions,
+or using inconsistent options in some cases: these should be checked.
 
 There should be options to explicitly set such things as start and end
 dates rather than an offset from the current time.
diff --git a/doc/man3/X509v3_get_ext_by_NID.pod b/doc/man3/X509v3_get_ext_by_NID.pod
index f77474ca80..79c68e1478 100644
--- a/doc/man3/X509v3_get_ext_by_NID.pod
+++ b/doc/man3/X509v3_get_ext_by_NID.pod
@@ -74,9 +74,9 @@ looks for an extension of criticality B<crit>. A zero value for B<crit>
 looks for a non-critical extension a nonzero value looks for a critical
 extension.
 
-X509v3_delete_ext() deletes the extension with index B<loc> from B<x>. The
-deleted extension is returned and must be freed by the caller. If B<loc>
-is in invalid index value B<NULL> is returned.
+X509v3_delete_ext() deletes the extension with index B<loc> from B<x>.
+The deleted extension is returned and must be freed by the caller.
+If B<loc> is in invalid index value B<NULL> is returned.
 
 X509v3_add_ext() adds extension B<ex> to stack B<*x> at position B<loc>. If
 B<loc> is B<-1> the new extension is added to the end. If B<*x> is B<NULL>
@@ -111,6 +111,11 @@ error. These search functions start from the extension B<after> the B<lastpos>
 parameter so it should initially be set to B<-1>, if it is set to zero the
 initial extension will not be checked.
 
+=head1 BUGS
+
+X509v3_delete_ext() and its variants are a bit counter-intuitive
+because these functions do not free the extension they delete.
+
 =head1 RETURN VALUES
 
 X509v3_get_ext_count() returns the extension count.
diff --git a/include/openssl/x509.h.in b/include/openssl/x509.h.in
index 1d9ca63405..bf525f427f 100644
--- a/include/openssl/x509.h.in
+++ b/include/openssl/x509.h.in
@@ -734,9 +734,9 @@ int X509_REQ_extension_nid(int nid);
 int *X509_REQ_get_extension_nids(void);
 void X509_REQ_set_extension_nids(int *nids);
 STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req);
-int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
-                                int nid);
-int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts);
+int X509_REQ_add_extensions_nid(X509_REQ *req,
+                                const STACK_OF(X509_EXTENSION) *exts, int nid);
+int X509_REQ_add_extensions(X509_REQ *req, const STACK_OF(X509_EXTENSION) *ext);
 int X509_REQ_get_attr_count(const X509_REQ *req);
 int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos);
 int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj,
diff --git a/test/recipes/25-test_x509.t b/test/recipes/25-test_x509.t
index e9550f1fe4..afaed66293 100644
--- a/test/recipes/25-test_x509.t
+++ b/test/recipes/25-test_x509.t
@@ -18,23 +18,23 @@ setup("test_x509");
 
 plan tests => 15;
 
-require_ok(srctop_file('test','recipes','tconversion.pl'));
+require_ok(srctop_file("test", "recipes", "tconversion.pl"));
 
 my @certs = qw(test certs);
-my $pem = srctop_file("test/certs", "cyrillic.pem");
+my $pem = srctop_file(@certs, "cyrillic.pem");
 my $out_msb = "out-cyrillic.msb";
 my $out_utf8 = "out-cyrillic.utf8";
-my $msb = srctop_file("test/certs", "cyrillic.msb");
-my $utf = srctop_file("test/certs", "cyrillic.utf8");
+my $msb = srctop_file(@certs, "cyrillic.msb");
+my $utf = srctop_file(@certs, "cyrillic.utf8");
 
 ok(run(app(["openssl", "x509", "-text", "-in", $pem, "-out", $out_msb,
             "-nameopt", "esc_msb"])));
-is(cmp_text($out_msb, srctop_file("test/certs", "cyrillic.msb")),
-   0, 'Comparing esc_msb output');
+is(cmp_text($out_msb, srctop_file(@certs, "cyrillic.msb")),
+   0, 'Comparing esc_msb output with cyrillic.msb');
 ok(run(app(["openssl", "x509", "-text", "-in", $pem, "-out", $out_utf8,
             "-nameopt", "utf8"])));
-is(cmp_text($out_utf8, srctop_file("test/certs", "cyrillic.utf8")),
-   0, 'Comparing utf8 output');
+is(cmp_text($out_utf8, srctop_file(@certs, "cyrillic.utf8")),
+   0, 'Comparing utf8 output with cyrillic.utf8');
 
  SKIP: {
     skip "DES disabled", 1 if disabled("des");
@@ -44,49 +44,42 @@ is(cmp_text($out_utf8, srctop_file("test/certs", "cyrillic.utf8")),
     my $out_pem = "out.pem";
     ok(run(app(["openssl", "x509", "-text", "-in", $p12, "-out", $out_pem,
                 "-passin", "pass:$p12pass"])));
-    unlink $out_pem;
+    # not unlinking $out_pem
 }
 
-SKIP: {
-    skip "EC disabled", 1 if disabled("ec");
-
-    # producing and checking self-issued (but not self-signed) cert
-    my @path = qw(test certs);
-    my $subj = "/CN=CA"; # using same DN as in issuer of ee-cert.pem
-    my $extfile = srctop_file("test", "v3_ca_exts.cnf");
-    my $pkey = srctop_file(@path, "ca-key.pem"); #  issuer private key
-    my $pubkey = "ca-pubkey.pem"; # the corresponding issuer public key
-    # use any (different) key for signing our self-issued cert:
-    my $signkey = srctop_file(@path, "ee-ecdsa-key.pem");
-    my $selfout = "self-issued.out";
-    my $testcert = srctop_file(@path, "ee-cert.pem");
-    ok(run(app(["openssl", "pkey", "-in", $pkey, "-pubout", "-out", $pubkey]))
-       &&
-       run(app(["openssl", "x509", "-new", "-force_pubkey", $pubkey,
-                "-subj", $subj, "-extfile", $extfile,
-                "-signkey", $signkey, "-out", $selfout]))
-       &&
-       run(app(["openssl", "verify", "-no_check_time",
-                "-trusted", $selfout, "-partial_chain", $testcert])));
-    unlink $pubkey;
-    unlink $selfout;
-}
+# producing and checking self-issued (but not self-signed) cert
+my $subj = "/CN=CA"; # using same DN as in issuer of ee-cert.pem
+my $extfile = srctop_file("test", "v3_ca_exts.cnf");
+my $pkey = srctop_file(@certs, "ca-key.pem"); # issuer private key
+my $pubkey = "ca-pubkey.pem"; # the corresponding issuer public key
+# use any (different) key for signing our self-issued cert:
+my $signkey = srctop_file(@certs, "serverkey.pem");
+my $selfout = "self-issued.out";
+my $testcert = srctop_file(@certs, "ee-cert.pem");
+ok(run(app(["openssl", "pkey", "-in", $pkey, "-pubout", "-out", $pubkey]))
+&& run(app(["openssl", "x509", "-new", "-force_pubkey", $pubkey,
+            "-subj", $subj, "-extfile", $extfile,
+            "-signkey", $signkey, "-out", $selfout]))
+&& run(app(["openssl", "verify", "-no_check_time",
+            "-trusted", $selfout, "-partial_chain", $testcert])));
+# not unlinking $pubkey
+# not unlinking $selfout
 
 subtest 'x509 -- x.509 v1 certificate' => sub {
     tconversion( -type => 'x509', -prefix => 'x509v1',
-                 -in => srctop_file("test","testx509.pem") );
+                 -in => srctop_file("test", "testx509.pem") );
 };
 subtest 'x509 -- first x.509 v3 certificate' => sub {
     tconversion( -type => 'x509', -prefix => 'x509v3-1',
-                 -in => srctop_file("test","v3-cert1.pem") );
+                 -in => srctop_file("test", "v3-cert1.pem") );
 };
 subtest 'x509 -- second x.509 v3 certificate' => sub {
     tconversion( -type => 'x509', -prefix => 'x509v3-2',
-                 -in => srctop_file("test","v3-cert2.pem") );
+                 -in => srctop_file("test", "v3-cert2.pem") );
 };
 
 subtest 'x509 -- pathlen' => sub {
-    ok(run(test(["v3ext", srctop_file("test/certs", "pathlen.pem")])));
+    ok(run(test(["v3ext", srctop_file(@certs, "pathlen.pem")])));
 };
 
 cert_contains(srctop_file(@certs, "fake-gp.pem"),
@@ -95,7 +88,7 @@ cert_contains(srctop_file(@certs, "fake-gp.pem"),
 
 sub test_errors { # actually tests diagnostics of OSSL_STORE
     my ($expected, $cert, @opts) = @_;
-    my $infile = srctop_file('test', 'certs', $cert);
+    my $infile = srctop_file(@certs, $cert);
     my @args = qw(openssl x509 -in);
     push(@args, $infile, @opts);
     my $tmpfile = 'out.txt';
diff --git a/test/recipes/80-test_ssl_old.t b/test/recipes/80-test_ssl_old.t
index 05b940ca8e..f6fb87bce5 100644
--- a/test/recipes/80-test_ssl_old.t
+++ b/test/recipes/80-test_ssl_old.t
@@ -17,7 +17,7 @@ use OpenSSL::Test qw/:DEFAULT with bldtop_file bldtop_dir srctop_file srctop_dir
 use OpenSSL::Test::Utils;
 
 BEGIN {
-setup("test_ssl");
+setup("test_ssl_old");
 }
 
 use lib srctop_dir('Configurations');
@@ -103,15 +103,15 @@ subtest 'test_ss' => sub {
     }
 };
 
-note('test_ssl -- key U');
+note('test_ssl_old -- key U');
 my $configfile = srctop_file("test","default-and-legacy.cnf");
 if (disabled("legacy")) {
     $configfile = srctop_file("test","default.cnf");
 }
 
-testssl("keyU.ss", $Ucert, $CAcert, "default", $configfile);
+testssl($Ukey, $Ucert, $CAcert, "default", $configfile);
 unless ($no_fips) {
-    testssl("keyU.ss", $Ucert, $CAcert, "fips",
+    testssl($Ukey, $Ucert, $CAcert, "fips",
             srctop_file("test","fips-and-base.cnf"));
 }
 


More information about the openssl-commits mailing list