On platforms that support it, use a SecTrustRef as the basis of CertificateInfo inste...
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 May 2016 18:23:47 +0000 (18:23 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 May 2016 18:23:47 +0000 (18:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=157220

Reviewed by Darin Adler.

Source/WebCore:

* platform/network/cf/CertificateInfo.h:
(WebCore::CertificateInfo::CertificateInfo):
(WebCore::CertificateInfo::trust):
(WebCore::CertificateInfo::isEmpty):
(WebCore::CertificateInfo::setCertificateChain): Deleted.
(WebCore::CertificateInfo::certificateChain): Deleted.
* platform/network/mac/CertificateInfoMac.mm:
(WebCore::CertificateInfo::type):
(WebCore::CertificateInfo::certificateChain):
(WebCore::CertificateInfo::containsNonRootSHA1SignedCertificate):
(WebCore::CertificateInfo::dump):
When supported, allow CertificateInfo to contain a SecTrustRef instead of a certificate chain. We keep
support for holding on to a certificate chain as well, since there is API that depends on this.

* platform/network/cocoa/ResourceResponseCocoa.mm:
(WebCore::ResourceResponse::platformCertificateInfo):
When supported, use the SecTrustRef from the error instead of extracting it's certificate chain.

Source/WebKit2:

* Shared/Authentication/mac/AuthenticationManager.mac.mm:
(WebKit::leafCertificate):
(WebKit::chain):
(WebKit::AuthenticationManager::tryUseCertificateInfoForChallenge):
When supported, get the SecCertificateRef from the SecTrustRef rather than the
stored certificate chain.

* Shared/cf/ArgumentCodersCF.cpp:
(IPC::typeFromCFTypeRef):
(IPC::encode):
(IPC::decode):
* Shared/cf/ArgumentCodersCF.h:
Add support for encoding/decoding SecTrustRef objects.

* Shared/mac/WebCoreArgumentCodersMac.mm:
(IPC::ArgumentCoder<CertificateInfo>::encode):
(IPC::ArgumentCoder<CertificateInfo>::decode):
Add support for encoding/decoding CertificateInfo's that contain SecTrustRef objects.

(IPC::encodeNSError):
(IPC::decodeNSError):
Simplify error encoding/decoding by not using an addition CertificateInfo object for encoding
the peerCertificateChain. Also, add the peerTrust to the userInfo that get's encoded/decoded.

* UIProcess/API/Cocoa/WKWebView.h:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView serverTrust]):
(-[WKWebView certificateChain]):
Add new serverTrust API and deprecate certificateChain.

* UIProcess/Cocoa/NavigationState.mm:
(WebKit::NavigationState::willChangeCertificateInfo):
(WebKit::NavigationState::didChangeCertificateInfo):
Add support for KVO of -[WKWebView serverTrust].

Source/WTF:

* wtf/Platform.h:
Add support for HAVE(SEC_TRUST_SERIALIZATION).

* wtf/spi/cocoa/SecuritySPI.h:
Add SPI access to SecTrustSerialize and SecTrustDeserialize.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@200463 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
Source/WTF/ChangeLog
Source/WTF/wtf/Platform.h
Source/WTF/wtf/spi/cocoa/SecuritySPI.h
Source/WebCore/ChangeLog
Source/WebCore/platform/network/cf/CertificateInfo.h
Source/WebCore/platform/network/cocoa/ResourceResponseCocoa.mm
Source/WebCore/platform/network/mac/CertificateInfoMac.mm
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/API/c/mac/WKCertificateInfoMac.h
Source/WebKit2/Shared/API/c/mac/WKCertificateInfoMac.mm
Source/WebKit2/Shared/Authentication/mac/AuthenticationManager.mac.mm
Source/WebKit2/Shared/cf/ArgumentCodersCF.cpp
Source/WebKit2/Shared/cf/ArgumentCodersCF.h
Source/WebKit2/Shared/mac/WebCoreArgumentCodersMac.mm
Source/WebKit2/UIProcess/API/Cocoa/WKWebView.h
Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit2/UIProcess/Cocoa/NavigationState.mm
Source/WebKit2/WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInFrame.mm
Source/WebKit2/WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInFramePrivate.h

