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.
This commit is contained in:
Andreas Steffen
2022-08-25 07:02:29 +02:00
parent 60a764bad9
commit a3914d7db5
+14 -4
View File
@@ -90,6 +90,11 @@ struct private_tls_peer_t {
*/ */
peer_state_t state; peer_state_t state;
/**
* Received a certificate request from server
*/
bool certreq_received;
/** /**
* TLS version we offered in hello * 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); extensions->destroy(extensions);
} }
this->certreq_received = TRUE;
this->state = STATE_CERTREQ_RECEIVED; this->state = STATE_CERTREQ_RECEIVED;
return NEED_MORE; return NEED_MORE;
} }
@@ -1478,6 +1484,9 @@ static status_t send_certificate(private_tls_peer_t *this,
version_min = this->tls->get_version_min(this->tls); version_min = this->tls->get_version_min(this->tls);
version_max = this->tls->get_version_max(this->tls); version_max = this->tls->get_version_max(this->tls);
if (this->peer)
{
if (!this->hashsig.len) if (!this->hashsig.len)
{ {
convert_cert_types(this); convert_cert_types(this);
@@ -1504,9 +1513,10 @@ static status_t send_certificate(private_tls_peer_t *this,
this->peer_auth->merge(this->peer_auth, auth, FALSE); 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 */ /* 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); writer->write_uint8(writer, 0);
} }
@@ -1524,7 +1534,7 @@ static status_t send_certificate(private_tls_peer_t *this,
free(data.ptr); free(data.ptr);
} }
/* extensions see RFC 8446, section 4.4.2 */ /* 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); certs->write_uint16(certs, 0);
} }
@@ -1767,7 +1777,7 @@ METHOD(tls_handshake_t, build, status_t,
case STATE_INIT: case STATE_INIT:
return send_client_hello(this, type, writer); return send_client_hello(this, type, writer);
case STATE_HELLO_DONE: case STATE_HELLO_DONE:
if (this->peer) if (this->peer || this->certreq_received)
{ {
return send_certificate(this, type, writer); return send_certificate(this, type, writer);
} }
@@ -1804,7 +1814,7 @@ METHOD(tls_handshake_t, build, status_t,
return NEED_MORE; return NEED_MORE;
} }
this->crypto->change_cipher(this->crypto, TRUE); this->crypto->change_cipher(this->crypto, TRUE);
if (this->peer) if (this->peer || this->certreq_received)
{ {
return send_certificate(this, type, writer); return send_certificate(this, type, writer);
} }