fix for nginx SSL session reuse

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

fix for nginx SSL session reuse

Ted Unangst-6
This issue also affects 5.4, 5.5 and 5.6. Patches available in the
respective directories.

5.5 patch follows.

http://ftp.openbsd.org/pub/OpenBSD/patches/5.5/common/011_nginx.patch.sig

untrusted comment: signature from openbsd 5.5 base secret key
RWRGy8gxk9N93yafiuGu4x20xhAgMsmcjCmHJrYJBolmNu2NJUqcC3s+pOmCbUPPX2GxRlEIotfwpbcVG23OoCHguJSk8FZc+Qk=

OpenBSD 5.5 errata 11, Oct 1, 2014:  Fix for the SSL session reuse
vulnerability (CVE-2014-3616).

Apply patch using:

    signify -Vep /etc/signify/openbsd-55-base.pub -x 011_nginx.patch.sig -m - | \
        (cd /usr/src && patch -p0)

Then build and install nginx:

    cd /usr/src/usr.sbin/nginx
    make -f Makefile.bsd-wrapper obj
    make -f Makefile.bsd-wrapper
    make -f Makefile.bsd-wrapper install

Index: usr.sbin/nginx/src/event/ngx_event_openssl.c
===================================================================
RCS file: /cvs/src/usr.sbin/nginx/src/event/ngx_event_openssl.c,v
retrieving revision 1.12
diff -u -p -u -r1.12 ngx_event_openssl.c
--- usr.sbin/nginx/src/event/ngx_event_openssl.c 1 Jun 2013 16:12:54 -0000 1.12
+++ usr.sbin/nginx/src/event/ngx_event_openssl.c 18 Sep 2014 14:18:24 -0000
@@ -27,6 +27,8 @@ static void ngx_ssl_connection_error(ngx
     ngx_err_t err, char *text);
 static void ngx_ssl_clear_error(ngx_log_t *log);
 
+static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl,
+    ngx_str_t *sess_ctx);
 ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data);
 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn,
     ngx_ssl_session_t *sess);
@@ -1659,13 +1661,15 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng
 {
     long  cache_mode;
 
+    if (ngx_ssl_session_id_context(ssl, sess_ctx) != NGX_OK) {
+    return NGX_ERROR;
+    }
+
     if (builtin_session_cache == NGX_SSL_NO_SCACHE) {
         SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF);
         return NGX_OK;
     }
 
-    SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
-
     if (builtin_session_cache == NGX_SSL_NONE_SCACHE) {
 
         /*
@@ -1769,6 +1773,94 @@ ngx_ssl_session_cache_init(ngx_shm_zone_
     return NGX_OK;
 }
 
+static ngx_int_t
+ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t *sess_ctx)
+{
+    int                   n, i;
+    X509                 *cert;
+    X509_NAME            *name;
+    EVP_MD_CTX            md;
+    unsigned int          len;
+    STACK_OF(X509_NAME)  *list;
+    u_char                buf[EVP_MAX_MD_SIZE];
+
+    /*
+     * Session ID context is set based on the string provided,
+     * the server certificate, and the client CA list.
+     */
+
+    EVP_MD_CTX_init(&md);
+
+    if (EVP_DigestInit_ex(&md, EVP_sha1(), NULL) == 0) {
+        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+                      "EVP_DigestInit_ex() failed");
+        goto failed;
+    }
+
+    if (EVP_DigestUpdate(&md, sess_ctx->data, sess_ctx->len) == 0) {
+        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+                      "EVP_DigestUpdate() failed");
+        goto failed;
+    }
+
+    cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
+
+    if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) {
+        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+                      "X509_digest() failed");
+        goto failed;
+    }
+
+    if (EVP_DigestUpdate(&md, buf, len) == 0) {
+        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+                      "EVP_DigestUpdate() failed");
+        goto failed;
+    }
+
+    list = SSL_CTX_get_client_CA_list(ssl->ctx);
+
+    if (list != NULL) {
+        n = sk_X509_NAME_num(list);
+
+        for (i = 0; i < n; i++) {
+            name = sk_X509_NAME_value(list, i);
+
+            if (X509_NAME_digest(name, EVP_sha1(), buf, &len) == 0) {
+                ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+                              "X509_NAME_digest() failed");
+                goto failed;
+            }
+
+            if (EVP_DigestUpdate(&md, buf, len) == 0) {
+                ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+                              "EVP_DigestUpdate() failed");
+                goto failed;
+            }
+        }
+    }
+
+    if (EVP_DigestFinal_ex(&md, buf, &len) == 0) {
+        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+                      "EVP_DigestUpdate() failed");
+        goto failed;
+    }
+
+    EVP_MD_CTX_cleanup(&md);
+
+    if (SSL_CTX_set_session_id_context(ssl->ctx, buf, len) == 0) {
+        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+                      "SSL_CTX_set_session_id_context() failed");
+        return NGX_ERROR;
+    }
+
+    return NGX_OK;
+
+failed:
+
+    EVP_MD_CTX_cleanup(&md);
+
+    return NGX_ERROR;
+}
 
 /*
  * The length of the session id is 16 bytes for SSLv2 sessions and