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)