index 0889da1..398d3c5 100644 (file)
@@ -1,3 +1,16 @@
+2016-05-02  Sam Weinig  <sam@webkit.org>
+
+        On platforms that support it, use a SecTrustRef as the basis of CertificateInfo instead of a chain of SecCertificateRefs.
+        https://bugs.webkit.org/show_bug.cgi?id=157220
+
+        Reviewed by Darin Adler.
+
+        * wtf/Platform.h:
+        Add support for HAVE(SEC_TRUST_SERIALIZATION).
+
+        * wtf/spi/cocoa/SecuritySPI.h:
+        Add SPI access to SecTrustSerialize and SecTrustDeserialize.
+
 2016-05-04  Filip Pizlo  <fpizlo@apple.com>
 
         Add HLE locks and synchronic TTAS locks to the ToyLocks benchmark suite
index 1d2a1bd..cd38085 100644 (file)
 #endif
 #endif
 
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000)
+#define HAVE_SEC_TRUST_SERIALIZATION 1
+#endif
 
 #if !defined(WTF_DEFAULT_EVENT_LOOP)
 #define WTF_DEFAULT_EVENT_LOOP 1
index 489aaf8..3116766 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <Security/SecCertificatePriv.h>
 #include <Security/SecTask.h>
+#include <Security/SecTrustPriv.h>
 
 #else
 
@@ -57,4 +58,9 @@ EXTERN_C SecTaskRef SecTaskCreateWithAuditToken(CFAllocatorRef, audit_token_t);
 EXTERN_C SecTaskRef SecTaskCreateFromSelf(CFAllocatorRef);
 EXTERN_C CFTypeRef SecTaskCopyValueForEntitlement(SecTaskRef, CFStringRef entitlement, CFErrorRef *);
 
+#if HAVE(SEC_TRUST_SERIALIZATION)
+EXTERN_C CF_RETURNS_RETAINED CFDataRef SecTrustSerialize(SecTrustRef, CFErrorRef *);
+EXTERN_C CF_RETURNS_RETAINED SecTrustRef SecTrustDeserialize(CFDataRef serializedTrust, CFErrorRef *);
+#endif
+
 #endif // SecuritySPI_h
index 9f02ec2..5f50867 100644 (file)
@@ -1,3 +1,28 @@
+2016-05-02  Sam Weinig  <sam@webkit.org>
+
+        On platforms that support it, use a SecTrustRef as the basis of CertificateInfo instead of a chain of SecCertificateRefs.
+        https://bugs.webkit.org/show_bug.cgi?id=157220
+
+        Reviewed by Darin Adler.
+
+        * platform/network/cf/CertificateInfo.h:
+        (WebCore::CertificateInfo::CertificateInfo):
+        (WebCore::CertificateInfo::trust):
+        (WebCore::CertificateInfo::isEmpty):
+        (WebCore::CertificateInfo::setCertificateChain): Deleted.
+        (WebCore::CertificateInfo::certificateChain): Deleted.
+        * platform/network/mac/CertificateInfoMac.mm:
+        (WebCore::CertificateInfo::type):
+        (WebCore::CertificateInfo::certificateChain):
+        (WebCore::CertificateInfo::containsNonRootSHA1SignedCertificate):
+        (WebCore::CertificateInfo::dump):
+        When supported, allow CertificateInfo to contain a SecTrustRef instead of a certificate chain. We keep
+        support for holding on to a certificate chain as well, since there is API that depends on this.
+
+        * platform/network/cocoa/ResourceResponseCocoa.mm:
+        (WebCore::ResourceResponse::platformCertificateInfo):
+        When supported, use the SecTrustRef from the error instead of extracting it's certificate chain.
+
 2016-05-04  Ada Chan  <adachan@apple.com>
 
         When exiting fullscreen, call a JS method immediately to implement the style changes for the presentation mode change right away
index 6d6d89b..cc53d6e 100644 (file)
 #include "PlatformExportMacros.h"
 #include <wtf/RetainPtr.h>
 
