Title: [273167] trunk
Revision
273167
Author
[email protected]
Date
2021-02-19 15:15:22 -0800 (Fri, 19 Feb 2021)

Log Message

PCM: Generate secret token and corresponding unlinkable token
https://bugs.webkit.org/show_bug.cgi?id=222019
<rdar://problem/73581412>

Reviewed by John Wilander.

Source/WebCore:

Covered by API tests.

This patch utilizes RSABSSA to generate secret token for PCM fraud prevention.

* Configurations/WebCore.xcconfig:
* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:
Paperwork to link CryptoKitCBridging.

* loader/PrivateClickMeasurement.cpp:
(WebCore::PrivateClickMeasurement::EphemeralSourceNonce::isValid const):
(WebCore::PrivateClickMeasurement::setEphemeralSourceNonce):
* loader/PrivateClickMeasurement.h:
(WebCore::PrivateClickMeasurement::attributeOnSite const):
(WebCore::PrivateClickMeasurement::ephemeralSourceNonce const):
(WebCore::PrivateClickMeasurement::clearEphemeralSourceNonce):
(WebCore::PrivateClickMeasurement::EphemeralSourceNonce::EphemeralSourceNonce): Deleted.
(WebCore::PrivateClickMeasurement::EphemeralSourceNonce::isValid const): Deleted.
(WebCore::PrivateClickMeasurement::setEphemeralSourceNonce): Deleted.
Groups functionalities behind HAVE_RSA_BSSA.

* loader/cocoa/PrivateClickMeasurementCocoa.mm: Added.
(WebCore::PrivateClickMeasurement::blindedSecretJson):
(WebCore::PrivateClickMeasurement::calculatePersistentBlindedToken):
Introduces new methods to generate the blinded secrets and unlinkable tokens.

Source/WTF:

* wtf/PlatformHave.h:
Adds a compile time flag for RSABSSA.

Tools:

* TestWebKitAPI/Tests/WebCore/PrivateClickMeasurement.cpp:
(TestWebKitAPI::TEST):
Add tests.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/http/tests/privateClickMeasurement/store-private-click-measurement-with-source-nonce-expected.txt (273166 => 273167)


--- trunk/LayoutTests/http/tests/privateClickMeasurement/store-private-click-measurement-with-source-nonce-expected.txt	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/LayoutTests/http/tests/privateClickMeasurement/store-private-click-measurement-with-source-nonce-expected.txt	2021-02-19 23:15:22 UTC (rev 273167)
@@ -18,7 +18,7 @@
 REQUEST_URI: /privateClickMeasurement/resources/signToken.php
 No cookies in token signing request.
 Request body:
-{"source_engagement_type":"click","source_nonce":"ABCDEFabcdef0123456789","unlinkable_token":"TODO","version":2}
+{}
 
 Unattributed Private Click Measurements:
 WebCore::PrivateClickMeasurement 1

Modified: trunk/Source/WTF/ChangeLog (273166 => 273167)


--- trunk/Source/WTF/ChangeLog	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/Source/WTF/ChangeLog	2021-02-19 23:15:22 UTC (rev 273167)
@@ -1,3 +1,14 @@
+2021-02-16  Jiewen Tan  <[email protected]>
+
+        PCM: Generate secret token and corresponding unlinkable token
+        https://bugs.webkit.org/show_bug.cgi?id=222019
+        <rdar://problem/73581412>
+
+        Reviewed by John Wilander.
+
+        * wtf/PlatformHave.h:
+        Adds a compile time flag for RSABSSA.
+
 2021-02-19  Jer Noble  <[email protected]>
 
         [Cocoa] Enable Opus decode support by default

Modified: trunk/Source/WTF/wtf/PlatformHave.h (273166 => 273167)


--- trunk/Source/WTF/wtf/PlatformHave.h	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/Source/WTF/wtf/PlatformHave.h	2021-02-19 23:15:22 UTC (rev 273167)
@@ -888,3 +888,8 @@
 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 120000
 #define HAVE_STATIC_FONT_REGISTRY 1
 #endif
+
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 120000) \
+    || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 150000)
+#define HAVE_RSA_BSSA 1
+#endif

Modified: trunk/Source/WebCore/ChangeLog (273166 => 273167)


--- trunk/Source/WebCore/ChangeLog	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/Source/WebCore/ChangeLog	2021-02-19 23:15:22 UTC (rev 273167)
@@ -1,3 +1,37 @@
+2021-02-16  Jiewen Tan  <[email protected]>
+
+        PCM: Generate secret token and corresponding unlinkable token
+        https://bugs.webkit.org/show_bug.cgi?id=222019
+        <rdar://problem/73581412>
+
+        Reviewed by John Wilander.
+
+        Covered by API tests.
+
+        This patch utilizes RSABSSA to generate secret token for PCM fraud prevention.
+
+        * Configurations/WebCore.xcconfig:
+        * SourcesCocoa.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        Paperwork to link CryptoKitCBridging.
+
+        * loader/PrivateClickMeasurement.cpp:
+        (WebCore::PrivateClickMeasurement::EphemeralSourceNonce::isValid const):
+        (WebCore::PrivateClickMeasurement::setEphemeralSourceNonce):
+        * loader/PrivateClickMeasurement.h:
+        (WebCore::PrivateClickMeasurement::attributeOnSite const):
+        (WebCore::PrivateClickMeasurement::ephemeralSourceNonce const):
+        (WebCore::PrivateClickMeasurement::clearEphemeralSourceNonce):
+        (WebCore::PrivateClickMeasurement::EphemeralSourceNonce::EphemeralSourceNonce): Deleted.
+        (WebCore::PrivateClickMeasurement::EphemeralSourceNonce::isValid const): Deleted.
+        (WebCore::PrivateClickMeasurement::setEphemeralSourceNonce): Deleted.
+        Groups functionalities behind HAVE_RSA_BSSA.
+
+        * loader/cocoa/PrivateClickMeasurementCocoa.mm: Added.
+        (WebCore::PrivateClickMeasurement::blindedSecretJson):
+        (WebCore::PrivateClickMeasurement::calculatePersistentBlindedToken):
+        Introduces new methods to generate the blinded secrets and unlinkable tokens.
+
 2021-02-19  Devin Rousso  <[email protected]>
 
         [Payment Request] add support for Apple Pay payment method mode

Modified: trunk/Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj (273166 => 273167)


--- trunk/Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/Source/WebCore/PAL/PAL.xcodeproj/project.pbxproj	2021-02-19 23:15:22 UTC (rev 273167)
@@ -138,6 +138,8 @@
 		570AB8F920AF6E3D00B8BE87 /* NSXPCConnectionSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 570AB8F820AF6E3D00B8BE87 /* NSXPCConnectionSPI.h */; };
 		572A107822B456F500F410C8 /* AuthKitSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 572A107722B456F500F410C8 /* AuthKitSPI.h */; };
 		576CA9D622B854AB0030143C /* AppSSOSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 576CA9D522B854AB0030143C /* AppSSOSPI.h */; };
