1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard
5*3f982cf4SFabien Sanglard #include "cast/streaming/frame_crypto.h"
6*3f982cf4SFabien Sanglard
7*3f982cf4SFabien Sanglard #include <array>
8*3f982cf4SFabien Sanglard #include <cstring>
9*3f982cf4SFabien Sanglard #include <vector>
10*3f982cf4SFabien Sanglard
11*3f982cf4SFabien Sanglard #include "gtest/gtest.h"
12*3f982cf4SFabien Sanglard #include "util/crypto/random_bytes.h"
13*3f982cf4SFabien Sanglard
14*3f982cf4SFabien Sanglard namespace openscreen {
15*3f982cf4SFabien Sanglard namespace cast {
16*3f982cf4SFabien Sanglard namespace {
17*3f982cf4SFabien Sanglard
TEST(FrameCryptoTest,EncryptsAndDecryptsFrames)18*3f982cf4SFabien Sanglard TEST(FrameCryptoTest, EncryptsAndDecryptsFrames) {
19*3f982cf4SFabien Sanglard // Prepare two frames with different FrameIds, but having the same payload
20*3f982cf4SFabien Sanglard // bytes.
21*3f982cf4SFabien Sanglard EncodedFrame frame0;
22*3f982cf4SFabien Sanglard frame0.frame_id = FrameId::first();
23*3f982cf4SFabien Sanglard const char kPayload[] = "The quick brown fox jumps over the lazy dog.";
24*3f982cf4SFabien Sanglard std::vector<uint8_t> buffer(
25*3f982cf4SFabien Sanglard reinterpret_cast<const uint8_t*>(kPayload),
26*3f982cf4SFabien Sanglard reinterpret_cast<const uint8_t*>(kPayload) + sizeof(kPayload));
27*3f982cf4SFabien Sanglard frame0.data = absl::Span<uint8_t>(buffer);
28*3f982cf4SFabien Sanglard EncodedFrame frame1;
29*3f982cf4SFabien Sanglard frame1.frame_id = frame0.frame_id + 1;
30*3f982cf4SFabien Sanglard frame1.data = frame0.data;
31*3f982cf4SFabien Sanglard
32*3f982cf4SFabien Sanglard const std::array<uint8_t, 16> key = GenerateRandomBytes16();
33*3f982cf4SFabien Sanglard const std::array<uint8_t, 16> iv = GenerateRandomBytes16();
34*3f982cf4SFabien Sanglard EXPECT_NE(0, memcmp(key.data(), iv.data(), sizeof(key)));
35*3f982cf4SFabien Sanglard const FrameCrypto crypto(key, iv);
36*3f982cf4SFabien Sanglard
37*3f982cf4SFabien Sanglard // Encrypt both frames, and confirm the encrypted data is something other than
38*3f982cf4SFabien Sanglard // the plaintext, and that both frames have different encrypted data.
39*3f982cf4SFabien Sanglard const EncryptedFrame encrypted_frame0 = crypto.Encrypt(frame0);
40*3f982cf4SFabien Sanglard EXPECT_EQ(frame0.frame_id, encrypted_frame0.frame_id);
41*3f982cf4SFabien Sanglard ASSERT_EQ(static_cast<int>(frame0.data.size()),
42*3f982cf4SFabien Sanglard FrameCrypto::GetPlaintextSize(encrypted_frame0));
43*3f982cf4SFabien Sanglard EXPECT_NE(0, memcmp(frame0.data.data(), encrypted_frame0.data.data(),
44*3f982cf4SFabien Sanglard frame0.data.size()));
45*3f982cf4SFabien Sanglard const EncryptedFrame encrypted_frame1 = crypto.Encrypt(frame1);
46*3f982cf4SFabien Sanglard EXPECT_EQ(frame1.frame_id, encrypted_frame1.frame_id);
47*3f982cf4SFabien Sanglard ASSERT_EQ(static_cast<int>(frame1.data.size()),
48*3f982cf4SFabien Sanglard FrameCrypto::GetPlaintextSize(encrypted_frame1));
49*3f982cf4SFabien Sanglard EXPECT_NE(0, memcmp(frame1.data.data(), encrypted_frame1.data.data(),
50*3f982cf4SFabien Sanglard frame1.data.size()));
51*3f982cf4SFabien Sanglard ASSERT_EQ(encrypted_frame0.data.size(), encrypted_frame1.data.size());
52*3f982cf4SFabien Sanglard EXPECT_NE(0,
53*3f982cf4SFabien Sanglard memcmp(encrypted_frame0.data.data(), encrypted_frame1.data.data(),
54*3f982cf4SFabien Sanglard encrypted_frame0.data.size()));
55*3f982cf4SFabien Sanglard
56*3f982cf4SFabien Sanglard // Now, decrypt the encrypted frames, and confirm the original payload
57*3f982cf4SFabien Sanglard // plaintext is retrieved.
58*3f982cf4SFabien Sanglard EncodedFrame decrypted_frame0;
59*3f982cf4SFabien Sanglard std::vector<uint8_t> decrypted_frame0_buffer(
60*3f982cf4SFabien Sanglard FrameCrypto::GetPlaintextSize(encrypted_frame0));
61*3f982cf4SFabien Sanglard decrypted_frame0.data = absl::Span<uint8_t>(decrypted_frame0_buffer);
62*3f982cf4SFabien Sanglard crypto.Decrypt(encrypted_frame0, &decrypted_frame0);
63*3f982cf4SFabien Sanglard EXPECT_EQ(frame0.frame_id, decrypted_frame0.frame_id);
64*3f982cf4SFabien Sanglard ASSERT_EQ(frame0.data.size(), decrypted_frame0.data.size());
65*3f982cf4SFabien Sanglard EXPECT_EQ(0, memcmp(frame0.data.data(), decrypted_frame0.data.data(),
66*3f982cf4SFabien Sanglard frame0.data.size()));
67*3f982cf4SFabien Sanglard
68*3f982cf4SFabien Sanglard EncodedFrame decrypted_frame1;
69*3f982cf4SFabien Sanglard std::vector<uint8_t> decrypted_frame1_buffer(
70*3f982cf4SFabien Sanglard FrameCrypto::GetPlaintextSize(encrypted_frame1));
71*3f982cf4SFabien Sanglard decrypted_frame1.data = absl::Span<uint8_t>(decrypted_frame1_buffer);
72*3f982cf4SFabien Sanglard crypto.Decrypt(encrypted_frame1, &decrypted_frame1);
73*3f982cf4SFabien Sanglard EXPECT_EQ(frame1.frame_id, decrypted_frame1.frame_id);
74*3f982cf4SFabien Sanglard ASSERT_EQ(frame1.data.size(), decrypted_frame1.data.size());
75*3f982cf4SFabien Sanglard EXPECT_EQ(0, memcmp(frame1.data.data(), decrypted_frame1.data.data(),
76*3f982cf4SFabien Sanglard frame1.data.size()));
77*3f982cf4SFabien Sanglard }
78*3f982cf4SFabien Sanglard
79*3f982cf4SFabien Sanglard } // namespace
80*3f982cf4SFabien Sanglard } // namespace cast
81*3f982cf4SFabien Sanglard } // namespace openscreen
82