+#if HAVE(SEC_TRUST_SERIALIZATION)
+#include <Security/SecTrust.h>
+#endif
+
 namespace WebCore {
 
 class CertificateInfo {
 public:
-    CertificateInfo() { }
-    CertificateInfo(RetainPtr<CFArrayRef> certificateChain)
-        : m_certificateChain(certificateChain)
-    { }
+     CertificateInfo() = default;
+    enum class Type {
+        None,
+        CertificateChain,
+#if HAVE(SEC_TRUST_SERIALIZATION)
+        Trust,
+#endif
+    };
+
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    explicit CertificateInfo(RetainPtr<SecTrustRef>&& trust)
+        : m_trust(WTFMove(trust))
+    {
+    }
+    SecTrustRef trust() const { return m_trust.get(); }
+#endif
+
+    CertificateInfo(RetainPtr<CFArrayRef>&& certificateChain)
+        : m_certificateChain(WTFMove(certificateChain))
+    {
+    }
 
-    void setCertificateChain(CFArrayRef certificateChain) { m_certificateChain = certificateChain; }
-    CFArrayRef certificateChain() const { return m_certificateChain.get(); }
+    WEBCORE_EXPORT CFArrayRef certificateChain() const;
 
+    WEBCORE_EXPORT Type type() const;
     WEBCORE_EXPORT bool containsNonRootSHA1SignedCertificate() const;
 
+    bool isEmpty() const { return type() == Type::None; }
+
+#if PLATFORM(COCOA)
+    static RetainPtr<CFArrayRef> certificateChainFromSecTrust(SecTrustRef);
+#endif
+
 #ifndef NDEBUG
     void dump() const;
 #endif
 
 private:
-    RetainPtr<CFArrayRef> m_certificateChain;
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    RetainPtr<SecTrustRef> m_trust;
+#endif
+    mutable RetainPtr<CFArrayRef> m_certificateChain;
 };
 
 }
-
 #endif
index ff9b364..c7f47ac 100644 (file)
@@ -99,12 +99,11 @@ CertificateInfo ResourceResponse::platformCertificateInfo() const
             return { };
     }
 
-    CFIndex count = SecTrustGetCertificateCount(trust);
-    auto certificateChain = CFArrayCreateMutable(0, count, &kCFTypeArrayCallBacks);
-    for (CFIndex i = 0; i < count; i++)
-        CFArrayAppendValue(certificateChain, SecTrustGetCertificateAtIndex(trust, i));
-
-    return CertificateInfo(adoptCF(certificateChain));
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    return CertificateInfo(trust);
+#else
+    return CertificateInfo(CertificateInfo::certificateChainFromSecTrust(trust));
+#endif
 }
 
 #if USE(CFNETWORK)
