blob: d7c4b124b85f6bbd2c8bfc324019ea227193df54 [file] [log] [blame]
/*
* 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 <WebCore/SFrameUtils.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 isEncrypting = true)
{
auto transformer = WebCore::RTCRtpSFrameTransformer::create();
transformer->setIsEncrypting(isEncrypting);
transformer->setMediaType(WebCore::RTCRtpTransformBackend::MediaType::Video);
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 Ref<WebCore::RTCRtpSFrameTransformer> createAudioTransformer(bool isEncrypting, WebCore::RTCRtpSFrameTransformer::CompatibilityMode mode)
{
auto transformer = WebCore::RTCRtpSFrameTransformer::create(mode);
transformer->setIsEncrypting(isEncrypting);
transformer->setMediaType(WebCore::RTCRtpTransformBackend::MediaType::Audio);
auto keyId = Vector<uint8_t>::from(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(
4,
98,
231,
89,
19,
177,
253,
241,
246,
85,
193,
64,
19,
72,
211,
48,
57,
235,
63,
57,
165,
252,
130,
58,
142,
14,
142,
223,
134,
92,
167,
253
));
}
TEST(RTCRtpSFrameTransformer, EncryptionKey)
{
auto transformer = createVideoTransformer();
checkVectorsAreEqual(transformer->encryptionKey(), Vector<uint8_t>::from(
180,
189,
66,
149,
6,
101,
148,
179,
158,
210,
132,
83,
75,
11,
43,
50
));
}
TEST(RTCRtpSFrameTransformer, SaltKey)
{
auto transformer = createVideoTransformer();
checkVectorsAreEqual(transformer->saltKey(), Vector<uint8_t>::from(
184,
43,
180,
28,
93,
139,
8,
109,
65,
142,
81,
22
));
}
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_TRUE(encryptedResult.has_value());
auto encrypted = WTFMove(encryptedResult.value());
auto decryptedResult = decryptor->transform({ encrypted.data(), encrypted.size() });
EXPECT_TRUE(decryptedResult.has_value());
checkVectorsAreEqual(decryptedResult.value(), 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_TRUE(encryptedResult.has_value());
auto encrypted = WTFMove(encryptedResult.value());
auto decryptedResult = decryptor->transform({ encrypted.data(), encrypted.size() });
EXPECT_TRUE(decryptedResult.has_value());
checkVectorsAreEqual(decryptedResult.value(), frame);
}
TEST(RTCRtpSFrameTransformer, EncryptDecryptAudio)
{
// We ignore compatiblity mode for audio.
uint64_t keyId = 1255995222;
auto encryptor = createAudioTransformer(true, WebCore::RTCRtpSFrameTransformer::CompatibilityMode::H264);
encryptor->setEncryptionKey(getRawKey(), keyId);
auto decryptor = createAudioTransformer(false, WebCore::RTCRtpSFrameTransformer::CompatibilityMode::None);
decryptor->setEncryptionKey(getRawKey(), keyId);
auto frame = Vector<uint8_t>::from(135, 89, 51, 166, 248, 129, 157, 111, 190, 134, 220, 56);
auto encryptedResult = encryptor->transform({ frame.data(), frame.size() });
EXPECT_TRUE(encryptedResult.has_value());
auto encrypted = WTFMove(encryptedResult.value());
auto decryptedResult = decryptor->transform({ encrypted.data(), encrypted.size() });
EXPECT_TRUE(decryptedResult.has_value());
checkVectorsAreEqual(decryptedResult.value(), 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_TRUE(result.has_value());
checkVectorsAreEqual(result.value(), Vector<uint8_t>::from(
15,
198,
31,
251,
197,
48,
139,
91,
51,
0,
176,
194,
94,
42,
248,
190,
103,
74,
123,
208,
120,
249,
75,
63,
244,
81,
244,
71,
64,
46,
28
));
}
TEST(RTCRtpSFrameTransformer, TransformCounter256)
{
auto transformer = createVideoTransformer();
uint8_t frame1[] = { 8, 164, 189, 18, 61, 117, 132, 43, 117, 169, 42 };
auto result = transformer->transform({ frame1, sizeof(frame1) });
EXPECT_TRUE(result.has_value());
for (size_t cptr = 0; cptr < 256; ++cptr) {
result = transformer->transform({ frame1, sizeof(frame1) });
EXPECT_TRUE(result.has_value());
}
checkVectorsAreEqual(result.value(), Vector<uint8_t>::from(
31,
198,
31,
251,
197,
48,
139,
91,
51,
1,
0,
37,
39,
205,
106,
44,
155,
25,
174,
2,
206,
198,
89,
82,
57,
224,
232,
26,
29,
98,
176,
57
));
}
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_TRUE(result.has_value());
checkVectorsAreEqual(result.value(), Vector<uint8_t>::from(
47,
198,
31,
251,
197,
48,
139,
91,
51,
1,
0,
0,
117,
5,
112,
126,
205,
197,
116,
213,
249,
178,
47,
154,
151,
123,
40,
58,
121,
201,
159,
90,
170
));
}
TEST(RTCRtpSFrameTransformer, RBSPEscaping)
{
uint8_t frame0[] = { 0, 33, 00, 24, 236, 156, 127, 8, 0, 0, 4 };
EXPECT_FALSE(WebCore::needsRbspUnescaping(frame0, sizeof(frame0)));
uint8_t frame0b[] = { 0, 33, 00, 24, 236, 156, 127, 8, 0, 0, 3 };
EXPECT_FALSE(WebCore::needsRbspUnescaping(frame0b, sizeof(frame0b)));
uint8_t frame1[] = { 0, 33, 00, 24, 236, 156, 127, 8, 0, 0, 3, 1 };
uint8_t frame1Unescaped[] = { 0, 33, 00, 24, 236, 156, 127, 8, 0, 0, 1 };
EXPECT_TRUE(WebCore::needsRbspUnescaping(frame1, sizeof(frame1)));
auto result = WebCore::fromRbsp(frame1, sizeof(frame1));
EXPECT_EQ(result.size(), sizeof(frame1Unescaped));
for (size_t i = 0; i < sizeof(frame1Unescaped); ++i)
EXPECT_EQ(result[i], frame1Unescaped[i]);
Vector<uint8_t> frame2 { 0, 0, 0, 65, 0, 0, 1, 66, 0, 0, 2, 67, 0, 0, 3, 68, 0, 0, 4, 0, 0, 1 };
Vector<uint8_t> escaped { 0, 0, 0, 65, 0, 0, 1, 66, 0, 0, 2, 67, 0, 0, 3, 68, 0, 0, 4, 0, 0, 1 };
WebCore::toRbsp(escaped, 0);
EXPECT_TRUE(WebCore::needsRbspUnescaping(escaped.data(), escaped.size()));
auto unescaped = WebCore::fromRbsp(escaped.data(), escaped.size());
EXPECT_EQ(unescaped.size(), frame2.size());
for (size_t i = 0; i < frame2.size(); ++i)
EXPECT_EQ(unescaped[i], frame2[i]);
}
}
#endif // ENABLE(WEB_RTC)