]> granicus.if.org Git - apache/blobdiff - modules/ssl/ssl_engine_pphrase.c
mod_ssl: Add support for loading private keys from ENGINEs. Support
[apache] / modules / ssl / ssl_engine_pphrase.c
index 4d06c4fe034c3fff3701172ac300cfee2f0427c6..76584535908f577e0f366b0286cf0ab3debf5b00 100644 (file)
@@ -129,6 +129,7 @@ static char *pphrase_array_get(apr_array_header_t *arr, int idx)
 }
 
 apr_status_t ssl_load_encrypted_pkey(server_rec *s, apr_pool_t *p, int idx,
+                                     const char *pkey_file,
                                      apr_array_header_t **pphrases)
 {
     SSLModConfigRec *mc = myModConfig(s);
@@ -143,32 +144,31 @@ apr_status_t ssl_load_encrypted_pkey(server_rec *s, apr_pool_t *p, int idx,
     int nPassPhraseRetry = 0;
     apr_time_t pkey_mtime = 0;
     apr_status_t rv;
-    pphrase_cb_arg_t ppcb_arg = {
-        s,
-        p,
-        *pphrases,
-        0,
-        NULL,
-        0,
-        0,
-        TRUE,
-        key_id,
-        APR_ARRAY_IDX(sc->server->pks->key_files, idx, const char *)
-    };
-
-    if (!ppcb_arg.pkey_file) {
+    pphrase_cb_arg_t ppcb_arg;
+
+    if (!pkey_file) {
          ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02573)
                       "Init: No private key specified for %s", key_id);
          return ssl_die(s);
     }
-    else if ((rv = exists_and_readable(ppcb_arg.pkey_file, p,
-                                       &pkey_mtime)) != APR_SUCCESS ) {
+    else if ((rv = exists_and_readable(pkey_file, p, &pkey_mtime))
+             != APR_SUCCESS ) {
          ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(02574)
-                      "Init: Can't open server private key file %s",
-                      ppcb_arg.pkey_file);
+                      "Init: Can't open server private key file %s", pkey_file);
          return ssl_die(s);
     }
 
+    ppcb_arg.s                     = s;
+    ppcb_arg.p                     = p;
+    ppcb_arg.aPassPhrase           = *pphrases;
+    ppcb_arg.nPassPhraseCur        = 0;
+    ppcb_arg.cpPassPhraseCur       = NULL;
+    ppcb_arg.nPassPhraseDialog     = 0;
+    ppcb_arg.nPassPhraseDialogCur  = 0;
+    ppcb_arg.bPassPhraseDialogOnce = TRUE;
+    ppcb_arg.key_id                = key_id;
+    ppcb_arg.pkey_file             = pkey_file;
+
     /*
      * if the private key is encrypted and SSLPassPhraseDialog
      * is configured to "builtin" it isn't possible to prompt for
@@ -216,7 +216,7 @@ apr_status_t ssl_load_encrypted_pkey(server_rec *s, apr_pool_t *p, int idx,
          * is not empty. */
         ERR_clear_error();
 
-        bReadable = ((pPrivateKey = SSL_read_PrivateKey(ppcb_arg.pkey_file,
+        bReadable = ((pPrivateKey = modssl_read_privatekey(ppcb_arg.pkey_file,
                      NULL, ssl_pphrase_Handle_CB, &ppcb_arg)) != NULL ?
                      TRUE : FALSE);
 
@@ -600,3 +600,52 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv)
      */
     return (len);
 }
+
+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
+apr_status_t modssl_load_engine_pkey(server_rec *s, apr_pool_t *p,
+                                     const char *keyid, EVP_PKEY **ppkey)
+{
+    SSLModConfigRec *mc = myModConfig(s);
+    EVP_PKEY *pPrivateKey = NULL;
+    ENGINE *e;
+    UI_METHOD *ui_method;
+
+    if (!mc->szCryptoDevice) {
+        ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10131)
+                     "Init: Cannot load private key `%s' without engine",
+                     keyid);
+        return ssl_die(s);
+    }
+
+    /*
+     * Using the builtin OpenSSL UI only, for now...
+     */
+    ui_method = UI_OpenSSL();
+
+    if (!(e = ENGINE_by_id(mc->szCryptoDevice))) {
+        ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10132)
+                     "Init: Failed to load Crypto Device API `%s'",
+                     mc->szCryptoDevice);
+        ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+        return ssl_die(s);
+    }
+
+    if (APLOGdebug(s)) {
+        ENGINE_ctrl_cmd_string(e, "VERBOSE", NULL, 0);
+    }
+    
+    pPrivateKey = ENGINE_load_private_key(e, keyid, ui_method, NULL);
+    if (pPrivateKey == NULL) {
+        ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10133)
+                     "Init: Unable to get the private key");
+        ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+        return ssl_die(s);
+    }
+
+    *ppkey = pPrivateKey;
+
+    ENGINE_free(e);
+
+    return APR_SUCCESS;
+}
+#endif