+		57F1C90925DCF0CF00E8F6EA /* CryptoKitCBridgingSoftLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 57F1C90725DCF0CF00E8F6EA /* CryptoKitCBridgingSoftLink.h */; };
+		57F1C90A25DCF0CF00E8F6EA /* CryptoKitCBridgingSoftLink.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57F1C90825DCF0CF00E8F6EA /* CryptoKitCBridgingSoftLink.mm */; };
 		57FD318A22B3593E008D0E8B /* AppSSOSoftLink.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57FD318922B3593E008D0E8B /* AppSSOSoftLink.mm */; };
 		57FD318B22B35989008D0E8B /* AppSSOSoftLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 57FD318822B3592F008D0E8B /* AppSSOSoftLink.h */; };
 		5C7C787323AC3E770065F47E /* ManagedConfigurationSoftLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C7C787123AC3E770065F47E /* ManagedConfigurationSoftLink.h */; };
@@ -341,6 +343,8 @@
 		570AB8F820AF6E3D00B8BE87 /* NSXPCConnectionSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSXPCConnectionSPI.h; sourceTree = "<group>"; };
 		572A107722B456F500F410C8 /* AuthKitSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuthKitSPI.h; sourceTree = "<group>"; };
 		576CA9D522B854AB0030143C /* AppSSOSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppSSOSPI.h; sourceTree = "<group>"; };
+		57F1C90725DCF0CF00E8F6EA /* CryptoKitCBridgingSoftLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CryptoKitCBridgingSoftLink.h; sourceTree = "<group>"; };
+		57F1C90825DCF0CF00E8F6EA /* CryptoKitCBridgingSoftLink.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CryptoKitCBridgingSoftLink.mm; sourceTree = "<group>"; };
 		57FD318822B3592F008D0E8B /* AppSSOSoftLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppSSOSoftLink.h; sourceTree = "<group>"; };
 		57FD318922B3593E008D0E8B /* AppSSOSoftLink.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AppSSOSoftLink.mm; sourceTree = "<group>"; };
 		5C7C787123AC3E770065F47E /* ManagedConfigurationSoftLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ManagedConfigurationSoftLink.h; sourceTree = "<group>"; };
@@ -691,6 +695,8 @@
 				57FD318922B3593E008D0E8B /* AppSSOSoftLink.mm */,
 				077E87B0226A460200A2AFF0 /* AVFoundationSoftLink.h */,
 				077E87AF226A460200A2AFF0 /* AVFoundationSoftLink.mm */,
+				57F1C90725DCF0CF00E8F6EA /* CryptoKitCBridgingSoftLink.h */,
+				57F1C90825DCF0CF00E8F6EA /* CryptoKitCBridgingSoftLink.mm */,
 				F44291661FA52705002CC93E /* FileSizeFormatterCocoa.mm */,
 				1C022EFC22CFE8E0006DF01B /* Gunzip.cpp */,
 				CDACB35E23873E480018D7CE /* MediaToolboxSoftLink.cpp */,
@@ -828,6 +834,7 @@
 				1CCEE4F520D871930047B097 /* CoreUISPI.h in Headers */,
 				0C5AF9191F43A4C7002EAC02 /* CoreUISPI.h in Headers */,
 				1C09D0531E31C44100725F18 /* CryptoDigest.h in Headers */,
+				57F1C90925DCF0CF00E8F6EA /* CryptoKitCBridgingSoftLink.h in Headers */,
 				0C2DA1411F3BEB4900DBC317 /* DataDetectorsCoreSPI.h in Headers */,
 				0C77858A1F45130F00F4EBB6 /* DataDetectorsSPI.h in Headers */,
 				0C5AF91A1F43A4C7002EAC02 /* DataDetectorsUISPI.h in Headers */,
@@ -1037,6 +1044,7 @@
 				0CF99CA81F738437007EE793 /* CoreMediaSoftLink.cpp in Sources */,
 				1C77C8C925D7972000635E0C /* CoreTextSoftLink.cpp in Sources */,
 				1C09D0561E31C46500725F18 /* CryptoDigestCommonCrypto.cpp in Sources */,
+				57F1C90A25DCF0CF00E8F6EA /* CryptoKitCBridgingSoftLink.mm in Sources */,
 				A1175B581F6B470500C4B9F0 /* DefaultSearchProvider.cpp in Sources */,
 				F44291641FA52670002CC93E /* FileSizeFormatter.cpp in Sources */,
 				F44291681FA52705002CC93E /* FileSizeFormatterCocoa.mm in Sources */,

Added: trunk/Source/WebCore/PAL/pal/cocoa/CryptoKitCBridgingSoftLink.h (0 => 273167)


--- trunk/Source/WebCore/PAL/pal/cocoa/CryptoKitCBridgingSoftLink.h	                        (rev 0)
+++ trunk/Source/WebCore/PAL/pal/cocoa/CryptoKitCBridgingSoftLink.h	2021-02-19 23:15:22 UTC (rev 273167)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 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 HAVE(RSA_BSSA)
+
+#import <CryptoKitCBridging/RSABSSA.h>
+#import <wtf/SoftLinking.h>
+
+SOFT_LINK_FRAMEWORK_FOR_HEADER(PAL, CryptoKitCBridging);
+
+SOFT_LINK_CLASS_FOR_HEADER(PAL, RSABSSATokenBlinder);
+
+#endif

Added: trunk/Source/WebCore/PAL/pal/cocoa/CryptoKitCBridgingSoftLink.mm (0 => 273167)


--- trunk/Source/WebCore/PAL/pal/cocoa/CryptoKitCBridgingSoftLink.mm	                        (rev 0)
+++ trunk/Source/WebCore/PAL/pal/cocoa/CryptoKitCBridgingSoftLink.mm	2021-02-19 23:15:22 UTC (rev 273167)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include "config.h"
+
+#if HAVE(RSA_BSSA)
+
+#import <wtf/SoftLinking.h>
+
+SOFT_LINK_PRIVATE_FRAMEWORK_FOR_SOURCE_WITH_EXPORT(PAL, CryptoKitCBridging, PAL_EXPORT);
+
+SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, CryptoKitCBridging, RSABSSATokenBlinder, PAL_EXPORT);
+
+#endif

Modified: trunk/Source/WebCore/SourcesCocoa.txt (273166 => 273167)


