Skip to content

Commit

Permalink
Generate serialization for SecTrustRef
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=268408
rdar://121955588

Reviewed by achristensen07 (Alex Christensen).

* Source/WebKit/DerivedSources-input.xcfilelist:
* Source/WebKit/DerivedSources.make:
* Source/WebKit/Shared/cf/ArgumentCodersCF.cpp:
(IPC::ArgumentCoder<SecTrustRef>::encode): Deleted.
(IPC::ArgumentCoder<RetainPtr<SecTrustRef>>::decode): Deleted.
* Source/WebKit/Shared/cf/ArgumentCodersCF.h:
* Source/WebKit/Shared/cf/CFTypes.serialization.in:
* Source/WebKit/Shared/cf/CoreIPCSecTrust.h: Added.
(WebKit::CoreIPCSecTrust::CoreIPCSecTrust):
(WebKit::CoreIPCSecTrust::createSecTrust const):
(WebKit::CoreIPCSecTrust::dataReference const):
* Source/WebKit/Shared/cf/CoreIPCSecTrust.serialization.in: Added.
* Source/WebKit/WebKit.xcodeproj/project.pbxproj:
* Tools/TestWebKitAPI/Tests/IPC/IPCSerialization.mm:
(compareSecTrustRefs):
(operator==):
(TEST):

Canonical link: https://commits.webkit.org/274017@main
  • Loading branch information
mscottapple authored and achristensen07 committed Feb 2, 2024
1 parent 98226f6 commit 1851891
Show file tree
Hide file tree
Showing 9 changed files with 222 additions and 49 deletions.
1 change: 1 addition & 0 deletions Source/WebKit/DerivedSources-input.xcfilelist
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ $(PROJECT_DIR)/Shared/cf/CFTypes.serialization.in
$(PROJECT_DIR)/Shared/cf/CoreIPCBoolean.serialization.in
$(PROJECT_DIR)/Shared/cf/CoreIPCNumber.serialization.in
$(PROJECT_DIR)/Shared/cf/CoreIPCSecCertificate.serialization.in
$(PROJECT_DIR)/Shared/cf/CoreIPCSecTrust.serialization.in
$(PROJECT_DIR)/Shared/ios/DynamicViewportSizeUpdate.serialization.in
$(PROJECT_DIR)/Shared/ios/GestureTypes.serialization.in
$(PROJECT_DIR)/Shared/ios/InteractionInformationAtPosition.serialization.in
Expand Down
1 change: 1 addition & 0 deletions Source/WebKit/DerivedSources.make
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,7 @@ SERIALIZATION_DESCRIPTION_FILES = \
Shared/cf/CoreIPCBoolean.serialization.in \
Shared/cf/CoreIPCNumber.serialization.in \
Shared/cf/CoreIPCSecCertificate.serialization.in \
Shared/cf/CoreIPCSecTrust.serialization.in \
Shared/mac/PDFContextMenuItem.serialization.in \
Shared/mac/SecItemRequestData.serialization.in \
Shared/mac/SecItemResponseData.serialization.in \
Expand Down
40 changes: 0 additions & 40 deletions Source/WebKit/Shared/cf/ArgumentCodersCF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -622,46 +622,6 @@ std::optional<RetainPtr<SecAccessControlRef>> ArgumentCoder<RetainPtr<SecAccessC
}
#endif

template<typename Encoder>
void ArgumentCoder<SecTrustRef>::encode(Encoder& encoder, SecTrustRef trust)
{
auto data = adoptCF(SecTrustSerialize(trust, nullptr));
if (!data) {
encoder << false;
return;
}

encoder << true << data;
}

template void ArgumentCoder<SecTrustRef>::encode<Encoder>(Encoder&, SecTrustRef);
template void ArgumentCoder<SecTrustRef>::encode<StreamConnectionEncoder>(StreamConnectionEncoder&, SecTrustRef);

template<typename Decoder>
std::optional<RetainPtr<SecTrustRef>> ArgumentCoder<RetainPtr<SecTrustRef>>::decode(Decoder& decoder)
{
std::optional<bool> hasTrust;
decoder >> hasTrust;
if (!hasTrust)
return std::nullopt;

if (!*hasTrust)
return { nullptr };

std::optional<RetainPtr<CFDataRef>> trustData;
decoder >> trustData;
if (!trustData)
return std::nullopt;

auto trust = adoptCF(SecTrustDeserialize(trustData->get(), nullptr));
if (!trust)
return std::nullopt;

return WTFMove(trust);
}

