diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
index 0c3163f05f0..4da24eddcc5 100644
--- a/modules/ssl/ssl_engine_init.c
+++ b/modules/ssl/ssl_engine_init.c
@@ -195,13 +195,18 @@ static void ssl_add_version_components(apr_pool_t *ptemp, apr_pool_t *pconf,
 */
 
 int ssl_is_challenge(conn_rec *c, const char *servername, 
-                     X509 **pcert, EVP_PKEY **pkey)
+                     X509 **pcert, EVP_PKEY **pkey,
+                     const char **pcert_pem, const char **pkey_pem)
 {
-    if (APR_SUCCESS == ssl_run_answer_challenge(c, servername, pcert, pkey)) {
-        return 1;
-    }
     *pcert = NULL;
     *pkey = NULL;
+    *pcert_pem = *pkey_pem = NULL;
+    if (ap_ssl_answer_challenge(c, servername, pcert_pem, pkey_pem)) {
+        return 1;
+    }
+    else if (OK == ssl_run_answer_challenge(c, servername, pcert, pkey)) {
+        return 1;
+    }
     return 0;
 }
 
@@ -1805,10 +1810,12 @@ static apr_status_t ssl_init_server_ctx(server_rec *s,
     /* Allow others to provide certificate files */
     pks = sc->server->pks;
     n = pks->cert_files->nelts;
+    ap_ssl_add_cert_files(s, p, pks->cert_files, pks->key_files);
     ssl_run_add_cert_files(s, p, pks->cert_files, pks->key_files);
 
     if (apr_is_empty_array(pks->cert_files)) {
         /* does someone propose a certiciate to fall back on here? */
+        ap_ssl_add_fallback_cert_files(s, p, pks->cert_files, pks->key_files);
         ssl_run_add_fallback_cert_files(s, p, pks->cert_files, pks->key_files);
         if (n < pks->cert_files->nelts) {
             pks->service_unavailable = 1;
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
index 29646b878b6..7c941f445bf 100644
--- a/modules/ssl/ssl_engine_kernel.c
+++ b/modules/ssl/ssl_engine_kernel.c
@@ -2316,16 +2316,33 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc)
 #ifdef HAVE_TLSEXT
 
 static apr_status_t set_challenge_creds(conn_rec *c, const char *servername,
-                                        SSL *ssl, X509 *cert, EVP_PKEY *key)
+                                        SSL *ssl, X509 *cert, EVP_PKEY *key,
+                                        const char *cert_pem, const char *key_pem)
 {
     SSLConnRec *sslcon = myConnConfig(c);
+    apr_status_t rv = APR_SUCCESS;
+    int our_data = 0;
     
     sslcon->service_unavailable = 1;
+    if (cert_pem) {
+        cert = NULL;
+        key = NULL;
+        our_data = 1;
+        
+        rv = modssl_read_cert(c->pool, cert_pem, key_pem, NULL, NULL, &cert, &key);
+        if (rv != APR_SUCCESS) {
+            ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(10266)
+                          "Failed to parse PEM of challenge certificate %s",
+                          servername);
+            goto cleanup;
+        }
+    }
+    
     if ((SSL_use_certificate(ssl, cert) < 1)) {
         ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(10086)
                       "Failed to configure challenge certificate %s",
                       servername);
-        return APR_EGENERAL;
+        rv = APR_EGENERAL; goto cleanup;
     }
     
     if (!SSL_use_PrivateKey(ssl, key)) {
@@ -2333,15 +2350,19 @@ static apr_status_t set_challenge_creds(conn_rec *c, const char *servername,
                       "error '%s' using Challenge key: %s",
                       ERR_error_string(ERR_peek_last_error(), NULL), 
                       servername);
-        return APR_EGENERAL;
+        rv = APR_EGENERAL; goto cleanup;
     }
     
     if (SSL_check_private_key(ssl) < 1) {
         ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(10088)
                       "Challenge certificate and private key %s "
                       "do not match", servername);
-        return APR_EGENERAL;
+        rv = APR_EGENERAL; goto cleanup;
     }
+    
+cleanup:
+    if (our_data && cert) X509_free(cert);
+    if (our_data && key) EVP_PKEY_free(key);
     return APR_SUCCESS;
 }
   