index 7991f55..f652737 100644 (file)
 
 namespace WebCore {
 
+#if PLATFORM(COCOA)
+RetainPtr<CFArrayRef> CertificateInfo::certificateChainFromSecTrust(SecTrustRef trust)
+{
+    auto count = SecTrustGetCertificateCount(trust);
+    auto certificateChain = CFArrayCreateMutable(0, count, &kCFTypeArrayCallBacks);
+    for (CFIndex i = 0; i < count; i++)
+        CFArrayAppendValue(certificateChain, SecTrustGetCertificateAtIndex(trust, i));
+    return adoptCF((CFArrayRef)certificateChain);
+}
+#endif
+
+CertificateInfo::Type CertificateInfo::type() const
+{
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    if (m_trust)
+        return Type::Trust;
+#endif
+    if (m_certificateChain)
+        return Type::CertificateChain;
+    return Type::None;
+}
+
+CFArrayRef CertificateInfo::certificateChain() const
+{
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    if (m_certificateChain)
+        return m_certificateChain.get();
+
+    if (m_trust) 
+        m_certificateChain = CertificateInfo::certificateChainFromSecTrust(m_trust.get());
+#endif
+
+    return m_certificateChain.get();
+}
+
 bool CertificateInfo::containsNonRootSHA1SignedCertificate() const
 {
-#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) || PLATFORM(IOS)
-    if (!m_certificateChain)
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    if (m_trust) {
+        // Allow only the root certificate (the last in the chain) to be SHA1.
+        for (CFIndex i = 0, size = SecTrustGetCertificateCount(trust()) - 1; i < size; ++i) {
+            auto certificate = SecTrustGetCertificateAtIndex(trust(), i);
+            if (SecCertificateGetSignatureHashAlgorithm(certificate) == kSecSignatureHashAlgorithmSHA1)
+                return true;
+        }
+
         return false;
+    }
+#endif
 
-    for (CFIndex i = 0, size = CFArrayGetCount(m_certificateChain.get()) - 1; i < size; ++i) {
-        SecCertificateRef certificate = (SecCertificateRef)CFArrayGetValueAtIndex(m_certificateChain.get(), i);
-        if (SecCertificateGetSignatureHashAlgorithm(certificate) == kSecSignatureHashAlgorithmSHA1)
-            return true;
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) || PLATFORM(IOS)
+    if (m_certificateChain) {
+        // Allow only the root certificate (the last in the chain) to be SHA1.
+        for (CFIndex i = 0, size = CFArrayGetCount(m_certificateChain.get()) - 1; i < size; ++i) {
+            auto certificate = (SecCertificateRef)CFArrayGetValueAtIndex(m_certificateChain.get(), i);
+            if (SecCertificateGetSignatureHashAlgorithm(certificate) == kSecSignatureHashAlgorithmSHA1)
+                return true;
+        }
+        return false;
     }
-    return false;
 #else
     notImplemented();
-    return false;
 #endif
+
+    return false;
 }
 
 #ifndef NDEBUG
 void CertificateInfo::dump() const
 {
-    unsigned entries = m_certificateChain ? CFArrayGetCount(m_certificateChain.get()) : 0;
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    if (m_trust) {
+        CFIndex entries = SecTrustGetCertificateCount(trust());
+
+        NSLog(@"CertificateInfo SecTrust\n");
+        NSLog(@"  Entries: %ld\n", entries);
+        for (CFIndex i = 0; i < entries; ++i) {
+            RetainPtr<CFStringRef> summary = adoptCF(SecCertificateCopySubjectSummary(SecTrustGetCertificateAtIndex(trust(), i)));
+            NSLog(@"  %@", (NSString *)summary.get());
+        }
+
+        return;
+    }
+#endif
+    if (m_certificateChain) {
+        CFIndex entries = CFArrayGetCount(m_certificateChain.get());
+
+        NSLog(@"CertificateInfo (Certificate Chain)\n");
+        NSLog(@"  Entries: %ld\n", entries);
+        for (CFIndex i = 0; i < entries; ++i) {
+            RetainPtr<CFStringRef> summary = adoptCF(SecCertificateCopySubjectSummary((SecCertificateRef)CFArrayGetValueAtIndex(m_certificateChain.get(), i)));
+            NSLog(@"  %@", (NSString *)summary.get());
+        }
 
-    NSLog(@"CertificateInfo\n");
-    NSLog(@"  Entries: %d\n", entries);
-    for (unsigned i = 0; i < entries; ++i) {
-        RetainPtr<CFStringRef> summary = adoptCF(SecCertificateCopySubjectSummary((SecCertificateRef)CFArrayGetValueAtIndex(m_certificateChain.get(), i)));
-        NSLog(@"  %@", (NSString *)summary.get());
+        return;
     }
+    
+    NSLog(@"CertificateInfo (Empty)\n");
 }
 #endif
 
index b115c52..a6d885e 100644 (file)
@@ -1,3 +1,45 @@
+2016-05-02  Sam Weinig  <sam@webkit.org>
+
+        On platforms that support it, use a SecTrustRef as the basis of CertificateInfo instead of a chain of SecCertificateRefs.
+        https://bugs.webkit.org/show_bug.cgi?id=157220
+
+        Reviewed by Darin Adler.
+
+        * Shared/Authentication/mac/AuthenticationManager.mac.mm:
+        (WebKit::leafCertificate):
+        (WebKit::chain):
+        (WebKit::AuthenticationManager::tryUseCertificateInfoForChallenge):
+        When supported, get the SecCertificateRef from the SecTrustRef rather than the
+        stored certificate chain.
+
+        * Shared/cf/ArgumentCodersCF.cpp:
+        (IPC::typeFromCFTypeRef):
+        (IPC::encode):
+        (IPC::decode):
+        * Shared/cf/ArgumentCodersCF.h:
+        Add support for encoding/decoding SecTrustRef objects.
+
+        * Shared/mac/WebCoreArgumentCodersMac.mm:
+        (IPC::ArgumentCoder<CertificateInfo>::encode):
+        (IPC::ArgumentCoder<CertificateInfo>::decode):
+        Add support for encoding/decoding CertificateInfo's that contain SecTrustRef objects.
+
+        (IPC::encodeNSError):
+        (IPC::decodeNSError):
+        Simplify error encoding/decoding by not using an addition CertificateInfo object for encoding
+        the peerCertificateChain. Also, add the peerTrust to the userInfo that get's encoded/decoded.
+
+        * UIProcess/API/Cocoa/WKWebView.h:
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView serverTrust]):
+        (-[WKWebView certificateChain]):
+        Add new serverTrust API and deprecate certificateChain.
+
+        * UIProcess/Cocoa/NavigationState.mm:
+        (WebKit::NavigationState::willChangeCertificateInfo):
+        (WebKit::NavigationState::didChangeCertificateInfo):
+        Add support for KVO of -[WKWebView serverTrust].
+
 2016-05-05  Daniel Bates  <dabates@apple.com>
 
         Remove workaround added in r200391 (rdar://problem/25992976)
index f502596..2490d58 100644 (file)
@@ -27,6 +27,7 @@
 #define WKCertificateInfoMac_h
 
 #include <CoreFoundation/CoreFoundation.h>
+#include <Security/SecTrust.h>
 #include <WebKit/WKBase.h>
 
 #ifdef __cplusplus
@@ -34,6 +35,9 @@ extern "C" {
 #endif
 
 WK_EXPORT WKCertificateInfoRef WKCertificateInfoCreateWithCertficateChain(CFArrayRef certificateChain);
+WK_EXPORT SecTrustRef WKCertificateInfoGetServerTrust(WKCertificateInfoRef certificateInfo);
+
+// Deprecated
 WK_EXPORT CFArrayRef WKCertificateInfoGetCertificateChain(WKCertificateInfoRef certificateInfo);
 
 #ifdef __cplusplus
index 32fa21f..c440b46 100644 (file)
@@ -42,3 +42,12 @@ CFArrayRef WKCertificateInfoGetCertificateChain(WKCertificateInfoRef certificate
 {
     return toImpl(certificateInfoRef)->certificateInfo().certificateChain();
 }
+
+SecTrustRef WKCertificateInfoGetServerTrust(WKCertificateInfoRef certificateInfoRef)
+{
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    return toImpl(certificateInfoRef)->certificateInfo().trust();
+#else
+    return nullptr;
+#endif
+}
index 4060851..5f71348 100644 (file)
@@ -36,18 +36,44 @@ using namespace WebCore;
 
 namespace WebKit {
 
+static SecCertificateRef leafCertificate(const CertificateInfo& certificateInfo)
+{
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    return SecTrustGetCertificateAtIndex(certificateInfo.trust(), 0);
+#else
+    ASSERT(CFArrayGetCount(certificateInfo.certificateChain()));
+    return (SecCertificateRef)CFArrayGetValueAtIndex(certificateInfo.certificateChain(), 0);
+#endif
+}
+
+static NSArray *chain(const CertificateInfo& certificateInfo)
+{
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    CFIndex count = SecTrustGetCertificateCount(certificateInfo.trust());
+    if (count < 2)
+        return nil;
+
+    NSMutableArray *array = [NSMutableArray array];
+    for (CFIndex i = 1; i < count; ++i)
+        [array addObject:(id)SecTrustGetCertificateAtIndex(certificateInfo.trust(), i)];
+        
+    return array;
+#else
+    CFIndex chainCount = CFArrayGetCount(certificateInfo.certificateChain());
+    return chainCount > 1 ? [(NSArray *)certificateInfo.certificateChain() subarrayWithRange:NSMakeRange(1, chainCount - 1)] : nil;
+#endif
+}
+
+
 // FIXME: This function creates an identity from a certificate, which should not be needed. We should pass an identity over IPC (as we do on iOS).
 bool AuthenticationManager::tryUseCertificateInfoForChallenge(const AuthenticationChallenge& challenge, const CertificateInfo& certificateInfo, ChallengeCompletionHandler completionHandler)
 {
-    CFArrayRef chain = certificateInfo.certificateChain();
-    if (!chain)
+    if (certificateInfo.isEmpty())
         return false;
-        
-    ASSERT(CFArrayGetCount(chain));
 
     // The passed-in certificate chain includes the identity certificate at index 0, and additional certificates starting at index 1.
     SecIdentityRef identity;
-    OSStatus result = SecIdentityCreateWithCertificate(NULL, (SecCertificateRef)CFArrayGetValueAtIndex(chain, 0), &identity);
+    OSStatus result = SecIdentityCreateWithCertificate(NULL, leafCertificate(certificateInfo), &identity);
     if (result != errSecSuccess) {
         LOG_ERROR("Unable to create SecIdentityRef with certificate - %i", result);
         if (completionHandler)
@@ -57,13 +83,7 @@ bool AuthenticationManager::tryUseCertificateInfoForChallenge(const Authenticati
         return true;
     }
 
-    CFIndex chainCount = CFArrayGetCount(chain);
-    NSArray *nsChain = chainCount > 1 ? [(NSArray *)chain subarrayWithRange:NSMakeRange(1, chainCount - 1)] : nil;
-
-    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity
-                                                             certificates:nsChain
-                                                              persistence:NSURLCredentialPersistenceNone];
-
+    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:chain(certificateInfo) persistence:NSURLCredentialPersistenceNone];
     if (completionHandler)
         completionHandler(AuthenticationChallengeDisposition::UseCredential, Credential(credential));
     else
index 48e85a0..b2eb0a4 100644 (file)
@@ -31,6 +31,7 @@
 #include "DataReference.h"
 #include <WebCore/CFURLExtras.h>
 #include <wtf/Vector.h>
+#include <wtf/spi/cocoa/SecuritySPI.h>
 
 #if USE(FOUNDATION)
 #import <Foundation/Foundation.h>
@@ -87,6 +88,9 @@ enum CFType {
 #if HAVE(SEC_ACCESS_CONTROL)
     SecAccessControl,
 #endif
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    SecTrust,
+#endif
     Null,
     Unknown,
 };
@@ -129,6 +133,10 @@ static CFType typeFromCFTypeRef(CFTypeRef type)
     if (typeID == SecAccessControlGetTypeID())
         return SecAccessControl;
 #endif
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    if (typeID == SecTrustGetTypeID())
+        return SecTrust;
+#endif
 
     ASSERT_NOT_REACHED();
     return Unknown;
@@ -182,6 +190,11 @@ void encode(ArgumentEncoder& encoder, CFTypeRef typeRef)
         encode(encoder, (SecAccessControlRef)typeRef);
         return;
 #endif
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    case SecTrust:
+        encode(encoder, (SecTrustRef)typeRef);
+        return;
+#endif
     case Null:
         return;
     case Unknown:
@@ -289,6 +302,15 @@ bool decode(ArgumentDecoder& decoder, RetainPtr<CFTypeRef>& result)
         return true;
     }
 #endif
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    case SecTrust: {
+        RetainPtr<SecTrustRef> trust;
+        if (!decode(decoder, trust))
+            return false;
+        result = adoptCF(trust.leakRef());
+        return true;
+    }
+#endif
     case Null:
         result = tokenNullTypeRef();
         return true;
@@ -741,7 +763,41 @@ bool decode(ArgumentDecoder& decoder, RetainPtr<SecAccessControlRef>& result)
 
     return true;
 }
+#endif
+
+#if HAVE(SEC_TRUST_SERIALIZATION)
+void encode(ArgumentEncoder& encoder, SecTrustRef trust)
+{
+    auto data = adoptCF(SecTrustSerialize(trust, nullptr));
+    if (!data) {
+        encoder << false;
+        return;
+    }
+
+    encoder << true;
+    IPC::encode(encoder, data.get());
+}
+
+bool decode(ArgumentDecoder& decoder, RetainPtr<SecTrustRef>& result)
+{
+    bool hasTrust;
+    if (!decoder.decode(hasTrust))
+        return false;
+
+    if (!hasTrust)
+        return true;
 
+    RetainPtr<CFDataRef> trustData;
+    if (!IPC::decode(decoder, trustData))
+        return false;
+
+    auto trust = adoptCF(SecTrustDeserialize(trustData.get(), nullptr));
+    if (!trust)
+        return false;
+
+    result = WTFMove(trust);
+    return true;
+}
 #endif
 
 } // namespace IPC
index 7ec7a7b..2bacfd7 100644 (file)
@@ -27,6 +27,7 @@
 #define ArgumentCodersCF_h
 
 #include <Security/SecCertificate.h>
+#include <Security/SecTrust.h>
 #include <wtf/RetainPtr.h>
 
 #if HAVE(SEC_KEYCHAIN)
@@ -94,6 +95,12 @@ void encode(ArgumentEncoder&, SecAccessControlRef);
 bool decode(ArgumentDecoder&, RetainPtr<SecAccessControlRef>& result);
 #endif
 
+#if HAVE(SEC_TRUST_SERIALIZATION)
+// SecTrustRef
+void encode(ArgumentEncoder&, SecTrustRef);
+bool decode(ArgumentDecoder&, RetainPtr<SecTrustRef>&);
+#endif
+
 #if PLATFORM(IOS)
 void setAllowsDecodingSecKeyRef(bool);
 #endif
index dffb3e0..d2315be 100644 (file)
@@ -163,30 +163,52 @@ bool ArgumentCoder<ResourceRequest>::decodePlatformData(ArgumentDecoder& decoder
 
 void ArgumentCoder<CertificateInfo>::encode(ArgumentEncoder& encoder, const CertificateInfo& certificateInfo)
 {
-    CFArrayRef certificateChain = certificateInfo.certificateChain();
-    if (!certificateChain) {
-        encoder << false;
-        return;
-    }
+    encoder.encodeEnum(certificateInfo.type());
 
-    encoder << true;
-    IPC::encode(encoder, certificateChain);
+    switch (certificateInfo.type()) {
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    case CertificateInfo::Type::Trust:
+        IPC::encode(encoder, certificateInfo.trust());
+        break;
+#endif
+    case CertificateInfo::Type::CertificateChain:
+        IPC::encode(encoder, certificateInfo.certificateChain());
+        break;
+    case CertificateInfo::Type::None:
+        // Do nothing.
+        break;
+    }
 }
 
 bool ArgumentCoder<CertificateInfo>::decode(ArgumentDecoder& decoder, CertificateInfo& certificateInfo)
 {
-    bool hasCertificateChain;
-    if (!decoder.decode(hasCertificateChain))
+    CertificateInfo::Type certificateInfoType;
+    if (!decoder.decodeEnum(certificateInfoType))
         return false;
 
-    if (!hasCertificateChain)
-        return true;
+    switch (certificateInfoType) {
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    case CertificateInfo::Type::Trust: {
+        RetainPtr<SecTrustRef> trust;
+        if (!IPC::decode(decoder, trust))
+            return false;
 
-    RetainPtr<CFArrayRef> certificateChain;
-    if (!IPC::decode(decoder, certificateChain))
-        return false;
+        certificateInfo = CertificateInfo(WTFMove(trust));
+        return true;
+    }
+#endif
+    case CertificateInfo::Type::CertificateChain: {
+        RetainPtr<CFArrayRef> certificateChain;
+        if (!IPC::decode(decoder, certificateChain))
+            return false;
 
-    certificateInfo.setCertificateChain(certificateChain.get());
+        certificateInfo = CertificateInfo(WTFMove(certificateChain));
+        return true;
+    }    
+    case CertificateInfo::Type::None:
+        // Do nothing.
+        break;
+    }
 
     return true;
 }
@@ -219,9 +241,7 @@ static void encodeNSError(ArgumentEncoder& encoder, NSError *nsError)
         }());
 
         CFDictionarySetValue(filteredUserInfo.get(), @"NSErrorClientCertificateChainKey", clientIdentityAndCertificates);