template std::optional<RetainPtr<SecTrustRef>> ArgumentCoder<RetainPtr<SecTrustRef>>::decode<Decoder>(Decoder&);

} // namespace IPC

namespace WTF {
Expand Down
7 changes: 0 additions & 7 deletions Source/WebKit/Shared/cf/ArgumentCodersCF.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,4 @@ template<> struct ArgumentCoder<RetainPtr<SecAccessControlRef>> : CFRetainPtrArg
};
#endif

template<> struct ArgumentCoder<SecTrustRef> {
template<typename Encoder> static void encode(Encoder&, SecTrustRef);
};
template<> struct ArgumentCoder<RetainPtr<SecTrustRef>> : CFRetainPtrArgumentCoder<SecTrustRef> {
template<typename Decoder> static std::optional<RetainPtr<SecTrustRef>> decode(Decoder&);
};

} // namespace IPC
4 changes: 4 additions & 0 deletions Source/WebKit/Shared/cf/CFTypes.serialization.in
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ additional_forward_declaration: typedef struct __SecCertificate *SecCertificateR
[WebKitPlatform, CustomHeader, AdditionalEncoder=StreamConnectionEncoder, ToCFMethod=result->createSecCertificate()] SecCertificateRef wrapped by WebKit::CoreIPCSecCertificate {
}

additional_forward_declaration: typedef struct __SecTrust *SecTrustRef
[WebKitPlatform, CustomHeader, AdditionalEncoder=StreamConnectionEncoder, ToCFMethod=result->createSecTrust()] SecTrustRef wrapped by WebKit::CoreIPCSecTrust {
}

#endif

#if USE(CG)
Expand Down
78 changes: 78 additions & 0 deletions Source/WebKit/Shared/cf/CoreIPCSecTrust.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (C) 2024 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/

#pragma once

#if USE(CF)

#import <wtf/RetainPtr.h>
#import <wtf/spi/cocoa/SecuritySPI.h>

namespace WebKit {

// For now, the only way to serialize/deserialize SecTrust objects is via
// SecTrustSerialize()/SecTrustDeserialize(). rdar://122051469

class CoreIPCSecTrust {
public:
CoreIPCSecTrust(SecTrustRef trust)
: m_trustData(adoptCF(SecTrustSerialize(trust, NULL)))
{
}

CoreIPCSecTrust(RetainPtr<CFDataRef> data)
: m_trustData(data)
{
}

CoreIPCSecTrust(const IPC::DataReference& data)
: m_trustData(data.empty() ? nullptr : adoptCF(CFDataCreate(kCFAllocatorDefault, data.data(), data.size())))
{
}

RetainPtr<SecTrustRef> createSecTrust() const
{
if (!m_trustData)
return nullptr;

return adoptCF(SecTrustDeserialize(m_trustData.get(), NULL));
}

IPC::DataReference dataReference() const
{
if (!m_trustData)
return { };

CFDataRef data = m_trustData.get();
return { CFDataGetBytePtr(data), static_cast<size_t>(CFDataGetLength(data)) };
}

private:
RetainPtr<CFDataRef> m_trustData;
};

} // namespace WebKit

#endif // USE(CF)
31 changes: 31 additions & 0 deletions Source/WebKit/Shared/cf/CoreIPCSecTrust.serialization.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright (C) 2024 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#if USE(CF)

webkit_platform_headers: "CoreIPCSecTrust.h"

[WebKitPlatform, AdditionalEncoder=StreamConnectionEncoder] class WebKit::CoreIPCSecTrust {
IPC::DataReference dataReference();
}

