Diff
Modified: trunk/LayoutTests/ChangeLog (275655 => 275656)
--- trunk/LayoutTests/ChangeLog 2021-04-08 08:58:24 UTC (rev 275655)
+++ trunk/LayoutTests/ChangeLog 2021-04-08 10:53:44 UTC (rev 275656)
@@ -1,3 +1,13 @@
+2021-04-08 Youenn Fablet <[email protected]>
+
+ Update SFrame implementation to latest version
+ https://bugs.webkit.org/show_bug.cgi?id=224276
+
+ Reviewed by Eric Carlson.
+
+ * webrtc/sframe-test-vectors-expected.txt: Added.
+ * webrtc/sframe-test-vectors.html: Added.
+
2021-04-07 Julian Gonzalez <[email protected]>
Nullptr dereference in ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline
Added: trunk/LayoutTests/webrtc/sframe-test-vectors-expected.txt (0 => 275656)
--- trunk/LayoutTests/webrtc/sframe-test-vectors-expected.txt (rev 0)
+++ trunk/LayoutTests/webrtc/sframe-test-vectors-expected.txt 2021-04-08 10:53:44 UTC (rev 275656)
@@ -0,0 +1,34 @@
+
+PASS Decryption test 1 for ciphersuite 1
+PASS Encryption/Decryption test 1 for ciphersuite 1
+PASS Decryption test 2 for ciphersuite 1
+PASS Encryption/Decryption test 2 for ciphersuite 1
+PASS Decryption test 3 for ciphersuite 1
+PASS Encryption/Decryption test 3 for ciphersuite 1
+PASS Decryption test 4 for ciphersuite 1
+PASS Encryption/Decryption test 4 for ciphersuite 1
+PASS Decryption test 5 for ciphersuite 1
+PASS Encryption/Decryption test 5 for ciphersuite 1
+PASS Decryption test 6 for ciphersuite 1
+PASS Encryption/Decryption test 6 for ciphersuite 1
+PASS Decryption test 7 for ciphersuite 1
+PASS Encryption/Decryption test 7 for ciphersuite 1
+PASS Decryption test 8 for ciphersuite 1
+PASS Encryption/Decryption test 8 for ciphersuite 1
+PASS Decryption test 1 for ciphersuite 2
+PASS Encryption/Decryption test 1 for ciphersuite 2
+PASS Decryption test 2 for ciphersuite 2
+PASS Encryption/Decryption test 2 for ciphersuite 2
+PASS Decryption test 3 for ciphersuite 2
+PASS Encryption/Decryption test 3 for ciphersuite 2
+PASS Decryption test 4 for ciphersuite 2
+PASS Encryption/Decryption test 4 for ciphersuite 2
+PASS Decryption test 5 for ciphersuite 2
+PASS Encryption/Decryption test 5 for ciphersuite 2
+PASS Decryption test 6 for ciphersuite 2
+PASS Encryption/Decryption test 6 for ciphersuite 2
+PASS Decryption test 7 for ciphersuite 2
+PASS Encryption/Decryption test 7 for ciphersuite 2
+PASS Decryption test 8 for ciphersuite 2
+PASS Encryption/Decryption test 8 for ciphersuite 2
+
Added: trunk/LayoutTests/webrtc/sframe-test-vectors.html (0 => 275656)
--- trunk/LayoutTests/webrtc/sframe-test-vectors.html (rev 0)
+++ trunk/LayoutTests/webrtc/sframe-test-vectors.html 2021-04-08 10:53:44 UTC (rev 275656)
@@ -0,0 +1,225 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>SFrame test vector</title>
+ <script src=""
+ <script src=""
+ </head>
+ <body>
+<script>
+// Tests taken from https://github.com/eomara/sframe/blob/master/test-vectors.json and updated to cope with key/counter length difference.
+// Test suite 1 is AES_CM_128_HMAC_SHA256_4, test suite 2 is AES_CM_128_HMAC_SHA256_8.
+// Test suites 3 and 4 are GCM and not yet added here since not supported.
+const tests = [
+ {
+ "cipher_suite": 1,
+ "base_key": "101112131415161718191a1b1c1d1e1f",
+ "key": "343d3290f5c0b936415bea9a43c6f5a2",
+ "salt": "42d662fbad5cd81eb3aad79a",
+ "plaintext": "46726f6d2068656176656e6c79206861726d6f6e79202f2f205468697320756e6976657273616c206672616d6520626567616e",
+ "encryptions": [
+ {
+ "kid": "7",
+ "ctr": "0",
+ "header": "0700",
+ "nonce": "42d662fbad5cd81eb3aad79a",
+ "ciphertext": "070065c67c6fb784631a7db1b589ffb62d75b78e28b0899e632fbbee3b944747a6382d75b6bd3788dc7b71b9295c7fb90b5098f7ad92befabb"
+ },
+ {
+ "kid": "7",
+ "ctr": "1",
+ "header": "0701",
+ "nonce": "42d662fbad5cd81eb3aad79b",
+ "ciphertext": "0701ec742e98d667be810f153ff0d4dad7969f69b310aa7c6b9cb911e83af09b0f0a6d74772d8195c8c9dae3878fd1cb10edb4176dd4a56026"
+ },
+ {
+ "kid": "7",
+ "ctr": "2",
+ "header": "0702",
+ "nonce": "42d662fbad5cd81eb3aad798",
+ "ciphertext": "0702ac9b495d37a1e48c712ade5cba72df0bf90f24aa022a454cfb92d8b87cd54335fb6b9eeded6a5aa4e2643d7a09946646001d0afd6a2d5f"
+ },
+ {
+ "kid": "15",
+ "ctr": "170",
+ "header": "080faa",
+ "nonce": "42d662fbad5cd81eb3aad730",
+ "ciphertext": "080faaeaa5adc70cae0d6ebd36805fa87d2351dd02c55c751cd351a7fdb7f0927b474eae3e800033e08100a440002da17579678b36dcafb808b3"
+ },
+ {
+ "kid": "511",
+ "ctr": "170",
+ "header": "0901ffaa",
+ "nonce": "42d662fbad5cd81eb3aad730",
+ "ciphertext": "0901ffaaeaa5adc70cae0d6ebd36805fa87d2351dd02c55c751cd351a7fdb7f0927b474eae3e800033e08100a440002da17579678b36dcc0a409c5"
+ },
+ {
+ "kid": "511",
+ "ctr": "543690",
+ "header": "2901ff084bca",
+ "nonce": "42d662fbad5cd81eb3a29c50",
+ "ciphertext": "2901ff084bca99362198463c4739ebe78d4c1158fc7b7e118e8d035130a583744af343a370ab964a76d31aba68939336187bd251a7f63e9ec25a2bed97"
+ },
+ {
+ "kid": "72057594037927935",
+ "ctr": "72057594037927935",
+ "header": "6effffffffffffffffffffffffffff",
+ "nonce": "42d662fbada327e14c552865",
+ "ciphertext": "6effffffffffffffffffffffffffffdca3655d5117bc838d6f4382ca468a4f992ff77bfd1d2f4391be6b33e8fb638dc48aa82f57fd91430c714def0b2089c8bfb2ac6a36e584"
+ },
+ {
+ "kid": "92057594037927935",
+ "ctr": "8",
+ "header": "0f01470de4df81ffff08",
+ "nonce": "42d662fbad5cd81eb3aad792",
+ "ciphertext": "0f01470de4df81ffff084db66f48555956af80a014f06670d7771071afc72ad7452fbb835d353d07d16e771b2ca3593a6a87b643e39370b404a2eb898de8114fb9"
+ }
+ ]
+ },
+ {
+ "cipher_suite": 2,
+ "base_key": "202122232425262728292a2b2c2d2e2f",
+ "key": "3fce747d505e46ec9b92d9f58ee7a5d4",
+ "salt": "77fbf5f1d82c73f6d2b353c9",
+ "plaintext": "46726f6d2068656176656e6c79206861726d6f6e79202f2f205468697320756e6976657273616c206672616d6520626567616e",
+ "encryptions": [
+ {
+ "kid": "7",
+ "ctr": "0",
+ "header": "0700",
+ "nonce": "77fbf5f1d82c73f6d2b353c900000000",
+ "ciphertext": "0700647513fce71aab7fed1e904fd9240343d77092c831f0d58fde0985a0f3e5ba4020e87a7b9c870b5f8f7f628d27690cc1e571e4e8b90ec99c582cfa"
+ },
+ {
+ "kid": "7",
+ "ctr": "1",
+ "header": "0701",
+ "nonce": "77fbf5f1d82c73f6d2b353c8",
+ "ciphertext": "07019e1bdf713b0d4c02f3dbf50a72ea773286e7da38f3872cc734f3e1b1448aab5009b424e05495214f96d02e4e8f8da975cc808fe931237a6ab700e8"
+ },
+ {
+ "kid": "7",
+ "ctr": "2",
+ "header": "0702",
+ "nonce": "77fbf5f1d82c73f6d2b353cb",
+ "ciphertext": "070220ad36fd9191453ace2d36a175ad8a69c1f16b8613d14b4f7ef30c68bc5609e349df38155cc1544d7dbfa079e3faae3c7883b479fccb144b0c78a5"
+ },
+ {
+ "kid": "15",
+ "ctr": "170",
+ "header": "080faa",
+ "nonce": "77fbf5f1d82c73f6d2b35363",
+ "ciphertext": "080faadab9b284a4b9e3aea36b9cdcae4a58e141d3f0f52f240ef80a93dbb8d809ede01b05b2cace18a22fb39c032724481c5baa181d081e260067ccd683"
+ },
+ {
+ "kid": "511",
+ "ctr": "170",
+ "header": "0901ffaa",
+ "nonce": "77fbf5f1d82c73f6d2b35363",
+ "ciphertext": "0901ffaadab9b284a4b9e3aea36b9cdcae4a58e141d3f0f52f240ef80a93dbb8d809ede01b05b2cace18a22fb39c032724481c5baa181dc24facba5e9f7ea5"
+ },
+ {
+ "kid": "511",
+ "ctr": "43690",
+ "header": "1901ffaaaa",
+ "nonce": "77fbf5f1d82c73f6d2b3f963",
+ "ciphertext": "1901ffaaaae0f2384e4dc472cb92238b5b722159205c4481665484de66985f155071655ca4e9d1c998781f8c7d439f8d1eb6f6071cd80fd2af2cd093aa260618"
+ },
+ {
+ "kid": "72057594037927935",
+ "ctr": "72057594037927935",
+ "header": "6effffffffffffffffffffffffffff",
+ "nonce": "77fbf5f1d8d38c092d4cac36",
+ "ciphertext": "6effffffffffffffffffffffffffff4b8c7429d7ee83eec5e53808b80555b1f80b1df9d97877575fa1c7fa35b6119c68ed6543020075959dcc4ca6900a7f9cf1d9366dfcb086029e8966"
+ },
+ {
+ "kid": "92057594037927935",
+ "ctr": "8",
+ "header": "0f01470de4df81ffff08",
+ "nonce": "77fbf5f1d82c73f6d2b353c1",
+ "ciphertext": "0f01470de4df81ffff08aaf4ea538ad99858a76f87b673dd548459dfbf98906fe82ce159ec738363b2af84d39c34418e2c56609d185ef66a3d7ce8d30547c1c9725439ac12"
+ }
+ ]
+ }
+];
+
+function hexaDecodeToUint8Array(encoded)
+{
+ return new Uint8Array(encoded.match(/[\da-f]{2}/gi).map(function (h) {
+ return parseInt(h, 16)
+ }));
+}
+
+function hexaEncodeUint8Array(buffer)
+{
+ return Array.prototype.map.call(new Uint8Array(buffer), x => {
+ return ('00' + x.toString(16)).slice(-2)
+ }).join('');
+}
+
+function numberOrBigIntFromString(string)
+{
+ const value = parseInt(string);
+ if ((''+ value) === string)
+ return string;
+ return BigInt(string);
+}
+
+async function doAESCMTest(testSuite, authenticationSize)
+{
+ let testCounter = 0;
+ const key = await crypto.subtle.importKey("raw", hexaDecodeToUint8Array(testSuite.base_key), "HKDF", false, ["deriveBits", "deriveKey"]);
+
+ for (const encryption of testSuite.encryptions) {
+ testCounter++;
+
+ promise_test(async () => {
+ const transform = new SFrameTransform({ role : 'decrypt', authenticationSize : authenticationSize });
+ transform.setEncryptionKey(key, numberOrBigIntFromString(encryption.kid));
+ const reader = transform.readable.getReader();
+ const writer = transform.writable.getWriter();
+
+ const encryptedData = hexaDecodeToUint8Array(encryption.ciphertext);
+ writer.write(encryptedData.buffer);
+ const decrypted = await reader.read();
+
+ const text = hexaEncodeUint8Array(new Uint8Array(decrypted.value));
+ assert_equals(text, testSuite.plaintext);
+ }, "Decryption test " + testCounter + " for ciphersuite " + testSuite.cipher_suite);
+
+ const plaintextData = hexaDecodeToUint8Array(testSuite.plaintext);
+ promise_test(async () => {
+ const transform1 = new SFrameTransform({ role : 'encrypt', authenticationSize : authenticationSize });
+ const transform2 = new SFrameTransform({ role : 'decrypt', authenticationSize : authenticationSize });
+ transform1.setEncryptionKey(key, numberOrBigIntFromString(encryption.kid));
+ transform2.setEncryptionKey(key, numberOrBigIntFromString(encryption.kid));
+ const reader = transform2.readable.getReader();
+ const writer = transform1.writable.getWriter();
+ transform1.readable.pipeTo(transform2.writable);
+
+ if (window.internals)
+ internals.setSFrameCounter(transform1, encryption.ctr);
+ else {
+ const counter = numberOrBigIntFromString(encryption.ctr);
+ if (typeof counter === "bigint")
+ return;
+ for (let i = 0; i < counter; ++i) {
+ await writer.write(new ArrayBuffer());
+ await reader.read();
+ }
+ }
+
+ writer.write(plaintextData.buffer);
+ const decrypted = await reader.read();
+
+ const text = hexaEncodeUint8Array(new Uint8Array(decrypted.value));
+ assert_equals(text, testSuite.plaintext);
+ }, "Encryption/Decryption test " + testCounter + " for ciphersuite " + testSuite.cipher_suite);
+ }
+}
+doAESCMTest(tests[0], 4);
+doAESCMTest(tests[1], 8);
+</script>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (275655 => 275656)
--- trunk/Source/WebCore/ChangeLog 2021-04-08 08:58:24 UTC (rev 275655)
+++ trunk/Source/WebCore/ChangeLog 2021-04-08 10:53:44 UTC (rev 275656)
@@ -1,3 +1,37 @@
+2021-04-08 Youenn Fablet <[email protected]>
+
+ Update SFrame implementation to latest version
+ https://bugs.webkit.org/show_bug.cgi?id=224276
+
+ Reviewed by Eric Carlson.
+
+ Update implementation according to latest draft at https://github.com/eomara/sframe/blob/master/draft-omara-sframe.md.
+ In particular, we derive keys with new algorithm and the generation of the signature by including header and data length as well as nonce.
+
+ Test: webrtc/sframe-test-vectors.html
+
+ * Modules/mediastream/RTCRtpSFrameTransform.cpp:
+ (WebCore::RTCRtpSFrameTransform::setCounterForTesting):
+ * Modules/mediastream/RTCRtpSFrameTransform.h:
+ * Modules/mediastream/RTCRtpSFrameTransformer.cpp:
+ (WebCore::computeIV):
+ (WebCore::RTCRtpSFrameTransformer::updateEncryptionKey):
+ (WebCore::RTCRtpSFrameTransformer::decryptFrame):
+ (WebCore::RTCRtpSFrameTransformer::encryptFrame):
+ (WebCore::RTCRtpSFrameTransformer::computeEncryptedDataSignature):
+ * Modules/mediastream/RTCRtpSFrameTransformer.h:
+ * Modules/mediastream/RTCRtpSFrameTransformerCocoa.cpp:
+ (WebCore::RTCRtpSFrameTransformer::computeSaltKey):
+ (WebCore::createBaseSFrameKey):
+ (WebCore::RTCRtpSFrameTransformer::computeAuthenticationKey):
+ (WebCore::RTCRtpSFrameTransformer::computeEncryptionKey):
+ (WebCore::encodeBigEndian):
+ (WebCore::RTCRtpSFrameTransformer::computeEncryptedDataSignature):
+ * testing/Internals.cpp:
+ (WebCore::Internals::setSFrameCounter):
+ * testing/Internals.h:
+ * testing/Internals.idl:
+
2021-04-08 Xabier Rodriguez Calvar <[email protected]>
Unreviewed. Fixed build warning.
Modified: trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp (275655 => 275656)
--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp 2021-04-08 08:58:24 UTC (rev 275655)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp 2021-04-08 10:53:44 UTC (rev 275656)
@@ -75,6 +75,11 @@
promise.settle(m_transformer->setEncryptionKey(rawKey.key(), keyId));
}
+void RTCRtpSFrameTransform::setCounterForTesting(uint64_t counter)
+{
+ m_transformer->setCounter(counter);
+}
+
uint64_t RTCRtpSFrameTransform::counterForTesting() const
{
return m_transformer->counter();
Modified: trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.h (275655 => 275656)
--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.h 2021-04-08 08:58:24 UTC (rev 275655)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.h 2021-04-08 10:53:44 UTC (rev 275656)
@@ -63,6 +63,7 @@
void initializeBackendForSender(RTCRtpTransformBackend&);
void willClearBackend(RTCRtpTransformBackend&);
+ WEBCORE_EXPORT void setCounterForTesting(uint64_t);
WEBCORE_EXPORT uint64_t counterForTesting() const;
WEBCORE_EXPORT uint64_t keyIdForTesting() const;
Modified: trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.cpp (275655 => 275656)
--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.cpp 2021-04-08 08:58:24 UTC (rev 275655)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.cpp 2021-04-08 10:53:44 UTC (rev 275656)
@@ -32,6 +32,8 @@
namespace WebCore {
+static constexpr unsigned AES_CM_128_HMAC_SHA256_NONCE_SIZE = 12;
+
static inline void writeUInt64(uint8_t* data, uint64_t value, uint8_t valueLength)
{
for (unsigned i = 0; i < valueLength; ++i)
@@ -71,13 +73,18 @@
static inline Vector<uint8_t> computeIV(uint64_t counter, const Vector<uint8_t>& saltKey)
{
+ // The saltKey is 12 bytes (AES_CM_128_HMAC_SHA256_NONCE_SIZE), we XOR with the counter as 12 bytes.
+ // We then extend it to 16 bytes since that is what is expected by the crypto routines.
Vector<uint8_t> iv(16);
- for (unsigned i = 0; i < 8; ++i) {
- auto value = (counter >> ((7 - i) * 8)) & 0xff;
+ for (unsigned i = 0; i < 4; ++i)
+ iv[i] = saltKey[i];
+ for (unsigned i = 11; i >= 4; --i) {
+ auto value = counter & 0xff;
+ counter = counter >> 8;
iv[i] = value ^ saltKey[i];
}
- for (unsigned i = 8; i < 16; ++i)
- iv[i] = saltKey[i];
+ for (unsigned i = 12; i < 16; ++i)
+ iv[i] = 0;
return iv;
}
@@ -161,7 +168,7 @@
if (saltKeyResult.hasException())
return saltKeyResult.releaseException();
- ASSERT(saltKeyResult.returnValue().size() >= 16);
+ ASSERT(saltKeyResult.returnValue().size() >= AES_CM_128_HMAC_SHA256_NONCE_SIZE);
auto authenticationKeyResult = computeAuthenticationKey(rawKey);
if (authenticationKeyResult.hasException())
@@ -240,9 +247,11 @@
if (frameSize < (header->size + m_authenticationSize))
return Exception { DataError, "Chunk is too small for authentication size" };
+ auto iv = computeIV(m_counter, m_saltKey);
+
// Compute signature
auto* transmittedSignature = frameData + frameSize - m_authenticationSize;
- auto signature = computeEncryptedDataSignature(frameData, frameSize - m_authenticationSize, m_authenticationKey);
+ auto signature = computeEncryptedDataSignature(iv, frameData, header->size, frameData + header->size, frameSize - m_authenticationSize - header->size, m_authenticationKey);
for (size_t cptr = 0; cptr < m_authenticationSize; ++cptr) {
if (signature[cptr] != transmittedSignature[cptr]) {
// FIXME: We should try ratcheting.
@@ -251,7 +260,6 @@
}
// 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);
@@ -311,7 +319,7 @@
std::memcpy(newDataPointer + headerSize, encryptedData.returnValue().data(), frameSize);
// Fill signature
- auto signature = computeEncryptedDataSignature(newDataPointer, frameSize + headerSize, m_authenticationKey);
+ auto signature = computeEncryptedDataSignature(iv, newDataPointer, headerSize, newDataPointer + headerSize, frameSize, m_authenticationKey);
std::memcpy(newDataPointer + frameSize + headerSize, signature.data(), m_authenticationSize);
if (m_compatibilityMode == CompatibilityMode::H264)
@@ -356,7 +364,7 @@
return Exception { NotSupportedError };
}
-Vector<uint8_t> RTCRtpSFrameTransformer::computeEncryptedDataSignature(const uint8_t*, size_t, const Vector<uint8_t>&)
+Vector<uint8_t> RTCRtpSFrameTransformer::computeEncryptedDataSignature(const Vector<uint8_t>&, const uint8_t*, size_t, const uint8_t*, size_t, const Vector<uint8_t>&)
{
return { };
}
Modified: trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.h (275655 => 275656)
--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.h 2021-04-08 08:58:24 UTC (rev 275655)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformer.h 2021-04-08 10:53:44 UTC (rev 275656)
@@ -74,7 +74,7 @@
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);
+ Vector<uint8_t> computeEncryptedDataSignature(const Vector<uint8_t>& nonce, const uint8_t* header, size_t headerSize, const uint8_t* data, size_t dataSize, const Vector<uint8_t>& key);
void updateAuthenticationSize();
Lock m_keyLock;
Modified: trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformerCocoa.cpp (275655 => 275656)
--- trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformerCocoa.cpp 2021-04-08 08:58:24 UTC (rev 275655)
+++ trunk/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransformerCocoa.cpp 2021-04-08 10:53:44 UTC (rev 275656)
@@ -35,20 +35,38 @@
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);
+ uint8_t usage[] = "SFrame10";
+ uint8_t info[] = "salt";
+ return deriveHDKFSHA256Bits(rawKey.data(), 16, usage, sizeof(usage) - 1, info, sizeof(info) - 1, 96);
}
+static ExceptionOr<Vector<uint8_t>> createBaseSFrameKey(const Vector<uint8_t>& rawKey)
+{
+ uint8_t usage[] = "SFrame10";
+ uint8_t info[] = "key";
+ return deriveHDKFSHA256Bits(rawKey.data(), 16, usage, sizeof(usage) - 1, info, sizeof(info) - 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);
+ auto key = createBaseSFrameKey(rawKey);
+ if (key.hasException())
+ return key;
+
+ uint8_t usage[] = "SFrame10 AES CM AEAD";
+ uint8_t info[] = "auth";
+ return deriveHDKFSHA256Bits(key.returnValue().data(), 16, usage, sizeof(usage) - 1, info, sizeof(info) - 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);
+ auto key = createBaseSFrameKey(rawKey);
+ if (key.hasException())
+ return key;
+
+ uint8_t usage[] = "SFrame10 AES CM AEAD";
+ uint8_t info[] = "enc";
+ return deriveHDKFSHA256Bits(key.returnValue().data(), 16, usage, sizeof(usage) - 1, info, sizeof(info) - 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)
@@ -61,11 +79,34 @@
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)
+static inline Vector<uint8_t, 8> encodeBigEndian(uint64_t value)
{
- return calculateSHA256Signature(key, data, size);
+ Vector<uint8_t, 8> result(8);
+ for (int i = 7; i >= 0; --i) {
+ result.data()[i] = value & 0xff;
+ value = value >> 8;
+ }
+ return result;
}
+Vector<uint8_t> RTCRtpSFrameTransformer::computeEncryptedDataSignature(const Vector<uint8_t>& nonce, const uint8_t* header, size_t headerSize, const uint8_t* data, size_t dataSize, const Vector<uint8_t>& key)
+{
+ auto headerLength = encodeBigEndian(headerSize);
+ auto dataLength = encodeBigEndian(dataSize);
+
+ Vector<uint8_t> result(CC_SHA256_DIGEST_LENGTH);
+ CCHmacContext context;
+ CCHmacInit(&context, kCCHmacAlgSHA256, key.data(), key.size());
+ CCHmacUpdate(&context, headerLength.data(), headerLength.size());
+ CCHmacUpdate(&context, dataLength.data(), dataLength.size());
+ CCHmacUpdate(&context, nonce.data(), 12);
+ CCHmacUpdate(&context, header, headerSize);
+ CCHmacUpdate(&context, data, dataSize);
+ CCHmacFinal(&context, result.data());
+
+ return result;
+}
+
void RTCRtpSFrameTransformer::updateAuthenticationSize()
{
if (m_authenticationSize > CC_SHA256_DIGEST_LENGTH)
Modified: trunk/Source/WebCore/testing/Internals.cpp (275655 => 275656)
--- trunk/Source/WebCore/testing/Internals.cpp 2021-04-08 08:58:24 UTC (rev 275655)
+++ trunk/Source/WebCore/testing/Internals.cpp 2021-04-08 10:53:44 UTC (rev 275656)
@@ -1595,6 +1595,12 @@
#endif
}
+void Internals::setSFrameCounter(RTCRtpSFrameTransform& transform, const String& counter)
+{
+ if (auto value = StringView(counter).toUInt64Strict())
+ transform.setCounterForTesting(*value);
+}
+
uint64_t Internals::sframeCounter(const RTCRtpSFrameTransform& transform)
{
return transform.counterForTesting();
Modified: trunk/Source/WebCore/testing/Internals.h (275655 => 275656)
--- trunk/Source/WebCore/testing/Internals.h 2021-04-08 08:58:24 UTC (rev 275655)
+++ trunk/Source/WebCore/testing/Internals.h 2021-04-08 10:53:44 UTC (rev 275656)
@@ -617,6 +617,7 @@
void setWebRTCH265Support(bool);
void setWebRTCVP9Support(bool supportVP9Profile0, bool supportVP9Profile2);
void setWebRTCVP9VTBSupport(bool);
+ void setSFrameCounter(RTCRtpSFrameTransform&, const String&);
uint64_t sframeCounter(const RTCRtpSFrameTransform&);
uint64_t sframeKeyId(const RTCRtpSFrameTransform&);
void setEnableWebRTCEncryption(bool);
Modified: trunk/Source/WebCore/testing/Internals.idl (275655 => 275656)
--- trunk/Source/WebCore/testing/Internals.idl 2021-04-08 08:58:24 UTC (rev 275655)
+++ trunk/Source/WebCore/testing/Internals.idl 2021-04-08 10:53:44 UTC (rev 275656)
@@ -825,6 +825,7 @@
[Conditional=WEB_RTC] undefined setWebRTCH265Support(boolean allowed);
[Conditional=WEB_RTC] undefined setWebRTCVP9Support(boolean supportVP9Profile0, boolean supportVP9Profile2);
[Conditional=WEB_RTC] undefined setWebRTCVP9VTBSupport(boolean allowed);
+ [Conditional=WEB_RTC] undefined setSFrameCounter(RTCRtpSFrameTransform transform, DOMString counter);
[Conditional=WEB_RTC] unsigned long long sframeCounter(RTCRtpSFrameTransform transform);
[Conditional=WEB_RTC] unsigned long long sframeKeyId(RTCRtpSFrameTransform transform);
Modified: trunk/Tools/ChangeLog (275655 => 275656)
--- trunk/Tools/ChangeLog 2021-04-08 08:58:24 UTC (rev 275655)
+++ trunk/Tools/ChangeLog 2021-04-08 10:53:44 UTC (rev 275656)
@@ -1,3 +1,15 @@
+2021-04-08 Youenn Fablet <[email protected]>
+
+ Update SFrame implementation to latest version
+ https://bugs.webkit.org/show_bug.cgi?id=224276
+
+ Reviewed by Eric Carlson.
+
+ Update tests according new way of deriving keys and generating the signature.
+
+ * TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp:
+ (TestWebKitAPI::TEST):
+
2021-04-07 Jonathan Bedard <[email protected]>
[webkitscmpy] Handle multiple double-branch commits
Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp (275655 => 275656)
--- trunk/Tools/TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp 2021-04-08 08:58:24 UTC (rev 275655)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/RTCRtpSFrameTransformerTests.cpp 2021-04-08 10:53:44 UTC (rev 275656)
@@ -116,38 +116,38 @@
{
auto transformer = createVideoTransformer();
checkVectorsAreEqual(transformer->authenticationKey(), Vector<uint8_t>::from(
- 92,
- 228,
- 139,
- 195,
+ 4,
98,
- 16,
- 4,
+ 231,
+ 89,
+ 19,
+ 177,
+ 253,
+ 241,
+ 246,
+ 85,
193,
- 221,
- 248,
- 232,
- 178,
- 135,
- 22,
- 141,
- 150,
+ 64,
+ 19,
+ 72,
+ 211,
+ 48,
+ 57,
+ 235,
+ 63,
+ 57,
165,
- 242,
- 73,
- 72,
- 10,
- 197,
- 15,
- 87,
- 181,
- 34,
- 120,
- 71,
- 42,
- 174,
- 131,
- 72
+ 252,
+ 130,
+ 58,
+ 142,
+ 14,
+ 142,
+ 223,
+ 134,
+ 92,
+ 167,
+ 253
));
}
@@ -155,22 +155,22 @@
{
auto transformer = createVideoTransformer();
checkVectorsAreEqual(transformer->encryptionKey(), Vector<uint8_t>::from(
- 207,
- 251,
- 52,
- 21,
+ 180,
+ 189,
+ 66,
+ 149,
+ 6,
101,
- 50,
- 232,
- 48,
- 211,
- 115,
+ 148,
+ 179,
+ 158,
+ 210,
+ 132,
+ 83,
+ 75,
11,
- 155,
- 101,
- 116,
- 153,
- 71
+ 43,
+ 50
));
}
@@ -178,22 +178,18 @@
{
auto transformer = createVideoTransformer();
checkVectorsAreEqual(transformer->saltKey(), Vector<uint8_t>::from(
- 229,
- 19,
- 42,
+ 184,
+ 43,
+ 180,
+ 28,
93,
- 164,
- 103,
- 120,
- 53,
- 25,
- 26,
- 237,
- 204,
- 79,
- 138,
- 138,
- 231
+ 139,
+ 8,
+ 109,
+ 65,
+ 142,
+ 81,
+ 22
));
}
@@ -274,27 +270,27 @@
91,
51,
0,
- 254,
- 171,
- 168,
- 127,
- 158,
- 97,
- 70,
- 4,
- 233,
- 156,
- 134,
- 220,
- 44,
- 50,
- 90,
- 3,
- 68,
- 200,
- 127,
- 223,
- 6
+ 176,
+ 194,
+ 94,
+ 42,
+ 248,
+ 190,
+ 103,
+ 74,
+ 123,
+ 208,
+ 120,
+ 249,
+ 75,
+ 63,
+ 244,
+ 81,
+ 244,
+ 71,
+ 64,
+ 46,
+ 28
));
}
@@ -309,6 +305,7 @@
result = transformer->transform(frame1, sizeof(frame1));
EXPECT_FALSE(result.hasException());
}
+
checkVectorsAreEqual(result.releaseReturnValue(), Vector<uint8_t>::from(
31,
198,
@@ -321,27 +318,27 @@
51,
1,
0,
- 124,
- 218,
- 61,
- 23,
- 78,
- 15,
- 190,
- 35,
- 255,
- 253,
- 120,
- 64,
- 28,
- 183,
- 172,
- 154,
- 144,
- 16,
- 229,
- 87,
- 52
+ 37,
+ 39,
+ 205,
+ 106,
+ 44,
+ 155,
+ 25,
+ 174,
+ 2,
+ 206,
+ 198,
+ 89,
+ 82,
+ 57,
+ 224,
+ 232,
+ 26,
+ 29,
+ 98,
+ 176,
+ 57
));
}
@@ -367,27 +364,27 @@
1,
0,
0,
- 98,
- 212,
- 137,
- 244,
- 209,
- 16,
- 89,
- 234,
- 21,
- 171,
- 15,
- 107,
- 50,
- 145,
- 73,
- 107,
- 165,
- 45,
- 190,
- 25,
- 82
+ 117,
+ 5,
+ 112,
+ 126,
+ 205,
+ 197,
+ 116,
+ 213,
+ 249,
+ 178,
+ 47,
+ 154,
+ 151,
+ 123,
+ 40,
+ 58,
+ 121,
+ 201,
+ 159,
+ 90,
+ 170
));
}