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 #ifndef CAST_STREAMING_FRAME_CRYPTO_H_ 6*3f982cf4SFabien Sanglard #define CAST_STREAMING_FRAME_CRYPTO_H_ 7*3f982cf4SFabien Sanglard 8*3f982cf4SFabien Sanglard #include <stddef.h> 9*3f982cf4SFabien Sanglard #include <stdint.h> 10*3f982cf4SFabien Sanglard 11*3f982cf4SFabien Sanglard #include <array> 12*3f982cf4SFabien Sanglard #include <vector> 13*3f982cf4SFabien Sanglard 14*3f982cf4SFabien Sanglard #include "absl/types/span.h" 15*3f982cf4SFabien Sanglard #include "cast/streaming/encoded_frame.h" 16*3f982cf4SFabien Sanglard #include "openssl/aes.h" 17*3f982cf4SFabien Sanglard #include "platform/base/macros.h" 18*3f982cf4SFabien Sanglard 19*3f982cf4SFabien Sanglard namespace openscreen { 20*3f982cf4SFabien Sanglard namespace cast { 21*3f982cf4SFabien Sanglard 22*3f982cf4SFabien Sanglard class FrameCollector; 23*3f982cf4SFabien Sanglard class FrameCrypto; 24*3f982cf4SFabien Sanglard 25*3f982cf4SFabien Sanglard // A subclass of EncodedFrame that represents an EncodedFrame with encrypted 26*3f982cf4SFabien Sanglard // payload data, and owns the buffer storing the encrypted payload data. Use 27*3f982cf4SFabien Sanglard // FrameCrypto (below) to explicitly convert between EncryptedFrames and 28*3f982cf4SFabien Sanglard // EncodedFrames. 29*3f982cf4SFabien Sanglard struct EncryptedFrame : public EncodedFrame { 30*3f982cf4SFabien Sanglard EncryptedFrame(); 31*3f982cf4SFabien Sanglard ~EncryptedFrame(); 32*3f982cf4SFabien Sanglard EncryptedFrame(EncryptedFrame&&) noexcept; 33*3f982cf4SFabien Sanglard EncryptedFrame& operator=(EncryptedFrame&&); 34*3f982cf4SFabien Sanglard 35*3f982cf4SFabien Sanglard protected: 36*3f982cf4SFabien Sanglard // Since only FrameCrypto and FrameCollector are trusted to generate the 37*3f982cf4SFabien Sanglard // payload data, only they are allowed direct access to the storage. 38*3f982cf4SFabien Sanglard friend class FrameCollector; 39*3f982cf4SFabien Sanglard friend class FrameCrypto; 40*3f982cf4SFabien Sanglard 41*3f982cf4SFabien Sanglard // Note: EncodedFrame::data must be updated whenever any mutations are 42*3f982cf4SFabien Sanglard // performed on this member! 43*3f982cf4SFabien Sanglard std::vector<uint8_t> owned_data_; 44*3f982cf4SFabien Sanglard }; 45*3f982cf4SFabien Sanglard 46*3f982cf4SFabien Sanglard // Encrypts EncodedFrames before sending, or decrypts EncryptedFrames that have 47*3f982cf4SFabien Sanglard // been received. 48*3f982cf4SFabien Sanglard class FrameCrypto { 49*3f982cf4SFabien Sanglard public: 50*3f982cf4SFabien Sanglard // Construct with the given 16-bytes AES key and IV mask. Both arguments 51*3f982cf4SFabien Sanglard // should be randomly-generated for each new streaming session. 52*3f982cf4SFabien Sanglard // GenerateRandomBytes() can be used to create them. 53*3f982cf4SFabien Sanglard FrameCrypto(const std::array<uint8_t, 16>& aes_key, 54*3f982cf4SFabien Sanglard const std::array<uint8_t, 16>& cast_iv_mask); 55*3f982cf4SFabien Sanglard 56*3f982cf4SFabien Sanglard ~FrameCrypto(); 57*3f982cf4SFabien Sanglard 58*3f982cf4SFabien Sanglard EncryptedFrame Encrypt(const EncodedFrame& encoded_frame) const; 59*3f982cf4SFabien Sanglard 60*3f982cf4SFabien Sanglard // Decrypt the given |encrypted_frame| into the output |encoded_frame|. The 61*3f982cf4SFabien Sanglard // caller must provide a sufficiently-sized data buffer (see 62*3f982cf4SFabien Sanglard // GetPlaintextSize()). 63*3f982cf4SFabien Sanglard void Decrypt(const EncryptedFrame& encrypted_frame, 64*3f982cf4SFabien Sanglard EncodedFrame* encoded_frame) const; 65*3f982cf4SFabien Sanglard 66*3f982cf4SFabien Sanglard // AES crypto inputs and outputs (for either encrypting or decrypting) are 67*3f982cf4SFabien Sanglard // always the same size in bytes. The following are just "documentative code." GetEncryptedSize(const EncodedFrame & encoded_frame)68*3f982cf4SFabien Sanglard static int GetEncryptedSize(const EncodedFrame& encoded_frame) { 69*3f982cf4SFabien Sanglard return encoded_frame.data.size(); 70*3f982cf4SFabien Sanglard } GetPlaintextSize(const EncryptedFrame & encrypted_frame)71*3f982cf4SFabien Sanglard static int GetPlaintextSize(const EncryptedFrame& encrypted_frame) { 72*3f982cf4SFabien Sanglard return encrypted_frame.data.size(); 73*3f982cf4SFabien Sanglard } 74*3f982cf4SFabien Sanglard 75*3f982cf4SFabien Sanglard private: 76*3f982cf4SFabien Sanglard // The 244-byte AES_KEY struct, derived from the |aes_key| passed to the ctor, 77*3f982cf4SFabien Sanglard // and initialized by boringssl's AES_set_encrypt_key() function. 78*3f982cf4SFabien Sanglard const AES_KEY aes_key_; 79*3f982cf4SFabien Sanglard 80*3f982cf4SFabien Sanglard // Random bytes used in the custom heuristic to generate a different 81*3f982cf4SFabien Sanglard // initialization vector for each frame. 82*3f982cf4SFabien Sanglard const std::array<uint8_t, 16> cast_iv_mask_; 83*3f982cf4SFabien Sanglard 84*3f982cf4SFabien Sanglard // AES-CTR is symmetric. Thus, the "meat" of both Encrypt() and Decrypt() is 85*3f982cf4SFabien Sanglard // the same. 86*3f982cf4SFabien Sanglard void EncryptCommon(FrameId frame_id, 87*3f982cf4SFabien Sanglard absl::Span<const uint8_t> in, 88*3f982cf4SFabien Sanglard absl::Span<uint8_t> out) const; 89*3f982cf4SFabien Sanglard }; 90*3f982cf4SFabien Sanglard 91*3f982cf4SFabien Sanglard } // namespace cast 92*3f982cf4SFabien Sanglard } // namespace openscreen 93*3f982cf4SFabien Sanglard 94*3f982cf4SFabien Sanglard #endif // CAST_STREAMING_FRAME_CRYPTO_H_ 95