add OSSL_STACK_OF_X509_free() for commonly used pattern
[openssl.git] / apps / lib / apps.c
index dafcf419bf51f876a3b22c77ad86e225f4a015d8..88c4f7b97ae23e58e12610d7942710e65b4321b4 100644 (file)
 # define _POSIX_C_SOURCE 2
 #endif
 
+#ifndef OPENSSL_NO_ENGINE
+/* We need to use some deprecated APIs */
+# define OPENSSL_SUPPRESS_DEPRECATED
+# include <openssl/engine.h>
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -35,6 +41,7 @@
 #include <openssl/ui.h>
 #include <openssl/safestack.h>
 #include <openssl/rsa.h>
+#include <openssl/rand.h>
 #include <openssl/bn.h>
 #include <openssl/ssl.h>
 #include <openssl/store.h>
@@ -68,12 +75,18 @@ typedef struct {
     unsigned long mask;
 } NAME_EX_TBL;
 
-static OSSL_LIB_CTX *app_libctx = NULL;
-
 static int set_table_opts(unsigned long *flags, const char *arg,
                           const NAME_EX_TBL * in_tbl);
 static int set_multi_opts(unsigned long *flags, const char *arg,
                           const NAME_EX_TBL * in_tbl);
+static
+int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin,
+                                 const char *pass, const char *desc,
+                                 EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+                                 EVP_PKEY **pparams,
+                                 X509 **pcert, STACK_OF(X509) **pcerts,
+                                 X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls,
+                                 int suppress_decode_errors);
 
 int app_init(long mesgwin);
 
@@ -184,17 +197,13 @@ int set_nameopt(const char *arg)
 
 unsigned long get_nameopt(void)
 {
-    return (nmflag_set) ? nmflag : XN_FLAG_ONELINE;
+    return (nmflag_set) ? nmflag : XN_FLAG_SEP_CPLUS_SPC | ASN1_STRFLGS_UTF8_CONVERT;
 }
 
-int dump_cert_text(BIO *out, X509 *x)
+void dump_cert_text(BIO *out, X509 *x)
 {
     print_name(out, "subject=", X509_get_subject_name(x));
-    BIO_puts(out, "\n");
     print_name(out, "issuer=", X509_get_issuer_name(x));
-    BIO_puts(out, "\n");
-
-    return 0;
 }
 
 int wrap_password_callback(char *buf, int bufsiz, int verify, void *userdata)
@@ -251,21 +260,21 @@ static char *app_get_pass(const char *arg, int keepbio)
     int i;
 
     /* PASS_SOURCE_SIZE_MAX = max number of chars before ':' in below strings */
