]> granicus.if.org Git - apache/commitdiff
Add API to support TLS channel bindings with mod_ssl.
authorJoe Orton <jorton@apache.org>
Wed, 27 Aug 2014 16:11:17 +0000 (16:11 +0000)
committerJoe Orton <jorton@apache.org>
Wed, 27 Aug 2014 16:11:17 +0000 (16:11 +0000)
* modules/ssl/mod_ssl.h: Define ssl_get_tls_cb.

* modules/ssl/ssl_engine_vars.c (ssl_get_tls_cb): New function.

Submitted by: Simo Sorce <simo redhat.com>

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1620926 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/ssl/ssl_engine_vars.c

diff --git a/CHANGES b/CHANGES
index 404e80a2401eea4c8c2a268efe56c566ff895e2a..68e605dd18f6d6753b355304c57e7fc5d4caa5c9 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,8 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
+  
+  *) mod_ssl: Add optional function "ssl_get_tls_cb" to allow support
+     for channel bindings.  [Simo Sorce <simo redhat.com>]
 
   *) mod_cache: Avoid sending 304 responses during failed revalidations
      PR56881. [Eric Covener]
index 97ff211d9cbfcbc675e97213fccf32950b292e6a..fa0b0e1fe142deb891a34ea540228bbb438137df 100644 (file)
@@ -59,6 +59,75 @@ static int ssl_is_https(conn_rec *c)
     return sslconn && sslconn->ssl;
 }
 
+/* SSLv3 uses 36 bytes for Finishd messages, TLS1.0 12 bytes,
+ * So tls-unique is max 36 bytes, however with tls-server-end-point,
+ * the CB data is the certificate signature, so we use the maximum
+ * hash size known to the library (currently 64).
+ * */
+#define TLS_CB_MAX EVP_MAX_MD_SIZE
+#define TLS_UNIQUE_PREFIX "tls-unique:"
+#define TLS_SERVER_END_POINT_PREFIX "tls-server-end-point:"
+
+static apr_status_t ssl_get_tls_cb(apr_pool_t *p, conn_rec *c, const char *type,
+                                   unsigned char **buf, apr_size_t *size)
+{
+    SSLConnRec *sslconn = myConnConfig(c);
+    const char *prefix;
+    apr_size_t preflen;
+    const unsigned char *data;
+    unsigned char cb[TLS_CB_MAX], *retbuf;
+    unsigned int l = 0;
+    X509 *x = NULL;
+
+    if (!sslconn || !sslconn->ssl) {
+        return APR_EGENERAL;
+    }
+    if (strcEQ(type, "SERVER_TLS_UNIQUE")) {
+        l = SSL_get_peer_finished(sslconn->ssl, cb, TLS_CB_MAX);
+    }
+    else if (strcEQ(type, "CLIENT_TLS_UNIQUE")) {
+        l = SSL_get_finished(sslconn->ssl, cb, TLS_CB_MAX);
+    }
+    else if (strcEQ(type, "SERVER_TLS_SERVER_END_POINT")) {
+        x = SSL_get_certificate(sslconn->ssl);
+    }
+    else if (strcEQ(type, "CLIENT_TLS_SERVER_END_POINT")) {
+        x = SSL_get_peer_certificate(sslconn->ssl);
+    }
+    if (l > 0) {
+        preflen = sizeof(TLS_UNIQUE_PREFIX) -1;
+        prefix = TLS_UNIQUE_PREFIX;
+        data = cb;
+    } 
+    else if (x != NULL) {
+        const EVP_MD *md;
+
+        md = EVP_get_digestbynid(OBJ_obj2nid(x->sig_alg->algorithm));
+        /* Override digest as specified by RFC 5929 section 4.1. */
+        if (md == NULL || md == EVP_md5() || md == EVP_sha1()) {
+            md = EVP_sha256();
+        }
+        if (!X509_digest(x, md, cb, &l)) {
+            return APR_EGENERAL;
+        }
+
+        preflen = sizeof(TLS_SERVER_END_POINT_PREFIX) - 1;
+        prefix = TLS_SERVER_END_POINT_PREFIX;
+        data = cb;
+    } 
+    else {
+        return APR_EGENERAL;
+    }
+
+    retbuf = apr_palloc(p, preflen + l);
+    memcpy(retbuf, prefix, preflen);
+    memcpy(&retbuf[preflen], data, l);
+    *size = preflen + l;
+    *buf = retbuf;
+
+    return APR_SUCCESS;
+}
+
 static const char var_interface[] = "mod_ssl/" AP_SERVER_BASEREVISION;
 static char var_library_interface[] = SSL_LIBRARY_TEXT;
 static char *var_library = NULL;
@@ -107,6 +176,7 @@ void ssl_var_register(apr_pool_t *p)
     char *cp, *cp2;
 
     APR_REGISTER_OPTIONAL_FN(ssl_is_https);
+    APR_REGISTER_OPTIONAL_FN(ssl_get_tls_cb);
     APR_REGISTER_OPTIONAL_FN(ssl_var_lookup);
     APR_REGISTER_OPTIONAL_FN(ssl_ext_list);