--- trunk/Source/WebCore/SourcesCocoa.txt	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/Source/WebCore/SourcesCocoa.txt	2021-02-19 23:15:22 UTC (rev 273167)
@@ -169,6 +169,7 @@
 loader/archive/cf/LegacyWebArchive.cpp
 loader/archive/cf/LegacyWebArchiveMac.mm
 loader/cocoa/DiskCacheMonitorCocoa.mm
+loader/cocoa/PrivateClickMeasurementCocoa.mm
 loader/cocoa/SubresourceLoaderCocoa.mm
 loader/ios/LegacyPreviewLoader.mm
 loader/mac/DocumentLoaderMac.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (273166 => 273167)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-02-19 23:15:22 UTC (rev 273167)
@@ -9421,6 +9421,7 @@
 		57EEAA571EA0AFBB00701124 /* CommonCryptoDERUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CommonCryptoDERUtilities.cpp; sourceTree = "<group>"; };
 		57EF5E5F1D20C83900171E60 /* TextCodecReplacement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextCodecReplacement.h; sourceTree = "<group>"; };
 		57EF5E611D20D28700171E60 /* TextCodecReplacement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextCodecReplacement.cpp; sourceTree = "<group>"; };
+		57F1C8E325DC6EE700E8F6EA /* PrivateClickMeasurementCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PrivateClickMeasurementCocoa.mm; sourceTree = "<group>"; };
 		57F827391DB72C22009D2BF4 /* RsaHashedKeyGenParams.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = RsaHashedKeyGenParams.idl; sourceTree = "<group>"; };
 		57FEDD3D1DB6D47F00EB96F5 /* RsaKeyGenParams.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = RsaKeyGenParams.idl; sourceTree = "<group>"; };
 		57FEDD3E1DB6D59200EB96F5 /* CryptoAlgorithmRsaKeyGenParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoAlgorithmRsaKeyGenParams.h; sourceTree = "<group>"; };
@@ -9736,7 +9737,7 @@
 		6A22E8721F1042C400F546C3 /* InspectorCanvas.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorCanvas.cpp; sourceTree = "<group>"; };
 		6A7279881F16C29B003F39B8 /* InspectorShaderProgram.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorShaderProgram.h; sourceTree = "<group>"; };
 		6A7279891F16C29B003F39B8 /* InspectorShaderProgram.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorShaderProgram.cpp; sourceTree = "<group>"; };
-		6B0A07F021FA4B5C00D57391 /* PrivateClickMeasurement.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrivateClickMeasurement.h; sourceTree = "<group>"; };
+		6B0A07F021FA4B5C00D57391 /* PrivateClickMeasurement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrivateClickMeasurement.h; sourceTree = "<group>"; };
 		6B0A07F121FA4B5C00D57391 /* PrivateClickMeasurement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PrivateClickMeasurement.cpp; sourceTree = "<group>"; };
 		6B1F480F22989EC400DE8B82 /* CrossSiteNavigationDataTransfer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CrossSiteNavigationDataTransfer.h; sourceTree = "<group>"; };
 		6B4D412B23983F88002494C2 /* LoggedInStatus.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LoggedInStatus.h; sourceTree = "<group>"; };
@@ -22973,6 +22974,7 @@
 			children = (
 				7EDAAFC819A2CBD10034DFD1 /* DiskCacheMonitorCocoa.h */,
 				7E4DE10C198B10B60051CB02 /* DiskCacheMonitorCocoa.mm */,
+				57F1C8E325DC6EE700E8F6EA /* PrivateClickMeasurementCocoa.mm */,
 				7E8FADC3199A95B100714968 /* SubresourceLoaderCocoa.mm */,
 			);
 			path = cocoa;

Modified: trunk/Source/WebCore/loader/PrivateClickMeasurement.cpp (273166 => 273167)


--- trunk/Source/WebCore/loader/PrivateClickMeasurement.cpp	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/Source/WebCore/loader/PrivateClickMeasurement.cpp	2021-02-19 23:15:22 UTC (rev 273167)
@@ -37,7 +37,7 @@
 namespace WebCore {
 
 static const char privateClickMeasurementTriggerAttributionPath[] = "/.well-known/private-click-measurement/trigger-attribution/";
-static const char privateClickMeasurementTokenSignaturePath[] = "/.well-known/private-click-measurement/sign-unlinkable-token/";
+static const char privateClickMeasurementTokenSignaturePath[] = "/.well-known/private-click-measurement/sign-secret-token/";
 static const char privateClickMeasurementTokenPublicKeyPath[] = "/.well-known/private-click-measurement/get-unlinkable-token-public-key/";
 static const char privateClickMeasurementReportAttributionPath[] = "/.well-known/private-click-measurement/report-attribution/";
 const size_t privateClickMeasurementAttributionTriggerDataPathSegmentSize = 2;
@@ -116,15 +116,15 @@
     return m_attributionTriggerData->priority > other.m_attributionTriggerData->priority;
 }
 
-URL PrivateClickMeasurement::tokenSignatureURL() const
+URL PrivateClickMeasurement::attributionReportURL() const
 {
-    if (!m_ephemeralSourceNonce || !m_ephemeralSourceNonce->isValid())
+    if (!isValid())
         return URL();
 
     StringBuilder builder;
     builder.appendLiteral("https://");
     builder.append(m_sourceSite.registrableDomain.string());
-    builder.appendLiteral(privateClickMeasurementTokenSignaturePath);
+    builder.appendLiteral(privateClickMeasurementReportAttributionPath);
 
     URL url { URL(), builder.toString() };
     if (url.isValid())
@@ -133,12 +133,51 @@
     return URL();
 }
 
-URL PrivateClickMeasurement::tokenPublicKeyURL() const
+Ref<JSON::Object> PrivateClickMeasurement::attributionReportJSON() const
 {
+    auto reportDetails = JSON::Object::create();
+    if (!m_attributionTriggerData || !isValid())
+        return reportDetails;
+
+    reportDetails->setString("source_engagement_type"_s, "click"_s);
+    reportDetails->setString("source_site"_s, m_sourceSite.registrableDomain.string());
+    reportDetails->setInteger("source_id"_s, m_sourceID.id);
+    reportDetails->setString("attributed_on_site"_s, m_attributeOnSite.registrableDomain.string());
+    reportDetails->setInteger("trigger_data"_s, m_attributionTriggerData->data);
+    reportDetails->setInteger("version"_s, 1);
+    return reportDetails;
+}
+
+// MARK: - Fraud Prevention
+
+static constexpr uint32_t EphemeralSourceNonceRequiredNumberOfBytes = 16;
+
+bool PrivateClickMeasurement::EphemeralSourceNonce::isValid() const
+{
+    // FIXME: Investigate if we can do with a simple length check instead of decoding.
+    // https://bugs.webkit.org/show_bug.cgi?id=221945
+    Vector<uint8_t> digest;
+    if (!base64URLDecode(nonce, digest))
+        return false;
+    return digest.size() == EphemeralSourceNonceRequiredNumberOfBytes;
+}
+
+void PrivateClickMeasurement::setEphemeralSourceNonce(EphemeralSourceNonce&& nonce)
+{
+    if (!nonce.isValid())
+        return;
+    m_ephemeralSourceNonce = WTFMove(nonce);
+}
+
+URL PrivateClickMeasurement::tokenSignatureURL() const
+{
+    if (!m_ephemeralSourceNonce || !m_ephemeralSourceNonce->isValid())
+        return URL();
+
     StringBuilder builder;
     builder.appendLiteral("https://");
     builder.append(m_sourceSite.registrableDomain.string());
-    builder.appendLiteral(privateClickMeasurementTokenPublicKeyPath);
+    builder.appendLiteral(privateClickMeasurementTokenSignaturePath);
 
     URL url { URL(), builder.toString() };
     if (url.isValid())
@@ -147,28 +186,12 @@
     return URL();
 }
 