@@ -2351,9 +2372,6 @@ static apr_status_t set_challenge_creds(conn_rec *c, const char *servername,
  */
 static apr_status_t init_vhost(conn_rec *c, SSL *ssl, const char *servername)
 {
-    X509 *cert;
-    EVP_PKEY *key;
-    
     if (c) {
         SSLConnRec *sslcon = myConnConfig(c);
 
@@ -2376,15 +2394,6 @@ static apr_status_t init_vhost(conn_rec *c, SSL *ssl, const char *servername)
                 sslcon->vhost_found = +1;
                 return APR_SUCCESS;
             }
-            else if (ssl_is_challenge(c, servername, &cert, &key)) {
-                /* With ACMEv1 we can have challenge connections to a unknown domains
-                 * that need to be answered with a special certificate and will
-                 * otherwise not answer any requests. */
-                if (set_challenge_creds(c, servername, ssl, cert, key) != APR_SUCCESS) {
-                    return APR_EGENERAL;
-                }
-                SSL_set_verify(ssl, SSL_VERIFY_NONE, ssl_callback_SSLVerify);
-            }
             else {
                 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02044)
                               "No matching SSL virtual host for servername "
@@ -2759,9 +2768,11 @@ int ssl_callback_alpn_select(SSL *ssl,
             const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
             X509 *cert;
             EVP_PKEY *key;
-            
-            if (ssl_is_challenge(c, servername, &cert, &key)) {
-                if (set_challenge_creds(c, servername, ssl, cert, key) != APR_SUCCESS) {
+            const char *cert_pem, *key_pem;
+
+            if (ssl_is_challenge(c, servername, &cert, &key, &cert_pem, &key_pem)) {
+                if (set_challenge_creds(c, servername, ssl, cert, key, 
+                                        cert_pem, key_pem) != APR_SUCCESS) {
                     return SSL_TLSEXT_ERR_ALERT_FATAL;
                 }
                 SSL_set_verify(ssl, SSL_VERIFY_NONE, ssl_callback_SSLVerify);
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
index 560c2fadfc8..a6fc7513a2e 100644
--- a/modules/ssl/ssl_private.h
+++ b/modules/ssl/ssl_private.h
@@ -36,6 +36,7 @@
 #include "http_connection.h"
 #include "http_request.h"
 #include "http_protocol.h"
+#include "http_ssl.h"
 #include "http_vhost.h"
 #include "util_script.h"
 #include "util_filter.h"
@@ -1122,7 +1123,8 @@ DH *modssl_get_dh_params(unsigned keylen);
 int modssl_request_is_tls(const request_rec *r, SSLConnRec **sslconn);
 
 int ssl_is_challenge(conn_rec *c, const char *servername, 
-                     X509 **pcert, EVP_PKEY **pkey);
+                     X509 **pcert, EVP_PKEY **pkey,
+                    const char **pcert_file, const char **pkey_file);
 
 /* Returns non-zero if the cert/key filename should be handled through
  * the configured ENGINE. */
diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c
index 74088f5e298..0a02ce28dd0 100644
--- a/modules/ssl/ssl_util_ssl.c
+++ b/modules/ssl/ssl_util_ssl.c
@@ -511,3 +511,77 @@ char *modssl_SSL_SESSION_id2sz(IDCONST unsigned char *id, int idlen,
 
     return str;
 }
+
+/*  _________________________________________________________________
+**
+**  Certficate/Key Stuff
+**  _________________________________________________________________
+*/
+
+apr_status_t modssl_read_cert(apr_pool_t *p, 
+                              const char *cert_pem, const char *key_pem,
+                              pem_password_cb *cb, void *ud,
+                              X509 **pcert, EVP_PKEY **pkey)
+{
+    BIO *in;
+    X509 *x = NULL;
+    EVP_PKEY *key = NULL;
+    apr_status_t rv = APR_SUCCESS;
+
+    in = BIO_new_mem_buf(cert_pem, -1);
+    if (in == NULL) {
+        rv = APR_ENOMEM; goto cleanup;
+    }
+    
+    x = PEM_read_bio_X509(in, NULL, cb, ud);
+    if (x == NULL) {
+        rv = APR_ENOENT; goto cleanup;
+    }
+    
+    BIO_free(in);
+    in = BIO_new_mem_buf(key_pem? key_pem : cert_pem, -1);
+    if (in == NULL) {
+        rv = APR_ENOMEM; goto cleanup;
+    }
+    key = PEM_read_bio_PrivateKey(in, NULL, cb, ud);
+    if (key == NULL) {
+        rv = APR_ENOENT; goto cleanup;
+    }
+    
+cleanup:
+    if (rv == APR_SUCCESS) {
+        *pcert = x;
+        *pkey = key;
+    }
+    else {
+        *pcert = NULL;
+        *pkey = NULL;
+        if (x) X509_free(x);
+        if (key) EVP_PKEY_free(key);
+    }
+    if (in != NULL) BIO_free(in);
+    return rv;
+}
+
+apr_status_t modssl_cert_get_pem(apr_pool_t *p,
+                                 X509 *cert1, X509 *cert2,
+                                 const char **ppem)
+{
+    apr_status_t rv = APR_ENOMEM;
+    BIO *bio;
+
+    if ((bio = BIO_new(BIO_s_mem())) == NULL) goto cleanup;
+    if (PEM_write_bio_X509(bio, cert1) != 1) goto cleanup;
+    if (cert2 && PEM_write_bio_X509(bio, cert2) != 1) goto cleanup;
+    rv = APR_SUCCESS;
+
+cleanup:
+    if (rv != APR_SUCCESS) {
+        *ppem = NULL;
+        if (bio) BIO_free(bio);
+    }
+    else {
+        *ppem = modssl_bio_free_read(p, bio);
+    }
+    return rv;
+}
diff --git a/modules/ssl/ssl_util_ssl.h b/modules/ssl/ssl_util_ssl.h
index ec89185b1b0..0f01128528a 100644
--- a/modules/ssl/ssl_util_ssl.h
+++ b/modules/ssl/ssl_util_ssl.h
@@ -82,7 +82,26 @@ char       *modssl_SSL_SESSION_id2sz(IDCONST unsigned char *, int, char *, int);
  * pool-allocated string.  If empty, returns NULL.  BIO_free(bio) is
  * called for both cases. */
 char *modssl_bio_free_read(apr_pool_t *p, BIO *bio);
-    
+
+/* Read a single certificate and its private key from the give string in PEM format.
+ * If `key_pem` is NULL, it will expect the key in `cert_pem`.
+ */
+apr_status_t modssl_read_cert(apr_pool_t *p, 
+                              const char *cert_pem, const char *key_pem,
+                              pem_password_cb *cb, void *ud, 
+                              X509 **pcert, EVP_PKEY **pkey);
+
+/* Convert a certificate (and optionally a second) into a PEM string.
+ * @param p pool for allocations
+ * @param cert1 the certificate to convert
+ * @param cert2 a second cert to add to the PEM afterwards or NULL.
+ * @param ppem the certificate(s) in PEM format, NUL-terminated.
+ * @return APR_SUCCESS if ppem is valid.
+ */
+apr_status_t modssl_cert_get_pem(apr_pool_t *p,
+                                 X509 *cert1, X509 *cert2,
+                                 const char **ppem);
+
 #endif /* __SSL_UTIL_SSL_H__ */
 /** @} */
 
diff --git a/modules/ssl/ssl_util_stapling.c b/modules/ssl/ssl_util_stapling.c
index 15415934972..17371378d11 100644
--- a/modules/ssl/ssl_util_stapling.c
+++ b/modules/ssl/ssl_util_stapling.c
@@ -134,6 +134,8 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
     X509 *issuer = NULL;
     OCSP_CERTID *cid = NULL;
     STACK_OF(OPENSSL_STRING) *aia = NULL;
+    const char *pem = NULL;
+    ap_bytes_t key;
     int rv = 1; /* until further notice */
 
     if (x == NULL)
@@ -153,7 +155,20 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
         return 1;
     }
 
-    if (ssl_run_init_stapling_status(s, p, x, issuer) == OK) {
+    if (X509_digest(x, EVP_sha1(), idx, NULL) != 1) {
+        rv = 0;
+        goto cleanup;
+    }
+
+    if (modssl_cert_get_pem(ptemp, x, issuer, &pem) != APR_SUCCESS) {
+        rv = 0;
+        goto cleanup;
+    }
+
+    key.data = idx;
+    key.len = sizeof(idx);
+    if (ap_ssl_ocsp_prime(s, p, &key, pem) == APR_SUCCESS
+        || ssl_run_init_stapling_status(s, p, x, issuer) == OK) {
         /* Someone's taken over or mod_ssl's own implementation is not enabled */
         if (mctx->stapling_enabled != TRUE) {
             SSL_CTX_set_tlsext_status_cb(mctx->ssl_ctx, stapling_cb);
@@ -167,11 +182,6 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
         goto cleanup;
     }
     
-    if (X509_digest(x, EVP_sha1(), idx, NULL) != 1) {
-        rv = 0;
-        goto cleanup;
-    }
-
     cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx));
     if (cinf) {
         /* 
@@ -232,14 +242,11 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
     return rv;
 }
 
-static certinfo *stapling_get_certinfo(server_rec *s, X509 *x, modssl_ctx_t *mctx,
-                                        SSL *ssl)
+static certinfo *stapling_get_certinfo(server_rec *s, UCHAR *idx, apr_size_t idx_len,
+                                       modssl_ctx_t *mctx, SSL *ssl)
 {
     certinfo *cinf;
-    UCHAR idx[SHA_DIGEST_LENGTH];
-    if (X509_digest(x, EVP_sha1(), idx, NULL) != 1)
-        return NULL;
-    cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx));
+    cinf = apr_hash_get(stapling_certinfo, idx, idx_len);
     if (cinf && cinf->cid)
         return cinf;
     ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01926)
@@ -776,6 +783,18 @@ static int get_and_check_cached_response(server_rec *s, modssl_ctx_t *mctx,
     return 0;
 }
 
+static void copy_ocsp_resp(const unsigned char *der, apr_size_t der_len, void *userdata)
+{
+    ap_bytes_t *resp = userdata;
+
+    resp->len = 0;
+    resp->data = der? OPENSSL_malloc(der_len) : NULL;
+    if (resp->data) {
+        memcpy(resp->data, der, der_len);
+        resp->len = der_len;
+    }
+}
+
 /* Certificate Status callback. This is called when a client includes a
  * certificate status request extension.
  *
@@ -790,13 +809,14 @@ static int stapling_cb(SSL *ssl, void *arg)
     SSLSrvConfigRec *sc = mySrvConfig(s);
     SSLConnRec *sslconn = myConnConfig(conn);
     modssl_ctx_t *mctx  = myCtxConfig(sslconn, sc);
+    UCHAR idx[SHA_DIGEST_LENGTH];
+    ap_bytes_t key, resp;
     certinfo *cinf = NULL;
     OCSP_RESPONSE *rsp = NULL;
     int rv;
     BOOL ok = TRUE;
     X509 *x;
-    unsigned char *rspder = NULL;
-    int rspderlen;
+    int rspderlen, provided = 0;
 
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01951)
                  "stapling_cb: OCSP Stapling callback called");
@@ -806,12 +826,26 @@ static int stapling_cb(SSL *ssl, void *arg)
         return SSL_TLSEXT_ERR_NOACK;
     }
 
-    if (ssl_run_get_stapling_status(&rspder, &rspderlen, conn, s, x) == APR_SUCCESS) {
+    if (X509_digest(x, EVP_sha1(), idx, NULL) != 1) {
+        return SSL_TLSEXT_ERR_NOACK;
+    }
+    key.data = idx;
+    key.len = sizeof(idx);
+
+    if (ap_ssl_ocsp_get_resp(s, conn, &key, copy_ocsp_resp, &resp) == APR_SUCCESS) {
+        provided = 1;
+    }
+    else if (ssl_run_get_stapling_status(&resp.data, &rspderlen, conn, s, x) == APR_SUCCESS) {
+        resp.len = (apr_size_t)rspderlen;
+        provided = 1;
+    }
+
+    if (provided) {
         /* a hook handles stapling for this certificate and determines the response */
-        if (rspder == NULL || rspderlen <= 0) {
+        if (resp.data == NULL || resp.len == 0) {
             return SSL_TLSEXT_ERR_NOACK;
         }
-        SSL_set_tlsext_status_ocsp_resp(ssl, rspder, rspderlen);
+        SSL_set_tlsext_status_ocsp_resp(ssl, resp.data, (int)resp.len);
         return SSL_TLSEXT_ERR_OK;
     }
     
@@ -821,7 +855,7 @@ static int stapling_cb(SSL *ssl, void *arg)
         return SSL_TLSEXT_ERR_NOACK;
     }
 
-    if ((cinf = stapling_get_certinfo(s, x, mctx, ssl)) == NULL) {
+    if ((cinf = stapling_get_certinfo(s, idx, sizeof(idx), mctx, ssl)) == NULL) {
         return SSL_TLSEXT_ERR_NOACK;
     }
 
