]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
cert auth: filter out unsupported cert types from TLS 1.2 CR
authorDaiki Ueno <ueno@gnu.org>
Fri, 14 May 2021 13:59:37 +0000 (15:59 +0200)
committerDaiki Ueno <ueno@gnu.org>
Mon, 17 May 2021 14:32:07 +0000 (16:32 +0200)
When the server is advertising signature algorithms in TLS 1.2
CertificateRequest, it shouldn't send certificate_types not backed by
any of those algorithms.

Signed-off-by: Daiki Ueno <ueno@gnu.org>
lib/auth/cert.c
tests/suite/tls-fuzzer/gnutls-cert.json

index 3073a33d3400ec44f133c5760df43aad870bb4f1..0b0f04b2b12d0e3eaa1af7d1fab493d2a25479fa 100644 (file)
@@ -64,6 +64,16 @@ typedef enum CertificateSigType { RSA_SIGN = 1, DSA_SIGN = 2, ECDSA_SIGN = 64,
 #endif
 } CertificateSigType;
 
+enum CertificateSigTypeFlags {
+       RSA_SIGN_FLAG = 1,
+       DSA_SIGN_FLAG = 1 << 1,
+       ECDSA_SIGN_FLAG = 1 << 2,
+#ifdef ENABLE_GOST
+       GOSTR34102012_256_SIGN_FLAG = 1 << 3,
+       GOSTR34102012_512_SIGN_FLAG = 1 << 4
+#endif
+};
+
 /* Moves data from an internal certificate struct (gnutls_pcert_st) to
  * another internal certificate struct (cert_auth_info_t), and deinitializes
  * the former.
@@ -1281,6 +1291,7 @@ _gnutls_gen_cert_server_cert_req(gnutls_session_t session,
        uint8_t tmp_data[CERTTYPE_SIZE];
        const version_entry_st *ver = get_version(session);
        unsigned init_pos = data->length;
+       enum CertificateSigTypeFlags flags;
 
        if (unlikely(ver == NULL))
                return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
@@ -1297,18 +1308,71 @@ _gnutls_gen_cert_server_cert_req(gnutls_session_t session,
                return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
        }
 
-       i = 1;
+       if (_gnutls_version_has_selectable_sighash(ver)) {
+               size_t j;
+
+               flags = 0;
+               for (j = 0; j < session->internals.priorities->sigalg.size; j++) {
+                       const gnutls_sign_entry_st *se =
+                               session->internals.priorities->sigalg.entry[j];
+                       switch (se->pk) {
+                       case GNUTLS_PK_RSA:
+                       case GNUTLS_PK_RSA_PSS:
+                               flags |= RSA_SIGN_FLAG;
+                               break;
+                       case GNUTLS_PK_DSA:
+                               flags |= DSA_SIGN_FLAG;
+                               break;
+                       case GNUTLS_PK_ECDSA:
+                               flags |= ECDSA_SIGN_FLAG;
+                               break;
 #ifdef ENABLE_GOST
-       if (_gnutls_kx_is_vko_gost(session->security_parameters.cs->kx_algorithm)) {
-               tmp_data[i++] = GOSTR34102012_256_SIGN;
-               tmp_data[i++] = GOSTR34102012_512_SIGN;
-       } else
+                       case GNUTLS_PK_GOST_12_256:
+                               flags |= GOSTR34102012_256_SIGN_FLAG;
+                               break;
+                       case GNUTLS_PK_GOST_12_512:
+                               flags |= GOSTR34102012_512_SIGN_FLAG;
+                               break;
+#endif
+                       default:
+                               gnutls_assert();
+                               _gnutls_debug_log(
+                                       "%s is unsupported for cert request\n",
+                                       gnutls_pk_get_name(se->pk));
+                       }
+               }
+
+       } else {
+#ifdef ENABLE_GOST
+               if (_gnutls_kx_is_vko_gost(session->security_parameters.
+                                          cs->kx_algorithm)) {
+                       flags = GOSTR34102012_256_SIGN_FLAG |
+                               GOSTR34102012_512_SIGN_FLAG;
+               } else
 #endif
-       {
+               {
+                       flags = RSA_SIGN_FLAG | DSA_SIGN_FLAG | ECDSA_SIGN_FLAG;
+               }
+       }
+
+       i = 1;
+       if (flags & RSA_SIGN_FLAG) {
                tmp_data[i++] = RSA_SIGN;
+       }
+       if (flags & DSA_SIGN_FLAG) {
                tmp_data[i++] = DSA_SIGN;
+       }
+       if (flags & ECDSA_SIGN_FLAG) {
                tmp_data[i++] = ECDSA_SIGN;
        }
+#ifdef ENABLE_GOST
+       if (flags & GOSTR34102012_256_SIGN_FLAG) {
+               tmp_data[i++] = GOSTR34102012_256_SIGN;
+       }
+       if (flags & GOSTR34102012_512_SIGN_FLAG) {
+               tmp_data[i++] = GOSTR34102012_512_SIGN;
+       }
+#endif
        tmp_data[0] = i - 1;
 
        ret = _gnutls_buffer_append_data(data, tmp_data, i);
index 6f5874c095fc7923ea806dbfea1f242a6735134f..e49cb432ff6f02bbfbfef19ddca251d0df77476b 100644 (file)
                          "-p", "@PORT@"]
         }
      ]
+    },
+    {"server_command": ["@SERVER@", "--http",
+                 "--x509keyfile", "tests/serverX509Key.pem",
+                 "--x509certfile", "tests/serverX509Cert.pem",
+                 "--debug=6",
+                 "--priority=NORMAL:+VERS-TLS1.2",
+                 "--port=@PORT@"],
+     "environment": {"PYTHONPATH" : "."},
+     "server_hostname": "localhost",
+     "server_port": @PORT@,
+     "tests" : [
+         {"name" : "test-certificate-request.py",
+          "arguments" : ["-k", "tests/clientX509Key.pem",
+                         "-c", "tests/clientX509Cert.pem",
+                         "-p", "@PORT@",
+                         "-s", "sha256+rsa rsa_pss_pss_sha256 rsa_pss_rsae_sha256 sha256+ecdsa rsa_pss_rsae_sha256 sha384+rsa rsa_pss_pss_sha384 rsa_pss_rsae_sha384 sha384+ecdsa ed448 sha512+rsa rsa_pss_pss_sha512 rsa_pss_rsae_sha512 sha512+ecdsa sha1+rsa sha1+ecdsa",
+                         "check cert types in cert request"]
+         }
+     ]
     }
 ]