From: Andreas Steffen Date: Fri, 19 Aug 2022 15:09:02 +0000 (+0200) Subject: libtls: Send empty cert payload upon cert request X-Git-Tag: 5.9.8dr1~2^2~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a3914d7db5db0a76098f63d3e0e2a6452548088c;p=thirdparty%2Fstrongswan.git libtls: Send empty cert payload upon cert request Currently when a TLS client doesn't have a certificate, it doesn't send a certficiate payload upon receiving a certificate request from the TLS server. According to the TLS 1.2 and 1.3 RFCs an empty certificate payload must be sent. --- diff --git a/src/libtls/tls_peer.c b/src/libtls/tls_peer.c index 04f4bcb37c..91f7efba82 100644 --- a/src/libtls/tls_peer.c +++ b/src/libtls/tls_peer.c @@ -90,6 +90,11 @@ struct private_tls_peer_t { */ peer_state_t state; + /** + * Received a certificate request from server + */ + bool certreq_received; + /** * TLS version we offered in hello */ @@ -982,6 +987,7 @@ static status_t process_certreq(private_tls_peer_t *this, bio_reader_t *reader) } extensions->destroy(extensions); } + this->certreq_received = TRUE; this->state = STATE_CERTREQ_RECEIVED; return NEED_MORE; } @@ -1478,35 +1484,39 @@ static status_t send_certificate(private_tls_peer_t *this, version_min = this->tls->get_version_min(this->tls); version_max = this->tls->get_version_max(this->tls); - if (!this->hashsig.len) - { - convert_cert_types(this); - } - enumerator = tls_create_private_key_enumerator(version_min, version_max, - this->hashsig, this->peer); - if (!enumerator || !enumerator->enumerate(enumerator, &key, &auth)) + + if (this->peer) { - if (!enumerator) + if (!this->hashsig.len) + { + convert_cert_types(this); + } + enumerator = tls_create_private_key_enumerator(version_min, version_max, + this->hashsig, this->peer); + if (!enumerator || !enumerator->enumerate(enumerator, &key, &auth)) { - DBG1(DBG_TLS, "no common signature algorithms found"); + if (!enumerator) + { + DBG1(DBG_TLS, "no common signature algorithms found"); + } + else + { + DBG1(DBG_TLS, "no usable TLS client certificate found for '%Y'", + this->peer); + } + this->peer->destroy(this->peer); + this->peer = NULL; } else { - DBG1(DBG_TLS, "no usable TLS client certificate found for '%Y'", - this->peer); + this->private = key->get_ref(key); + this->peer_auth->merge(this->peer_auth, auth, FALSE); } - this->peer->destroy(this->peer); - this->peer = NULL; - } - else - { - this->private = key->get_ref(key); - this->peer_auth->merge(this->peer_auth, auth, FALSE); + DESTROY_IF(enumerator); } - DESTROY_IF(enumerator); /* certificate request context as described in RFC 8446, section 4.4.2 */ - if (this->tls->get_version_max(this->tls) > TLS_1_2) + if (version_max > TLS_1_2) { writer->write_uint8(writer, 0); } @@ -1524,7 +1534,7 @@ static status_t send_certificate(private_tls_peer_t *this, free(data.ptr); } /* extensions see RFC 8446, section 4.4.2 */ - if (this->tls->get_version_max(this->tls) > TLS_1_2) + if (version_max > TLS_1_2) { certs->write_uint16(certs, 0); } @@ -1767,7 +1777,7 @@ METHOD(tls_handshake_t, build, status_t, case STATE_INIT: return send_client_hello(this, type, writer); case STATE_HELLO_DONE: - if (this->peer) + if (this->peer || this->certreq_received) { return send_certificate(this, type, writer); } @@ -1804,7 +1814,7 @@ METHOD(tls_handshake_t, build, status_t, return NEED_MORE; } this->crypto->change_cipher(this->crypto, TRUE); - if (this->peer) + if (this->peer || this->certreq_received) { return send_certificate(this, type, writer); }