-Ref<JSON::Object> PrivateClickMeasurement::tokenSignatureJSON() const
+URL PrivateClickMeasurement::tokenPublicKeyURL() const
 {
-    auto reportDetails = JSON::Object::create();
-    if (!m_ephemeralSourceNonce || !m_ephemeralSourceNonce->isValid())
-        return reportDetails;
-
-    reportDetails->setString("source_engagement_type"_s, "click"_s);
-    reportDetails->setString("source_nonce"_s, m_ephemeralSourceNonce->nonce);
-    reportDetails->setString("unlinkable_token"_s, "TODO"_s);
-    reportDetails->setInteger("version"_s, 2);
-    return reportDetails;
-}
-
-URL PrivateClickMeasurement::attributionReportURL() const
-{
-    if (!isValid())
-        return URL();
-
     StringBuilder builder;
     builder.appendLiteral("https://");
     builder.append(m_sourceSite.registrableDomain.string());
-    builder.appendLiteral(privateClickMeasurementReportAttributionPath);
+    builder.appendLiteral(privateClickMeasurementTokenPublicKeyPath);
 
     URL url { URL(), builder.toString() };
     if (url.isValid())
@@ -177,19 +200,24 @@
     return URL();
 }
 
-Ref<JSON::Object> PrivateClickMeasurement::attributionReportJSON() const
+Ref<JSON::Object> PrivateClickMeasurement::tokenSignatureJSON(const String& serverPublicKeyBase64URL)
 {
     auto reportDetails = JSON::Object::create();
-    if (!m_attributionTriggerData || !isValid())
+    if (!m_ephemeralSourceNonce || !m_ephemeralSourceNonce->isValid())
         return reportDetails;
 
+    String token;
+#if PLATFORM(COCOA)
+    token = sourceSecretToken(serverPublicKeyBase64URL);
+#endif
+    if (token.isEmpty())
+        return reportDetails;
+
     reportDetails->setString("source_engagement_type"_s, "click"_s);
-    reportDetails->setString("source_site"_s, m_sourceSite.registrableDomain.string());
-    reportDetails->setInteger("source_id"_s, m_sourceID.id);
-    reportDetails->setString("attributed_on_site"_s, m_attributeOnSite.registrableDomain.string());
-    reportDetails->setInteger("trigger_data"_s, m_attributionTriggerData->data);
-    reportDetails->setInteger("version"_s, 1);
+    reportDetails->setString("source_nonce"_s, m_ephemeralSourceNonce->nonce);
+    reportDetails->setString("source_secret_token"_s, token);
+    reportDetails->setInteger("version"_s, 2);
     return reportDetails;
 }
 
-}
+} // namespace WebCore

Modified: trunk/Source/WebCore/loader/PrivateClickMeasurement.h (273166 => 273167)


--- trunk/Source/WebCore/loader/PrivateClickMeasurement.h	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/Source/WebCore/loader/PrivateClickMeasurement.h	2021-02-19 23:15:22 UTC (rev 273167)
@@ -36,6 +36,16 @@
 #include <wtf/text/StringHash.h>
 #include <wtf/text/WTFString.h>
 
+#if PLATFORM(COCOA)
+#include <wtf/RetainPtr.h>
+#endif
+
+#if PLATFORM(COCOA)
+OBJC_CLASS RSABSSATokenReady;
+OBJC_CLASS RSABSSATokenWaitingActivation;
+OBJC_CLASS RSABSSATokenBlinder;
+#endif
+
 namespace WebCore {
 
 class PrivateClickMeasurement {
@@ -201,31 +211,6 @@
         static const bool safeToCompareToEmptyOrDeleted = false;
     };
 
-    struct EphemeralSourceNonce {
-        static constexpr uint32_t RequiredNumberOfBytes = 16;
-
-        EphemeralSourceNonce() = default;
-        explicit EphemeralSourceNonce(const String& nonceString)
-            : nonce { nonceString }
-        {
-        }
-
-        // FIXME: Investigate if we can do with a simple length check instead of decoding.
-        // https://bugs.webkit.org/show_bug.cgi?id=221945
-        bool isValid() const
-        {
-            Vector<uint8_t> digest;
-            if (!base64URLDecode(nonce, digest))
-                return false;
-            return digest.size() == RequiredNumberOfBytes;
-        }
-
-        String nonce;
-
-        template<class Encoder> void encode(Encoder&) const;
-        template<class Decoder> static Optional<EphemeralSourceNonce> decode(Decoder&);
-    };
-
     struct Priority {
         static constexpr uint32_t MaxEntropy = 63;
 
@@ -277,16 +262,10 @@
     WEBCORE_EXPORT static Expected<AttributionTriggerData, String> parseAttributionRequest(const URL& redirectURL);
     WEBCORE_EXPORT Optional<Seconds> attributeAndGetEarliestTimeToSend(AttributionTriggerData&&);
     WEBCORE_EXPORT bool hasHigherPriorityThan(const PrivateClickMeasurement&) const;
-    WEBCORE_EXPORT URL tokenPublicKeyURL() const;
-    WEBCORE_EXPORT URL tokenSignatureURL() const;
-    WEBCORE_EXPORT Ref<JSON::Object> tokenSignatureJSON() const;
     WEBCORE_EXPORT URL attributionReportURL() const;
     WEBCORE_EXPORT Ref<JSON::Object> attributionReportJSON() const;
     const SourceSite& sourceSite() const { return m_sourceSite; };
     const AttributeOnSite& attributeOnSite() const { return m_attributeOnSite; };
-    void setEphemeralSourceNonce(EphemeralSourceNonce&& nonce) { m_ephemeralSourceNonce = WTFMove(nonce); };
-    Optional<EphemeralSourceNonce> ephemeralSourceNonce() const { return !m_ephemeralSourceNonce ? WTF::nullopt : m_ephemeralSourceNonce->isValid() ? m_ephemeralSourceNonce : WTF::nullopt; };
-    void clearEphemeralSourceNonce() { m_ephemeralSourceNonce  = WTF::nullopt; };
     WallTime timeOfAdClick() const { return m_timeOfAdClick; }
     Optional<WallTime> earliestTimeToSend() const { return m_earliestTimeToSend; };
     void setEarliestTimeToSend(WallTime time) { m_earliestTimeToSend = time; }
@@ -297,11 +276,40 @@
     const String& sourceDescription() const { return m_sourceDescription; }
     const String& purchaser() const { return m_purchaser; }
 
+    // MARK: - Fraud Prevention
+    struct EphemeralSourceNonce {
+        String nonce;
+
+        WEBCORE_EXPORT bool isValid() const;
+
+        template<class Encoder> void encode(Encoder&) const;
+        template<class Decoder> static Optional<EphemeralSourceNonce> decode(Decoder&);
+    };
+
+    WEBCORE_EXPORT void setEphemeralSourceNonce(EphemeralSourceNonce&&);
+    Optional<EphemeralSourceNonce> ephemeralSourceNonce() const { return m_ephemeralSourceNonce; };
+    void clearEphemeralSourceNonce() { m_ephemeralSourceNonce.reset(); };
+
+    struct SourceUnlinkableToken {
+        String tokenBase64URL;
+        String keyIDBase64URL;
+        String signatureBase64URL;
+    };
+
+    WEBCORE_EXPORT URL tokenPublicKeyURL() const;
+    WEBCORE_EXPORT URL tokenSignatureURL() const;
+
+    WEBCORE_EXPORT Ref<JSON::Object> tokenSignatureJSON(const String& serverPublicKeyBase64URL);
+    WEBCORE_EXPORT Optional<SourceUnlinkableToken> calculateSourceUnlinkableToken(const String& serverResponseBase64URL);
+
     template<class Encoder> void encode(Encoder&) const;
     template<class Decoder> static Optional<PrivateClickMeasurement> decode(Decoder&);
 
 private:
     bool isValid() const;
+#if PLATFORM(COCOA)
+    String sourceSecretToken(const String& serverPublicKeyBase64URL);
+#endif
 
     SourceID m_sourceID;
     SourceSite m_sourceSite;
@@ -310,9 +318,19 @@
     String m_purchaser;
     WallTime m_timeOfAdClick;
 
-    Optional<EphemeralSourceNonce> m_ephemeralSourceNonce;
     Optional<AttributionTriggerData> m_attributionTriggerData;
     Optional<WallTime> m_earliestTimeToSend;
+
+    struct SourceSecretToken {
+#if PLATFORM(COCOA)
+        RetainPtr<RSABSSATokenBlinder> blinder;
+        RetainPtr<RSABSSATokenWaitingActivation> waitingToken;
+        RetainPtr<RSABSSATokenReady> readyToken;
+#endif
+    };
+
+    Optional<EphemeralSourceNonce> m_ephemeralSourceNonce;
+    SourceSecretToken m_sourceSecretToken;
 };
 
 template<class Encoder>

Added: trunk/Source/WebCore/loader/cocoa/PrivateClickMeasurementCocoa.mm (0 => 273167)


--- trunk/Source/WebCore/loader/cocoa/PrivateClickMeasurementCocoa.mm	                        (rev 0)
+++ trunk/Source/WebCore/loader/cocoa/PrivateClickMeasurementCocoa.mm	2021-02-19 23:15:22 UTC (rev 273167)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#import "config.h"
+#import "PrivateClickMeasurement.h"
+
+#import <pal/cocoa/CryptoKitCBridgingSoftLink.h>
+
+namespace WebCore {
+
+String PrivateClickMeasurement::sourceSecretToken(const String& serverPublicKeyBase64URL)
+{
+#if HAVE(RSA_BSSA)
+    {
+        Vector<uint8_t> serverPublicKeyData;
+        if (!base64URLDecode(serverPublicKeyBase64URL, serverPublicKeyData))
+            return emptyString();
+        auto serverPublicKey = adoptNS([[NSData alloc] initWithBytes:serverPublicKeyData.data() length:serverPublicKeyData.size()]);
+
+        // FIXME(222018): Check error.
+        m_sourceSecretToken.blinder = adoptNS([PAL::allocRSABSSATokenBlinderInstance() initWithPublicKey:serverPublicKey.get() error:nullptr]);
+        if (!m_sourceSecretToken.blinder)
+            return emptyString();
+    }
+
+    // FIXME(222018): Check error.
+    m_sourceSecretToken.waitingToken = [m_sourceSecretToken.blinder tokenWaitingActivationWithContent:nullptr error:nullptr];
+    if (!m_sourceSecretToken.waitingToken)
+        return emptyString();
+
+    return WTF::base64URLEncode([m_sourceSecretToken.waitingToken blindedMessage].bytes, [m_sourceSecretToken.waitingToken blindedMessage].length);
+#else
+    UNUSED_PARAM(serverPublicKeyBase64URL);
+    return emptyString();
+#endif // HAVE(RSA_BSSA)
+}
+
+auto PrivateClickMeasurement::calculateSourceUnlinkableToken(const String& serverResponseBase64URL) -> Optional<SourceUnlinkableToken>
+{
+#if HAVE(RSA_BSSA)
+    if (!m_sourceSecretToken.waitingToken)
+        return WTF::nullopt;
+
+    {
+        Vector<uint8_t> serverResponseData;
+        if (!base64URLDecode(serverResponseBase64URL, serverResponseData))
+            return WTF::nullopt;
+        auto serverResponse = adoptNS([[NSData alloc] initWithBytes:serverResponseData.data() length:serverResponseData.size()]);
+
+        // FIXME(222018): Check error.
+        m_sourceSecretToken.readyToken = [m_sourceSecretToken.waitingToken activateTokenWithServerResponse:serverResponse.get() error:nullptr];
+        if (!m_sourceSecretToken.readyToken)
+            return WTF::nullopt;
+    }
+
+    SourceUnlinkableToken token;
+    token.tokenBase64URL = WTF::base64URLEncode([m_sourceSecretToken.readyToken tokenContent].bytes, [m_sourceSecretToken.readyToken tokenContent].length);
+    token.keyIDBase64URL = WTF::base64URLEncode([m_sourceSecretToken.readyToken keyId].bytes, [m_sourceSecretToken.readyToken keyId].length);
+    token.signatureBase64URL = WTF::base64URLEncode([m_sourceSecretToken.readyToken signature].bytes, [m_sourceSecretToken.readyToken signature].length);
+
+    return token;
+#else
+    UNUSED_PARAM(serverResponseBase64URL);
+    return WTF::nullopt;
+#endif // HAVE(RSA_BSSA)
+}
+
+} // namespace WebCore

Modified: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.cpp (273166 => 273167)


--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.cpp	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.cpp	2021-02-19 23:15:22 UTC (rev 273167)
@@ -157,12 +157,12 @@
         }
 
         // FIXME: Receive and extra the server public key, rdar://73582032.
-        getSignedUnlinkableToken(WTFMove(attribution));
+        getSignedSecretToken(WTFMove(attribution), emptyString());
     });
 
 }
 
-void PrivateClickMeasurementManager::getSignedUnlinkableToken(PrivateClickMeasurement&& attribution)
+void PrivateClickMeasurementManager::getSignedSecretToken(PrivateClickMeasurement&& attribution, const String& tokenPublicKeyBase64URL)
 {
     if (!featureEnabled())
         return;
@@ -178,10 +178,10 @@
     if (tokenSignatureURL.isEmpty() || !tokenSignatureURL.isValid())
         return;
 
-    auto loadParameters = generateNetworkResourceLoadParametersForHttpPost(WTFMove(tokenSignatureURL), attribution.tokenSignatureJSON(), pcmDataCarried);
+    auto loadParameters = generateNetworkResourceLoadParametersForHttpPost(WTFMove(tokenSignatureURL), attribution.tokenSignatureJSON(tokenPublicKeyBase64URL), pcmDataCarried);
 
-    RELEASE_LOG_INFO(PrivateClickMeasurement, "About to fire a unlinkable token signing request.");
-    m_networkProcess->broadcastConsoleMessage(m_sessionID, MessageSource::PrivateClickMeasurement, MessageLevel::Log, "[Private Click Measurement] About to fire a unlinkable token signing request."_s);
+    RELEASE_LOG_INFO(PrivateClickMeasurement, "About to fire a secret token signing request.");
+    m_networkProcess->broadcastConsoleMessage(m_sessionID, MessageSource::PrivateClickMeasurement, MessageLevel::Log, "[Private Click Measurement] About to fire a secret token signing request."_s);
 
     m_pingLoadFunction(WTFMove(loadParameters), [weakThis = makeWeakPtr(*this)](const WebCore::ResourceError& error, const WebCore::ResourceResponse& response) {
         if (!weakThis)
@@ -188,11 +188,11 @@
             return;
 
         if (!error.isNull()) {
-            weakThis->m_networkProcess->broadcastConsoleMessage(weakThis->m_sessionID, MessageSource::PrivateClickMeasurement, MessageLevel::Error, makeString("[Private Click Measurement] Received error: '"_s, error.localizedDescription(), "' for unlinkable token signing request."_s));
+            weakThis->m_networkProcess->broadcastConsoleMessage(weakThis->m_sessionID, MessageSource::PrivateClickMeasurement, MessageLevel::Error, makeString("[Private Click Measurement] Received error: '"_s, error.localizedDescription(), "' for secret token signing request."_s));
             return;
         }
         
-        // FIXME: Receive and store the signed unlinkable token, rdar://73582032.
+        // FIXME: Receive and store the signed secret token, rdar://73582032.
     });
 
 }

Modified: trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.h (273166 => 273167)


--- trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.h	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/Source/WebKit/NetworkProcess/PrivateClickMeasurementManager.h	2021-02-19 23:15:22 UTC (rev 273167)
@@ -70,7 +70,7 @@
 
 private:
     void getTokenPublicKey(PrivateClickMeasurement&&);
-    void getSignedUnlinkableToken(PrivateClickMeasurement&&);
+    void getSignedSecretToken(PrivateClickMeasurement&&, const String& tokenPublicKeyBase64URL);
     void clearSentAttribution(PrivateClickMeasurement&&);
     void attribute(const SourceSite&, const AttributeOnSite&, AttributionTriggerData&&);
     void fireConversionRequest(const PrivateClickMeasurement&);

Modified: trunk/Tools/ChangeLog (273166 => 273167)


--- trunk/Tools/ChangeLog	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/Tools/ChangeLog	2021-02-19 23:15:22 UTC (rev 273167)
@@ -1,3 +1,15 @@
+2021-02-16  Jiewen Tan  <[email protected]>
+
+        PCM: Generate secret token and corresponding unlinkable token
+        https://bugs.webkit.org/show_bug.cgi?id=222019
+        <rdar://problem/73581412>
+
+        Reviewed by John Wilander.
+
+        * TestWebKitAPI/Tests/WebCore/PrivateClickMeasurement.cpp:
+        (TestWebKitAPI::TEST):
+        Add tests.
+
 2021-02-19  Aditya Keerthi  <[email protected]>
 
         [iOS][FCR] Enable the new appearance by default

Modified: trunk/Tools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig (273166 => 273167)


--- trunk/Tools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/Tools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig	2021-02-19 23:15:22 UTC (rev 273167)
@@ -55,6 +55,12 @@
 WK_PDFKIT_LDFLAGS_iphoneos = -framework PDFKit;
 WK_PDFKIT_LDFLAGS_iphonesimulator = -framework PDFKit;
 
+WK_SYSTEM_LDFLAGS = $(WK_SYSTEM_LDFLAGS_$(WK_PLATFORM_NAME));
+WK_SYSTEM_LDFLAGS_macosx = -framework System;
+WK_SYSTEM_LDFLAGS_iphoneos = $(WK_SYSTEM_LDFLAGS_$(WK_IOS_15));
+WK_SYSTEM_LDFLAGS_iphonesimulator = $(WK_SYSTEM_LDFLAGS_$(WK_IOS_15));
+WK_SYSTEM_LDFLAGS_IOS_SINCE_15 = -framework System;
+
 WK_HID_LDFLAGS = $(WK_HID_LDFLAGS_$(WK_PLATFORM_NAME));
 WK_HID_LDFLAGS_macosx = $(WK_HID_LDFLAGS$(WK_MACOS_1015));
 WK_HID_LDFLAGS_MACOS_SINCE_1015 = -framework HID;
@@ -71,7 +77,7 @@
 WK_OPENGL_LDFLAGS_appletvsimulator = $(WK_OPENGL_LDFLAGS_iphonesimulator);
 WK_OPENGL_LDFLAGS_macosx = -framework OpenGL;
 
-OTHER_LDFLAGS = $(inherited) $(UNEXPORTED_SYMBOL_LDFLAGS) -lgtest -force_load $(BUILT_PRODUCTS_DIR)/libTestWebKitAPI.a -framework _javascript_Core -framework WebKit -lWebCoreTestSupport $(WK_AUTHKIT_LDFLAGS) -framework Network $(WK_PDFKIT_LDFLAGS) $(WK_HID_LDFLAGS) $(WK_OPENGL_LDFLAGS) $(OTHER_LDFLAGS_PLATFORM_$(WK_COCOA_TOUCH));
+OTHER_LDFLAGS = $(inherited) $(UNEXPORTED_SYMBOL_LDFLAGS) -lgtest -force_load $(BUILT_PRODUCTS_DIR)/libTestWebKitAPI.a -framework _javascript_Core -framework WebKit -lWebCoreTestSupport $(WK_AUTHKIT_LDFLAGS) -framework Network $(WK_SYSTEM_LDFLAGS) $(WK_PDFKIT_LDFLAGS) $(WK_HID_LDFLAGS) $(WK_OPENGL_LDFLAGS) $(OTHER_LDFLAGS_PLATFORM_$(WK_COCOA_TOUCH));
 OTHER_LDFLAGS_PLATFORM_ = -framework Cocoa -framework Carbon;
 
 // FIXME: This should not be built on iOS. Instead we should create and use a TestWebKitAPI application.

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (273166 => 273167)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2021-02-19 23:15:22 UTC (rev 273167)
@@ -441,6 +441,7 @@
 		57C624502346C21E00383FE7 /* web-authentication-get-assertion.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 57C6244F2346C1EC00383FE7 /* web-authentication-get-assertion.html */; };
 		57EDFC5C245A1A3F00959521 /* web-authentication-make-credential-la-no-mock.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 57EDFC5B245A18F500959521 /* web-authentication-make-credential-la-no-mock.html */; };
 		57EDFC60245A299C00959521 /* web-authentication-get-assertion-la-no-mock.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 57EDFC5F245A279900959521 /* web-authentication-get-assertion-la-no-mock.html */; };
+		57F1C91125DDD51900E8F6EA /* PrivateClickMeasurementCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57F1C91025DDD51900E8F6EA /* PrivateClickMeasurementCocoa.mm */; };
 		57F4AAA0208FAEF000A68E9E /* SSLKeyGenerator.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57F4AA9F208FA83D00A68E9E /* SSLKeyGenerator.mm */; };
 		57F56A5C1C7F8CC100F31D7E /* IsNavigationActionTrusted.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 57F56A5B1C7F8A4000F31D7E /* IsNavigationActionTrusted.html */; };
 		5C0160C121A132460077FA32 /* JITEnabled.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C0160C021A132320077FA32 /* JITEnabled.mm */; };
@@ -2233,6 +2234,7 @@
 		57EDFC5B245A18F500959521 /* web-authentication-make-credential-la-no-mock.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-la-no-mock.html"; sourceTree = "<group>"; };
 		57EDFC5F245A279900959521 /* web-authentication-get-assertion-la-no-mock.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-get-assertion-la-no-mock.html"; sourceTree = "<group>"; };
 		57F10D921C7E7B3800ECDF30 /* IsNavigationActionTrusted.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IsNavigationActionTrusted.mm; sourceTree = "<group>"; };
+		57F1C91025DDD51900E8F6EA /* PrivateClickMeasurementCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PrivateClickMeasurementCocoa.mm; sourceTree = "<group>"; };
 		57F4AA9F208FA83D00A68E9E /* SSLKeyGenerator.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SSLKeyGenerator.mm; sourceTree = "<group>"; };
 		57F56A5B1C7F8A4000F31D7E /* IsNavigationActionTrusted.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = IsNavigationActionTrusted.html; sourceTree = "<group>"; };
 		5C0160C021A132320077FA32 /* JITEnabled.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = JITEnabled.mm; sourceTree = "<group>"; };
@@ -4711,6 +4713,7 @@
 			children = (
 				0711DF51226A95FB003DD2F7 /* AVFoundationSoftLinkTest.mm */,
 				751B05D51F8EAC1A0028A09E /* DatabaseTrackerTest.mm */,
+				57F1C91025DDD51900E8F6EA /* PrivateClickMeasurementCocoa.mm */,
 				5769C50A1D9B0001000847FB /* SerializedCryptoKeyWrap.mm */,
 				A17991861E1C994E00A505ED /* SharedBuffer.mm */,
 				CD89D0381C4EDB2A00040A04 /* WebCoreNSURLSession.mm */,
@@ -5486,6 +5489,7 @@
 				A1EC11881F42541200D0146E /* PreviewConverter.cpp in Sources */,
 				7CCE7F0C1A411AE600447C4C /* PrivateBrowsingPushStateNoHistoryCallback.cpp in Sources */,
 				6B0A07F721FA9C2B00D57391 /* PrivateClickMeasurement.cpp in Sources */,
+				57F1C91125DDD51900E8F6EA /* PrivateClickMeasurementCocoa.mm in Sources */,
 				4647B1261EBA3B850041D7EF /* ProcessDidTerminate.cpp in Sources */,
 				41882F0321010C0D002FF288 /* ProcessPreWarming.mm in Sources */,
 				CDA4438E21F7A47700379489 /* ProcessSuspendMediaBuffering.mm in Sources */,

Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/PrivateClickMeasurement.cpp (273166 => 273167)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/PrivateClickMeasurement.cpp	2021-02-19 23:01:20 UTC (rev 273166)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/PrivateClickMeasurement.cpp	2021-02-19 23:15:22 UTC (rev 273167)
@@ -24,6 +24,7 @@
  */
 
 #include "config.h"
+#include "Test.h"
 
 #include <WebCore/PrivateClickMeasurement.h>
 #include <wtf/URL.h>
@@ -300,4 +301,25 @@
     ASSERT_FALSE(ephemeralNonce.isValid());
 }
 
