Enable End-to-End Encrypted Audio Payloads.

This change integrates the FrameDecryptorInterface and the FrameEncryptorInterface into
the audio media path. If a FrameEncryptorInterface is set on an outgoing audio RTPSender
then each outgoing audio payload will first pass through the provided FrameEncryptor which
will have a chance to modify the payload contents for the purposes of encryption.

If a FrameDecryptorInterface is set on an incoming audio RtpReceiver then each incoming
audio payload will first pass through the provided FrameDecryptor which have a chance to
modify the payload contents for the purpose of decryption.

While AEAD is supported by the FrameDecryptor/FrameEncryptor interfaces this CL does not
use it and so it is left as null.

Bug: webrtc:9681
Change-Id: Ic383a9dce280528739f9d271357c2220e0a0dccf
Reviewed-on: https://webrtc-review.googlesource.com/c/101702
Commit-Queue: Benjamin Wright <benwright@webrtc.org>
Reviewed-by: Fredrik Solenberg <solenberg@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Emad Omara <emadomara@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25001}
diff --git a/audio/channel_send.cc b/audio/channel_send.cc
index 0c9328f..d3748b3 100644
--- a/audio/channel_send.cc
+++ b/audio/channel_send.cc
@@ -19,6 +19,7 @@
 
 #include "absl/memory/memory.h"
 #include "api/array_view.h"
+#include "api/crypto/frameencryptorinterface.h"
 #include "audio/utility/audio_frame_operations.h"
 #include "call/rtp_transport_controller_send_interface.h"
 #include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
@@ -260,6 +261,35 @@
     _rtpRtcpModule->SetAudioLevel(rms_level_.Average());
   }
 
+  // E2EE Custom Audio Frame Encryption (This is optional).
+  // Keep this buffer around for the lifetime of the send call.
+  rtc::Buffer encrypted_audio_payload;
+  if (frame_encryptor_ != nullptr) {
+    // TODO(benwright@webrtc.org) - Allocate enough to always encrypt inline.
+    // Allocate a buffer to hold the maximum possible encrypted payload.
+    size_t max_ciphertext_size = frame_encryptor_->GetMaxCiphertextByteSize(
+        cricket::MEDIA_TYPE_AUDIO, payloadSize);
+    encrypted_audio_payload.SetSize(max_ciphertext_size);
+
+    // Encrypt the audio payload into the buffer.
+    size_t bytes_written = 0;
+    int encrypt_status = frame_encryptor_->Encrypt(
+        cricket::MEDIA_TYPE_AUDIO, _rtpRtcpModule->SSRC(),
+        /*additional_data=*/nullptr,
+        rtc::ArrayView<const uint8_t>(payloadData, payloadSize),
+        encrypted_audio_payload, &bytes_written);
+    if (encrypt_status != 0) {
+      RTC_DLOG(LS_ERROR) << "Channel::SendData() failed encrypt audio payload: "
+                         << encrypt_status;
+      return -1;
+    }
+    // Resize the buffer to the exact number of bytes actually used.
+    encrypted_audio_payload.SetSize(bytes_written);
+    // Rewrite the payloadData and size to the new encrypted payload.
+    payloadData = encrypted_audio_payload.data();
+    payloadSize = encrypted_audio_payload.size();
+  }
+
   // Push data from ACM to RTP/RTCP-module to deliver audio frame for
   // packetization.
   // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
@@ -322,7 +352,8 @@
 ChannelSend::ChannelSend(rtc::TaskQueue* encoder_queue,
                          ProcessThread* module_process_thread,
                          RtcpRttStats* rtcp_rtt_stats,
-                         RtcEventLog* rtc_event_log)
+                         RtcEventLog* rtc_event_log,
+                         FrameEncryptorInterface* frame_encryptor)
     : event_log_(rtc_event_log),
       _timeStamp(0),  // This is just an offset, RTP module will add it's own
                       // random offset
@@ -342,7 +373,8 @@
                                                    kMaxRetransmissionWindowMs)),
       use_twcc_plr_for_ana_(
           webrtc::field_trial::FindFullName("UseTwccPlrForAna") == "Enabled"),
-      encoder_queue_(encoder_queue) {
+      encoder_queue_(encoder_queue),
+      frame_encryptor_(frame_encryptor) {
   RTC_DCHECK(module_process_thread);
   RTC_DCHECK(encoder_queue);
   audio_coding_.reset(AudioCodingModule::Create(AudioCodingModule::Config()));
@@ -949,5 +981,16 @@
   return rtt;
 }
 
+void ChannelSend::SetFrameEncryptor(FrameEncryptorInterface* frame_encryptor) {
+  rtc::CritScope cs(&encoder_queue_lock_);
+  if (encoder_queue_is_active_) {
+    encoder_queue_->PostTask([this, frame_encryptor]() {
+      this->frame_encryptor_ = frame_encryptor;
+    });
+  } else {
+    frame_encryptor_ = frame_encryptor;
+  }
+}
+
 }  // namespace voe
 }  // namespace webrtc