From 339bef12f478b3a12c59571c53645e31280baf7e Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Fri, 14 May 2021 15:59:37 +0200 Subject: [PATCH] cert auth: filter out unsupported cert types from TLS 1.2 CR 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 --- lib/auth/cert.c | 76 +++++++++++++++++++++++-- tests/suite/tls-fuzzer/gnutls-cert.json | 19 +++++++ 2 files changed, 89 insertions(+), 6 deletions(-) diff --git a/lib/auth/cert.c b/lib/auth/cert.c index 3073a33d3..0b0f04b2b 100644 --- a/lib/auth/cert.c +++ b/lib/auth/cert.c @@ -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); -- 2.31.1