1use std::time::{SystemTime, UNIX_EPOCH};
2
3use crate::crypto::{compute_mac, verify_mac, SessionKeys};
4use crate::handshake::HandshakeError;
5use crate::messages::{Acknowledge, ControlEnvelope, ControlOp, MessageType};
6use crate::{handshake::transport::ReliableControlChannel, handshake::HandshakeTransport};
7use serde_json::json;
8use uuid::Uuid;
9
10pub struct ControlCrypto {
12 keys: SessionKeys,
13}
14
15impl ControlCrypto {
16 pub fn new(keys: SessionKeys) -> Self {
17 Self { keys }
18 }
19
20 pub fn mac_for_payload(
21 &self,
22 seq: u64,
23 session_id: &Uuid,
24 payload: &serde_json::Value,
25 ) -> Result<Vec<u8>, HandshakeError> {
26 let bytes = serde_cbor::to_vec(payload)
27 .map_err(|e| HandshakeError::Protocol(format!("payload encode: {}", e)))?;
28 compute_mac(&self.keys, seq, &bytes, session_id.as_bytes())
29 .map_err(|e| HandshakeError::Authentication(e.to_string()))
30 }
31
32 pub fn verify_mac(
33 &self,
34 seq: u64,
35 session_id: &Uuid,
36 payload: &serde_json::Value,
37 mac: &[u8],
38 ) -> Result<(), HandshakeError> {
39 let bytes = serde_cbor::to_vec(payload)
40 .map_err(|e| HandshakeError::Protocol(format!("payload encode: {}", e)))?;
41 if verify_mac(&self.keys, seq, &bytes, session_id.as_bytes(), mac) {
42 Ok(())
43 } else {
44 Err(HandshakeError::Authentication(
45 "control MAC validation failed".into(),
46 ))
47 }
48 }
49}
50
51pub struct ControlClient {
53 pub device_id: Uuid,
54 pub crypto: ControlCrypto,
55 pub session_id: Uuid,
56}
57
58impl ControlClient {
59 pub fn new(device_id: Uuid, session_id: Uuid, crypto: ControlCrypto) -> Self {
60 Self {
61 device_id,
62 crypto,
63 session_id,
64 }
65 }
66
67 pub fn envelope(
68 &self,
69 seq: u64,
70 op: ControlOp,
71 payload: serde_json::Value,
72 ) -> Result<ControlEnvelope, HandshakeError> {
73 let mac = self
74 .crypto
75 .mac_for_payload(seq, &self.session_id, &payload)?;
76 Ok(ControlEnvelope {
77 message_type: MessageType::AlpineControl,
78 session_id: self.session_id,
79 seq,
80 op,
81 payload,
82 mac,
83 })
84 }
85
86 pub async fn send<T: HandshakeTransport + Send>(
87 &self,
88 channel: &mut ReliableControlChannel<T>,
89 op: ControlOp,
90 payload: serde_json::Value,
91 ) -> Result<Acknowledge, HandshakeError> {
92 let seq = channel.next_seq();
93 let env = self.envelope(seq, op, payload)?;
94 channel.send_reliable(env).await
95 }
96
97 pub fn now_ms() -> u64 {
98 SystemTime::now()
99 .duration_since(UNIX_EPOCH)
100 .unwrap_or_default()
101 .as_millis() as u64
102 }
103}
104
105pub struct ControlResponder {
107 pub crypto: ControlCrypto,
108 pub session_id: Uuid,
109}
110
111impl ControlResponder {
112 pub fn new(session_id: Uuid, crypto: ControlCrypto) -> Self {
113 Self { crypto, session_id }
114 }
115
116 pub fn verify(&self, env: &ControlEnvelope) -> Result<(), HandshakeError> {
117 self.crypto
118 .verify_mac(env.seq, &env.session_id, &env.payload, &env.mac)
119 }
120
121 pub fn ack(
122 &self,
123 seq: u64,
124 ok: bool,
125 detail: Option<String>,
126 ) -> Result<Acknowledge, HandshakeError> {
127 let payload = json!({"ok": ok, "detail": detail});
128 let mac = self
129 .crypto
130 .mac_for_payload(seq, &self.session_id, &payload)?;
131 Ok(Acknowledge {
132 message_type: MessageType::AlpineControlAck,
133 session_id: self.session_id,
134 seq,
135 ok,
136 detail,
137 mac,
138 })
139 }
140}