xref: /aosp_15_r20/external/openscreen/cast/streaming/frame_crypto.h (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
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