-    if (strncmp(arg, "pass:", 5) == 0)
-        return OPENSSL_strdup(arg + 5);
-    if (strncmp(arg, "env:", 4) == 0) {
-        tmp = getenv(arg + 4);
+    if (CHECK_AND_SKIP_PREFIX(arg, "pass:"))
+        return OPENSSL_strdup(arg);
+    if (CHECK_AND_SKIP_PREFIX(arg, "env:")) {
+        tmp = getenv(arg);
         if (tmp == NULL) {
-            BIO_printf(bio_err, "No environment variable %s\n", arg + 4);
+            BIO_printf(bio_err, "No environment variable %s\n", arg);
             return NULL;
         }
         return OPENSSL_strdup(tmp);
     }
     if (!keepbio || pwdbio == NULL) {
-        if (strncmp(arg, "file:", 5) == 0) {
-            pwdbio = BIO_new_file(arg + 5, "r");
+        if (CHECK_AND_SKIP_PREFIX(arg, "file:")) {
+            pwdbio = BIO_new_file(arg, "r");
             if (pwdbio == NULL) {
-                BIO_printf(bio_err, "Can't open file %s\n", arg + 5);
+                BIO_printf(bio_err, "Can't open file %s\n", arg);
                 return NULL;
             }
 #if !defined(_WIN32)
@@ -277,13 +286,13 @@ static char *app_get_pass(const char *arg, int keepbio)
              * on real Windows descriptors, such as those obtained
              * with CreateFile.
              */
-        } else if (strncmp(arg, "fd:", 3) == 0) {
+        } else if (CHECK_AND_SKIP_PREFIX(arg, "fd:")) {
             BIO *btmp;
-            i = atoi(arg + 3);
+            i = atoi(arg);
             if (i >= 0)
                 pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
             if ((i < 0) || !pwdbio) {
-                BIO_printf(bio_err, "Can't access file descriptor %s\n", arg + 3);
+                BIO_printf(bio_err, "Can't access file descriptor %s\n", arg);
                 return NULL;
             }
             /*
@@ -327,50 +336,13 @@ static char *app_get_pass(const char *arg, int keepbio)
     return OPENSSL_strdup(tpass);
 }
 
-OSSL_LIB_CTX *app_get0_libctx(void)
-{
-    return app_libctx;
-}
-
-static const char *app_propq = NULL;
-
-int app_set_propq(const char *arg)
-{
-    app_propq = arg;
-    return 1;
-}
-
-const char *app_get0_propq(void)
-{
-    return app_propq;
-}
-
-OSSL_LIB_CTX *app_create_libctx(void)
-{
-    /*
-     * Load the NULL provider into the default library context and create a
-     * library context which will then be used for any OPT_PROV options.
-     */
-    if (app_libctx == NULL) {
-
-        if (!app_provider_load(NULL, "null")) {
-            BIO_puts(bio_err, "Failed to create null provider\n");
-            return NULL;
-        }
-        app_libctx = OSSL_LIB_CTX_new();
-    }
-    if (app_libctx == NULL)
-        BIO_puts(bio_err, "Failed to create library context\n");
-    return app_libctx;
-}
-
 CONF *app_load_config_bio(BIO *in, const char *filename)
 {
     long errorline = -1;
     CONF *conf;
     int i;
 
-    conf = NCONF_new_ex(app_libctx, NULL);
+    conf = NCONF_new_ex(app_get0_libctx(), NULL);
     i = NCONF_load_bio(conf, in, &errorline);
     if (i > 0)
         return conf;
@@ -403,14 +375,18 @@ CONF *app_load_config_verbose(const char *filename, int verbose)
 
 CONF *app_load_config_internal(const char *filename, int quiet)
 {
-    BIO *in = NULL; /* leads to empty config in case filename == "" */
+    BIO *in;
     CONF *conf;
 
-    if (*filename != '\0'
-        && (in = bio_open_default_(filename, 'r', FORMAT_TEXT, quiet)) == NULL)
-        return NULL;
-    conf = app_load_config_bio(in, filename);
-    BIO_free(in);
+    if (filename == NULL || *filename != '\0') {
+        if ((in = bio_open_default_(filename, 'r', FORMAT_TEXT, quiet)) == NULL)
+            return NULL;
+        conf = app_load_config_bio(in, filename);
+        BIO_free(in);
+    } else {
+        /* Return empty config if filename is empty string. */
+        conf = NCONF_new_ex(app_get0_libctx(), NULL);
+    }
     return conf;
 }
 
@@ -474,10 +450,8 @@ CONF *app_load_config_modules(const char *configfile)
     return conf;
 }
 
-#define IS_HTTP(uri) ((uri) != NULL \
-        && strncmp(uri, OSSL_HTTP_PREFIX, strlen(OSSL_HTTP_PREFIX)) == 0)
-#define IS_HTTPS(uri) ((uri) != NULL \
-        && strncmp(uri, OSSL_HTTPS_PREFIX, strlen(OSSL_HTTPS_PREFIX)) == 0)
+#define IS_HTTP(uri) ((uri) != NULL  && HAS_PREFIX(uri, OSSL_HTTP_PREFIX))
+#define IS_HTTPS(uri) ((uri) != NULL && HAS_PREFIX(uri, OSSL_HTTPS_PREFIX))
 
 X509 *load_cert_pass(const char *uri, int format, int maybe_stdin,
                      const char *pass, const char *desc)
@@ -600,27 +574,37 @@ EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
     return pkey;
 }
 
