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