From 9d3ffa096ad1c618461953241cdf1c99624fa6a1 Mon Sep 17 00:00:00 2001 From: AnotherTest Date: Sun, 2 Aug 2020 05:26:21 +0430 Subject: [PATCH] LibTLS: Add (basic) support for sending client certificates --- Libraries/LibTLS/ClientHandshake.cpp | 8 +++-- Libraries/LibTLS/Exchange.cpp | 53 ++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/Libraries/LibTLS/ClientHandshake.cpp b/Libraries/LibTLS/ClientHandshake.cpp index 28d27215dc..52389f0e0f 100644 --- a/Libraries/LibTLS/ClientHandshake.cpp +++ b/Libraries/LibTLS/ClientHandshake.cpp @@ -439,7 +439,9 @@ ssize_t TLSv12::handle_payload(const ByteBuffer& vbuffer) } else { // we do not support "certificate request" dbg() << "certificate request"; - ASSERT_NOT_REACHED(); + if (on_tls_certificate_request) + on_tls_certificate_request(*this); + m_context.client_verified = VerificationNeeded; } break; case ServerHelloDone: @@ -590,8 +592,10 @@ ssize_t TLSv12::handle_payload(const ByteBuffer& vbuffer) // nothing to write break; case WritePacketStage::ClientHandshake: - // Note: currently not used if (m_context.client_verified == VerificationNeeded) { +#ifdef TLS_DEBUG + dbg() << "> Client Certificate"; +#endif auto packet = build_certificate(); write_packet(packet); m_context.client_verified = Verified; diff --git a/Libraries/LibTLS/Exchange.cpp b/Libraries/LibTLS/Exchange.cpp index aeaa9c1cc4..9350977131 100644 --- a/Libraries/LibTLS/Exchange.cpp +++ b/Libraries/LibTLS/Exchange.cpp @@ -166,8 +166,57 @@ bool TLSv12::compute_master_secret(size_t length) ByteBuffer TLSv12::build_certificate() { - dbg() << "FIXME: build_certificate"; - return {}; + PacketBuilder builder { MessageType::Handshake, m_context.version }; + + Vector certificates; + Vector* local_certificates = nullptr; + + if (m_context.is_server) { + dbg() << "Unsupported: Server mode"; + ASSERT_NOT_REACHED(); + } else { + local_certificates = &m_context.client_certificates; + } + + constexpr size_t der_length_delta = 3; + constexpr size_t certificate_vector_header_size = 3; + + size_t total_certificate_size = 0; + + for (size_t i = 0; i < local_certificates->size(); ++i) { + auto& certificate = local_certificates->at(i); + if (!certificate.der.is_empty()) { + total_certificate_size += certificate.der.size() + der_length_delta; + + // FIXME: Check for and respond with only the requested certificate types. + if (true) { + certificates.append(&certificate); + } + } + } + + builder.append((u8)HandshakeType::CertificateMessage); + + if (!total_certificate_size) { +#ifdef TLS_DEBUG + dbg() << "No certificates, sending empty certificate message"; +#endif + builder.append_u24(certificate_vector_header_size); + builder.append_u24(total_certificate_size); + } else { + builder.append_u24(total_certificate_size + certificate_vector_header_size); // 3 bytes for header + builder.append_u24(total_certificate_size); + + for (auto& certificate : certificates) { + if (!certificate->der.is_empty()) { + builder.append_u24(certificate->der.size()); + builder.append(certificate->der); + } + } + } + auto packet = builder.build(); + update_packet(packet); + return packet; } ByteBuffer TLSv12::build_change_cipher_spec()