mirror of
https://github.com/rustdesk/hbb_common.git
synced 2026-10-26 22:20:52 +00:00
stream: refuse a key exchange version set_negotiated_key does not know
Version 1 is matched explicitly and any other picked version is an error, so adding a version without its arm here fails instead of running as version 1. WebRTC takes only version 0, as both handshakes already require. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019aokqJuhjvB3kijXtAg5Ns
This commit is contained in:
1 parent
cbc8772d4a
commit
cee8cf3dc3
1 file changed
+34
-13
+34
-13
@@ -1,4 +1,4 @@
|
|||||||
use crate::{config, tcp, websocket, ResultType};
|
use crate::{bail, config, tcp, websocket, ResultType};
|
||||||
#[cfg(feature = "webrtc")]
|
#[cfg(feature = "webrtc")]
|
||||||
use crate::webrtc;
|
use crate::webrtc;
|
||||||
use sodiumoxide::crypto::secretbox::Key;
|
use sodiumoxide::crypto::secretbox::Key;
|
||||||
@@ -81,8 +81,8 @@ impl Stream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The stream key for the key exchange version in `t.picked`: version 0 is `set_key`, and
|
/// The stream key for the key exchange version in `t.picked`: version 0 is `set_key`, and
|
||||||
/// later versions derive one key per direction from the transcript. `is_initiator` is the
|
/// version 1 derives one key per direction from the transcript. Any other version is refused
|
||||||
/// side that sent the sealed key.
|
/// rather than run as one of these. `is_initiator` is the side that sent the sealed key.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_negotiated_key(
|
pub fn set_negotiated_key(
|
||||||
&mut self,
|
&mut self,
|
||||||
@@ -90,18 +90,18 @@ impl Stream {
|
|||||||
is_initiator: bool,
|
is_initiator: bool,
|
||||||
t: &tcp::KxTranscript,
|
t: &tcp::KxTranscript,
|
||||||
) -> ResultType<()> {
|
) -> ResultType<()> {
|
||||||
if t.picked == 0 {
|
match t.picked {
|
||||||
self.set_key(key);
|
0 => {
|
||||||
return Ok(());
|
self.set_key(key);
|
||||||
}
|
|
||||||
match self {
|
|
||||||
#[cfg(feature = "webrtc")]
|
|
||||||
Stream::WebRTC(s) => {
|
|
||||||
s.set_key(key);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Stream::WebSocket(s) => s.set_key_split(key, is_initiator, t),
|
1 => match self {
|
||||||
Stream::Tcp(s) => s.set_key_split(key, is_initiator, t),
|
#[cfg(feature = "webrtc")]
|
||||||
|
Stream::WebRTC(_) => bail!("key exchange version 1 does not apply to WebRTC"),
|
||||||
|
Stream::WebSocket(s) => s.set_key_split(key, is_initiator, t),
|
||||||
|
Stream::Tcp(s) => s.set_key_split(key, is_initiator, t),
|
||||||
|
},
|
||||||
|
v => bail!("unsupported key exchange version {}", v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,3 +313,24 @@ impl Drop for Stream {
|
|||||||
self.close_webrtc();
|
self.close_webrtc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_set_negotiated_key_refuses_unknown_versions() {
|
||||||
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
|
||||||
|
let addr = listener.local_addr().unwrap();
|
||||||
|
let mut stream = Stream::from(TcpStream::connect(addr).await.unwrap(), addr);
|
||||||
|
let t = |picked| tcp::KxTranscript {
|
||||||
|
initiator_pk: &[1u8; 32],
|
||||||
|
responder_pk: &[2u8; 32],
|
||||||
|
advertised: 1,
|
||||||
|
picked,
|
||||||
|
};
|
||||||
|
let mut set = |picked| stream.set_negotiated_key(Key([0u8; 32]), true, &t(picked));
|
||||||
|
assert!(set(2).is_err());
|
||||||
|
assert!(set(1).is_ok());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user