mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-01-29 00:32:37 +00:00
Implement control stream v2 encryption
This commit is contained in:
parent
2f80145b8e
commit
23fb07d4a2
18
src/rtsp.cpp
18
src/rtsp.cpp
@ -518,16 +518,24 @@ namespace rtsp_stream {
|
||||
std::stringstream ss;
|
||||
|
||||
// Tell the client about our supported features
|
||||
ss << "a=x-ss-general.featureFlags: " << (uint32_t) platf::get_capabilities() << std::endl;
|
||||
ss << "a=x-ss-general.featureFlags:" << (uint32_t) platf::get_capabilities() << std::endl;
|
||||
|
||||
// Always request new control stream encryption if the client supports it
|
||||
uint32_t encryption_flags_supported = SS_ENC_CONTROL_V2 | SS_ENC_AUDIO;
|
||||
uint32_t encryption_flags_requested = SS_ENC_CONTROL_V2;
|
||||
|
||||
// Report supported and required encryption flags
|
||||
ss << "a=x-ss-general.encryptionSupported:" << encryption_flags_supported << std::endl;
|
||||
ss << "a=x-ss-general.encryptionRequested:" << encryption_flags_requested << std::endl;
|
||||
|
||||
if (video::last_encoder_probe_supported_ref_frames_invalidation) {
|
||||
ss << "a=x-nv-video[0].refPicInvalidation:1"sv << std::endl;
|
||||
}
|
||||
|
||||
if (video::active_hevc_mode != 1) {
|
||||
ss << "sprop-parameter-sets=AAAAAU"sv << std::endl;
|
||||
}
|
||||
|
||||
if (video::last_encoder_probe_supported_ref_frames_invalidation) {
|
||||
ss << "x-nv-video[0].refPicInvalidation=1"sv << std::endl;
|
||||
}
|
||||
|
||||
if (video::active_av1_mode != 1) {
|
||||
ss << "a=rtpmap:98 AV1/90000"sv << std::endl;
|
||||
}
|
||||
|
@ -381,11 +381,11 @@ namespace stream {
|
||||
crypto::cipher::gcm_t cipher;
|
||||
crypto::aes_t legacy_input_enc_iv; // Only used when the client doesn't support full control stream encryption
|
||||
|
||||
uint32_t connect_data; // Used for new clients with ML_FF_SESSION_ID_V1
|
||||
std::uint32_t connect_data; // Used for new clients with ML_FF_SESSION_ID_V1
|
||||
std::string expected_peer_address; // Only used for legacy clients without ML_FF_SESSION_ID_V1
|
||||
|
||||
net::peer_t peer;
|
||||
std::uint8_t seq;
|
||||
std::uint32_t seq;
|
||||
|
||||
platf::feedback_queue_t feedback_queue;
|
||||
safe::mail_raw_t::event_t<video::hdr_info_t> hdr_queue;
|
||||
@ -414,9 +414,29 @@ namespace stream {
|
||||
return plaintext;
|
||||
}
|
||||
|
||||
crypto::aes_t iv(16);
|
||||
auto seq = session->control.seq++;
|
||||
iv[0] = seq;
|
||||
|
||||
crypto::aes_t iv;
|
||||
if (session->config.encryptionFlagsEnabled & SS_ENC_CONTROL_V2) {
|
||||
// We use the deterministic IV construction algorithm specified in NIST SP 800-38D
|
||||
// Section 8.2.1. The sequence number is our "invocation" field and the 'CH' in the
|
||||
// high bytes is the "fixed" field. Because each client provides their own unique
|
||||
// key, our values in the fixed field need only uniquely identify each independent
|
||||
// use of the client's key with AES-GCM in our code.
|
||||
//
|
||||
// The sequence number is 32 bits long which allows for 2^32 control stream messages
|
||||
// to be sent to each client before the IV repeats.
|
||||
iv.resize(12);
|
||||
std::copy_n((uint8_t *) &seq, sizeof(seq), std::begin(iv));
|
||||
iv[10] = 'H'; // Host originated
|
||||
iv[11] = 'C'; // Control stream
|
||||
}
|
||||
else {
|
||||
// Nvidia's old style encryption uses a 16-byte IV
|
||||
iv.resize(16);
|
||||
|
||||
iv[0] = (std::uint8_t) seq;
|
||||
}
|
||||
|
||||
auto packet = (control_encrypted_p) tagged_cipher.data();
|
||||
|
||||
@ -915,11 +935,27 @@ namespace stream {
|
||||
std::string_view tagged_cipher { (char *) header->payload(), (size_t) tagged_cipher_length };
|
||||
|
||||
auto &cipher = session->control.cipher;
|
||||
crypto::aes_t iv(16);
|
||||
iv[0] = (std::uint8_t) seq;
|
||||
crypto::aes_t iv;
|
||||
if (session->config.encryptionFlagsEnabled & SS_ENC_CONTROL_V2) {
|
||||
// We use the deterministic IV construction algorithm specified in NIST SP 800-38D
|
||||
// Section 8.2.1. The sequence number is our "invocation" field and the 'CC' in the
|
||||
// high bytes is the "fixed" field. Because each client provides their own unique
|
||||
// key, our values in the fixed field need only uniquely identify each independent
|
||||
// use of the client's key with AES-GCM in our code.
|
||||
//
|
||||
// The sequence number is 32 bits long which allows for 2^32 control stream messages
|
||||
// to be received from each client before the IV repeats.
|
||||
iv.resize(12);
|
||||
std::copy_n((uint8_t *) &seq, sizeof(seq), std::begin(iv));
|
||||
iv[10] = 'C'; // Client originated
|
||||
iv[11] = 'C'; // Control stream
|
||||
}
|
||||
else {
|
||||
// Nvidia's old style encryption uses a 16-byte IV
|
||||
iv.resize(16);
|
||||
|
||||
// update control sequence
|
||||
++session->control.seq;
|
||||
iv[0] = (std::uint8_t) seq;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> plaintext;
|
||||
if (cipher.decrypt(tagged_cipher, plaintext, &iv)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user