-    };
-
-    IPC::encode(encoder, filteredUserInfo.get());
+    }
 
     id peerCertificateChain = [userInfo objectForKey:@"NSErrorPeerCertificateChainKey"];
     if (!peerCertificateChain) {
@@ -233,7 +253,15 @@ static void encodeNSError(ArgumentEncoder& encoder, NSError *nsError)
         }
     }
     ASSERT(!peerCertificateChain || [peerCertificateChain isKindOfClass:[NSArray class]]);
-    encoder << CertificateInfo((CFArrayRef)peerCertificateChain);
+    if (peerCertificateChain)
+        CFDictionarySetValue(filteredUserInfo.get(), @"NSErrorPeerCertificateChainKey", peerCertificateChain);
+
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    if (SecTrustRef peerTrust = (SecTrustRef)[userInfo objectForKey:NSURLErrorFailingURLPeerTrustErrorKey])
+        CFDictionarySetValue(filteredUserInfo.get(), NSURLErrorFailingURLPeerTrustErrorKey, peerTrust);
+#endif
+
+    IPC::encode(encoder, filteredUserInfo.get());
 
     if (id underlyingError = [userInfo objectForKey:NSUnderlyingErrorKey]) {
         ASSERT([underlyingError isKindOfClass:[NSError class]]);
@@ -269,15 +297,6 @@ static bool decodeNSError(ArgumentDecoder& decoder, RetainPtr<NSError>& nsError)
     if (!IPC::decode(decoder, userInfo))
         return false;
 
-    CertificateInfo certificate;
-    if (!decoder.decode(certificate))
-        return false;
-
-    if (certificate.certificateChain()) {
-        userInfo = adoptCF(CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(userInfo.get()) + 1, userInfo.get()));
-        CFDictionarySetValue((CFMutableDictionaryRef)userInfo.get(), CFSTR("NSErrorPeerCertificateChainKey"), (CFArrayRef)certificate.certificateChain());
-    }
-
     bool hasUnderlyingError = false;
     if (!decoder.decode(hasUnderlyingError))
         return false;
