QUIC: Forbid non-QUIC ciphers
authorHugo Landau <hlandau@openssl.org>
Mon, 16 Jan 2023 15:20:05 +0000 (15:20 +0000)
committerPauli <pauli@openssl.org>
Tue, 4 Jul 2023 23:02:26 +0000 (09:02 +1000)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20061)

ssl/quic/quic_local.h
ssl/t1_lib.c
test/quicapitest.c

index 50bc472945600558aca1a4a543fc3bd7354f9f17..b02b63cd47255da956355e901bb558b0f1ada41f 100644 (file)
@@ -218,6 +218,7 @@ int ossl_quic_trace(int write_p, int version, int content_type,
 
 #  define OSSL_QUIC_ANY_VERSION     0x5155
 #  define IS_QUIC_METHOD(m)         ((m)->version == OSSL_QUIC_ANY_VERSION)
+#  define IS_QUIC_CTX(ctx)          IS_QUIC_METHOD((ctx)->method)
 
 #  define QUIC_CONNECTION_FROM_SSL_int(ssl, c)   \
      ((ssl) == NULL ? NULL                       \
index b4b13a164331cfafb785440d23212b41b94e7c49..ccc3a40b1f020ffb6d66bb7113275eecc0931ec5 100644 (file)
@@ -2064,6 +2064,18 @@ int ssl_cipher_disabled(const SSL_CONNECTION *s, const SSL_CIPHER *c,
         return 1;
     if (s->s3.tmp.max_ver == 0)
         return 1;
+
+    if (SSL_IS_QUIC_HANDSHAKE(s))
+        /* For QUIC, only allow these ciphersuites. */
+        switch (SSL_CIPHER_get_id(c)) {
+        case TLS1_3_CK_AES_128_GCM_SHA256:
+        case TLS1_3_CK_AES_256_GCM_SHA384:
+        case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
+            break;
+        default:
+            return 1;
+        }
+
     if (!SSL_CONNECTION_IS_DTLS(s)) {
         int min_tls = c->min_tls;
 
index 0d6565e55af49787b6cbcaafa116357f32adfcf4..5cffcff60d2827535354b96afbe450e4b989d9e9 100644 (file)
@@ -313,14 +313,34 @@ static int test_ssl_trace(void)
 }
 #endif
 
+static int ensure_valid_ciphers(const STACK_OF(SSL_CIPHER) *ciphers)
+{
+    size_t i;
+
+    /* Ensure ciphersuite list is suitably subsetted. */
+    for (i = 0; i < (size_t)sk_SSL_CIPHER_num(ciphers); ++i) {
+        const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i);
+        switch (SSL_CIPHER_get_id(cipher)) {
+            case TLS1_3_CK_AES_128_GCM_SHA256:
+            case TLS1_3_CK_AES_256_GCM_SHA384:
+            case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
+                break;
+            default:
+                TEST_error("forbidden cipher: %s", SSL_CIPHER_get_name(cipher));
+                return 0;
+        }
+    }
+
+    return 1;
+}
+
 /*
  * Test that handshake-layer APIs which shouldn't work don't work with QUIC.
  */
-static int test_quic_forbidden_apis(void)
+static int test_quic_forbidden_apis_ctx(void)
 {
     int testresult = 0;
     SSL_CTX *ctx = NULL;
-    SSL *ssl = NULL;
 
     if (!TEST_ptr(ctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method())))
         goto err;
@@ -329,6 +349,47 @@ static int test_quic_forbidden_apis(void)
     if (!TEST_true(SSL_CTX_set_tlsext_use_srtp(ctx, "SRTP_AEAD_AES_128_GCM")))
         goto err;
 
+    /*
+     * List of ciphersuites we do and don't allow in QUIC.
+     */
+#define QUIC_CIPHERSUITES \
+    "TLS_AES_128_GCM_SHA256:"           \
+    "TLS_AES_256_GCM_SHA384:"           \
+    "TLS_CHACHA20_POLY1305_SHA256"
+
+#define NON_QUIC_CIPHERSUITES           \
+    "TLS_AES_128_CCM_SHA256:"           \
+    "TLS_AES_256_CCM_SHA384:"           \
+    "TLS_AES_128_CCM_8_SHA256"
+
+    /* Set TLSv1.3 ciphersuite list for the SSL_CTX. */
+    if (!TEST_true(SSL_CTX_set_ciphersuites(ctx,
+                                            QUIC_CIPHERSUITES ":"
+                                            NON_QUIC_CIPHERSUITES)))
+        goto err;
+
+    /*
+     * Forbidden ciphersuites should show up in SSL_CTX accessors, they are only
+     * filtered in SSL_get1_supported_ciphers, so we don't check for
+     * non-inclusion here.
+     */
+
+    testresult = 1;
+err:
+    SSL_CTX_free(ctx);
+    return testresult;
+}
+
+static int test_quic_forbidden_apis(void)
+{
+    int testresult = 0;
+    SSL_CTX *ctx = NULL;
+    SSL *ssl = NULL;
+    STACK_OF(SSL_CIPHER) *ciphers = NULL;
+
+    if (!TEST_ptr(ctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method())))
+        goto err;
+
     if (!TEST_ptr(ssl = SSL_new(ctx)))
         goto err;
 
@@ -336,8 +397,20 @@ static int test_quic_forbidden_apis(void)
     if (!TEST_true(SSL_set_tlsext_use_srtp(ssl, "SRTP_AEAD_AES_128_GCM")))
         goto err;
 
+    /* Set TLSv1.3 ciphersuite list for the SSL_CTX. */
+    if (!TEST_true(SSL_set_ciphersuites(ssl,
+                                        QUIC_CIPHERSUITES ":"
+                                        NON_QUIC_CIPHERSUITES)))
+        goto err;
+
+    /* Non-QUIC ciphersuites must not appear in supported ciphers list. */
+    if (!TEST_ptr(ciphers = SSL_get1_supported_ciphers(ssl))
+        || !TEST_true(ensure_valid_ciphers(ciphers)))
+        goto err;
+
     testresult = 1;
 err:
+    sk_SSL_CIPHER_free(ciphers);
     SSL_free(ssl);
     SSL_CTX_free(ctx);
     return testresult;
@@ -404,6 +477,7 @@ int setup_tests(void)
 #if !defined(OPENSSL_NO_SSL_TRACE) && !defined(OPENSSL_NO_EC) && defined(OPENSSL_NO_ZLIB)
     ADD_TEST(test_ssl_trace);
 #endif
+    ADD_TEST(test_quic_forbidden_apis_ctx);
     ADD_TEST(test_quic_forbidden_apis);
     return 1;
  err: