Title: [269830] trunk
Revision
269830
Author
[email protected]
Date
2020-11-15 09:59:54 -0800 (Sun, 15 Nov 2020)

Log Message

Add a WebRTC SFrame transform
https://bugs.webkit.org/show_bug.cgi?id=218752

Reviewed by Eric Carlson.

Source/WebCore:

Introduce a RTCRtpSFrameTransform that implements the SFrame format.
RTCRtpSFrameTransform is a RTCRtpTransform that can be set to RTCRtp sender and receiver objects.
API supports setting encryption key.
Minor refactoring to reuse WebCrypto routines for encryption/decryption.

Test: webrtc/audio-sframe.html

* DerivedSources-input.xcfilelist:
* DerivedSources-output.xcfilelist:
* DerivedSources.make:
* Modules/mediastream/RTCRtpSFrameTransform.cpp: Added.
(WebCore::RTCRtpSFrameTransform::RTCRtpSFrameTransform):
(WebCore::RTCRtpSFrameTransform::~RTCRtpSFrameTransform):
(WebCore::RTCRtpSFrameTransform::setEncryptionKey):
(WebCore::RTCRtpSFrameTransform::initializeTransformer):
(WebCore::RTCRtpSFrameTransform::initializeBackendForReceiver):
(WebCore::RTCRtpSFrameTransform::initializeBackendForSender):
(WebCore::RTCRtpSFrameTransform::willClearBackend):
* Modules/mediastream/RTCRtpSFrameTransform.h: Added.
* Modules/mediastream/RTCRtpSFrameTransform.idl: Added.
* Modules/mediastream/RTCRtpSFrameTransformer.cpp: Added.
(WebCore::writeUInt64):
(WebCore::lengthOfUInt64):
(WebCore::computeFirstHeaderByte):
(WebCore::computeIV):
(WebCore::parseSFrameHeader):
(WebCore::RTCRtpSFrameTransformer::create):
(WebCore::RTCRtpSFrameTransformer::RTCRtpSFrameTransformer):
(WebCore::RTCRtpSFrameTransformer::~RTCRtpSFrameTransformer):
(WebCore::RTCRtpSFrameTransformer::setEncryptionKey):
(WebCore::RTCRtpSFrameTransformer::decryptFrame):
(WebCore::RTCRtpSFrameTransformer::encryptFrame):
(WebCore::RTCRtpSFrameTransformer::transform):
(WebCore::RTCRtpSFrameTransformer::computeSaltKey):
(WebCore::RTCRtpSFrameTransformer::computeAuthenticationKey):
(WebCore::RTCRtpSFrameTransformer::computeEncryptionKey):
(WebCore::RTCRtpSFrameTransformer::decryptData):
(WebCore::RTCRtpSFrameTransformer::encryptData):
(WebCore::RTCRtpSFrameTransformer::computeEncryptedDataSignature):
* Modules/mediastream/RTCRtpSFrameTransformer.h: Added.
(WebCore::RTCRtpSFrameTransformer::setIsSending):
(WebCore::RTCRtpSFrameTransformer::setIsProcessingAudio):
* Modules/mediastream/RTCRtpSFrameTransformerCocoa.cpp: Added.
(WebCore::deriveHDKFSHA256Bits):
(WebCore::transformAES_CTR):
(WebCore::RTCRtpSFrameTransformer::computeSaltKey):
(WebCore::RTCRtpSFrameTransformer::computeAuthenticationKey):
(WebCore::RTCRtpSFrameTransformer::computeEncryptionKey):
(WebCore::RTCRtpSFrameTransformer::decryptData):
(WebCore::RTCRtpSFrameTransformer::encryptData):
(WebCore::RTCRtpSFrameTransformer::computeEncryptedDataSignature):
* Sources.txt:
* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:
* WebCore.xcodeproj/project.pbxproj:
* crypto/mac/CryptoAlgorithmAES_CTRMac.cpp:
(WebCore::CryptoAlgorithmAES_CTR::platformEncrypt):
(WebCore::CryptoAlgorithmAES_CTR::platformDecrypt):
(WebCore::transformAES_CTR): Deleted.
* crypto/mac/CryptoAlgorithmHKDFMac.cpp:
(WebCore::CryptoAlgorithmHKDF::platformDeriveBits):
* crypto/mac/CryptoUtilitiesCocoa.cpp: Added.
(WebCore::transformAES_CTR):
(WebCore::deriveHDKFSHA256Bits):
* crypto/mac/CryptoUtilitiesCocoa.h: Added.
* bindings/js/WebCoreBuiltinNames.h:

Tools:

Add unit tests that validate SFrame generation and parsing.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp: Added.
(TestWebKitAPI::getRawKey):
(TestWebKitAPI::createVideoTransformer):
(TestWebKitAPI::checkVectorsAreEqual):
(TestWebKitAPI::TEST):

LayoutTests:

* webrtc/audio-sframe-expected.txt: Added.
* webrtc/audio-sframe.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (269829 => 269830)


--- trunk/LayoutTests/ChangeLog	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/LayoutTests/ChangeLog	2020-11-15 17:59:54 UTC (rev 269830)
@@ -1,3 +1,13 @@
+2020-11-15  Youenn Fablet  <[email protected]>
+
+        Add a WebRTC SFrame transform
+        https://bugs.webkit.org/show_bug.cgi?id=218752
+
+        Reviewed by Eric Carlson.
+
+        * webrtc/audio-sframe-expected.txt: Added.
+        * webrtc/audio-sframe.html: Added.
+
 2020-11-15  Philippe Normand  <[email protected]>
 
         [GStreamer] WebAudio to MediaStream support

Added: trunk/LayoutTests/webrtc/audio-sframe-expected.txt (0 => 269830)


--- trunk/LayoutTests/webrtc/audio-sframe-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/webrtc/audio-sframe-expected.txt	2020-11-15 17:59:54 UTC (rev 269830)
@@ -0,0 +1,4 @@
+
+
+PASS Audio exchange with SFrame
+

Added: trunk/LayoutTests/webrtc/audio-sframe.html (0 => 269830)


--- trunk/LayoutTests/webrtc/audio-sframe.html	                        (rev 0)
+++ trunk/LayoutTests/webrtc/audio-sframe.html	2020-11-15 17:59:54 UTC (rev 269830)
@@ -0,0 +1,50 @@
+<!doctype html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <script src=""
+        <script src=""
+    </head>
+    <body>
+        <video id="audio" autoplay playsInline></video>
+        <script src =""
+        <script>
+promise_test(async (test) => {
+    let sender, receiver;
+    const localStream = await navigator.mediaDevices.getUserMedia({audio: true});
+    const key = await crypto.subtle.importKey("raw", new Uint8Array([143, 77, 43, 10, 72, 19, 37, 67, 236, 219, 24, 93, 26, 165, 91, 178]), "HKDF", false, ["deriveBits", "deriveKey"]);
+    const stream = await new Promise((resolve, reject) => {
+        createConnections((firstConnection) => {
+            sender = firstConnection.addTrack(localStream.getAudioTracks()[0], localStream);
+            let transform = new RTCRtpSFrameTransform;
+            transform.setEncryptionKey(key);
+            sender.transform = transform;
+        }, (secondConnection) => {
+            secondConnection._ontrack_ = (trackEvent) => {
+                let transform = new RTCRtpSFrameTransform;
+                transform.setEncryptionKey(key);
+                receiver = trackEvent.receiver;
+                receiver.transform = transform;
+                resolve(trackEvent.streams[0]);
+            };
+        });
+        setTimeout(() => reject("Test timed out"), 5000);
+    });
+
+    audio.srcObject = stream;
+    await audio.play();
+
+    if (window.internals) {
+        const senderCounter = internals.sframeCounter(sender.transform);
+        const receiverCounter = internals.sframeCounter(receiver.transform);
+
+        let counter = 0;
+        while (receiverCounter === internals.sframeCounter(receiver.transform) && ++counter < 100)
+            await new Promise(resolve => setTimeout(resolve, 50));
+        assert_not_equals(internals.sframeCounter(receiver.transform), receiverCounter, "receiver");
+        assert_not_equals(internals.sframeCounter(sender.transform), senderCounter, "sender");
+    }
+}, "Audio exchange with SFrame");
+        </script>
+    </body>
+</html>

Modified: trunk/Source/WebCore/CMakeLists.txt (269829 => 269830)


--- trunk/Source/WebCore/CMakeLists.txt	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/CMakeLists.txt	2020-11-15 17:59:54 UTC (rev 269830)
@@ -402,6 +402,7 @@
     Modules/mediastream/RTCRtpReceiver+Transform.idl
     Modules/mediastream/RTCRtpReceiver.idl
     Modules/mediastream/RTCRtpRtxParameters.idl
+    Modules/mediastream/RTCRtpSFrameTransform.idl
     Modules/mediastream/RTCRtpSendParameters.idl
     Modules/mediastream/RTCRtpSender+Transform.idl
     Modules/mediastream/RTCRtpSender.idl

Modified: trunk/Source/WebCore/ChangeLog (269829 => 269830)


--- trunk/Source/WebCore/ChangeLog	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/ChangeLog	2020-11-15 17:59:54 UTC (rev 269830)
@@ -1,5 +1,79 @@
 2020-11-15  Youenn Fablet  <[email protected]>
 
+        Add a WebRTC SFrame transform
+        https://bugs.webkit.org/show_bug.cgi?id=218752
+
+        Reviewed by Eric Carlson.
+
+        Introduce a RTCRtpSFrameTransform that implements the SFrame format.
+        RTCRtpSFrameTransform is a RTCRtpTransform that can be set to RTCRtp sender and receiver objects.
+        API supports setting encryption key.
+        Minor refactoring to reuse WebCrypto routines for encryption/decryption.
+
+        Test: webrtc/audio-sframe.html
+
+        * DerivedSources-input.xcfilelist:
+        * DerivedSources-output.xcfilelist:
+        * DerivedSources.make:
+        * Modules/mediastream/RTCRtpSFrameTransform.cpp: Added.
+        (WebCore::RTCRtpSFrameTransform::RTCRtpSFrameTransform):
+        (WebCore::RTCRtpSFrameTransform::~RTCRtpSFrameTransform):
+        (WebCore::RTCRtpSFrameTransform::setEncryptionKey):
+        (WebCore::RTCRtpSFrameTransform::initializeTransformer):
+        (WebCore::RTCRtpSFrameTransform::initializeBackendForReceiver):
+        (WebCore::RTCRtpSFrameTransform::initializeBackendForSender):
+        (WebCore::RTCRtpSFrameTransform::willClearBackend):
+        * Modules/mediastream/RTCRtpSFrameTransform.h: Added.
+        * Modules/mediastream/RTCRtpSFrameTransform.idl: Added.
+        * Modules/mediastream/RTCRtpSFrameTransformer.cpp: Added.
+        (WebCore::writeUInt64):
+        (WebCore::lengthOfUInt64):
+        (WebCore::computeFirstHeaderByte):
+        (WebCore::computeIV):
+        (WebCore::parseSFrameHeader):
+        (WebCore::RTCRtpSFrameTransformer::create):
+        (WebCore::RTCRtpSFrameTransformer::RTCRtpSFrameTransformer):
+        (WebCore::RTCRtpSFrameTransformer::~RTCRtpSFrameTransformer):
+        (WebCore::RTCRtpSFrameTransformer::setEncryptionKey):
+        (WebCore::RTCRtpSFrameTransformer::decryptFrame):
+        (WebCore::RTCRtpSFrameTransformer::encryptFrame):
+        (WebCore::RTCRtpSFrameTransformer::transform):
+        (WebCore::RTCRtpSFrameTransformer::computeSaltKey):
+        (WebCore::RTCRtpSFrameTransformer::computeAuthenticationKey):
+        (WebCore::RTCRtpSFrameTransformer::computeEncryptionKey):
+        (WebCore::RTCRtpSFrameTransformer::decryptData):
+        (WebCore::RTCRtpSFrameTransformer::encryptData):
+        (WebCore::RTCRtpSFrameTransformer::computeEncryptedDataSignature):
+        * Modules/mediastream/RTCRtpSFrameTransformer.h: Added.
+        (WebCore::RTCRtpSFrameTransformer::setIsSending):
+        (WebCore::RTCRtpSFrameTransformer::setIsProcessingAudio):
+        * Modules/mediastream/RTCRtpSFrameTransformerCocoa.cpp: Added.
+        (WebCore::deriveHDKFSHA256Bits):
+        (WebCore::transformAES_CTR):
+        (WebCore::RTCRtpSFrameTransformer::computeSaltKey):
+        (WebCore::RTCRtpSFrameTransformer::computeAuthenticationKey):
+        (WebCore::RTCRtpSFrameTransformer::computeEncryptionKey):
+        (WebCore::RTCRtpSFrameTransformer::decryptData):
+        (WebCore::RTCRtpSFrameTransformer::encryptData):
+        (WebCore::RTCRtpSFrameTransformer::computeEncryptedDataSignature):
+        * Sources.txt:
+        * SourcesCocoa.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * crypto/mac/CryptoAlgorithmAES_CTRMac.cpp:
+        (WebCore::CryptoAlgorithmAES_CTR::platformEncrypt):
+        (WebCore::CryptoAlgorithmAES_CTR::platformDecrypt):
+        (WebCore::transformAES_CTR): Deleted.
+        * crypto/mac/CryptoAlgorithmHKDFMac.cpp:
+        (WebCore::CryptoAlgorithmHKDF::platformDeriveBits):
+        * crypto/mac/CryptoUtilitiesCocoa.cpp: Added.
+        (WebCore::transformAES_CTR):
+        (WebCore::deriveHDKFSHA256Bits):
+        * crypto/mac/CryptoUtilitiesCocoa.h: Added.
+        * bindings/js/WebCoreBuiltinNames.h:
+
+2020-11-15  Youenn Fablet  <[email protected]>
+
         AudioSampleDataSource::pullSamplesInternal does not need to pass its sampleCount parameter as in/out
         https://bugs.webkit.org/show_bug.cgi?id=218899
 

Modified: trunk/Source/WebCore/DerivedSources-input.xcfilelist (269829 => 269830)


--- trunk/Source/WebCore/DerivedSources-input.xcfilelist	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/DerivedSources-input.xcfilelist	2020-11-15 17:59:54 UTC (rev 269830)
@@ -236,6 +236,7 @@
 $(PROJECT_DIR)/Modules/mediastream/RTCRtpReceiver+Transform.idl
 $(PROJECT_DIR)/Modules/mediastream/RTCRtpReceiver.idl
 $(PROJECT_DIR)/Modules/mediastream/RTCRtpRtxParameters.idl
+$(PROJECT_DIR)/Modules/mediastream/RTCRtpSFrameTransform.idl
 $(PROJECT_DIR)/Modules/mediastream/RTCRtpSendParameters.idl
 $(PROJECT_DIR)/Modules/mediastream/RTCRtpSender+Transform.idl
 $(PROJECT_DIR)/Modules/mediastream/RTCRtpSender.idl

Modified: trunk/Source/WebCore/DerivedSources-output.xcfilelist (269829 => 269830)


--- trunk/Source/WebCore/DerivedSources-output.xcfilelist	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/DerivedSources-output.xcfilelist	2020-11-15 17:59:54 UTC (rev 269830)
@@ -1705,6 +1705,8 @@
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpReceiver.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpRtxParameters.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpRtxParameters.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpSFrameTransform.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpSFrameTransform.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpSendParameters.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpSendParameters.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSRTCRtpSender+Transform.cpp

Modified: trunk/Source/WebCore/DerivedSources.make (269829 => 269830)


--- trunk/Source/WebCore/DerivedSources.make	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/DerivedSources.make	2020-11-15 17:59:54 UTC (rev 269830)
@@ -263,6 +263,7 @@
     $(WebCore)/Modules/mediastream/RTCRtpSendParameters.idl \
     $(WebCore)/Modules/mediastream/RTCRtpSender.idl \
     $(WebCore)/Modules/mediastream/RTCRtpSender+Transform.idl \
+    $(WebCore)/Modules/mediastream/RTCRtpSFrameTransform.idl \
     $(WebCore)/Modules/mediastream/RTCRtpSynchronizationSource.idl \
     $(WebCore)/Modules/mediastream/RTCRtpTransceiver.idl \
     $(WebCore)/Modules/mediastream/RTCRtpTransceiverDirection.idl \

Added: trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp (0 => 269830)


--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp	                        (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp	2020-11-15 17:59:54 UTC (rev 269830)
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2020 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. ``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
+ * 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 "RTCRtpSFrameTransform.h"
+
+#if ENABLE(WEB_RTC)
+
+#include "CryptoKeyRaw.h"
+#include "Logging.h"
+#include "RTCRtpSFrameTransformer.h"
+#include "RTCRtpTransformableFrame.h"
+
+namespace WebCore {
+
+RTCRtpSFrameTransform::RTCRtpSFrameTransform()
+    : m_transformer(RTCRtpSFrameTransformer::create())
+{
+}
+
+RTCRtpSFrameTransform::~RTCRtpSFrameTransform()
+{
+}
+
+void RTCRtpSFrameTransform::setEncryptionKey(CryptoKey& key, Optional<uint64_t> keyId, DOMPromiseDeferred<void>&& promise)
+{
+    auto algorithm = key.algorithm();
+    if (!WTF::holds_alternative<CryptoKeyAlgorithm>(algorithm)) {
+        promise.reject(Exception { TypeError, "Invalid key"_s });
+        return;
+    }
+
+    if (WTF::get<CryptoKeyAlgorithm>(algorithm).name != "HKDF") {
+        promise.reject(Exception { TypeError, "Only HKDF is supported"_s });
+        return;
+    }
+
+    auto& rawKey = downcast<CryptoKeyRaw>(key);
+    promise.settle(m_transformer->setEncryptionKey(rawKey.key(), keyId));
+}
+
+uint64_t RTCRtpSFrameTransform::counterForTesting() const
+{
+    return m_transformer->counter();
+}
+
+void RTCRtpSFrameTransform::initializeTransformer(RTCRtpTransformBackend& backend, Side side)
+{
+    m_transformer->setIsSending(side == Side::Sender);
+    m_transformer->setIsProcessingAudio(backend.mediaType() == RTCRtpTransformBackend::MediaType::Audio);
+
+    backend.setTransformableFrameCallback([transformer = m_transformer, backend = makeRef(backend)](auto&& frame) {
+        auto chunk = frame.data();
+        auto result = transformer->transform(chunk.data, chunk.size);
+
+        if (result.hasException()) {
+            RELEASE_LOG_ERROR(WebRTC, "RTCRtpSFrameTransform failed transforming a frame");
+            return;
+        }
+
+        frame.setData({ result.returnValue().data(), result.returnValue().size() });
+
+        backend->processTransformedFrame(WTFMove(frame));
+    });
+}
+
+
+void RTCRtpSFrameTransform::initializeBackendForReceiver(RTCRtpTransformBackend& backend)
+{
+    initializeTransformer(backend, Side::Receiver);
+}
+
+void RTCRtpSFrameTransform::initializeBackendForSender(RTCRtpTransformBackend& backend)
+{
+    initializeTransformer(backend, Side::Sender);
+}
+
+void RTCRtpSFrameTransform::willClearBackend(RTCRtpTransformBackend& backend)
+{
+    backend.clearTransformableFrameCallback();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_RTC)

Copied: trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.h (from rev 269829, trunk/Source/WebCore/testing/MockRTCRtpTransform.idl) (0 => 269830)


--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.h	                        (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.h	2020-11-15 17:59:54 UTC (rev 269830)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 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. ``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
+ * 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 ENABLE(WEB_RTC)
+
+#include "JSDOMPromiseDeferred.h"
+#include "RTCRtpTransform.h"
+
+namespace WebCore {
+
+class CryptoKey;
+class RTCRtpSFrameTransformer;
+
+class RTCRtpSFrameTransform final : public RTCRtpTransform {
+public:
+    static Ref<RTCRtpSFrameTransform> create() { return adoptRef(*new RTCRtpSFrameTransform); }
+    ~RTCRtpSFrameTransform();
+
+    void setEncryptionKey(CryptoKey&, Optional<uint64_t>, DOMPromiseDeferred<void>&&);
+
+    WEBCORE_EXPORT uint64_t counterForTesting() const;
+
+private:
+    RTCRtpSFrameTransform();
+
+    void initializeBackendForReceiver(RTCRtpTransformBackend&) final;
+    void initializeBackendForSender(RTCRtpTransformBackend&) final;
+    void willClearBackend(RTCRtpTransformBackend&) final;
+
+    enum class Side { Sender, Receiver };
+    void initializeTransformer(RTCRtpTransformBackend&, Side);
+
+    Ref<RTCRtpSFrameTransformer> m_transformer;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_RTC)

Copied: trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.idl (from rev 269829, trunk/Source/WebCore/testing/MockRTCRtpTransform.idl) (0 => 269830)


--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.idl	                        (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.idl	2020-11-15 17:59:54 UTC (rev 269830)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 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. ``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
+ * 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.
+ */
+
+[
+    Conditional=WEB_RTC,
+    EnabledBySetting=WebRTCInsertableStreams,
+    ExportMacro=WEBCORE_EXPORT,
+    Exposed=Window,
+    JSGenerateToNativeObject,
+] interface RTCRtpSFrameTransform : RTCRtpTransform {
+    constructor();
+
+    Promise<undefined> setEncryptionKey(CryptoKey key, optional unsigned long long keyID);
+    // FIXME: Add support for missing methods.
+    // Promise<undefined> ratchetEncryptionKey();
+    // Promise<undefined> setSigningKey(CryptoKey key);
+};

Added: trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.cpp (0 => 269830)


--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.cpp	                        (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.cpp	2020-11-15 17:59:54 UTC (rev 269830)
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2020 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. ``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
+ * 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 "RTCRtpSFrameTransformer.h"
+
+#if ENABLE(WEB_RTC)
+
+namespace WebCore {
+
+static inline void writeUInt64(uint8_t* data, uint64_t value, uint8_t valueLength)
+{
+    for (unsigned i = 0; i < valueLength; ++i)
+        *data++ = (value >> ((valueLength - 1 - i) * 8)) & 0xff;
+}
+
+static inline uint64_t readUInt64(const uint8_t* data, size_t size)
+{
+    uint64_t value = 0;
+    while (size--)
+        value = (value << 8) | *data++;
+    return value;
+}
+
+static inline uint8_t lengthOfUInt64(uint64_t value)
+{
+    uint8_t length = 0;
+    do {
+        ++length;
+        value = value >> 8;
+    } while (value);
+    return length;
+}
+
+static inline uint8_t computeFirstHeaderByte(uint64_t keyId, uint64_t counter)
+{
+    uint8_t value = 0;
+    value |= (lengthOfUInt64(counter) - 1) << 4;
+    if (keyId < 8)
+        value |= keyId;
+    else {
+        value |= (lengthOfUInt64(keyId) - 1);
+        value |= 1 << 3;
+    }
+    return value;
+}
+
+static inline Vector<uint8_t> computeIV(uint64_t counter, const Vector<uint8_t>& saltKey)
+{
+    Vector<uint8_t> iv(16);
+    for (unsigned i = 0; i < 8; ++i) {
+        auto value = (counter >> ((7 - i) * 8)) & 0xff;
+        iv[i] = value ^ saltKey[i];
+    }
+    for (unsigned i = 8; i < 16; ++i)
+        iv[i] = saltKey[i];
+    return iv;
+}
+
+static inline bool hasSignature(uint8_t firstByte)
+{
+    return firstByte & 0x80;
+}
+
+static inline bool hasLongKeyLength(uint8_t firstByte)
+{
+    return firstByte & 0x08;
+}
+
+struct SFrameHeaderInfo {
+    uint8_t size;
+    uint64_t keyId;
+    uint64_t counter;
+};
+static inline Optional<SFrameHeaderInfo> parseSFrameHeader(const uint8_t* data, size_t size)
+{
+    auto* start = data;
+
+    uint64_t keyId = 0;
+    uint64_t counter = 0;
+
+    auto firstByte = *data++;
+
+    // Signature bit.
+    if (hasSignature(firstByte))
+        return { };
+
+    size_t counterLength = ((firstByte >> 4) & 0x07) + 1;
+
+    if (size < counterLength + 1)
+        return { };
+
+    if (hasLongKeyLength(firstByte)) {
+        size_t keyLength = (firstByte & 0x07) + 1;
+        if (size < counterLength + keyLength + 1)
+            return { };
+
+        keyId = readUInt64(data, keyLength);
+        data += keyLength;
+
+        counter = readUInt64(data, counterLength);
+        data += counterLength;
+    } else {
+        keyId = firstByte & 0x07;
+        counter = readUInt64(data, counterLength);
+        data += counterLength;
+    }
+    uint8_t headerSize = data - start;
+    return SFrameHeaderInfo { headerSize, keyId, counter };
+}
+
+Ref<RTCRtpSFrameTransformer> RTCRtpSFrameTransformer::create()
+{
+    return adoptRef(*new RTCRtpSFrameTransformer());
+}
+
+RTCRtpSFrameTransformer::RTCRtpSFrameTransformer()
+{
+}
+
+RTCRtpSFrameTransformer::~RTCRtpSFrameTransformer()
+{
+}
+
+ExceptionOr<void> RTCRtpSFrameTransformer::setEncryptionKey(const Vector<uint8_t>& rawKey, Optional<uint64_t> keyId)
+{
+    auto saltKeyResult = computeSaltKey(rawKey);
+    if (saltKeyResult.hasException())
+        return saltKeyResult.releaseException();
+
+    auto authenticationKeyResult = computeAuthenticationKey(rawKey);
+    if (authenticationKeyResult.hasException())
+        return authenticationKeyResult.releaseException();
+
+    auto encryptionKeyResult = computeEncryptionKey(rawKey);
+    if (encryptionKeyResult.hasException())
+        return encryptionKeyResult.releaseException();
+
+    auto locker = holdLock(m_keyLock);
+
+    m_saltKey = saltKeyResult.releaseReturnValue();
+    m_authenticationKey = authenticationKeyResult.releaseReturnValue();
+    m_encryptionKey = encryptionKeyResult.releaseReturnValue();
+
+    if (keyId)
+        m_keyId = *keyId;
+
+    m_hasKey = true;
+    return { };
+}
+
+ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::decryptFrame(const uint8_t* frameData, size_t frameSize)
+{
+    // FIXME: Support signature.
+
+    auto locker = holdLock(m_keyLock);
+
+    auto header = parseSFrameHeader(frameData, frameSize);
+
+    if (!header)
+        return Exception { NotSupportedError };
+
+    if (header->counter <= m_counter && m_counter)
+        return Exception { InvalidStateError };
+    m_counter = header->counter;
+
+    if (header->keyId != m_keyId) {
+        // FIXME: We should search for keys.
+        return Exception { NotSupportedError };
+    }
+
+    // Compute signature
+    auto* transmittedSignature = frameData + frameSize - m_authenticationSize;
+    auto signature = computeEncryptedDataSignature(frameData, frameSize  - m_authenticationSize, m_authenticationKey);
+    for (size_t cptr = 0; cptr < m_authenticationSize; ++cptr) {
+        if (signature[cptr] != transmittedSignature[cptr]) {
+            // FIXME: We should try ratcheting.
+            return Exception { NotSupportedError };
+        }
+    }
+
+    // Decrypt data
+    auto iv = computeIV(m_counter, m_saltKey);
+    auto dataSize = frameSize - header->size - m_authenticationSize;
+    auto result = decryptData(frameData + header->size, dataSize, iv, m_encryptionKey);
+
+    if (result.hasException())
+        return result.releaseException();
+
+    return result.releaseReturnValue();
+}
+
+ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::encryptFrame(const uint8_t* frameData, size_t frameSize)
+{
+    // FIXME: Support signature.
+
+    static const unsigned MaxHeaderSize = 17;
+
+    auto locker = holdLock(m_keyLock);
+
+    auto iv = computeIV(m_counter, m_saltKey);
+
+    Vector<uint8_t> transformedData;
+    transformedData.resize(frameSize + MaxHeaderSize + m_authenticationSize);
+
+    // Fill header.
+    size_t headerSize = 1;
+    transformedData[0] = computeFirstHeaderByte(m_keyId, m_counter);
+    if (m_keyId >= 8) {
+        auto keyIdLength = lengthOfUInt64(m_keyId);
+        writeUInt64(transformedData.data() + headerSize, m_keyId, keyIdLength);
+        headerSize += keyIdLength;
+    }
+    auto counterLength = lengthOfUInt64(m_counter);
+    writeUInt64(transformedData.data() + headerSize, m_counter, counterLength);
+    headerSize += counterLength;
+
+    transformedData.resize(frameSize + headerSize + m_authenticationSize);
+
+    // Fill encrypted data
+    auto encryptedData = encryptData(frameData, frameSize, iv, m_encryptionKey);
+    ASSERT(!encryptedData.hasException());
+    if (encryptedData.hasException())
+        return encryptedData.releaseException();
+
+    std::memcpy(transformedData.data() + headerSize, encryptedData.returnValue().data(), frameSize);
+
+    // Fill signature
+    auto signature = computeEncryptedDataSignature(transformedData.data(), frameSize + headerSize, m_authenticationKey);
+    std::memcpy(transformedData.data() + frameSize + headerSize, signature.data(), m_authenticationSize);
+
+    ++m_counter;
+
+    return transformedData;
+}
+
+ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::transform(const uint8_t* data, size_t size)
+{
+    if (!m_hasKey)
+        return Exception { InvalidStateError };
+
+    return m_isSending ? encryptFrame(data, size) : decryptFrame(data, size);
+}
+
+#if !PLATFORM(COCOA)
+ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::computeSaltKey(const Vector<uint8_t>&)
+{
+    return Exception { NotSupportedError };
+}
+
+ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::computeAuthenticationKey(const Vector<uint8_t>&)
+{
+    return Exception { NotSupportedError };
+}
+
+ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::computeEncryptionKey(const Vector<uint8_t>&)
+{
+    return Exception { NotSupportedError };
+}
+
+ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::decryptData(const uint8_t*, size_t, const Vector<uint8_t>&, const Vector<uint8_t>&)
+{
+    return Exception { NotSupportedError };
+}
+
+ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::encryptData(const uint8_t*, size_t, const Vector<uint8_t>&, const Vector<uint8_t>&)
+{
+    return Exception { NotSupportedError };
+}
+
+Vector<uint8_t> RTCRtpSFrameTransformer::computeEncryptedDataSignature(const uint8_t*, size_t, const Vector<uint8_t>&)
+{
+    return { };
+}
+#endif // !PLATFORM(COCOA)
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_RTC)

Added: trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.h (0 => 269830)


--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.h	                        (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.h	2020-11-15 17:59:54 UTC (rev 269830)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 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 ENABLE(WEB_RTC)
+
+#include "ExceptionOr.h"
+#include <wtf/Lock.h>
+#include <wtf/ThreadSafeRefCounted.h>
+
+namespace WebCore {
+
+class CryptoKey;
+
+class RTCRtpSFrameTransformer : public ThreadSafeRefCounted<RTCRtpSFrameTransformer, WTF::DestructionThread::Main> {
+public:
+    WEBCORE_EXPORT static Ref<RTCRtpSFrameTransformer> create();
+    WEBCORE_EXPORT ~RTCRtpSFrameTransformer();
+
+    void setIsSending(bool);
+    void setIsProcessingAudio(bool);
+
+    WEBCORE_EXPORT ExceptionOr<void> setEncryptionKey(const Vector<uint8_t>& rawKey, Optional<uint64_t>);
+    WEBCORE_EXPORT ExceptionOr<Vector<uint8_t>> transform(const uint8_t*, size_t);
+
+    const Vector<uint8_t>& authenticationKey() const { return m_authenticationKey; }
+    const Vector<uint8_t>& encryptionKey() const { return m_encryptionKey; }
+    const Vector<uint8_t>& saltKey() const { return m_saltKey; }
+
+    uint64_t counter() const { return m_counter; }
+    void setCounter(uint64_t counter) { m_counter = counter; }
+
+private:
+    WEBCORE_EXPORT RTCRtpSFrameTransformer();
+
+    ExceptionOr<Vector<uint8_t>> decryptFrame(const uint8_t*, size_t);
+    ExceptionOr<Vector<uint8_t>> encryptFrame(const uint8_t*, size_t);
+
+    ExceptionOr<Vector<uint8_t>> computeSaltKey(const Vector<uint8_t>&);
+    ExceptionOr<Vector<uint8_t>> computeAuthenticationKey(const Vector<uint8_t>&);
+    ExceptionOr<Vector<uint8_t>> computeEncryptionKey(const Vector<uint8_t>&);
+
+    ExceptionOr<Vector<uint8_t>> encryptData(const uint8_t*, size_t, const Vector<uint8_t>& iv, const Vector<uint8_t>& key);
+    ExceptionOr<Vector<uint8_t>> decryptData(const uint8_t*, size_t, const Vector<uint8_t>& iv, const Vector<uint8_t>& key);
+    Vector<uint8_t> computeEncryptedDataSignature(const uint8_t*, size_t, const Vector<uint8_t>& key);
+
+    Lock m_keyLock;
+    bool m_hasKey { false };
+    Vector<uint8_t> m_authenticationKey;
+    Vector<uint8_t> m_encryptionKey;
+    Vector<uint8_t> m_saltKey;
+
+    bool m_isSending { false };
+    uint64_t m_authenticationSize { 10 };
+    uint64_t m_keyId { 0 };
+    uint64_t m_counter { 0 };
+};
+
+inline void RTCRtpSFrameTransformer::setIsSending(bool isSending)
+{
+    m_isSending = isSending;
+}
+
+inline void RTCRtpSFrameTransformer::setIsProcessingAudio(bool isProcessingAudio)
+{
+    m_authenticationSize = isProcessingAudio ? 4 : 10;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_RTC)

Added: trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformerCocoa.cpp (0 => 269830)


--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformerCocoa.cpp	                        (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformerCocoa.cpp	2020-11-15 17:59:54 UTC (rev 269830)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 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. ``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
+ * 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 "RTCRtpSFrameTransformer.h"
+
+#if ENABLE(WEB_RTC)
+
+#include "CryptoUtilitiesCocoa.h"
+#include <CommonCrypto/CommonCrypto.h>
+
+namespace WebCore {
+
+ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::computeSaltKey(const Vector<uint8_t>& rawKey)
+{
+    uint8_t usage[] = "SFrameSaltKey";
+    return deriveHDKFSHA256Bits(rawKey.data(), 16, rawKey.data() + 16, rawKey.size() - 16, usage, sizeof(usage) - 1, 128);
+}
+
+ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::computeAuthenticationKey(const Vector<uint8_t>& rawKey)
+{
+    uint8_t usage[] = "SFrameAuthenticationKey";
+    return deriveHDKFSHA256Bits(rawKey.data(), 16, rawKey.data() + 16, rawKey.size() - 16, usage, sizeof(usage) - 1, 256);
+}
+
+ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::computeEncryptionKey(const Vector<uint8_t>& rawKey)
+{
+    uint8_t usage[] = "SFrameEncryptionKey";
+    return deriveHDKFSHA256Bits(rawKey.data(), 16, rawKey.data() + 16, rawKey.size() - 16, usage, sizeof(usage) - 1, 128);
+}
+
+ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::decryptData(const uint8_t* data, size_t size, const Vector<uint8_t>& iv, const Vector<uint8_t>& key)
+{
+    return transformAES_CTR(kCCDecrypt, iv, iv.size(), key, data, size);
+}
+
+ExceptionOr<Vector<uint8_t>> RTCRtpSFrameTransformer::encryptData(const uint8_t* data, size_t size, const Vector<uint8_t>& iv, const Vector<uint8_t>& key)
+{
+    return transformAES_CTR(kCCEncrypt, iv, iv.size(), key, data, size);
+}
+
+Vector<uint8_t> RTCRtpSFrameTransformer::computeEncryptedDataSignature(const uint8_t* data, size_t size, const Vector<uint8_t>& key)
+{
+    Vector<uint8_t> result(CC_SHA256_DIGEST_LENGTH);
+    CCHmac(kCCHmacAlgSHA256, key.data(), key.size(), data, size, result.data());
+    return result;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_RTC)

Modified: trunk/Source/WebCore/Sources.txt (269829 => 269830)


--- trunk/Source/WebCore/Sources.txt	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/Sources.txt	2020-11-15 17:59:54 UTC (rev 269830)
@@ -163,6 +163,8 @@
 Modules/mediastream/RTCPeerConnection.cpp
 Modules/mediastream/RTCPeerConnectionIceEvent.cpp
 Modules/mediastream/RTCRtpReceiver.cpp
+Modules/mediastream/RTCRtpSFrameTransform.cpp
+Modules/mediastream/RTCRtpSFrameTransformer.cpp
 Modules/mediastream/RTCRtpSender.cpp
 Modules/mediastream/RTCRtpTransform.cpp
 Modules/mediastream/RTCRtpTransceiver.cpp
@@ -3320,6 +3322,7 @@
 JSRTCRtpParameters.cpp
 JSRTCRtpReceiver.cpp
 JSRTCRtpRtxParameters.cpp
+JSRTCRtpSFrameTransform.cpp
 JSRTCRtpSendParameters.cpp
 JSRTCRtpSender.cpp
 JSRTCRtpSynchronizationSource.cpp

Modified: trunk/Source/WebCore/SourcesCocoa.txt (269829 => 269830)


--- trunk/Source/WebCore/SourcesCocoa.txt	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/SourcesCocoa.txt	2020-11-15 17:59:54 UTC (rev 269830)
@@ -89,6 +89,7 @@
 Modules/applepay/paymentrequest/ApplePayPaymentHandler.cpp
 Modules/async-clipboard/ios/ClipboardImageReaderIOS.mm
 Modules/async-clipboard/mac/ClipboardImageReaderMac.mm
+Modules/mediastream/RTCRtpSFrameTransformerCocoa.cpp
 Modules/plugins/QuickTimePluginReplacement.mm
 Modules/plugins/YouTubePluginReplacement.cpp
 Modules/webdatabase/cocoa/DatabaseManagerCocoa.mm
@@ -128,6 +129,7 @@
 crypto/mac/CryptoKeyECMac.cpp
 crypto/mac/CryptoKeyMac.cpp
 crypto/mac/CryptoKeyRSAMac.cpp
+crypto/mac/CryptoUtilitiesCocoa.cpp
 crypto/mac/SerializedCryptoKeyWrapMac.mm
 dom/DataTransferMac.mm
 dom/ios/MouseEventIOS.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (269829 => 269830)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-11-15 17:59:54 UTC (rev 269830)
@@ -1108,6 +1108,8 @@
 		4181C5D62555C1B900AEB0FF /* MockRTCRtpTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 4181C5D52555C1B900AEB0FF /* MockRTCRtpTransform.h */; };
 		4181C5D72555C49A00AEB0FF /* MockRTCRtpTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4181C5D32555C1B100AEB0FF /* MockRTCRtpTransform.cpp */; };
 		4181C639255AE90F00AEB0FF /* JSMockRTCRtpTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D6F3E921C1F85550061DBE4 /* JSMockRTCRtpTransform.cpp */; };
+		4181C648255B4C2800AEB0FF /* RTCRtpSFrameTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4181C642255B4C2600AEB0FF /* RTCRtpSFrameTransformer.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		4181C64A255B4C2800AEB0FF /* RTCRtpSFrameTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 4181C644255B4C2700AEB0FF /* RTCRtpSFrameTransform.h */; };
 		418205471E53E98C00D62207 /* RTCController.h in Headers */ = {isa = PBXBuildFile; fileRef = 418205451E53C8CD00D62207 /* RTCController.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		41826BF223FB597700B922B1 /* DocumentIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 41826BF123FB597000B922B1 /* DocumentIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		4184F5161EAF05A800F18BF0 /* OrientationNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 4184F5151EAF059800F18BF0 /* OrientationNotifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -7698,6 +7700,12 @@
 		4181C5D32555C1B100AEB0FF /* MockRTCRtpTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MockRTCRtpTransform.cpp; sourceTree = "<group>"; };
 		4181C5D52555C1B900AEB0FF /* MockRTCRtpTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockRTCRtpTransform.h; sourceTree = "<group>"; };
 		4181C636255AE26100AEB0FF /* MockRTCRtpTransform.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = MockRTCRtpTransform.idl; sourceTree = "<group>"; };
+		4181C63F255B4C2500AEB0FF /* RTCRtpSFrameTransformerCocoa.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RTCRtpSFrameTransformerCocoa.cpp; sourceTree = "<group>"; };
+		4181C641255B4C2600AEB0FF /* RTCRtpSFrameTransformer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RTCRtpSFrameTransformer.cpp; sourceTree = "<group>"; };
+		4181C642255B4C2600AEB0FF /* RTCRtpSFrameTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCRtpSFrameTransformer.h; sourceTree = "<group>"; };
+		4181C643255B4C2700AEB0FF /* RTCRtpSFrameTransform.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RTCRtpSFrameTransform.idl; sourceTree = "<group>"; };
+		4181C644255B4C2700AEB0FF /* RTCRtpSFrameTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCRtpSFrameTransform.h; sourceTree = "<group>"; };
+		4181C645255B4C2800AEB0FF /* RTCRtpSFrameTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RTCRtpSFrameTransform.cpp; sourceTree = "<group>"; };
 		418205451E53C8CD00D62207 /* RTCController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTCController.h; sourceTree = "<group>"; };
 		418205481E53EAAD00D62207 /* RTCController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RTCController.cpp; sourceTree = "<group>"; };
 		41826BF123FB597000B922B1 /* DocumentIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentIdentifier.h; sourceTree = "<group>"; };
@@ -7731,6 +7739,8 @@
 		419BC2DC1685329900D64D6D /* VisitedLinkState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VisitedLinkState.cpp; sourceTree = "<group>"; };
 		419BC2DD1685329900D64D6D /* VisitedLinkState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VisitedLinkState.h; sourceTree = "<group>"; };
 		419BE7521BC7F3DB00E1C85B /* WebCoreBuiltinNames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebCoreBuiltinNames.h; sourceTree = "<group>"; };
+		419D9305255E842700DA1984 /* CryptoUtilitiesCocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CryptoUtilitiesCocoa.h; sourceTree = "<group>"; };
+		419D9307255E842800DA1984 /* CryptoUtilitiesCocoa.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CryptoUtilitiesCocoa.cpp; sourceTree = "<group>"; };
 		419FAFAD1ABABCD5005B3572 /* ReadableStreamBYOBReader.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ReadableStreamBYOBReader.idl; sourceTree = "<group>"; };
 		419FAFAD1ABABCD5005B828B /* ReadableStreamDefaultReader.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ReadableStreamDefaultReader.idl; sourceTree = "<group>"; };
 		41A023ED1A39DB7900F722CF /* ReadableStream.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ReadableStream.idl; sourceTree = "<group>"; };
@@ -17088,6 +17098,12 @@
 				413C8B2E2552F27B00E65055 /* RTCRtpSenderWithTransform.h */,
 				414AD3FC2149842000521676 /* RTCRtpSendParameters.h */,
 				414AD3FE2149842000521676 /* RTCRtpSendParameters.idl */,
+				4181C645255B4C2800AEB0FF /* RTCRtpSFrameTransform.cpp */,
+				4181C644255B4C2700AEB0FF /* RTCRtpSFrameTransform.h */,
+				4181C643255B4C2700AEB0FF /* RTCRtpSFrameTransform.idl */,
+				4181C641255B4C2600AEB0FF /* RTCRtpSFrameTransformer.cpp */,
+				4181C642255B4C2600AEB0FF /* RTCRtpSFrameTransformer.h */,
+				4181C63F255B4C2500AEB0FF /* RTCRtpSFrameTransformerCocoa.cpp */,
 				415E1BB62150152A0022DA96 /* RTCRtpSynchronizationSource.h */,
 				415E1BB7215015300022DA96 /* RTCRtpSynchronizationSource.idl */,
 				5E5E2B101CFC3E4B000C0D85 /* RTCRtpTransceiver.cpp */,
@@ -28255,6 +28271,8 @@
 				5750A97A1E69161600705C4A /* CryptoKeyECMac.cpp */,
 				E19AC3F8182566F700349426 /* CryptoKeyMac.cpp */,
 				E164FAA418315E1A00DB4E61 /* CryptoKeyRSAMac.cpp */,
+				419D9307255E842800DA1984 /* CryptoUtilitiesCocoa.cpp */,
+				419D9305255E842700DA1984 /* CryptoUtilitiesCocoa.h */,
 				E18DF33618AAF14D00773E59 /* SerializedCryptoKeyWrapMac.mm */,
 			);
 			path = mac;
@@ -34093,6 +34111,8 @@
 				413C8B352552F27D00E65055 /* RTCRtpReceiverWithTransform.h in Headers */,
 				5E2C43611BCEE3230001E2BC /* RTCRtpSender.h in Headers */,
 				413C8B332552F27D00E65055 /* RTCRtpSenderWithTransform.h in Headers */,
+				4181C64A255B4C2800AEB0FF /* RTCRtpSFrameTransform.h in Headers */,
+				4181C648255B4C2800AEB0FF /* RTCRtpSFrameTransformer.h in Headers */,
 				5E5E2B141CFC3E75000C0D85 /* RTCRtpTransceiver.h in Headers */,
 				31EB54DF1E7DC74400C1623B /* RTCRtpTransceiverDirection.h in Headers */,
 				413C8B342552F27D00E65055 /* RTCRtpTransform.h in Headers */,

Modified: trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h (269829 => 269830)


--- trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h	2020-11-15 17:59:54 UTC (rev 269830)
@@ -219,6 +219,7 @@
     macro(RTCPeerConnection) \
     macro(RTCPeerConnectionIceEvent) \
     macro(RTCRtpReceiver) \
+    macro(RTCRtpSFrameTransform) \
     macro(RTCRtpSender) \
     macro(RTCRtpTransceiver) \
     macro(RTCRtpTransform) \

Modified: trunk/Source/WebCore/crypto/mac/CryptoAlgorithmAES_CTRMac.cpp (269829 => 269830)


--- trunk/Source/WebCore/crypto/mac/CryptoAlgorithmAES_CTRMac.cpp	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/crypto/mac/CryptoAlgorithmAES_CTRMac.cpp	2020-11-15 17:59:54 UTC (rev 269830)
@@ -31,100 +31,23 @@
 
 #include "CryptoAlgorithmAesCtrParams.h"
 #include "CryptoKeyAES.h"
-#include <CommonCrypto/CommonCrypto.h>
+#include "CryptoUtilitiesCocoa.h"
 
 namespace WebCore {
 
-static ExceptionOr<Vector<uint8_t>> transformAES_CTR(CCOperation operation, const Vector<uint8_t>& counter, size_t counterLength, const Vector<uint8_t>& key, const Vector<uint8_t>& data)
-{
-    // FIXME: We should remove the following hack once <rdar://problem/31361050> is fixed.
-    // counter = nonce + counter
-    // CommonCrypto currently can neither reset the counter nor detect overflow once the counter reaches its max value restricted
-    // by the counterLength. It then increments the nonce which should stay same for the whole operation. To remedy this issue,
-    // we detect the overflow ahead and divide the operation into two parts.
-    size_t numberOfBlocks = data.size() % kCCBlockSizeAES128 ? data.size() / kCCBlockSizeAES128 + 1 : data.size() / kCCBlockSizeAES128;
-
-    // Detect loop
-    if (counterLength < sizeof(size_t) * 8 && numberOfBlocks > (static_cast<size_t>(1) << counterLength))
-        return Exception { OperationError };
-
-    // Calculate capacity before overflow
-    CryptoAlgorithmAES_CTR::CounterBlockHelper counterBlockHelper(counter, counterLength);
-    size_t capacity = counterBlockHelper.countToOverflowSaturating();
-
-    // Divide data into two parts if necessary.
-    size_t headSize = data.size();
-    if (capacity < numberOfBlocks)
-        headSize = capacity * kCCBlockSizeAES128;
-
-    // first part: compute the first n=capacity blocks of data if capacity is insufficient. Otherwise, return the result.
-    CCCryptorRef cryptor;
-    CCCryptorStatus status = CCCryptorCreateWithMode(operation, kCCModeCTR, kCCAlgorithmAES128, ccNoPadding, counter.data(), key.data(), key.size(), 0, 0, 0, kCCModeOptionCTR_BE, &cryptor);
-    if (status)
-        return Exception { OperationError };
-
-    Vector<uint8_t> head(CCCryptorGetOutputLength(cryptor, headSize, true));
-
-    size_t bytesWritten;
-    status = CCCryptorUpdate(cryptor, data.data(), headSize, head.data(), head.size(), &bytesWritten);
-    if (status)
-        return Exception { OperationError };
-
-    uint8_t* p = head.data() + bytesWritten;
-    status = CCCryptorFinal(cryptor, p, head.end() - p, &bytesWritten);
-    p += bytesWritten;
-    if (status)
-        return Exception { OperationError };
-
-    ASSERT_WITH_SECURITY_IMPLICATION(p <= head.end());
-    head.shrink(p - head.begin());
-
-    CCCryptorRelease(cryptor);
-
-    if (capacity >= numberOfBlocks)
-        return WTFMove(head);
-
-    // second part: compute the remaining data and append them to the head.
-    // reset counter
-    Vector<uint8_t> remainingCounter = counterBlockHelper.counterVectorAfterOverflow();
-    status = CCCryptorCreateWithMode(operation, kCCModeCTR, kCCAlgorithmAES128, ccNoPadding, remainingCounter.data(), key.data(), key.size(), 0, 0, 0, kCCModeOptionCTR_BE, &cryptor);
-    if (status)
-        return Exception { OperationError };
-
-    size_t tailSize = data.size() - headSize;
-    Vector<uint8_t> tail(CCCryptorGetOutputLength(cryptor, tailSize, true));
-
-    status = CCCryptorUpdate(cryptor, data.data() + headSize, tailSize, tail.data(), tail.size(), &bytesWritten);
-    if (status)
-        return Exception { OperationError };
-
-    p = tail.data() + bytesWritten;
-    status = CCCryptorFinal(cryptor, p, tail.end() - p, &bytesWritten);
-    p += bytesWritten;
-    if (status)
-        return Exception { OperationError };
-
-    ASSERT_WITH_SECURITY_IMPLICATION(p <= tail.end());
-    tail.shrink(p - tail.begin());
-
-    CCCryptorRelease(cryptor);
-
-    head.appendVector(tail);
-    return WTFMove(head);
-}
-
 ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CTR::platformEncrypt(const CryptoAlgorithmAesCtrParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& plainText)
 {
     ASSERT(parameters.counterVector().size() == kCCBlockSizeAES128);
-    return transformAES_CTR(kCCEncrypt, parameters.counterVector(), parameters.length, key.key(), plainText);
+    return transformAES_CTR(kCCEncrypt, parameters.counterVector(), parameters.length, key.key(), plainText.data(), plainText.size());
 }
 
 ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CTR::platformDecrypt(const CryptoAlgorithmAesCtrParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& cipherText)
 {
-      ASSERT(parameters.counterVector().size() == kCCBlockSizeAES128);
-    return transformAES_CTR(kCCDecrypt, parameters.counterVector(), parameters.length, key.key(), cipherText);
+    ASSERT(parameters.counterVector().size() == kCCBlockSizeAES128);
+    return transformAES_CTR(kCCDecrypt, parameters.counterVector(), parameters.length, key.key(), cipherText.data(), cipherText.size());
 }
 
+
 } // namespace WebCore
 
 #endif // ENABLE(WEB_CRYPTO)

Modified: trunk/Source/WebCore/crypto/mac/CryptoAlgorithmHKDFMac.cpp (269829 => 269830)


--- trunk/Source/WebCore/crypto/mac/CryptoAlgorithmHKDFMac.cpp	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/crypto/mac/CryptoAlgorithmHKDFMac.cpp	2020-11-15 17:59:54 UTC (rev 269830)
@@ -28,25 +28,18 @@
 
 #if ENABLE(WEB_CRYPTO)
 
-#include "CommonCryptoUtilities.h"
 #include "CryptoAlgorithmHkdfParams.h"
 #include "CryptoKeyRaw.h"
+#include "CryptoUtilitiesCocoa.h"
 
 namespace WebCore {
 
 ExceptionOr<Vector<uint8_t>> CryptoAlgorithmHKDF::platformDeriveBits(const CryptoAlgorithmHkdfParams& parameters, const CryptoKeyRaw& key, size_t length)
 {
-    Vector<uint8_t> result(length / 8);
     CCDigestAlgorithm digestAlgorithm;
     getCommonCryptoDigestAlgorithm(parameters.hashIdentifier, digestAlgorithm);
 
-    ALLOW_DEPRECATED_DECLARATIONS_BEGIN
-    // <rdar://problem/32439455> Currently, when key data is empty, CCKeyDerivationHMac will bail out.
-    // <rdar://problem/48896021> Reminder: Switch to CCDeriveKey now that CCKeyDerivationHMac is deprecated.
-    if (CCKeyDerivationHMac(kCCKDFAlgorithmHKDF, digestAlgorithm, 0, key.key().data(), key.key().size(), 0, 0, parameters.infoVector().data(), parameters.infoVector().size(), 0, 0, parameters.saltVector().data(), parameters.saltVector().size(), result.data(), result.size()))
-        return Exception { OperationError };
-    ALLOW_DEPRECATED_DECLARATIONS_END
-    return WTFMove(result);
+    return deriveHDKFBits(digestAlgorithm, key.key().data(), key.key().size(), parameters.saltVector().data(), parameters.saltVector().size(), parameters.infoVector().data(), parameters.infoVector().size(), length);
 }
 
 }

Copied: trunk/Source/WebCore/crypto/mac/CryptoUtilitiesCocoa.cpp (from rev 269829, trunk/Source/WebCore/crypto/mac/CryptoAlgorithmAES_CTRMac.cpp) (0 => 269830)


--- trunk/Source/WebCore/crypto/mac/CryptoUtilitiesCocoa.cpp	                        (rev 0)
+++ trunk/Source/WebCore/crypto/mac/CryptoUtilitiesCocoa.cpp	2020-11-15 17:59:54 UTC (rev 269830)
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2020 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 "CryptoUtilitiesCocoa.h"
+
+#if ENABLE(WEB_CRYPTO) || ENABLE(WEB_RTC)
+
+#include "CryptoAlgorithmAES_CTR.h"
+#include <CommonCrypto/CommonCrypto.h>
+
+namespace WebCore {
+
+ExceptionOr<Vector<uint8_t>> transformAES_CTR(CCOperation operation, const Vector<uint8_t>& counter, size_t counterLength, const Vector<uint8_t>& key, const uint8_t* data, size_t dataSize)
+{
+    // FIXME: We should remove the following hack once <rdar://problem/31361050> is fixed.
+    // counter = nonce + counter
+    // CommonCrypto currently can neither reset the counter nor detect overflow once the counter reaches its max value restricted
+    // by the counterLength. It then increments the nonce which should stay same for the whole operation. To remedy this issue,
+    // we detect the overflow ahead and divide the operation into two parts.
+    size_t numberOfBlocks = dataSize % kCCBlockSizeAES128 ? dataSize / kCCBlockSizeAES128 + 1 : dataSize / kCCBlockSizeAES128;
+
+    // Detect loop
+    if (counterLength < sizeof(size_t) * 8 && numberOfBlocks > (static_cast<size_t>(1) << counterLength))
+        return Exception { OperationError };
+
+    // Calculate capacity before overflow
+    CryptoAlgorithmAES_CTR::CounterBlockHelper counterBlockHelper(counter, counterLength);
+    size_t capacity = counterBlockHelper.countToOverflowSaturating();
+
+    // Divide data into two parts if necessary.
+    size_t headSize = dataSize;
+    if (capacity < numberOfBlocks)
+        headSize = capacity * kCCBlockSizeAES128;
+
+    // first part: compute the first n=capacity blocks of data if capacity is insufficient. Otherwise, return the result.
+    CCCryptorRef cryptor;
+    CCCryptorStatus status = CCCryptorCreateWithMode(operation, kCCModeCTR, kCCAlgorithmAES128, ccNoPadding, counter.data(), key.data(), key.size(), 0, 0, 0, kCCModeOptionCTR_BE, &cryptor);
+    if (status)
+        return Exception { OperationError };
+
+    Vector<uint8_t> head(CCCryptorGetOutputLength(cryptor, headSize, true));
+
+    size_t bytesWritten;
+    status = CCCryptorUpdate(cryptor, data, headSize, head.data(), head.size(), &bytesWritten);
+    if (status)
+        return Exception { OperationError };
+
+    uint8_t* p = head.data() + bytesWritten;
+    status = CCCryptorFinal(cryptor, p, head.end() - p, &bytesWritten);
+    p += bytesWritten;
+    if (status)
+        return Exception { OperationError };
+
+    ASSERT_WITH_SECURITY_IMPLICATION(p <= head.end());
+    head.shrink(p - head.begin());
+
+    CCCryptorRelease(cryptor);
+
+    if (capacity >= numberOfBlocks)
+        return WTFMove(head);
+
+    // second part: compute the remaining data and append them to the head.
+    // reset counter
+    Vector<uint8_t> remainingCounter = counterBlockHelper.counterVectorAfterOverflow();
+    status = CCCryptorCreateWithMode(operation, kCCModeCTR, kCCAlgorithmAES128, ccNoPadding, remainingCounter.data(), key.data(), key.size(), 0, 0, 0, kCCModeOptionCTR_BE, &cryptor);
+    if (status)
+        return Exception { OperationError };
+
+    size_t tailSize = dataSize - headSize;
+    Vector<uint8_t> tail(CCCryptorGetOutputLength(cryptor, tailSize, true));
+
+    status = CCCryptorUpdate(cryptor, data + headSize, tailSize, tail.data(), tail.size(), &bytesWritten);
+    if (status)
+        return Exception { OperationError };
+
+    p = tail.data() + bytesWritten;
+    status = CCCryptorFinal(cryptor, p, tail.end() - p, &bytesWritten);
+    p += bytesWritten;
+    if (status)
+        return Exception { OperationError };
+
+    ASSERT_WITH_SECURITY_IMPLICATION(p <= tail.end());
+    tail.shrink(p - tail.begin());
+
+    CCCryptorRelease(cryptor);
+
+    head.appendVector(tail);
+    return WTFMove(head);
+}
+
+ExceptionOr<Vector<uint8_t>> deriveHDKFBits(CCDigestAlgorithm digestAlgorithm, const uint8_t* key, size_t keySize, const uint8_t* salt, size_t saltSize, const uint8_t* info, size_t infoSize, size_t length)
+{
+    Vector<uint8_t> result(length / 8);
+    Vector<uint8_t> infoVector;
+
+    ALLOW_DEPRECATED_DECLARATIONS_BEGIN
+    // <rdar://problem/32439455> Currently, when key data is empty, CCKeyDerivationHMac will bail out.
+    // <rdar://problem/48896021> Reminder: Switch to CCDeriveKey now that CCKeyDerivationHMac is deprecated.
+    if (CCKeyDerivationHMac(kCCKDFAlgorithmHKDF, digestAlgorithm, 0, key, keySize, 0, 0, info, infoSize, 0, 0, salt, saltSize, result.data(), result.size()))
+        return Exception { OperationError };
+    ALLOW_DEPRECATED_DECLARATIONS_END
+    return WTFMove(result);
+}
+
+ExceptionOr<Vector<uint8_t>> deriveHDKFSHA256Bits(const uint8_t* key, size_t keySize, const uint8_t* salt, size_t saltSize, const uint8_t* info, size_t infoSize, size_t length)
+{
+    return deriveHDKFBits(kCCDigestSHA256, key, keySize, salt, saltSize, info, infoSize, length);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_CRYPTO)

Copied: trunk/Source/WebCore/crypto/mac/CryptoUtilitiesCocoa.h (from rev 269829, trunk/Source/WebCore/crypto/mac/CryptoAlgorithmHKDFMac.cpp) (0 => 269830)


--- trunk/Source/WebCore/crypto/mac/CryptoUtilitiesCocoa.h	                        (rev 0)
+++ trunk/Source/WebCore/crypto/mac/CryptoUtilitiesCocoa.h	2020-11-15 17:59:54 UTC (rev 269830)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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 ENABLE(WEB_CRYPTO) || ENABLE(WEB_RTC)
+
+#include "ExceptionOr.h"
+#include <wtf/Vector.h>
+
+typedef uint32_t CCDigestAlgorithm;
+typedef uint32_t CCOperation;
+
+namespace WebCore {
+
+ExceptionOr<Vector<uint8_t>> transformAES_CTR(CCOperation, const Vector<uint8_t>& counter, size_t counterLength, const Vector<uint8_t>& key, const uint8_t* data, size_t dataSize);
+ExceptionOr<Vector<uint8_t>> deriveHDKFBits(CCDigestAlgorithm, const uint8_t* key, size_t keySize, const uint8_t* salt, size_t saltSize, const uint8_t* info, size_t infoSize, size_t length);
+ExceptionOr<Vector<uint8_t>> deriveHDKFSHA256Bits(const uint8_t* key, size_t keySize, const uint8_t* salt, size_t saltSize, const uint8_t* info, size_t infoSize, size_t length);
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_CRYPTO) || ENABLE(WEB_RTC)

Modified: trunk/Source/WebCore/testing/Internals.cpp (269829 => 269830)


--- trunk/Source/WebCore/testing/Internals.cpp	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/testing/Internals.cpp	2020-11-15 17:59:54 UTC (rev 269830)
@@ -153,6 +153,7 @@
 #include "PluginData.h"
 #include "PrintContext.h"
 #include "PseudoElement.h"
+#include "RTCRtpSFrameTransform.h"
 #include "Range.h"
 #include "ReadableStream.h"
 #include "RenderEmbeddedObject.h"
@@ -1581,6 +1582,11 @@
     return MockRTCRtpTransform::create();
 }
 
+uint64_t Internals::sframeCounter(const RTCRtpSFrameTransform& transform)
+{
+    return transform.counterForTesting();
+}
+
 void Internals::setEnableWebRTCEncryption(bool value)
 {
 #if USE(LIBWEBRTC)

Modified: trunk/Source/WebCore/testing/Internals.h (269829 => 269830)


--- trunk/Source/WebCore/testing/Internals.h	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/testing/Internals.h	2020-11-15 17:59:54 UTC (rev 269830)
@@ -124,6 +124,10 @@
 class ServiceWorker;
 #endif
 
+#if ENABLE(WEB_RTC)
+class RTCRtpSFrameTransform;
+#endif
+
 #if ENABLE(WEBXR)
 class WebXRTest;
 #endif
@@ -607,6 +611,7 @@
     void setWebRTCVP9Support(bool);
     void setWebRTCVP9VTBSupport(bool);
     Ref<MockRTCRtpTransform> createMockRTCRtpTransform();
+    uint64_t sframeCounter(const RTCRtpSFrameTransform&);
     void setEnableWebRTCEncryption(bool);
     void setUseDTLS10(bool);
     void setUseGPUProcessForWebRTC(bool);

Modified: trunk/Source/WebCore/testing/Internals.idl (269829 => 269830)


--- trunk/Source/WebCore/testing/Internals.idl	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/testing/Internals.idl	2020-11-15 17:59:54 UTC (rev 269830)
@@ -803,6 +803,7 @@
     [Conditional=WEB_RTC] undefined setWebRTCVP9Support(boolean allowed);
     [Conditional=WEB_RTC] undefined setWebRTCVP9VTBSupport(boolean allowed);
     [Conditional=WEB_RTC] MockRTCRtpTransform createMockRTCRtpTransform();
+    [Conditional=WEB_RTC] unsigned long long sframeCounter(RTCRtpSFrameTransform transform);
 
     [Conditional=MEDIA_STREAM] undefined setMockAudioTrackChannelNumber(MediaStreamTrack track, unsigned short count);
     [Conditional=MEDIA_STREAM] undefined setShouldInterruptAudioOnPageVisibilityChange(boolean shouldInterrupt);

Modified: trunk/Source/WebCore/testing/MockRTCRtpTransform.idl (269829 => 269830)


--- trunk/Source/WebCore/testing/MockRTCRtpTransform.idl	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Source/WebCore/testing/MockRTCRtpTransform.idl	2020-11-15 17:59:54 UTC (rev 269830)
@@ -26,6 +26,7 @@
 [
     Conditional=WEB_RTC,
     JSGenerateToJSObject,
+    JSGenerateToNativeObject,
     LegacyNoInterfaceObject,
 ] interface MockRTCRtpTransform : RTCRtpTransform {
     readonly attribute boolean isProcessing;

Modified: trunk/Tools/ChangeLog (269829 => 269830)


--- trunk/Tools/ChangeLog	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Tools/ChangeLog	2020-11-15 17:59:54 UTC (rev 269830)
@@ -1,3 +1,19 @@
+2020-11-15  Youenn Fablet  <[email protected]>
+
+        Add a WebRTC SFrame transform
+        https://bugs.webkit.org/show_bug.cgi?id=218752
+
+        Reviewed by Eric Carlson.
+
+        Add unit tests that validate SFrame generation and parsing.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp: Added.
+        (TestWebKitAPI::getRawKey):
+        (TestWebKitAPI::createVideoTransformer):
+        (TestWebKitAPI::checkVectorsAreEqual):
+        (TestWebKitAPI::TEST):
+
 2020-11-13  Sihui Liu  <[email protected]>
 
         Implement basic permission check for SpeechRecognition

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (269829 => 269830)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2020-11-15 17:47:17 UTC (rev 269829)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2020-11-15 17:59:54 UTC (rev 269830)
@@ -236,6 +236,7 @@
 		4135FB852011FABF00332139 /* libWebCoreTestSupport.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4135FB862011FABF00332139 /* libWebCoreTestSupport.dylib */; };
 		414AD6862285D1C000777F2D /* StorageQuota.mm in Sources */ = {isa = PBXBuildFile; fileRef = 414AD6852285D1B000777F2D /* StorageQuota.mm */; };
 		41661C662355E85E00D33C27 /* getUserMedia-webaudio.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 41661C652355D98B00D33C27 /* getUserMedia-webaudio.html */; };
+		4181C62D255A891100AEB0FF /* RTCRtpSFrameTransformerTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4181C62C255A891100AEB0FF /* RTCRtpSFrameTransformerTests.cpp */; };
 		41848F4424891879000E2588 /* open-window-with-file-url-with-host.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 41848F4324891815000E2588 /* open-window-with-file-url-with-host.html */; };
 		41882F0321010C0D002FF288 /* ProcessPreWarming.mm in Sources */ = {isa = PBXBuildFile; fileRef = 41882F0221010A70002FF288 /* ProcessPreWarming.mm */; };
 		44077BB123144B5000179E2D /* DataDetectorsTestIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 44077BB0231449D200179E2D /* DataDetectorsTestIOS.mm */; };
@@ -1962,6 +1963,7 @@
 		4135FB862011FABF00332139 /* libWebCoreTestSupport.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; path = libWebCoreTestSupport.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
 		414AD6852285D1B000777F2D /* StorageQuota.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = StorageQuota.mm; sourceTree = "<group>"; };
 		41661C652355D98B00D33C27 /* getUserMedia-webaudio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "getUserMedia-webaudio.html"; sourceTree = "<group>"; };
+		4181C62C255A891100AEB0FF /* RTCRtpSFrameTransformerTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RTCRtpSFrameTransformerTests.cpp; sourceTree = "<group>"; };
 		41848F4324891815000E2588 /* open-window-with-file-url-with-host.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "open-window-with-file-url-with-host.html"; sourceTree = "<group>"; };
 		41882F0221010A70002FF288 /* ProcessPreWarming.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ProcessPreWarming.mm; sourceTree = "<group>"; };
 		41973B5C1AF22875006C7B36 /* SharedBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SharedBuffer.cpp; sourceTree = "<group>"; };
@@ -3534,6 +3536,7 @@
 				041A1E33216FFDBC00789E0A /* PublicSuffix.cpp */,
 				6B4E861B2220A5520022F389 /* RegistrableDomain.cpp */,
 				F418BE141F71B7DC001970E6 /* RoundedRectTests.cpp */,
+				4181C62C255A891100AEB0FF /* RTCRtpSFrameTransformerTests.cpp */,
 				CDCFA7A91E45122F00C2433D /* SampleMap.cpp */,
 				CE06DF9A1E1851F200E570C9 /* SecurityOrigin.cpp */,
 				41973B5C1AF22875006C7B36 /* SharedBuffer.cpp */,
@@ -5422,6 +5425,7 @@
 				5CCB10E3213457D800AC5AF0 /* RestoreSessionStateWithoutNavigation.mm in Sources */,
 				46E816F81E79E29C00375ADC /* RestoreStateAfterTermination.mm in Sources */,
 				F418BE151F71B7DC001970E6 /* RoundedRectTests.cpp in Sources */,
+				4181C62D255A891100AEB0FF /* RTCRtpSFrameTransformerTests.cpp in Sources */,
 				A180C0FA1EE67DF000468F47 /* RunOpenPanel.mm in Sources */,
 				F4D2986E20FEE7370092D636 /* RunScriptAfterDocumentLoad.mm in Sources */,
 				5CA985532113CF780057EB6B /* SafeBrowsing.mm in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp (0 => 269830)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp	2020-11-15 17:59:54 UTC (rev 269830)
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2020 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 ENABLE(WEB_RTC)
+
+#include <WebCore/RTCRtpSFrameTransformer.h>
+#include <wtf/Vector.h>
+
+namespace TestWebKitAPI {
+
+Vector<uint8_t> getRawKey()
+{
+    return Vector<uint8_t>::from(
+        249,
+        195,
+        202,
+        159,
+        56,
+        191,
+        103,
+        247,
+        245,
+        213,
+        20,
+        68,
+        67,
+        20,
+        151,
+        185,
+        242,
+        78,
+        176,
+        158,
+        91,
+        205,
+        138,
+        55,
+        176,
+        147,
+        198,
+        243,
+        146,
+        204,
+        243,
+        220
+    );
+}
+
+static Ref<WebCore::RTCRtpSFrameTransformer> createVideoTransformer(bool isSending = true)
+{
+    auto transformer = WebCore::RTCRtpSFrameTransformer::create();
+    transformer->setIsSending(isSending);
+    transformer->setIsProcessingAudio(false);
+
+    auto keyId = Vector<uint8_t>::from(198, 31, 251, 197, 48, 139, 91, 51);
+    uint64_t keyIdValue = 0;
+    for (auto value : keyId)
+        keyIdValue = value + (keyIdValue << 8);
+
+    auto keyResult = transformer->setEncryptionKey(getRawKey(), keyIdValue);
+    EXPECT_FALSE(keyResult.hasException());
+
+    return transformer;
+}
+
+static void checkVectorsAreEqual(const Vector<uint8_t>& computed, const Vector<uint8_t>& expected)
+{
+    EXPECT_EQ(computed.size(), expected.size());
+    for (size_t cptr = 0; cptr < std::min(computed.size(), expected.size()); ++cptr)
+        EXPECT_EQ(computed[cptr], expected[cptr]);
+}
+
+TEST(RTCRtpSFrameTransformer, AuthenticationKey)
+{
+    auto transformer = createVideoTransformer();
+    checkVectorsAreEqual(transformer->authenticationKey(), Vector<uint8_t>::from(
+        92,
+        228,
+        139,
+        195,
+        98,
+        16,
+        4,
+        193,
+        221,
+        248,
+        232,
+        178,
+        135,
+        22,
+        141,
+        150,
+        165,
+        242,
+        73,
+        72,
+        10,
+        197,
+        15,
+        87,
+        181,
+        34,
+        120,
+        71,
+        42,
+        174,
+        131,
+        72
+    ));
+}
+
+TEST(RTCRtpSFrameTransformer, EncryptionKey)
+{
+    auto transformer = createVideoTransformer();
+    checkVectorsAreEqual(transformer->encryptionKey(), Vector<uint8_t>::from(
+        207,
+        251,
+        52,
+        21,
+        101,
+        50,
+        232,
+        48,
+        211,
+        115,
+        11,
+        155,
+        101,
+        116,
+        153,
+        71
+    ));
+}
+
+TEST(RTCRtpSFrameTransformer, SaltKey)
+{
+    auto transformer = createVideoTransformer();
+    checkVectorsAreEqual(transformer->saltKey(), Vector<uint8_t>::from(
+        229,
+        19,
+        42,
+        93,
+        164,
+        103,
+        120,
+        53,
+        25,
+        26,
+        237,
+        204,
+        79,
+        138,
+        138,
+        231
+    ));
+}
+
+TEST(RTCRtpSFrameTransformer, EncryptDecrypt)
+{
+    auto encryptor = createVideoTransformer();
+    auto decryptor = createVideoTransformer(false);
+    auto frame = Vector<uint8_t>::from(135, 89, 51, 166, 248, 129, 157, 111, 190, 134, 220);
+
+    auto encryptedResult = encryptor->transform(frame.data(), frame.size());
+    EXPECT_FALSE(encryptedResult.hasException());
+
+    auto encrypted = encryptedResult.releaseReturnValue();
+    auto decryptedResult = decryptor->transform(encrypted.data(), encrypted.size());
+    EXPECT_FALSE(decryptedResult.hasException());
+
+    checkVectorsAreEqual(decryptedResult.returnValue(), frame);
+}
+
+TEST(RTCRtpSFrameTransformer, EncryptDecryptKeyID0)
+{
+    auto encryptor = createVideoTransformer();
+    encryptor->setEncryptionKey(getRawKey(), 0);
+
+    auto decryptor = createVideoTransformer(false);
+    decryptor->setEncryptionKey(getRawKey(), 0);
+
+    auto frame = Vector<uint8_t>::from(135, 89, 51, 166, 248, 129, 157, 111, 190, 134, 220);
+
+    auto encryptedResult = encryptor->transform(frame.data(), frame.size());
+    EXPECT_FALSE(encryptedResult.hasException());
+
+    auto encrypted = encryptedResult.releaseReturnValue();
+    auto decryptedResult = decryptor->transform(encrypted.data(), encrypted.size());
+    EXPECT_FALSE(decryptedResult.hasException());
+
+    checkVectorsAreEqual(decryptedResult.returnValue(), frame);
+}
+
+TEST(RTCRtpSFrameTransformer, TransformCounter0)
+{
+    auto transformer = createVideoTransformer();
+
+    uint8_t frame1[] = { 135, 89, 51, 166, 248, 129, 157, 111, 190, 134, 220 };
+    auto result = transformer->transform(frame1, sizeof(frame1));
+    EXPECT_FALSE(result.hasException());
+
+    checkVectorsAreEqual(result.releaseReturnValue(), Vector<uint8_t>::from(
+        15,
+        198,
+        31,
+        251,
+        197,
+        48,
+        139,
+        91,
+        51,
+        0,
+        254,
+        171,
+        168,
+        127,
+        158,
+        97,
+        70,
+        4,
+        233,
+        156,
+        134,
+        220,
+        44,
+        50,
+        90,
+        3,
+        68,
+        200,
+        127,
+        223,
+        6
+    ));
+}
+
+TEST(RTCRtpSFrameTransformer, TransformCounter256)
+{
+    auto transformer = createVideoTransformer();
+
+    uint8_t frame1[] = { 8, 164, 189, 18, 61, 117, 132, 43, 117, 169, 42 };
+    WebCore::ExceptionOr<Vector<uint8_t>> result = Vector<uint8_t>();
+    result = transformer->transform(frame1, sizeof(frame1));
+    for (size_t cptr = 0; cptr < 256; ++cptr) {
+        result = transformer->transform(frame1, sizeof(frame1));
+        EXPECT_FALSE(result.hasException());
+    }
+    checkVectorsAreEqual(result.releaseReturnValue(), Vector<uint8_t>::from(
+        31,
+        198,
+        31,
+        251,
+        197,
+        48,
+        139,
+        91,
+        51,
+        1,
+        0,
+        124,
+        218,
+        61,
+        23,
+        78,
+        15,
+        190,
+        35,
+        255,
+        253,
+        120,
+        64,
+        28,
+        183,
+        172,
+        154,
+        144,
+        16,
+        229,
+        87,
+        52
+    ));
+}
+
+TEST(RTCRtpSFrameTransformer, TransformCounter65536)
+{
+    auto transformer = createVideoTransformer();
+    transformer->setCounter(65536);
+
+    uint8_t frame1[] = { 0, 33, 244, 24, 236, 156, 127, 8, 48, 88, 220 };
+    auto result = transformer->transform(frame1, sizeof(frame1));
+    EXPECT_FALSE(result.hasException());
+
+    checkVectorsAreEqual(result.releaseReturnValue(), Vector<uint8_t>::from(
+        47,
+        198,
+        31,
+        251,
+        197,
+        48,
+        139,
+        91,
+        51,
+        1,
+        0,
+        0,
+        98,
+        212,
+        137,
+        244,
+        209,
+        16,
+        89,
+        234,
+        21,
+        171,
+        15,
+        107,
+        50,
+        145,
+        73,
+        107,
+        165,
+        45,
+        190,
+        25,
+        82
+    ));
+}
+
+}
+
+#endif // ENABLE(WEB_RTC)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to