+#if HAVE(RSA_BSSA)
+TEST(PrivateClickMeasurement, InvalidBlindedSecret)
+{
+    const char serverPublicKeyBase64URL[] = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzb1dThrtYwVh46SjInegKhAqpbJwm1XnTBCvybSK8zk53R0Am1hG33AVF5J1lqYf36wp663GasclHtqzvxFZIvDA1DUSH4aZz_fDHCTTxEeJVPORS3zNN2UjWwbtnwsh4BmDTi-z_cDn0LAz2JuZyKlyFt5GgVLAQvL9H3VLHU9_XHNK-uboyXfcHRTtrDnpu3c6wvX5dd-AJoLmIQTZBEJfVkxBGznk1qKHjc6nASAirKF_wJCnuwAK8C6BAcjNcwUWCeKp0YECzCXU--JXd2OEU-QhxPC67faiDOh3V0vlfqZLtrlbnanUCKrvhw7GaGOGYotIrnZtuNfxC14d_XNVd1FS8nHjRTHnEgw_jnlSssfgStz0uJtcmkfgoJBvOE4mIRpi7iSlRfXNkKsWX1J-gwcnCVo5u0uJEW6X6NyvEGYJ8w5BPfwsQuK9y-4Z7ikt9IOucEHY7ThDmi9TNNhHBVj0Gu4wGoSjq3a6vL5N10ZSHXoq1XgfGPrmHhhL90cjvWonoyOXsUqlXEzTjD2W9897Q-Mx9BUNrGQPqmIx8F5MwxWcOrye8WRp4Q88n2YSUnV7C8ayld3v1Fh7N5jeSqeVmtDVRYTn2sVfNqgXrzgdigJcQR8vFENu6nzFPwsrXPMaCiLUnZNUmQ1ZSLQeQyhYXxHqRJrnuCDWXLkCAwEAAQ";
+
+    PrivateClickMeasurement pcm;
+    auto sourceSecretToken = pcm.tokenSignatureJSON(serverPublicKeyBase64URL);
+    EXPECT_EQ(sourceSecretToken->asObject()->size(), 0ul);
+
+    auto ephemeralNonce = PrivateClickMeasurement::EphemeralSourceNonce { "ABCDEFabcdef0123456789"_s };
+    EXPECT_TRUE(ephemeralNonce.isValid());
+    pcm.setEphemeralSourceNonce(WTFMove(ephemeralNonce));
+
+    sourceSecretToken = pcm.tokenSignatureJSON(serverPublicKeyBase64URL);
+    EXPECT_EQ(sourceSecretToken->asObject()->size(), 4ul);
+
+    auto persistentToken = pcm.calculateSourceUnlinkableToken(emptyString());
+    EXPECT_FALSE(persistentToken);
+}
+#endif
+
 } // namespace TestWebKitAPI

Added: trunk/Tools/TestWebKitAPI/Tests/WebCore/cocoa/PrivateClickMeasurementCocoa.mm (0 => 273167)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/cocoa/PrivateClickMeasurementCocoa.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/cocoa/PrivateClickMeasurementCocoa.mm	2021-02-19 23:15:22 UTC (rev 273167)
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include "config.h"
+#include "Test.h"
+
+#if HAVE(RSA_BSSA)
+
+#include <Security/SecKeyPriv.h>
+#include <WebCore/PrivateClickMeasurement.h>
+
+extern "C" {
+#include <corecrypto/cc_priv.h>
+#include <corecrypto/ccrng.h>
+#include <corecrypto/ccrsa.h>
+#include <corecrypto/ccrsabssa.h>
+}
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+TEST(PrivateClickMeasurement, ValidBlindedSecret)
+{
+    auto ephemeralNonce = PrivateClickMeasurement::EphemeralSourceNonce { "ABCDEFabcdef0123456789"_s };
+    EXPECT_TRUE(ephemeralNonce.isValid());
+
+    PrivateClickMeasurement pcm;
+    pcm.setEphemeralSourceNonce(WTFMove(ephemeralNonce));
+
+    // Generate the server key pair.
+    size_t modulusNBits = 4096;
+    int error = 0;
+
+    struct ccrng_state* rng = ccrng(&error);
+    EXPECT_EQ(error, CCERR_OK);
+
+    const uint8_t e[] = { 0x1, 0x00, 0x01 };
+    ccrsa_full_ctx_decl(ccn_sizeof(modulusNBits), rsaPrivateKey);
+    error = ccrsa_generate_key(modulusNBits, rsaPrivateKey, sizeof(e), e, rng);
+    EXPECT_EQ(error, CCERR_OK);
+
+    ccrsa_pub_ctx_t rsaPublicKey = ccrsa_ctx_public(rsaPrivateKey);
+    size_t modulusNBytes = cc_ceiling(ccrsa_pubkeylength(rsaPublicKey), 8);
+
+    const struct ccrsabssa_ciphersuite *ciphersuite = &ccrsabssa_ciphersuite_rsa4096_sha384;
+
+    size_t exportSize = ccder_encode_rsa_pub_size(rsaPublicKey);
+    auto publicKey = adoptNS([[NSMutableData alloc] initWithLength:exportSize]);
+    ccder_encode_rsa_pub(rsaPublicKey, static_cast<uint8_t*>([publicKey mutableBytes]), static_cast<uint8_t*>([publicKey mutableBytes]) + [publicKey length]);
+
+    auto secKey = adoptCF(SecKeyCreateWithData((__bridge CFDataRef)publicKey.get(), (__bridge CFDictionaryRef)@{
+        (__bridge id)kSecAttrKeyType: (__bridge id)kSecAttrKeyTypeRSA,
+        (__bridge id)kSecAttrKeyClass: (__bridge id)kSecAttrKeyClassPublic
+    }, nil));
+    EXPECT_NOT_NULL(secKey);
+
+    auto spkiData = adoptCF(SecKeyCopySubjectPublicKeyInfo(secKey.get()));
+    auto *nsSpkiData = (__bridge NSData *)spkiData.get();
+
+    // Continue the test.
+    auto sourceSecretToken = pcm.tokenSignatureJSON(WTF::base64URLEncode(nsSpkiData.bytes, nsSpkiData.length));
+    EXPECT_EQ(sourceSecretToken->asObject()->size(), 4ul);
+    EXPECT_STREQ(sourceSecretToken->getString("source_engagement_type"_s).utf8().data(), "click");
+    EXPECT_STREQ(sourceSecretToken->getString("source_nonce"_s).utf8().data(), "ABCDEFabcdef0123456789");
+    EXPECT_FALSE(sourceSecretToken->getString("source_secret_token"_s).isEmpty());
+    EXPECT_EQ(sourceSecretToken->getInteger("version"_s), 2);
+
+    // Generate the signature.
+    Vector<uint8_t> blindedMessage;
+    base64URLDecode(sourceSecretToken->getString("source_secret_token"_s), blindedMessage);
+
+    auto blindedSignature = adoptNS([[NSMutableData alloc] initWithLength: modulusNBytes]);
+    ccrsabssa_sign_blinded_message(ciphersuite, rsaPrivateKey, blindedMessage.data(), blindedMessage.size(), static_cast<uint8_t *>([blindedSignature mutableBytes]), [blindedSignature length], rng);
+
+    // Continue the test.
+    auto persistentToken = pcm.calculateSourceUnlinkableToken(WTF::base64URLEncode([blindedSignature bytes], [blindedSignature length]));
+    EXPECT_TRUE(persistentToken);
+    EXPECT_FALSE(persistentToken->tokenBase64URL.isEmpty());
+    EXPECT_FALSE(persistentToken->keyIDBase64URL.isEmpty());
+    EXPECT_FALSE(persistentToken->signatureBase64URL.isEmpty());
+}
+
+} // namespace TestWebKitAPI
+
+#endif // EHAVE(RSA_BSSA)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to