| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "cast/streaming/frame_crypto.h" |
| |
| #include <array> |
| #include <cstring> |
| #include <vector> |
| |
| #include "gtest/gtest.h" |
| #include "util/crypto/random_bytes.h" |
| |
| namespace openscreen { |
| namespace cast { |
| namespace { |
| |
| TEST(FrameCryptoTest, EncryptsAndDecryptsFrames) { |
| // Prepare two frames with different FrameIds, but having the same payload |
| // bytes. |
| EncodedFrame frame0; |
| frame0.frame_id = FrameId::first(); |
| const char kPayload[] = "The quick brown fox jumps over the lazy dog."; |
| std::vector<uint8_t> buffer( |
| reinterpret_cast<const uint8_t*>(kPayload), |
| reinterpret_cast<const uint8_t*>(kPayload) + sizeof(kPayload)); |
| frame0.data = absl::Span<uint8_t>(buffer); |
| EncodedFrame frame1; |
| frame1.frame_id = frame0.frame_id + 1; |
| frame1.data = frame0.data; |
| |
| const std::array<uint8_t, 16> key = GenerateRandomBytes16(); |
| const std::array<uint8_t, 16> iv = GenerateRandomBytes16(); |
| EXPECT_NE(0, memcmp(key.data(), iv.data(), sizeof(key))); |
| const FrameCrypto crypto(key, iv); |
| |
| // Encrypt both frames, and confirm the encrypted data is something other than |
| // the plaintext, and that both frames have different encrypted data. |
| const EncryptedFrame encrypted_frame0 = crypto.Encrypt(frame0); |
| EXPECT_EQ(frame0.frame_id, encrypted_frame0.frame_id); |
| ASSERT_EQ(static_cast<int>(frame0.data.size()), |
| FrameCrypto::GetPlaintextSize(encrypted_frame0)); |
| EXPECT_NE(0, memcmp(frame0.data.data(), encrypted_frame0.data.data(), |
| frame0.data.size())); |
| const EncryptedFrame encrypted_frame1 = crypto.Encrypt(frame1); |
| EXPECT_EQ(frame1.frame_id, encrypted_frame1.frame_id); |
| ASSERT_EQ(static_cast<int>(frame1.data.size()), |
| FrameCrypto::GetPlaintextSize(encrypted_frame1)); |
| EXPECT_NE(0, memcmp(frame1.data.data(), encrypted_frame1.data.data(), |
| frame1.data.size())); |
| ASSERT_EQ(encrypted_frame0.data.size(), encrypted_frame1.data.size()); |
| EXPECT_NE(0, |
| memcmp(encrypted_frame0.data.data(), encrypted_frame1.data.data(), |
| encrypted_frame0.data.size())); |
| |
| // Now, decrypt the encrypted frames, and confirm the original payload |
| // plaintext is retrieved. |
| EncodedFrame decrypted_frame0; |
| std::vector<uint8_t> decrypted_frame0_buffer( |
| FrameCrypto::GetPlaintextSize(encrypted_frame0)); |
| decrypted_frame0.data = absl::Span<uint8_t>(decrypted_frame0_buffer); |
| crypto.Decrypt(encrypted_frame0, &decrypted_frame0); |
| EXPECT_EQ(frame0.frame_id, decrypted_frame0.frame_id); |
| ASSERT_EQ(frame0.data.size(), decrypted_frame0.data.size()); |
| EXPECT_EQ(0, memcmp(frame0.data.data(), decrypted_frame0.data.data(), |
| frame0.data.size())); |
| |
| EncodedFrame decrypted_frame1; |
| std::vector<uint8_t> decrypted_frame1_buffer( |
| FrameCrypto::GetPlaintextSize(encrypted_frame1)); |
| decrypted_frame1.data = absl::Span<uint8_t>(decrypted_frame1_buffer); |
| crypto.Decrypt(encrypted_frame1, &decrypted_frame1); |
| EXPECT_EQ(frame1.frame_id, decrypted_frame1.frame_id); |
| ASSERT_EQ(frame1.data.size(), decrypted_frame1.data.size()); |
| EXPECT_EQ(0, memcmp(frame1.data.data(), decrypted_frame1.data.data(), |
| frame1.data.size())); |
| } |
| |
| } // namespace |
| } // namespace cast |
| } // namespace openscreen |