-EVP_PKEY *load_keyparams(const char *uri, int format, int maybe_stdin,
-                         const char *keytype, const char *desc)
+EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin,
+                                 const char *keytype, const char *desc,
+                                 int suppress_decode_errors)
 {
     EVP_PKEY *params = NULL;
 
     if (desc == NULL)
         desc = "key parameters";
 
-    (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc,
-                              NULL, NULL, &params, NULL, NULL, NULL, NULL);
+    (void)load_key_certs_crls_suppress(uri, format, maybe_stdin, NULL, desc,
+                                       NULL, NULL, &params, NULL, NULL, NULL,
+                                       NULL, suppress_decode_errors);
     if (params != NULL && keytype != NULL && !EVP_PKEY_is_a(params, keytype)) {
-        BIO_printf(bio_err,
-                   "Unable to load %s from %s (unexpected parameters type)\n",
-                   desc, uri);
-        ERR_print_errors(bio_err);
+        if (!suppress_decode_errors) {
+            BIO_printf(bio_err,
+                       "Unable to load %s from %s (unexpected parameters type)\n",
+                       desc, uri);
+            ERR_print_errors(bio_err);
+        }
         EVP_PKEY_free(params);
         params = NULL;
     }
     return params;
 }
 
+EVP_PKEY *load_keyparams(const char *uri, int format, int maybe_stdin,
+                         const char *keytype, const char *desc)
+{
+    return load_keyparams_suppress(uri, format, maybe_stdin, keytype, desc, 0);
+}
+
 void app_bail_out(char *fmt, ...)
 {
     va_list args;
@@ -629,7 +613,7 @@ void app_bail_out(char *fmt, ...)
     BIO_vprintf(bio_err, fmt, args);
     va_end(args);
     ERR_print_errors(bio_err);
-    exit(1);
+    exit(EXIT_FAILURE);
 }
 
 void *app_malloc(size_t sz, const char *what)
