You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by jo...@apache.org on 2018/05/08 12:39:22 UTC

svn commit: r1831168 - in /httpd/httpd/trunk: ./ docs/log-message-tags/ docs/manual/mod/ modules/ssl/

Author: jorton
Date: Tue May  8 12:39:22 2018
New Revision: 1831168

URL: http://svn.apache.org/viewvc?rev=1831168&view=rev
Log:
mod_ssl: Add support for loading TLS certificates through the PKCS#11
engine.

* modules/ssl/ssl_util.c (modssl_is_engine_id): Renamed
  from modssl_is_engine_key.
  
* modules/ssl/ssl_engine_config.c (ssl_cmd_SSLCertificateKeyFile):
  Adjust accordingly.
  (ssl_cmd_SSLCertificateFile): Also allow ENGINE cert ids.

* modules/ssl/ssl_engine_pphrase.c (modssl_load_engine_keypair):
  Rename from modssl_load_engine_key; load certificate if
  cert id is passed.

* modules/ssl/ssl_engine_init.c (ssl_init_server_certs): Optionally
  load the certificate from the engine as well.

* docs/manual/: Update manual.

Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/docs/log-message-tags/next-number
    httpd/httpd/trunk/docs/manual/mod/mod_ssl.xml
    httpd/httpd/trunk/modules/ssl/ssl_engine_config.c
    httpd/httpd/trunk/modules/ssl/ssl_engine_init.c
    httpd/httpd/trunk/modules/ssl/ssl_engine_pphrase.c
    httpd/httpd/trunk/modules/ssl/ssl_private.h
    httpd/httpd/trunk/modules/ssl/ssl_util.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1831168&r1=1831167&r2=1831168&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Tue May  8 12:39:22 2018
@@ -3,8 +3,9 @@ Changes with Apache 2.5.1
 
   *) mod_ldap: Abort on LDAP locking errors. [Eric Covener]
 
-  *) mod_ssl: Support loading private keys from an OpenSSL engine using a
-     PKCS#11 URI.  [Anderson Sasaki <ansasaki redhat.com>, Joe Orton]
+  *) mod_ssl: Support loading certificates and private keys from the
+     PKCS#11 OpenSSL engine.  [Anderson Sasaki <ansasaki redhat.com>,
+     Joe Orton]
 
   *) mod_slomem_shm: Handle a generation number when the slotmem size changes,
      modifying the number of proxy balancers or balancer members on restart

Modified: httpd/httpd/trunk/docs/log-message-tags/next-number
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/log-message-tags/next-number?rev=1831168&r1=1831167&r2=1831168&view=diff
==============================================================================
--- httpd/httpd/trunk/docs/log-message-tags/next-number (original)
+++ httpd/httpd/trunk/docs/log-message-tags/next-number Tue May  8 12:39:22 2018
@@ -1 +1 @@
-10136
+10137

Modified: httpd/httpd/trunk/docs/manual/mod/mod_ssl.xml
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_ssl.xml?rev=1831168&r1=1831167&r2=1831168&view=diff
==============================================================================
--- httpd/httpd/trunk/docs/manual/mod/mod_ssl.xml (original)
+++ httpd/httpd/trunk/docs/manual/mod/mod_ssl.xml Tue May  8 12:39:22 2018
@@ -866,15 +866,16 @@ SSLCipherSuite RSA:!EXP:!NULL:+HIGH:+MED
 
 <directivesynopsis>
 <name>SSLCertificateFile</name>
-<description>Server PEM-encoded X.509 certificate data file</description>
-<syntax>SSLCertificateFile <var>file-path</var></syntax>
+<description>Server PEM-encoded X.509 certificate data file or token identifier</description>
+<syntax>SSLCertificateFile <var>file-path</var>|<var>certid</var></syntax>
 <contextlist><context>server config</context>
 <context>virtual host</context></contextlist>
+<compatibility><var>certid</var> available in 2.5.1 and later.</compatibility>
 
 <usage>
 <p>
-This directive points to a file with certificate data in PEM format.
-At a minimum, the file must include an end-entity (leaf) certificate.
+This directive points to a file with certificate data in PEM format, or the certificate identifier through a configured cryptographic token.
+If using a PEM file, at minimum, the file must include an end-entity (leaf) certificate.
 The directive can be used multiple times (referencing different filenames)
 to support multiple algorithms for server authentication - typically
 RSA, DSA, and ECC. The number of supported algorithms depends on the
