summaryrefslogtreecommitdiff
path: root/Libraries/LibTLS
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-08-02 05:26:21 +0430
committerAndreas Kling <kling@serenityos.org>2020-08-02 18:57:51 +0200
commit9d3ffa096ad1c618461953241cdf1c99624fa6a1 (patch)
tree1dd242f83609afc99e328c2da89785f947a8e94c /Libraries/LibTLS
parente54a5b7fb88f6f8a87674bb3bb95099872ba2676 (diff)
downloadserenity-9d3ffa096ad1c618461953241cdf1c99624fa6a1.zip
LibTLS: Add (basic) support for sending client certificates
Diffstat (limited to 'Libraries/LibTLS')
-rw-r--r--Libraries/LibTLS/ClientHandshake.cpp8
-rw-r--r--Libraries/LibTLS/Exchange.cpp53
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<const Certificate*> certificates;
+ Vector<Certificate>* 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()