@@ -696,8 +680,8 @@ int load_cert_certs(const char *uri,
     int ret = 0;
     char *pass_string;
 
-    if (exclude_http && (strncasecmp(uri, "http://", 7) == 0
-                         || strncasecmp(uri, "https://", 8) == 0)) {
+    if (exclude_http && (HAS_CASE_PREFIX(uri, "http://")
+                         || HAS_CASE_PREFIX(uri, "https://"))) {
         BIO_printf(bio_err, "error: HTTP retrieval not allowed for %s\n", desc);
         return ret;
     }
@@ -712,7 +696,7 @@ int load_cert_certs(const char *uri,
             warn_cert(uri, *pcert, 0, vpm);
         warn_certs(uri, *pcerts, 1, vpm);
     } else {
-        sk_X509_pop_free(*pcerts, X509_free);
+        OSSL_STACK_OF_X509_free(*pcerts);
         *pcerts = NULL;
     }
     return ret;
@@ -737,7 +721,7 @@ STACK_OF(X509) *load_certs_multifile(char *files, const char *pass,
         if (!X509_add_certs(result, certs,
                             X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
             goto oom;
-        sk_X509_pop_free(certs, X509_free);
+        OSSL_STACK_OF_X509_free(certs);
         certs = NULL;
         files = next;
     }
@@ -746,8 +730,8 @@ STACK_OF(X509) *load_certs_multifile(char *files, const char *pass,
  oom:
     BIO_printf(bio_err, "out of memory\n");
  err:
-    sk_X509_pop_free(certs, X509_free);
-    sk_X509_pop_free(result, X509_free);
+    OSSL_STACK_OF_X509_free(certs);
+    OSSL_STACK_OF_X509_free(result);
     return NULL;
 }
 
@@ -788,7 +772,7 @@ X509_STORE *load_certstore(char *input, const char *pass, const char *desc,
             return NULL;
         }
         ok = (store = sk_X509_to_store(store, certs)) != NULL;
-        sk_X509_pop_free(certs, X509_free);
+        OSSL_STACK_OF_X509_free(certs);
         certs = NULL;
         if (!ok)
             return NULL;
@@ -810,7 +794,7 @@ int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs,
                                   NULL, NULL, certs, NULL, NULL);
 
     if (!ret && was_NULL) {
-        sk_X509_pop_free(*certs, X509_free);
+        OSSL_STACK_OF_X509_free(*certs);
         *certs = NULL;
     }
     return ret;
@@ -837,7 +821,7 @@ int load_crls(const char *uri, STACK_OF(X509_CRL) **crls,
 
 static const char *format2string(int format)
 {
-    switch(format) {
+    switch (format) {
     case FORMAT_PEM:
         return "PEM";
     case FORMAT_ASN1:
@@ -861,12 +845,14 @@ static const char *format2string(int format)
  * In any case (also on error) the caller is responsible for freeing all members
  * of *pcerts and *pcrls (as far as they are not NULL).
  */
-int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
-                        const char *pass, const char *desc,
-                        EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
-                        EVP_PKEY **pparams,
-                        X509 **pcert, STACK_OF(X509) **pcerts,
-                        X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls)
+static
+int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin,
+                                 const char *pass, const char *desc,
+                                 EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+                                 EVP_PKEY **pparams,
+                                 X509 **pcert, STACK_OF(X509) **pcerts,
+                                 X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls,
+                                 int suppress_decode_errors)
 {
     PW_CB_DATA uidata;
     OSSL_STORE_CTX *ctx = NULL;
@@ -884,7 +870,6 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
     const char *input_type;
     OSSL_PARAM itp[2];
     const OSSL_PARAM *params = NULL;
-    /* TODO make use of the engine reference 'eng' when loading pkeys */
 
     if (ppkey != NULL) {
         *ppkey = NULL;
@@ -983,10 +968,6 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
          * certificate in it. We just retry until eof.
          */
         if (info == NULL) {
-            if (OSSL_STORE_error(ctx)) {
-                ERR_print_errors(bio_err);
-                ERR_clear_error();
-            }
             continue;
         }
 
@@ -1070,12 +1051,14 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
                 any = 1;
             failed = "CRL";
         }
-        if (failed != NULL)
-            BIO_printf(bio_err, "Could not read");
-        if (any)
-            BIO_printf(bio_err, " any");
+        if (!suppress_decode_errors) {
+            if (failed != NULL)
+                BIO_printf(bio_err, "Could not read");
+            if (any)
+                BIO_printf(bio_err, " any");
+        }
     }
-    if (failed != NULL) {
+    if (!suppress_decode_errors && failed != NULL) {
         if (desc != NULL && strstr(desc, failed) != NULL) {
             BIO_printf(bio_err, " %s", desc);
         } else {
@@ -1088,9 +1071,23 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
         BIO_printf(bio_err, "\n");
         ERR_print_errors(bio_err);
     }
+    if (suppress_decode_errors || failed == NULL)
+        /* clear any spurious errors */
+        ERR_clear_error();
     return failed == NULL;
 }
 
+int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
+                        const char *pass, const char *desc,
+                        EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+                        EVP_PKEY **pparams,
+                        X509 **pcert, STACK_OF(X509) **pcerts,
+                        X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls)
+{
+    return load_key_certs_crls_suppress(uri, format, maybe_stdin, pass, desc,
+                                        ppkey, ppubkey, pparams, pcert, pcerts,
+                                        pcrl, pcrls, 0);
+}
 
 #define X509V3_EXT_UNKNOWN_MASK         (0xfL << 16)
 /* Return error for unknown extensions */
@@ -1172,6 +1169,15 @@ int set_name_ex(unsigned long *flags, const char *arg)
     return 1;
 }
 
+int set_dateopt(unsigned long *dateopt, const char *arg)
+{
+    if (strcasecmp(arg, "rfc_822") == 0)
+        *dateopt = ASN1_DTFLGS_RFC822;
+    else if (strcasecmp(arg, "iso_8601") == 0)
+        *dateopt = ASN1_DTFLGS_ISO8601;
+    return 0;
+}
+
 int set_ext_copy(int *copy_type, const char *arg)
 {
     if (strcasecmp(arg, "none") == 0)
@@ -1277,6 +1283,8 @@ void print_name(BIO *out, const char *title, const X509_NAME *nm)
     int indent = 0;
     unsigned long lflags = get_nameopt();
 
+    if (out == NULL)
+        return;
     if (title != NULL)
         BIO_puts(out, title);
     if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
@@ -1932,7 +1940,7 @@ X509_NAME *parse_name(const char *cp, int chtype, int canmulti,
             ERR_print_errors(bio_err);
             BIO_printf(bio_err,
                        "%s: Error adding %s name attribute \"/%s=%s\"\n",
-                       opt_getprog(), desc, typestr ,valstr);
+                       opt_getprog(), desc, typestrvalstr);
             goto err;
         }
     }
@@ -2096,29 +2104,43 @@ unsigned char *next_protos_parse(size_t *outlen, const char *in)
     return out;
 }
 
-void print_cert_checks(BIO *bio, X509 *x,
+int check_cert_attributes(BIO *bio, X509 *x,
                        const char *checkhost,
-                       const char *checkemail, const char *checkip)
+                       const char *checkemail, const char *checkip, int print)
 {
+    int valid_host = 0;
+    int valid_mail = 0;
+    int valid_ip = 0;
+    int ret = 1;
+
     if (x == NULL)
-        return;
-    if (checkhost) {
-        BIO_printf(bio, "Hostname %s does%s match certificate\n",
-                   checkhost,
-                   X509_check_host(x, checkhost, 0, 0, NULL) == 1
-                       ? "" : " NOT");
+        return 0;
+
+    if (checkhost != NULL) {
+        valid_host = X509_check_host(x, checkhost, 0, 0, NULL);
+        if (print)
+            BIO_printf(bio, "Hostname %s does%s match certificate\n",
+                       checkhost, valid_host == 1 ? "" : " NOT");
+        ret = ret && valid_host;
     }
 
-    if (checkemail) {
-        BIO_printf(bio, "Email %s does%s match certificate\n",
-                   checkemail, X509_check_email(x, checkemail, 0, 0)
-                   ? "" : " NOT");
+    if (checkemail != NULL) {
+        valid_mail = X509_check_email(x, checkemail, 0, 0);
+        if (print)
+            BIO_printf(bio, "Email %s does%s match certificate\n",
+                       checkemail, valid_mail ? "" : " NOT");
+        ret = ret && valid_mail;
     }
 
-    if (checkip) {
-        BIO_printf(bio, "IP %s does%s match certificate\n",
-                   checkip, X509_check_ip_asc(x, checkip, 0) ? "" : " NOT");
+    if (checkip != NULL) {
+        valid_ip   =  X509_check_ip_asc(x, checkip, 0);
+        if (print)
+            BIO_printf(bio, "IP %s does%s match certificate\n",
+                       checkip,  valid_ip ? "" : " NOT");
+        ret = ret && valid_ip;
     }
+
+    return ret;
 }
 
 static int do_pkey_ctx_init(EVP_PKEY_CTX *pkctx, STACK_OF(OPENSSL_STRING) *opts)
@@ -2214,8 +2236,8 @@ static int adapt_keyid_ext(X509 *cert, X509V3_CTX *ext_ctx,
     idx = X509v3_get_ext_by_OBJ(exts, X509_EXTENSION_get_object(new_ext), -1);
     if (idx >= 0) {
         X509_EXTENSION *found_ext = X509v3_get_ext(exts, idx);
-        ASN1_OCTET_STRING *data = X509_EXTENSION_get_data(found_ext);
-        int disabled = ASN1_STRING_length(data) <= 2; /* config said "none" */
+        ASN1_OCTET_STRING *encoded = X509_EXTENSION_get_data(found_ext);
+        int disabled = ASN1_STRING_length(encoded) <= 2; /* indicating "none" */
 
         if (disabled) {
             X509_delete_ext(cert, idx);
@@ -2229,6 +2251,16 @@ static int adapt_keyid_ext(X509 *cert, X509V3_CTX *ext_ctx,
     return rv;
 }
 
+int cert_matches_key(const X509 *cert, const EVP_PKEY *pkey)
+{
+    int match;
+
+    ERR_set_mark();
+    match = X509_check_private_key(cert, pkey);
+    ERR_pop_to_mark();
+    return match;
+}
+
 /* Ensure RFC 5280 compliance, adapt keyIDs as needed, and sign the cert info */
 int do_X509_sign(X509 *cert, EVP_PKEY *pkey, const char *md,
                  STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx)
@@ -2244,21 +2276,17 @@ int do_X509_sign(X509 *cert, EVP_PKEY *pkey, const char *md,
             goto end;
 
         /*
-         * Add default SKID before such that default AKID can make use of it
+         * Add default SKID before AKID such that AKID can make use of it
          * in case the certificate is self-signed
          */
         /* Prevent X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER */
         if (!adapt_keyid_ext(cert, ext_ctx, "subjectKeyIdentifier", "hash", 1))
             goto end;
         /* Prevent X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER */
-        ERR_set_mark();
-        self_sign = X509_check_private_key(cert, pkey);
-        ERR_pop_to_mark();
+        self_sign = cert_matches_key(cert, pkey);
         if (!adapt_keyid_ext(cert, ext_ctx, "authorityKeyIdentifier",
                              "keyid, issuer", !self_sign))
             goto end;
-
-        /* TODO any further measures for ensuring default RFC 5280 compliance */
     }
 
     if (mctx != NULL && do_sign_init(mctx, pkey, md, sigopts) > 0)
@@ -2294,23 +2322,35 @@ int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const char *md,
     return rv;
 }
 
+/*
+ * do_X509_verify returns 1 if the signature is valid,
+ * 0 if the signature check fails, or -1 if error occurs.
+ */
 int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts)
 {
     int rv = 0;
 
     if (do_x509_init(x, vfyopts) > 0)
-        rv = (X509_verify(x, pkey) > 0);
+        rv = X509_verify(x, pkey);
+    else
+        rv = -1;
     return rv;
 }
 
+/*
+ * do_X509_REQ_verify returns 1 if the signature is valid,
+ * 0 if the signature check fails, or -1 if error occurs.
+ */
 int do_X509_REQ_verify(X509_REQ *x, EVP_PKEY *pkey,
                        STACK_OF(OPENSSL_STRING) *vfyopts)
 {
     int rv = 0;
 
     if (do_x509_req_init(x, vfyopts) > 0)
-        rv = (X509_REQ_verify_ex(x, pkey,
-                                 app_get0_libctx(), app_get0_propq()) > 0);
+        rv = X509_REQ_verify_ex(x, pkey,
+                                 app_get0_libctx(), app_get0_propq());
+    else
+        rv = -1;
     return rv;
 }
 
@@ -2504,7 +2544,7 @@ ASN1_VALUE *app_http_get_asn1(const char *url, const char *proxy,
     mem = OSSL_HTTP_get(url, proxy, no_proxy, NULL /* bio */, NULL /* rbio */,
                         app_http_tls_cb, &info, 0 /* buf_size */, headers,
                         expected_content_type, 1 /* expect_asn1 */,
-                        HTTP_DEFAULT_MAX_RESP_LEN, timeout);
+                        OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout);
     resp = ASN1_item_d2i_bio(it, mem, NULL);
     BIO_free(mem);
 
@@ -2521,6 +2561,7 @@ ASN1_VALUE *app_http_post_asn1(const char *host, const char *port,
                                const STACK_OF(CONF_VALUE) *headers,
                                const char *content_type,
                                ASN1_VALUE *req, const ASN1_ITEM *req_it,
+                               const char *expected_content_type,
                                long timeout, const ASN1_ITEM *rsp_it)
 {
     APP_HTTP_TLS_INFO info;
@@ -2538,8 +2579,8 @@ ASN1_VALUE *app_http_post_asn1(const char *host, const char *port,
                              proxy, no_proxy, NULL /* bio */, NULL /* rbio */,
                              app_http_tls_cb, &info,
                              0 /* buf_size */, headers, content_type, req_mem,
-                             NULL /* expected_ct */, 1 /* expect_asn1 */,
-                             HTTP_DEFAULT_MAX_RESP_LEN, timeout,
+                             expected_content_type, 1 /* expect_asn1 */,
+                             OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout,
                              0 /* keep_alive */);
     BIO_free(req_mem);
     res = ASN1_item_d2i_bio(rsp_it, rsp, NULL);
@@ -2836,9 +2877,9 @@ int raw_write_stdout(const void *buf, int siz)
 #   include <floss.h(floss_write)>
 #  endif
 # endif
-int raw_write_stdout(const void *buf,int siz)
+int raw_write_stdout(const void *buf, int siz)
 {
-       return write(fileno(stdout),(void*)buf,siz);
+       return write(fileno(stdout), (void*)buf, siz);
 }
 #else
 # if defined(__TANDEM)
@@ -2951,28 +2992,32 @@ BIO *bio_open_owner(const char *filename, int format, int private)
 {
     FILE *fp = NULL;
     BIO *b = NULL;
-    int fd = -1, bflags, mode, textmode;
+    int textmode, bflags;
+#ifndef OPENSSL_NO_POSIX_IO
+    int fd = -1, mode;
+#endif
 
     if (!private || filename == NULL || strcmp(filename, "-") == 0)
         return bio_open_default(filename, 'w', format);
 
+    textmode = FMT_istext(format);
+#ifndef OPENSSL_NO_POSIX_IO
     mode = O_WRONLY;
-#ifdef O_CREAT
+# ifdef O_CREAT
     mode |= O_CREAT;
-#endif
-#ifdef O_TRUNC
+# endif
+# ifdef O_TRUNC
     mode |= O_TRUNC;
-#endif
-    textmode = FMT_istext(format);
+# endif
     if (!textmode) {
-#ifdef O_BINARY
+# ifdef O_BINARY
         mode |= O_BINARY;
-#elif defined(_O_BINARY)
+# elif defined(_O_BINARY)
         mode |= _O_BINARY;
-#endif
+# endif
     }
 
-#ifdef OPENSSL_SYS_VMS
+# ifdef OPENSSL_SYS_VMS
     /* VMS doesn't have O_BINARY, it just doesn't make sense.  But,
      * it still needs to know that we're going binary, or fdopen()
      * will fail with "invalid argument"...  so we tell VMS what the
@@ -2981,18 +3026,22 @@ BIO *bio_open_owner(const char *filename, int format, int private)
     if (!textmode)
         fd = open(filename, mode, 0600, "ctx=bin");
     else
-#endif
+# endif
         fd = open(filename, mode, 0600);
     if (fd < 0)
         goto err;
     fp = fdopen(fd, modestr('w', format));
+#else   /* OPENSSL_NO_POSIX_IO */
+    /* Have stdio but not Posix IO, do the best we can */
+    fp = fopen(filename, modestr('w', format));
+#endif  /* OPENSSL_NO_POSIX_IO */
     if (fp == NULL)
         goto err;
     bflags = BIO_CLOSE;
     if (textmode)
         bflags |= BIO_FP_TEXT;
     b = BIO_new_fp(fp, bflags);
-    if (b)
+    if (b != NULL)
         return b;
 
  err:
@@ -3000,10 +3049,12 @@ BIO *bio_open_owner(const char *filename, int format, int private)
                opt_getprog(), filename, strerror(errno));
     ERR_print_errors(bio_err);
     /* If we have fp, then fdopen took over fd, so don't close both. */
-    if (fp)
+    if (fp != NULL)
         fclose(fp);
+#ifndef OPENSSL_NO_POSIX_IO
     else if (fd >= 0)
         close(fd);
+#endif
     return NULL;
 }
 
@@ -3257,3 +3308,62 @@ void app_params_free(OSSL_PARAM *params)
         OPENSSL_free(params);
     }
 }
+
+EVP_PKEY *app_keygen(EVP_PKEY_CTX *ctx, const char *alg, int bits, int verbose)
+{
+    EVP_PKEY *res = NULL;
+
+    if (verbose && alg != NULL) {
+        BIO_printf(bio_err, "Generating %s key", alg);
+        if (bits > 0)
+            BIO_printf(bio_err, " with %d bits\n", bits);
+        else
+            BIO_printf(bio_err, "\n");
+    }
+    if (!RAND_status())
+        BIO_printf(bio_err, "Warning: generating random key material may take a long time\n"
+                   "if the system has a poor entropy source\n");
+    if (EVP_PKEY_keygen(ctx, &res) <= 0)
+        app_bail_out("%s: Error generating %s key\n", opt_getprog(),
+                     alg != NULL ? alg : "asymmetric");
+    return res;
+}
+
+EVP_PKEY *app_paramgen(EVP_PKEY_CTX *ctx, const char *alg)
+{
+    EVP_PKEY *res = NULL;
+
+    if (!RAND_status())
+        BIO_printf(bio_err, "Warning: generating random key parameters may take a long time\n"
+                   "if the system has a poor entropy source\n");
+    if (EVP_PKEY_paramgen(ctx, &res) <= 0)
+        app_bail_out("%s: Generating %s key parameters failed\n",
+                     opt_getprog(), alg != NULL ? alg : "asymmetric");
+    return res;
+}
+
+/*
+ * Return non-zero if the legacy path is still an option.
+ * This decision is based on the global command line operations and the
+ * behaviour thus far.
+ */
+int opt_legacy_okay(void)
+{
+    int provider_options = opt_provider_option_given();
+    int libctx = app_get0_libctx() != NULL || app_get0_propq() != NULL;
+#ifndef OPENSSL_NO_ENGINE
+    ENGINE *e = ENGINE_get_first();
+
+    if (e != NULL) {
+        ENGINE_free(e);
+        return 1;
+    }
+#endif
+    /*
+     * Having a provider option specified or a custom library context or
+     * property query, is a sure sign we're not using legacy.
+     */
+    if (provider_options || libctx)
+        return 0;
+    return 1;
+}