@@ -915,6 +916,18 @@ after the certificates using a separate
 key is encrypted, the pass phrase dialog is forced at startup time.
 </p>
 
+<p>As an alternative to storing certificates and private keys in
+files, a certificate identifier can be used to identify a certificate
+stored in a token.  Currently, only <a
+href="https://tools.ietf.org/html/rfc7512">PKCS#11 URIs</a> are
+recognized as certificate identifiers, and can be used in conjunction
+with the OpenSSL <code>pkcs11</code> engine configured with <directive
+module="mod_ssl">SSLCryptoDevice</directive>.  If <directive
+module="mod_ssl">SSLCertificateKeyFile</directive> is omitted, the
+certificate and private key can be loaded through the single
+identifier specified with <directive
+module="mod_ssl">SSLCertificateFile</directive>.</p>
+
 <note>
 <title>DH parameter interoperability with primes > 1024 bit</title>
 <p>
@@ -960,7 +973,12 @@ thus using a custom/suitable length.
 
 <example><title>Example</title>
 <highlight language="config">
+# Example using a PEM-encoded file.
 SSLCertificateFile "/usr/local/apache2/conf/ssl.crt/server.crt"
+# Example use of a certificate and private key from a PKCS#11 token:
+SSLCryptoDevice pkcs11
+...
+SSLCertificateFile "pkcs11:token=My%20Token%20Name;id=45"
 </highlight>
 </example>
 </usage>