#endif // USE(CF)
6 changes: 6 additions & 0 deletions Source/WebKit/WebKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1331,6 +1331,7 @@
53BA47D11DC2EF5E004DF4AD /* NetworkDataTaskBlob.h in Headers */ = {isa = PBXBuildFile; fileRef = 539EB5471DC2EE40009D48CF /* NetworkDataTaskBlob.h */; };
53CFBBC82224D1B500266546 /* TextCheckerCompletion.h in Headers */ = {isa = PBXBuildFile; fileRef = 53CFBBC72224D1B000266546 /* TextCheckerCompletion.h */; };
561A54532B61E49E00073A72 /* CoreIPCSecCertificate.h in Headers */ = {isa = PBXBuildFile; fileRef = 561A54512B61E49E00073A72 /* CoreIPCSecCertificate.h */; };
562674F52B69B4C8008BB425 /* CoreIPCSecTrust.h in Headers */ = {isa = PBXBuildFile; fileRef = 562674F32B69B4C7008BB425 /* CoreIPCSecTrust.h */; };
570AB8F320AE3BD700B8BE87 /* SecKeyProxyStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 570AB8F220AE3BD700B8BE87 /* SecKeyProxyStore.h */; };
570DAAAE23026F5C00E8FC04 /* NfcService.h in Headers */ = {isa = PBXBuildFile; fileRef = 570DAAAC23026F5C00E8FC04 /* NfcService.h */; };
570DAAC22303730300E8FC04 /* NfcConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 570DAAC02303730300E8FC04 /* NfcConnection.h */; };
Expand Down Expand Up @@ -5653,6 +5654,8 @@
55AD09422408A02E00DE4D2F /* RemoteImageBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteImageBuffer.h; sourceTree = "<group>"; };
561A54512B61E49E00073A72 /* CoreIPCSecCertificate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CoreIPCSecCertificate.h; sourceTree = "<group>"; };
561A54522B61E49E00073A72 /* CoreIPCSecCertificate.serialization.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = CoreIPCSecCertificate.serialization.in; sourceTree = "<group>"; };
562674F32B69B4C7008BB425 /* CoreIPCSecTrust.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreIPCSecTrust.h; sourceTree = "<group>"; };
562674F42B69B4C8008BB425 /* CoreIPCSecTrust.serialization.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CoreIPCSecTrust.serialization.in; sourceTree = "<group>"; };
570AB8F220AE3BD700B8BE87 /* SecKeyProxyStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecKeyProxyStore.h; sourceTree = "<group>"; };
570AB90020B2517400B8BE87 /* AuthenticationChallengeProxyCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AuthenticationChallengeProxyCocoa.mm; sourceTree = "<group>"; };
570AB90320B2541C00B8BE87 /* SecKeyProxyStore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SecKeyProxyStore.mm; sourceTree = "<group>"; };
Expand Down Expand Up @@ -9012,6 +9015,8 @@
F4EFF36A2AF0267200479AB8 /* CoreIPCNumber.serialization.in */,
561A54512B61E49E00073A72 /* CoreIPCSecCertificate.h */,
561A54522B61E49E00073A72 /* CoreIPCSecCertificate.serialization.in */,
562674F32B69B4C7008BB425 /* CoreIPCSecTrust.h */,
562674F42B69B4C8008BB425 /* CoreIPCSecTrust.serialization.in */,
);
path = cf;
sourceTree = "<group>";
Expand Down Expand Up @@ -15219,6 +15224,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
562674F52B69B4C8008BB425 /* CoreIPCSecTrust.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
103 changes: 101 additions & 2 deletions Tools/TestWebKitAPI/Tests/IPC/IPCSerialization.mm
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#import "MessageSenderInlines.h"
#import "test.h"
#import <Foundation/NSValue.h>
#import <Security/Security.h>
#import <WebCore/FontCocoa.h>
#import <limits.h>
#import <pal/spi/cocoa/ContactsSPI.h>
Expand Down Expand Up @@ -92,7 +93,8 @@ CFTypeRef valueAsCFType() const
RetainPtr<CFDataRef>,
RetainPtr<CFBooleanRef>,
RetainPtr<CGColorRef>,
RetainPtr<CFDictionaryRef>
RetainPtr<CFDictionaryRef>,
RetainPtr<SecTrustRef>
> ValueType;

ValueType value;
Expand All @@ -115,6 +117,84 @@ CFTypeRef valueAsCFType() const
} };
}

static bool compareSecTrustRefs(SecTrustRef trust1, SecTrustRef trust2)
{
// SecTrust doesn't compare equal after round-tripping through SecTrustSerialize/SecTrustDeserialize <rdar://122051396>
// Therefore, we compare all the attributes we can access to verify equality.
SecKeyRef pk1 = SecTrustCopyPublicKey(trust1);
SecKeyRef pk2 = SecTrustCopyPublicKey(trust2);
EXPECT_TRUE(pk1);
EXPECT_TRUE(pk2);
bool equal = CFEqual(pk1, pk2);
CFRelease(pk1);
CFRelease(pk2);
EXPECT_TRUE(equal);
if (!equal)
return false;

equal = (SecTrustGetCertificateCount(trust1) == SecTrustGetCertificateCount(trust2));
EXPECT_TRUE(equal);
if (!equal)
return false;

CFDataRef ex1 = SecTrustCopyExceptions(trust1);
CFDataRef ex2 = SecTrustCopyExceptions(trust2);
EXPECT_TRUE(ex1);
EXPECT_TRUE(ex2);
equal = CFEqual(ex1, ex2);
CFRelease(ex1);
CFRelease(ex2);
EXPECT_TRUE(equal);
if (!equal)
return false;

CFArrayRef array1, array2;
EXPECT_TRUE(SecTrustCopyPolicies(trust1, &array1) == errSecSuccess);
EXPECT_TRUE(SecTrustCopyPolicies(trust2, &array2) == errSecSuccess);
equal = CFEqual(array1, array2);
CFRelease(array1);
CFRelease(array2);
EXPECT_TRUE(equal);
if (!equal)
return false;

EXPECT_TRUE(SecTrustCopyPolicies(trust1, &array1) == errSecSuccess);
EXPECT_TRUE(SecTrustCopyPolicies(trust2, &array2) == errSecSuccess);
equal = CFEqual(array1, array2);
CFRelease(array1);
CFRelease(array2);
EXPECT_TRUE(equal);
if (!equal)
return false;

array1 = SecTrustCopyProperties(trust1);
array2 = SecTrustCopyProperties(trust2);
EXPECT_TRUE(array1);
EXPECT_TRUE(array2);
equal = CFEqual(array1, array2);
CFRelease(array1);
CFRelease(array2);
EXPECT_TRUE(equal);
if (!equal)
return false;

Boolean bool1, bool2;
EXPECT_TRUE(SecTrustGetNetworkFetchAllowed(trust1, &bool1) == errSecSuccess);
EXPECT_TRUE(SecTrustGetNetworkFetchAllowed(trust2, &bool2) == errSecSuccess);
equal = (bool1 == bool2);
EXPECT_TRUE(equal);
if (!equal)
return false;

SecTrustResultType result1, result2;
EXPECT_TRUE(SecTrustGetTrustResult(trust1, &result1) == errSecSuccess);
EXPECT_TRUE(SecTrustGetTrustResult(trust2, &result2) == errSecSuccess);
equal = (result1 == result2);
EXPECT_TRUE(equal);

return equal;
}

inline bool operator==(const CFHolderForTesting& a, const CFHolderForTesting& b)
{
auto aObject = a.valueAsCFType();
Expand All @@ -128,7 +208,13 @@ CFTypeRef valueAsCFType() const

// Sometimes the CF input and CF output fail the CFEqual call above (Such as CFDictionaries containing certain things)
// In these cases, give the Obj-C equivalent equality check a chance.
return [(NSObject *)aObject isEqual: (NSObject *)bObject];
if ([(NSObject *)aObject isEqual: (NSObject *)bObject])
return true;

if (CFGetTypeID(aObject) == SecTrustGetTypeID() && CFGetTypeID(bObject) == SecTrustGetTypeID())
return compareSecTrustRefs((SecTrustRef)aObject, (SecTrustRef)bObject);

return false;
}

struct ObjCHolderForTesting {
Expand Down Expand Up @@ -645,6 +731,19 @@ String certDataBase64(""
// - NSRect
runValueTest([NSValue valueWithRange:NSMakeRange(1, 2)]);
runValueTest([NSValue valueWithRect:NSMakeRect(1, 2, 79, 80)]);

// SecTrust -- evaluate the trust of the cert created above
SecTrustRef trust = NULL;
SecPolicyRef policy = SecPolicyCreateBasicX509();
EXPECT_TRUE(SecTrustCreateWithCertificates(cert.get(), policy, &trust) == errSecSuccess);
EXPECT_TRUE(trust);
runTestCF({ trust });

EXPECT_TRUE(SecTrustEvaluateWithError(trust, NULL) == errSecSuccess);
runTestCF({ trust });

CFRelease(trust);
CFRelease(policy);
}

#if PLATFORM(MAC)
Expand Down

0 comments on commit 1851891

Please sign in to comment.