Untitled diff
60 lines
Index: ssl/s3_lib.c
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
===================================================================
index e94ee83..3cd7e3a 100644
--- a/ssl/s3_lib.c 2016-11-10 15:03:46.000000000 +0100
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c 2016-12-08 03:08:45.167225455 +0100
+++ b/ssl/s3_lib.c
@@ -3582,6 +3582,7 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL
@@ -3582,6 +3582,7 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
     STACK_OF(SSL_CIPHER) *prio, *allow;
     STACK_OF(SSL_CIPHER) *prio, *allow;
     int i, ii, ok;
     int i, ii, ok;
     unsigned long alg_k, alg_a, mask_k, mask_a;
     unsigned long alg_k, alg_a, mask_k, mask_a;
+    int use_chacha = 0;
+    int use_chacha = 0;
     /* Let's see which ciphers we can support */
     /* Let's see which ciphers we can support */
@@ -3610,13 +3611,20 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL
@@ -3610,13 +3611,20 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
         fprintf(stderr, "%p:%s\n", (void *)c, c->name);
         fprintf(stderr, "%p:%s\n", (void *)c, c->name);
     }
     }
 #endif
 #endif
-
-
+retry:
+retry:
     if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || tls1_suiteb(s)) {
     if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || tls1_suiteb(s)) {
         prio = srvr;
         prio = srvr;
         allow = clnt;
         allow = clnt;
+    /* Use ChaCha20+Poly1305 iff it's client's most preferred cipher suite */
+        /* Use ChaCha20+Poly1305 if it's client's most preferred cipher suite */
+        if (sk_SSL_CIPHER_num(clnt) > 0) {
+        if (sk_SSL_CIPHER_num(clnt) > 0) {
+            c = sk_SSL_CIPHER_value(clnt, 0);
+            c = sk_SSL_CIPHER_value(clnt, 0);
+            if (c->algorithm_enc == SSL_CHACHA20POLY1305)
+            if (c->algorithm_enc == SSL_CHACHA20POLY1305)
+                use_chacha = 1;
+                use_chacha = 1;
+        }
+        }
     } else {
     } else {
         prio = clnt;
         prio = clnt;
         allow = srvr;
         allow = srvr;
+        use_chacha = 1;
+        use_chacha = 1;
     }
     }
     tls1_set_cert_validity(s);
     tls1_set_cert_validity(s);
@@ -3634,6 +3642,10 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL
@@ -3634,6 +3642,10 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
              DTLS_VERSION_GT(s->version, c->max_dtls)))
              DTLS_VERSION_GT(s->version, c->max_dtls)))
             continue;
             continue;
+                /* Skip ChaCha unless top client priority */
+        /* Skip ChaCha unless top client priority */
+        if ((c->algorithm_enc == SSL_CHACHA20POLY1305) && !use_chacha)
+        if (c->algorithm_enc == SSL_CHACHA20POLY1305 && !use_chacha)
+            continue;
+            continue;
+
+
         mask_k = s->s3->tmp.mask_k;
         mask_k = s->s3->tmp.mask_k;
         mask_a = s->s3->tmp.mask_a;
         mask_a = s->s3->tmp.mask_a;
 #ifndef OPENSSL_NO_SRP
 #ifndef OPENSSL_NO_SRP
@@ -3687,6 +3699,15 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL
@@ -3687,6 +3699,14 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
             break;
             break;
         }
         }
     }
     }
+
+
+        if (ret == NULL && !use_chacha) {
+    if (ret == NULL && !use_chacha) {
+        /* If no shared cipher was found due to some unusual preferences, try
+        /* If no shared cipher was found due to some unusual preferences, try
+         * again with CHACHA enabled even if not top priority */
+         * again with CHACHA enabled even if not top priority */
+        use_chacha = 1;
+        use_chacha = 1;
+        goto retry;
+        goto retry;
+    }
+    }
+
+
+
     return (ret);
     return (ret);
 }
 }