Modified: httpd/httpd/trunk/modules/ssl/ssl_engine_config.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_engine_config.c?rev=1831168&r1=1831167&r2=1831168&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/ssl/ssl_engine_config.c (original)
+++ httpd/httpd/trunk/modules/ssl/ssl_engine_config.c Tue May  8 12:39:22 2018
@@ -1016,7 +1016,9 @@ const char *ssl_cmd_SSLCertificateFile(c
     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
     const char *err;
 
-    if ((err = ssl_cmd_check_file(cmd, &arg))) {
+    /* Only check for non-ENGINE based certs. */
+    if (!modssl_is_engine_id(arg)
+        && (err = ssl_cmd_check_file(cmd, &arg))) {
         return err;
     }
 
@@ -1033,7 +1035,7 @@ const char *ssl_cmd_SSLCertificateKeyFil
     const char *err;
 
     /* Check keyfile exists for non-ENGINE keys. */
-    if (!modssl_is_engine_key(arg)
+    if (!modssl_is_engine_id(arg)
         && (err = ssl_cmd_check_file(cmd, &arg))) {
         return err;
     }

Modified: httpd/httpd/trunk/modules/ssl/ssl_engine_init.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_engine_init.c?rev=1831168&r1=1831167&r2=1831168&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/ssl/ssl_engine_init.c (original)
+++ httpd/httpd/trunk/modules/ssl/ssl_engine_init.c Tue May  8 12:39:22 2018
@@ -1251,13 +1251,17 @@ static apr_status_t ssl_init_server_cert
                                           const char *));
          i++) {
         EVP_PKEY *pkey;
+        const char *engine_certfile = NULL;
 
         key_id = apr_psprintf(ptemp, "%s:%d", vhost_id, i);
 
         ERR_clear_error();
 
         /* first the certificate (public key) */
-        if (mctx->cert_chain) {
+        if (modssl_is_engine_id(certfile)) {
+            engine_certfile = certfile;
+        }
+        else if (mctx->cert_chain) {
             if ((SSL_CTX_use_certificate_file(mctx->ssl_ctx, certfile,
                                               SSL_FILETYPE_PEM) < 1)) {
                 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02561)
@@ -1286,12 +1290,28 @@ static apr_status_t ssl_init_server_cert
 
         ERR_clear_error();
 
-        if (modssl_is_engine_key(keyfile)) {
+        if (modssl_is_engine_id(keyfile)) {
             apr_status_t rv;
 
-            if ((rv = modssl_load_engine_pkey(s, ptemp, keyfile, &pkey))) {
+            cert = NULL;
+            
+            if ((rv = modssl_load_engine_keypair(s, ptemp, engine_certfile,
+                                                 keyfile, &cert, &pkey))) {
                 return rv;
             }
+
+            if (cert) {
+                if (SSL_CTX_use_certificate(mctx->ssl_ctx, cert) < 1) {
+                    ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO()
+                                 "Failed to configure engine certificate %s, check %s",
+                                 key_id, certfile);
+                    ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+                    return APR_EGENERAL;
+                }
+
+                /* SSL_CTX now owns the cert. */
+                X509_free(cert);
+            }                    
             
             if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) < 1) {
                 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10130)

Modified: httpd/httpd/trunk/modules/ssl/ssl_engine_pphrase.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_engine_pphrase.c?rev=1831168&r1=1831167&r2=1831168&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/ssl/ssl_engine_pphrase.c (original)
+++ httpd/httpd/trunk/modules/ssl/ssl_engine_pphrase.c Tue May  8 12:39:22 2018
@@ -588,11 +588,11 @@ int ssl_pphrase_Handle_CB(char *buf, int
 }
 
 #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)
+apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
+                                        const char *certid, const char *keyid,
+                                        X509 **pubkey, EVP_PKEY **privkey)
 {
     SSLModConfigRec *mc = myModConfig(s);
-    EVP_PKEY *pPrivateKey = NULL;
     ENGINE *e;
     UI_METHOD *ui_method;
 
@@ -619,17 +619,31 @@ apr_status_t modssl_load_engine_pkey(ser
     if (APLOGdebug(s)) {
         ENGINE_ctrl_cmd_string(e, "VERBOSE", NULL, 0);
     }
-    
-    pPrivateKey = ENGINE_load_private_key(e, keyid, ui_method, NULL);
-    if (pPrivateKey == NULL) {
+
+    if (certid) {
+        struct {
+            const char *cert_id;
+            X509 *cert;
+        } params = { certid, NULL };
+
+        if (!ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &params, NULL, 1)) {
+            ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10136)
+                         "Init: Unable to get the certificate");
+            ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+            return ssl_die(s);
+        }
+
+        *pubkey = params.cert;
+    }
+
+    *privkey = ENGINE_load_private_key(e, keyid, ui_method, NULL);
+    if (*privkey == 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;

Modified: httpd/httpd/trunk/modules/ssl/ssl_private.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_private.h?rev=1831168&r1=1831167&r2=1831168&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/ssl/ssl_private.h (original)
+++ httpd/httpd/trunk/modules/ssl/ssl_private.h Tue May  8 12:39:22 2018
@@ -996,10 +996,13 @@ BOOL         ssl_util_vhost_matches(cons
 /**  Pass Phrase Support  */
 apr_status_t ssl_load_encrypted_pkey(server_rec *, apr_pool_t *, int,
                                      const char *, apr_array_header_t **);
-/* Load private key from the configured ENGINE, returned as **pkey.
- * Errors logged on failure. */
-apr_status_t modssl_load_engine_pkey(server_rec *s, apr_pool_t *p,
-                                     const char *keyid, EVP_PKEY **ppkey);
+
+/* Load public and/or private key from the configured ENGINE. Private
+ * key returned as *pkey.  certid can be NULL, in which case *pubkey
+ * is not altered.  Errors logged on failure. */
+apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
+                                        const char *certid, const char *keyid,
+                                        X509 **pubkey, EVP_PKEY **privkey);
 
 /**  Diffie-Hellman Parameter Support  */
 DH           *ssl_dh_GetParamFromFile(const char *);
@@ -1105,8 +1108,8 @@ DH *modssl_get_dh_params(unsigned keylen
 int modssl_request_is_tls(const request_rec *r, SSLConnRec **sslconn);
 
 /* Returns non-zero if the cert/key filename should be handled through
- * the configure ENGINE. */
-int modssl_is_engine_key(const char *name);
+ * the configured ENGINE. */
+int modssl_is_engine_id(const char *name);
 
 #if HAVE_VALGRIND
 extern int ssl_running_on_valgrind;

Modified: httpd/httpd/trunk/modules/ssl/ssl_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_util.c?rev=1831168&r1=1831167&r2=1831168&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/ssl/ssl_util.c (original)
+++ httpd/httpd/trunk/modules/ssl/ssl_util.c Tue May  8 12:39:22 2018
@@ -515,7 +515,7 @@ void ssl_util_thread_setup(apr_pool_t *p
 
 #endif /* #if APR_HAS_THREADS && MODSSL_USE_OPENSSL_PRE_1_1_API */
 
-int modssl_is_engine_key(const char *name)
+int modssl_is_engine_id(const char *name)
 {
 #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
     /* ### Can handle any other special ENGINE key names here? */