index 2acbd78..d77c987 100644 (file)
@@ -164,12 +164,11 @@ WK_CLASS_AVAILABLE(10_10, 8_0)
  */
 @property (nonatomic, readonly) BOOL hasOnlySecureContent;
 
-/*! @abstract An array of SecCertificateRef objects forming the certificate
- chain for the currently committed navigation.
- @discussion The certificates are ordered from leaf (at index 0) to anchor.
- @link WKWebView @/link is key-value observing (KVO) compliant for this property.
+/*! @abstract A SecTrustRef for the currently committed navigation.
+ @discussion @link WKWebView @/link is key-value observing (KVO) compliant 
+ for this property.
  */
-@property (nonatomic, readonly, copy) NSArray *certificateChain WK_AVAILABLE(10_11, 9_0);
+@property (nonatomic, readonly, nullable) SecTrustRef serverTrust WK_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
 
 /*! @abstract A Boolean value indicating whether there is a back item in
  the back-forward list that can be navigated to.
@@ -305,6 +304,12 @@ WK_CLASS_AVAILABLE(10_10, 8_0)
 
 #endif
 
+@interface WKWebView (WKDeprecated)
+
+@property (nonatomic, readonly, copy) NSArray *certificateChain WK_DEPRECATED(10_11, WK_MAC_TBA, 9_0, WK_IOS_TBA, "Please use serverTrust");
+
+@end
+
 NS_ASSUME_NONNULL_END
 
 #endif
index 3329f68..19d6300 100644 (file)
@@ -721,13 +721,17 @@ static uint32_t convertSystemLayoutDirection(NSUserInterfaceLayoutDirection dire
     return _page->pageLoadState().hasOnlySecureContent();
 }
 
-- (NSArray *)certificateChain
+- (SecTrustRef)serverTrust
 {
+#if HAVE(SEC_TRUST_SERIALIZATION)
     auto certificateInfo = _page->pageLoadState().certificateInfo();
     if (!certificateInfo)
-        return @[ ];
+        return nil;
 
-    return (NSArray *)certificateInfo->certificateInfo().certificateChain() ?: @[ ];
+    return certificateInfo->certificateInfo().trust();
+#else
+    return nil;
+#endif
 }
 
 - (BOOL)canGoBack
@@ -4491,6 +4495,19 @@ static constexpr std::chrono::milliseconds didFinishLoadingTimeout = std::chrono
 @end
 #endif
 
+@implementation WKWebView (WKDeprecated)
+
+- (NSArray *)certificateChain
+{
+    auto certificateInfo = _page->pageLoadState().certificateInfo();
+    if (!certificateInfo)
+        return @[ ];
+
+    return (NSArray *)certificateInfo->certificateInfo().certificateChain() ?: @[ ];
+}
+
+@end
+
 #if PLATFORM(IOS) && USE(APPLE_INTERNAL_SDK)
 #import <WebKitAdditions/WKWebViewAdditions.mm>
 #endif
index 7013e18..87f953b 100644 (file)
@@ -902,12 +902,14 @@ void NavigationState::didChangeNetworkRequestsInProgress()
 
 void NavigationState::willChangeCertificateInfo()
 {
+    [m_webView willChangeValueForKey:@"serverTrust"];
     [m_webView willChangeValueForKey:@"certificateChain"];
 }
 
 void NavigationState::didChangeCertificateInfo()
 {
     [m_webView didChangeValueForKey:@"certificateChain"];
+    [m_webView didChangeValueForKey:@"serverTrust"];
 }
 
 void NavigationState::willChangeWebProcessIsResponsive()
index 5188739..fc0c9ad 100644 (file)
@@ -122,6 +122,15 @@ using namespace WebKit;
     return (NSArray *)_frame->certificateInfo().certificateChain();
 }
 
+- (SecTrustRef)_serverTrust
+{
+#if HAVE(SEC_TRUST_SERIALIZATION)
+    return _frame->certificateInfo().trust();
+#else
+    return nil;
+#endif
+}
+
 - (NSURL *)_provisionalURL
 {
     return [NSURL _web_URLWithWTFString:_frame->provisionalURL()];
index 1cfd59c..8310ac5 100644 (file)
@@ -37,6 +37,7 @@
 
 @property (nonatomic, readonly) BOOL _hasCustomContentProvider;
 @property (nonatomic, readonly) NSArray *_certificateChain;
+@property (nonatomic, readonly) SecTrustRef _serverTrust;
 @property (nonatomic, readonly) NSURL *_provisionalURL;
 
 @property (nonatomic, readonly) WKWebProcessPlugInFrame *_parentFrame;