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