← All reports

Implement 2-QWAC fetching

Component: WebKit NetworkProcess | 3dfdbed

Source/WebKit/NetworkProcess/QualifiedServerTrustFetch.cpp

+void QualifiedServerTrustFetch::didFinishLoading(const NetworkLoadMetrics&)
+{
+ WebCore::CertificateInfo qualifiedServerTrust;
+ if (m_debugEnabledForTesting) {
+ // FIXME: Once implementation of SecQWACTLSBindingVerify is available, ...
+ qualifiedServerTrust = m_serverTrust;
+ }
+#if PLATFORM(COCOA)
+ else if (canLoad_Security_SecQWACTLSBindingVerify()) {
+ SecTrustRef trust { nullptr };
+ bool success = softLink_Security_SecQWACTLSBindingVerify(m_buffer.takeBuffer()->makeContiguous()->createCFData().get(), m_serverTrust.trust(), &trust, nullptr);
+ if (trust)
+ qualifiedServerTrust = WebCore::CertificateInfo(adoptCF(trust));
+ }
+#endif
+ ...
+}

Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp

+void NetworkResourceLoader::checkForQualifiedServerTrust(const WebCore::ResourceResponse& response)
+{
+ ...
+ if (!response.url().protocolIs("https"_s))
+ return;
+ ...
+ for (const auto& header : headerSet) {
+ if (!WebCore::LinkRelAttribute(nullptr, header.rel()).isTLSCertificateBinding)
+ continue;
+ URL url { header.url() };
+ if (!url.isValid())
+ continue;
+ if (protocolHostAndPortAreEqual(response.url(), url))
+ return QualifiedServerTrustFetch::create(*session, url, m_parameters, *tlsCertificates);
+ }
+}

2-QWAC is a proposed mechanism (ETSI TS 119 411-5) for binding a site's TLS certificate to a separately-issued "qualified" certificate delivered out-of-band, intended to strengthen trust signals beyond standard CA-issued certs. In WebKit's process model the network process handles all raw network I/O and TLS trust evaluation, while the UI process owns the WKWebView-facing API and per-page state.

WebKit now parses a tls-certificate-binding Link header on the main resource response, fetches the referenced same-origin URL in the network process via a new QualifiedServerTrustFetch object, evaluates it, and forwards the result to the UI process through a new NetworkProcessProxy::ReceivedQualifiedServerTrust IPC message, exposed as a new KVO-observable WKWebView.qualifiedServerTrust property. LinkRelAttribute parsing was generalized to accept a null Document, since header inspection in the network process has no Document — turning a previously document-bound API into one that must tolerate being called without a document context.

Web page load                         Network Process                        UI Process
  │                                         │                                      │
  ├─ main resource response ───────────────►│                                      │
  │   Link: <url>; rel=tls-certificate-      ├─ parse Link header                  │
  │         binding                          ├─ QualifiedServerTrustFetch::create  │
  │                                          │     (same-origin check, then         │
  │                                          │      m_networkLoad->start())          │
  │                                          │     fetch(url) ────► server          │
  │                                          │◄──── response ───────               │
  │                                          ├─ SecQWACTLSBindingVerify (or         │
  │                                          │   debug-only TLS-trust reuse)        │
  │                                          ├─ IPC: receivedQualifiedServerTrust ─►│
  │                                          │                                      ├─ WebPageProxy::receivedQualifiedServerTrust
  │                                          │                                      ├─ PageLoadState::receivedQualifiedServerTrust
  │                                          │                                      └─ WKWebView.qualifiedServerTrust (KVO)

A brand-new cross-process trust-establishing feature triggered by a server-supplied response header, where the actual binding validation is a soft-linked private SPI that may not be available. When SecQWACTLSBindingVerify cannot be loaded, the fetch simply produces an empty trust result; only under an explicit testing-only debug flag does it reuse the existing TLS trust as a stand-in.

The forward-facing pattern is a keep-alive map of in-flight loads keyed by page, where a second request replaces an in-flight one and cancel-versus-completion ordering decides whether the old object's completion path still runs. Narrow: the global keep-alive map in QualifiedServerTrustFetch is the instance here — the tell is a static or process-global container holding Refs to load objects that also self-remove on completion, since a replacement insert and a completion removal racing on the same key can drop the wrong entry. Wider: audit the other network-process objects using the same keep-alive-until-completion idiom — PingLoad, beacon and preconnect paths, and the NetworkResourceLoader completion handlers — for the same replace-while-in-flight shape, plus their own buffering caps (this one caps at 10MB in didReceiveBuffer) for the unbounded-accumulation variant. Widest: the newly nullable-Document path in LinkRelAttribute is the portable lesson — any API generalized from "always has a context object" to "may be called without one" leaves every existing caller's implicit non-null assumption unverified; grep for other Document*-taking parsers in Source/WebCore that have grown a null-tolerant overload and check each body for a dereference the new call site can reach.