1pub mod session_negotiation;
8
9use {
10 crate::{
11 cryptography::PrivateKey,
12 remote_signing::session_negotiation::{
13 PeerKeys, PublicKeyPeerDecrypt, SessionInitiatePeer, SessionJoinContext,
14 SessionJoinPeerPreJoin,
15 },
16 AppleCodesignError,
17 },
18 base64::{engine::general_purpose::STANDARD as STANDARD_ENGINE, Engine},
19 bcder::{
20 encode::{PrimitiveContent, Values},
21 Mode, Oid,
22 },
23 bytes::Bytes,
24 log::{debug, error, warn},
25 serde::{de::DeserializeOwned, Deserialize, Serialize},
26 signature::Signer,
27 std::{
28 cell::{RefCell, RefMut},
29 net::TcpStream,
30 },
31 thiserror::Error,
32 tungstenite::{
33 client::IntoClientRequest,
34 protocol::{Message, WebSocket, WebSocketConfig},
35 stream::MaybeTlsStream,
36 },
37 x509_certificate::{
38 CapturedX509Certificate, KeyAlgorithm, KeyInfoSigner, Sign, Signature, SignatureAlgorithm,
39 X509CertificateError,
40 },
41 zeroize::Zeroizing,
42};
43
44pub const DEFAULT_SERVER_URL: &str = "wss://ws.codesign.gregoryszorc.com/";
46
47#[derive(Debug, Error)]
49pub enum RemoteSignError {
50 #[error("unexpected message received from relay server: {0}")]
51 ServerUnexpectedMessage(String),
52
53 #[error("error reported from relay server: {0}")]
54 ServerError(String),
55
56 #[error("not compatible with relay server; try upgrading to a new release?")]
57 ServerIncompatible,
58
59 #[error("cryptography error: {0}")]
60 Crypto(String),
61
62 #[error("bad client state: {0}")]
63 ClientState(&'static str),
64
65 #[error("joining state not wanted for this session type: {0}")]
66 SessionJoinUnwantedState(String),
67
68 #[error("session join string error: {0}")]
69 SessionJoinString(String),
70
71 #[error("base64 decode error: {0}")]
72 Base64(#[from] base64::DecodeError),
73
74 #[error("I/O error: {0}")]
75 Io(#[from] std::io::Error),
76
77 #[error("PEM encoding error: {0}")]
78 Pem(#[from] pem::PemError),
79
80 #[error("JSON serialization error: {0}")]
81 SerdeJson(#[from] serde_json::Error),
82
83 #[error("SPAKE error: {0}")]
84 Spake(spake2::Error),
85
86 #[error("SPKI error: {0}")]
87 Spki(#[from] spki::Error),
88
89 #[error("websocket error: {0}")]
90 Websocket(#[from] tungstenite::Error),
91
92 #[error("X.509 certificate handler error: {0}")]
93 X509(#[from] X509CertificateError),
94}
95
96#[derive(Clone, Copy, Debug, PartialEq, Serialize)]
97#[serde(rename_all = "kebab-case")]
98enum ApiMethod {
99 Hello,
100 CreateSession,
101 JoinSession,
102 SendMessage,
103 Goodbye,
104}
105
106#[derive(Clone, Debug, Serialize)]
108struct ClientMessage {
109 request_id: String,
111 api: ApiMethod,
113 payload: Option<ClientPayload>,
115}
116
117#[derive(Clone, Debug, Serialize)]
119#[serde(untagged)]
120enum ClientPayload {
121 CreateSession {
122 session_id: String,
123 ttl: u64,
124 context: Option<String>,
125 },
126 JoinSession {
127 session_id: String,
128 context: Option<String>,
129 },
130 SendMessage {
131 session_id: String,
132 message: String,
133 },
134 Goodbye {
135 session_id: String,
136 reason: Option<String>,
137 },
138}
139
140#[derive(Clone, Copy, Debug, Deserialize, PartialEq)]
141#[serde(rename_all = "kebab-case")]
142enum ServerMessageType {
143 Error,
144 Greeting,
145 SessionCreated,
146 SessionJoined,
147 MessageSent,
148 PeerMessage,
149 SessionClosed,
150}
151
152#[derive(Clone, Debug, Deserialize)]
154struct ServerMessage {
155 request_id: Option<String>,
157 #[serde(rename = "type")]
159 typ: ServerMessageType,
160 ttl: Option<u64>,
161 payload: Option<serde_json::Value>,
162}
163
164impl ServerMessage {
165 fn into_result(self) -> Result<Self, RemoteSignError> {
166 if self.typ == ServerMessageType::Error {
167 let error = self.as_error()?;
168 Err(RemoteSignError::ServerError(format!(
169 "{}: {}",
170 error.code, error.message
171 )))
172 } else {
173 Ok(self)
174 }
175 }
176
177 fn as_type<T: DeserializeOwned>(
178 &self,
179 message_type: ServerMessageType,
180 ) -> Result<T, RemoteSignError> {
181 if self.typ == message_type {
182 if let Some(value) = &self.payload {
183 Ok(serde_json::from_value(value.clone())?)
184 } else {
185 Err(RemoteSignError::ClientState(
186 "no payload for requested type",
187 ))
188 }
189 } else {
190 Err(RemoteSignError::ClientState(
191 "requested payload for wrong message type",
192 ))
193 }
194 }
195
196 fn as_error(&self) -> Result<ServerError, RemoteSignError> {
197 self.as_type::<ServerError>(ServerMessageType::Error)
198 }
199
200 fn as_greeting(&self) -> Result<ServerGreeting, RemoteSignError> {
201 self.as_type::<ServerGreeting>(ServerMessageType::Greeting)
202 }
203
204 fn as_session_joined(&self) -> Result<ServerJoined, RemoteSignError> {
205 self.as_type::<ServerJoined>(ServerMessageType::SessionJoined)
206 }
207
208 fn as_peer_message(&self) -> Result<ServerPeerMessage, RemoteSignError> {
209 self.as_type::<ServerPeerMessage>(ServerMessageType::PeerMessage)
210 }
211
212 fn as_session_closed(&self) -> Result<ServerSessionClosed, RemoteSignError> {
213 self.as_type::<ServerSessionClosed>(ServerMessageType::SessionClosed)
214 }
215}
216
217#[derive(Clone, Debug, Deserialize)]
219#[serde(untagged)]
220enum ServerPayload {
221 Error(ServerError),
222 Greeting(ServerGreeting),
223 SessionJoined(ServerJoined),
224 PeerMessage(ServerPeerMessage),
225 SessionClosed(ServerSessionClosed),
226}
227
228#[derive(Clone, Debug, Deserialize)]
229struct ServerError {
230 code: String,
231 message: String,
232}
233
234#[derive(Clone, Debug, Deserialize)]
235struct ServerGreeting {
236 apis: Vec<String>,
237 motd: Option<String>,
238}
239
240#[derive(Clone, Debug, Deserialize)]
241struct ServerJoined {
242 context: Option<String>,
243}
244
245#[derive(Clone, Debug, Deserialize)]
246struct ServerPeerMessage {
247 message: String,
248}
249
250#[derive(Clone, Debug, Deserialize)]
251struct ServerSessionClosed {
252 reason: Option<String>,
253}
254
255#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
256#[serde(rename_all = "kebab-case")]
257enum PeerMessageType {
258 Ping,
259 Pong,
260 RequestSigningCertificate,
261 SigningCertificate,
262 SignRequest,
263 Signature,
264}
265
266#[derive(Clone, Debug, Deserialize, Serialize)]
268struct PeerMessage {
269 #[serde(rename = "type")]
270 typ: PeerMessageType,
271 payload: Option<serde_json::Value>,
272}
273
274impl PeerMessage {
275 fn require_type(self, typ: PeerMessageType) -> Result<Self, RemoteSignError> {
276 if self.typ == typ {
277 Ok(self)
278 } else {
279 Err(RemoteSignError::ServerUnexpectedMessage(format!(
280 "{:?}",
281 self.typ
282 )))
283 }
284 }
285
286 fn as_type<T: DeserializeOwned>(
287 &self,
288 message_type: PeerMessageType,
289 ) -> Result<T, RemoteSignError> {
290 if self.typ == message_type {
291 if let Some(value) = &self.payload {
292 Ok(serde_json::from_value(value.clone())?)
293 } else {
294 Err(RemoteSignError::ClientState(
295 "no payload for requested type",
296 ))
297 }
298 } else {
299 Err(RemoteSignError::ClientState(
300 "requested payload for wrong message type",
301 ))
302 }
303 }
304
305 fn as_signing_certificate(&self) -> Result<PeerSigningCertificate, RemoteSignError> {
306 self.as_type::<PeerSigningCertificate>(PeerMessageType::SigningCertificate)
307 }
308
309 fn as_sign_request(&self) -> Result<PeerSignRequest, RemoteSignError> {
310 self.as_type::<PeerSignRequest>(PeerMessageType::SignRequest)
311 }
312
313 fn as_signature(&self) -> Result<PeerSignature, RemoteSignError> {
314 self.as_type::<PeerSignature>(PeerMessageType::Signature)
315 }
316}
317
318#[derive(Clone, Debug, Deserialize, Serialize)]
319struct PeerCertificate {
320 certificate: String,
321 #[serde(skip_serializing_if = "Vec::is_empty")]
322 chain: Vec<String>,
323}
324
325#[derive(Clone, Debug, Deserialize, Serialize)]
326#[serde(untagged)]
327enum PeerPayload {
328 SigningCertificate(PeerSigningCertificate),
329 SignRequest(PeerSignRequest),
330 Signature(PeerSignature),
331}
332
333#[derive(Clone, Debug, Deserialize, Serialize)]
334struct PeerSigningCertificate {
335 certificates: Vec<PeerCertificate>,
336}
337
338#[derive(Clone, Debug, Deserialize, Serialize)]
339struct PeerSignRequest {
340 message: String,
341}
342
343#[derive(Clone, Debug, Deserialize, Serialize)]
344struct PeerSignature {
345 message: String,
346 signature: String,
347 algorithm_oid: String,
348}
349
350const REQUIRED_ACTIONS: [&str; 4] = ["create-session", "join-session", "send-message", "goodbye"];
351
352enum ServerResponse {
354 Closed,
356
357 Message(ServerMessage),
359}
360
361pub type SessionInfoCallback = fn(sjs_base64: &str, sjs_pem: &str) -> Result<(), RemoteSignError>;
363
364fn create_websocket(
365 req: impl IntoClientRequest,
366) -> Result<WebSocket<MaybeTlsStream<TcpStream>>, RemoteSignError> {
367 let config = WebSocketConfig {
368 ..Default::default()
369 };
370
371 let req = req.into_client_request()?;
372 warn!("connecting to {}", req.uri());
373
374 let (ws, _) = tungstenite::client::connect_with_config(req, Some(config), 5)?;
375
376 Ok(ws)
377}
378
379fn wait_for_server_response(
380 ws: &mut WebSocket<MaybeTlsStream<TcpStream>>,
381) -> Result<ServerResponse, RemoteSignError> {
382 loop {
383 match ws.read()? {
384 Message::Text(text) => {
385 let message = serde_json::from_str::<ServerMessage>(&text)?;
386 debug!(
387 "received message; request-id: {}; type: {:?}",
388 message
389 .request_id
390 .as_ref()
391 .unwrap_or(&"(not set)".to_string()),
392 message.typ
393 );
394
395 return Ok(ServerResponse::Message(message));
396 }
397 Message::Binary(_) => {
398 return Err(RemoteSignError::ServerUnexpectedMessage(
399 "binary websocket message".into(),
400 ))
401 }
402 Message::Pong(_) => {}
404 Message::Ping(_) => {}
405 Message::Frame(_) => {}
406 Message::Close(_) => {
407 return Ok(ServerResponse::Closed);
408 }
409 }
410 }
411}
412
413fn wait_for_server_message(
414 ws: &mut WebSocket<MaybeTlsStream<TcpStream>>,
415) -> Result<ServerMessage, RemoteSignError> {
416 match wait_for_server_response(ws)? {
417 ServerResponse::Closed => Err(RemoteSignError::ClientState("server closed connection")),
418 ServerResponse::Message(m) => {
419 debug!(
420 "received server message {:?}; remaining session TTL: {}",
421 m.typ,
422 m.ttl.unwrap_or_default()
423 );
424 Ok(m)
425 }
426 }
427}
428
429fn wait_for_expected_server_message(
430 ws: &mut WebSocket<MaybeTlsStream<TcpStream>>,
431 message_type: ServerMessageType,
432) -> Result<ServerMessage, RemoteSignError> {
433 let res = wait_for_server_message(ws)?.into_result()?;
434
435 if res.typ == message_type {
436 Ok(res)
437 } else {
438 Err(RemoteSignError::ServerUnexpectedMessage(format!(
439 "{:?}",
440 res.typ
441 )))
442 }
443}
444
445pub struct UnjoinedSigningClient {
449 ws: WebSocket<MaybeTlsStream<TcpStream>>,
450}
451
452impl UnjoinedSigningClient {
453 fn new(req: impl IntoClientRequest) -> Result<Self, RemoteSignError> {
454 let ws = create_websocket(req)?;
455
456 let mut slf = Self { ws };
457
458 slf.send_hello()?;
459
460 Ok(slf)
461 }
462
463 pub fn new_initiator(
465 req: impl IntoClientRequest,
466 initiator: Box<dyn SessionInitiatePeer>,
467 session_info_cb: Option<SessionInfoCallback>,
468 ) -> Result<InitiatorClient, RemoteSignError> {
469 let slf = Self::new(req)?;
470 slf.create_session_and_wait_for_signer(initiator, session_info_cb)
471 }
472
473 pub fn new_signer(
475 joiner: Box<dyn SessionJoinPeerPreJoin>,
476 signing_key: &dyn KeyInfoSigner,
477 signing_cert: CapturedX509Certificate,
478 certificates: Vec<CapturedX509Certificate>,
479 default_server_url: String,
480 ) -> Result<SigningClient, RemoteSignError> {
481 let join_context = joiner.join_context()?;
487
488 let server_url = join_context
489 .server_url
490 .as_ref()
491 .unwrap_or(&default_server_url);
492
493 let slf = Self::new(server_url)?;
494 slf.join_session(join_context, signing_key, signing_cert, certificates)
495 }
496
497 fn create_session_and_wait_for_signer(
499 mut self,
500 initiator: Box<dyn SessionInitiatePeer>,
501 session_info_cb: Option<SessionInfoCallback>,
502 ) -> Result<InitiatorClient, RemoteSignError> {
503 let session_id = initiator.session_id().to_string();
504
505 self.send_request(
506 ApiMethod::CreateSession,
507 Some(ClientPayload::CreateSession {
508 session_id: session_id.clone(),
509 ttl: 600,
510 context: initiator
511 .session_create_context()
512 .map(|x| STANDARD_ENGINE.encode(x)),
513 }),
514 )?;
515
516 let sjs_base64 = initiator.session_join_string_base64()?;
517 let sjs_pem = initiator.session_join_string_pem()?;
518
519 wait_for_expected_server_message(&mut self.ws, ServerMessageType::SessionCreated)?;
520 warn!("session successfully created on server");
521
522 if let Some(cb) = session_info_cb {
523 cb(&sjs_base64, &sjs_pem)?;
524 }
525
526 let res = wait_for_expected_server_message(&mut self.ws, ServerMessageType::SessionJoined)?;
527
528 let joined = res.as_session_joined()?;
529 warn!("signer joined session; deriving shared encryption key");
530
531 let context = if let Some(context) = joined.context {
532 Some(STANDARD_ENGINE.decode(context)?)
533 } else {
534 None
535 };
536
537 let keys = initiator.negotiate_session(context)?;
538
539 let mut client = PairedClient {
540 ws: self.ws,
541 session_id,
542 keys,
543 };
544
545 client.send_ping()?;
546
547 let (signing_cert, signing_chain) = client.request_signing_certificate()?;
548
549 if let Some(name) = signing_cert.subject_common_name() {
550 warn!("remote signer will sign with certificate: {}", name);
551 }
552
553 Ok(InitiatorClient {
554 client: RefCell::new(client),
555 signing_cert,
556 signing_chain,
557 })
558 }
559
560 pub fn join_session(
564 mut self,
565 join_context: SessionJoinContext,
566 signing_key: &dyn KeyInfoSigner,
567 signing_cert: CapturedX509Certificate,
568 certificates: Vec<CapturedX509Certificate>,
569 ) -> Result<SigningClient, RemoteSignError> {
570 let session_id = join_context.session_id.clone();
571
572 warn!("joining session...");
573 self.send_request(
574 ApiMethod::JoinSession,
575 Some(ClientPayload::JoinSession {
576 session_id: session_id.clone(),
577 context: join_context.peer_context.map(|x| STANDARD_ENGINE.encode(x)),
578 }),
579 )?;
580
581 wait_for_expected_server_message(&mut self.ws, ServerMessageType::SessionJoined)?;
582
583 warn!("successfully joined signing session {}", session_id);
584
585 let keys = join_context.peer_handshake.negotiate_session()?;
586
587 let mut client = PairedClient {
588 ws: self.ws,
589 session_id,
590 keys,
591 };
592
593 warn!("verifying encrypted communications with peer");
594 client.send_ping()?;
595
596 Ok(SigningClient {
597 client: RefCell::new(client),
598 signing_key,
599 signing_cert,
600 certificates,
601 })
602 }
603
604 fn send_request(
605 &mut self,
606 api: ApiMethod,
607 payload: Option<ClientPayload>,
608 ) -> Result<(), RemoteSignError> {
609 let request_id = uuid::Uuid::new_v4().to_string();
610
611 let message = ClientMessage {
612 request_id,
613 api,
614 payload,
615 };
616
617 let body = serde_json::to_string(&message)?;
618 self.ws.send(body.into())?;
619 self.ws.flush()?;
620
621 Ok(())
622 }
623
624 fn send_hello(&mut self) -> Result<(), RemoteSignError> {
625 self.send_request(ApiMethod::Hello, None)?;
626
627 let res = wait_for_expected_server_message(&mut self.ws, ServerMessageType::Greeting)?;
628 let greeting = res.as_greeting()?;
629
630 if let Some(motd) = &greeting.motd {
631 warn!("message from remote server: {}", motd);
632 }
633
634 for required in REQUIRED_ACTIONS {
635 if !greeting.apis.contains(&required.to_string()) {
636 error!("server does not support required action {}", required);
637 return Err(RemoteSignError::ServerIncompatible);
638 }
639 }
640
641 Ok(())
642 }
643}
644
645pub struct PairedClient {
647 ws: WebSocket<MaybeTlsStream<TcpStream>>,
648 session_id: String,
649 keys: PeerKeys,
650}
651
652impl Drop for PairedClient {
653 fn drop(&mut self) {
654 warn!("disconnecting from relay server");
655 }
656}
657
658impl PairedClient {
659 fn send_request(
660 &mut self,
661 api: ApiMethod,
662 payload: Option<ClientPayload>,
663 ) -> Result<(), RemoteSignError> {
664 let request_id = uuid::Uuid::new_v4().to_string();
665
666 let message = ClientMessage {
667 request_id,
668 api,
669 payload,
670 };
671
672 let body = serde_json::to_string(&message)?;
673 self.ws.send(body.into())?;
674 self.ws.flush()?;
675
676 Ok(())
677 }
678
679 fn decrypt_peer_message(
680 &mut self,
681 message: &ServerPeerMessage,
682 ) -> Result<PeerMessage, RemoteSignError> {
683 let ciphertext = STANDARD_ENGINE.decode(&message.message)?;
684
685 let plaintext = self.keys.open(ciphertext)?;
686
687 Ok(serde_json::from_slice(&plaintext)?)
688 }
689
690 fn send_encrypted_message(
691 &mut self,
692 message_type: PeerMessageType,
693 payload: Option<PeerPayload>,
694 ) -> Result<(), RemoteSignError> {
695 let message = PeerMessage {
696 typ: message_type,
697 payload: if let Some(payload) = payload {
698 Some(serde_json::to_value(payload)?)
699 } else {
700 None
701 },
702 };
703
704 let ciphertext = self.keys.seal(&serde_json::to_vec(&message)?)?;
705
706 self.send_request(
707 ApiMethod::SendMessage,
708 Some(ClientPayload::SendMessage {
709 session_id: self.session_id.clone(),
710 message: STANDARD_ENGINE.encode(ciphertext),
711 }),
712 )?;
713
714 Ok(())
715 }
716
717 fn wait_for_peer_message(&mut self) -> Result<Option<PeerMessage>, RemoteSignError> {
718 let res = wait_for_server_message(&mut self.ws)?.into_result()?;
719
720 if let Ok(closed) = res.as_session_closed() {
721 warn!(
722 "signing session closed; reason: {}",
723 closed
724 .reason
725 .as_ref()
726 .unwrap_or(&"(none given)".to_string())
727 );
728 Ok(None)
729 } else {
730 let message = res.as_peer_message()?;
731
732 Ok(Some(self.decrypt_peer_message(&message)?))
733 }
734 }
735
736 fn wait_for_server_and_peer_response(&mut self) -> Result<PeerMessage, RemoteSignError> {
737 let mut response = None;
738
739 for _ in 0..2 {
742 let res = wait_for_server_message(&mut self.ws)?.into_result()?;
743
744 match res.typ {
745 ServerMessageType::MessageSent => {}
746 ServerMessageType::PeerMessage => {
747 let message = res.as_peer_message()?;
748
749 response = Some(self.decrypt_peer_message(&message)?);
750 }
751 m => return Err(RemoteSignError::ServerUnexpectedMessage(format!("{m:?}"))),
752 }
753 }
754
755 if let Some(response) = response {
756 Ok(response)
757 } else {
758 Err(RemoteSignError::ClientState(
759 "failed to receive response from server or peer",
760 ))
761 }
762 }
763
764 fn send_goodbye(&mut self, reason: Option<String>) -> Result<(), RemoteSignError> {
765 warn!("terminating signing session on relay");
766 self.send_request(
767 ApiMethod::Goodbye,
768 Some(ClientPayload::Goodbye {
769 session_id: self.session_id.clone(),
770 reason,
771 }),
772 )?;
773
774 wait_for_server_message(&mut self.ws)?.into_result()?;
775 warn!("relay server confirmed session termination");
776
777 Ok(())
778 }
779
780 fn send_ping(&mut self) -> Result<(), RemoteSignError> {
781 self.send_encrypted_message(PeerMessageType::Ping, None)?;
784 let message = self.wait_for_server_and_peer_response()?;
785 if !matches!(message.typ, PeerMessageType::Ping) {
786 return Err(RemoteSignError::ServerUnexpectedMessage(
787 "unexpected response to ping message".into(),
788 ));
789 }
790
791 self.send_encrypted_message(PeerMessageType::Pong, None)?;
792 let message = self.wait_for_server_and_peer_response()?;
793 if !matches!(message.typ, PeerMessageType::Pong) {
794 return Err(RemoteSignError::ServerUnexpectedMessage(
795 "unexpected response to ping message".into(),
796 ));
797 }
798
799 Ok(())
800 }
801
802 pub fn request_signing_certificate(
804 &mut self,
805 ) -> Result<(CapturedX509Certificate, Vec<CapturedX509Certificate>), RemoteSignError> {
806 warn!("requesting signing certificate info from signer");
807 self.send_encrypted_message(PeerMessageType::RequestSigningCertificate, None)?;
808 let res = self
809 .wait_for_server_and_peer_response()?
810 .require_type(PeerMessageType::SigningCertificate)?;
811
812 let cert = res.as_signing_certificate()?;
813
814 if let Some(cert) = cert.certificates.get(0) {
815 let cert_der = STANDARD_ENGINE.decode(&cert.certificate)?;
816 let chain_der = cert
817 .chain
818 .iter()
819 .map(|x| STANDARD_ENGINE.decode(x))
820 .collect::<Result<Vec<_>, base64::DecodeError>>()?;
821
822 let cert = CapturedX509Certificate::from_der(cert_der)?;
823 let chain = chain_der
824 .into_iter()
825 .map(CapturedX509Certificate::from_der)
826 .collect::<Result<Vec<_>, X509CertificateError>>()?;
827
828 return Ok((cert, chain));
829 }
830
831 Err(RemoteSignError::ClientState(
832 "did not receive any signing certificates from peer",
833 ))
834 }
835}
836
837pub struct InitiatorClient {
839 client: RefCell<PairedClient>,
840 signing_cert: CapturedX509Certificate,
841 signing_chain: Vec<CapturedX509Certificate>,
842}
843
844impl InitiatorClient {
845 pub fn signing_certificate(&self) -> &CapturedX509Certificate {
847 &self.signing_cert
848 }
849
850 pub fn certificate_chain(&self) -> &[CapturedX509Certificate] {
852 &self.signing_chain
853 }
854}
855
856impl Signer<Signature> for InitiatorClient {
857 fn try_sign(&self, message: &[u8]) -> Result<Signature, signature::Error> {
858 let mut client = self.client.borrow_mut();
859
860 warn!("sending signing request to remote signer");
861
862 client
863 .send_encrypted_message(
864 PeerMessageType::SignRequest,
865 Some(PeerPayload::SignRequest(PeerSignRequest {
866 message: STANDARD_ENGINE.encode(message),
867 })),
868 )
869 .map_err(signature::Error::from_source)?;
870
871 let response = client
872 .wait_for_server_and_peer_response()
873 .map_err(signature::Error::from_source)?
874 .require_type(PeerMessageType::Signature)
875 .map_err(signature::Error::from_source)?;
876
877 let peer_signature = response
878 .as_signature()
879 .map_err(signature::Error::from_source)?;
880
881 warn!("received signature from remote signer");
882
883 let signature = STANDARD_ENGINE
884 .decode(&peer_signature.signature)
885 .map_err(signature::Error::from_source)?;
886 let oid_der = STANDARD_ENGINE
887 .decode(&peer_signature.algorithm_oid)
888 .map_err(signature::Error::from_source)?;
889
890 bcder::decode::Constructed::decode(oid_der.as_ref(), Mode::Der, |cons| {
891 Oid::take_from(cons)
892 })
893 .map_err(|_| {
894 signature::Error::from_source(RemoteSignError::Crypto(
895 "error parsing signature OID".into(),
896 ))
897 })?;
898
899 if let Err(e) = self.signing_cert.verify_signed_data(message, &signature) {
903 error!("Peer issued signature did not verify against the certificate they provided");
904 error!("The peer could be acting maliciously. Or it could just be buggy.");
905 error!("Either way, it didn't issue a valid signature, so we're giving up.");
906
907 return Err(signature::Error::from_source(e));
908 }
909
910 Ok(signature.into())
911 }
912}
913
914impl Sign for InitiatorClient {
915 fn sign(&self, message: &[u8]) -> Result<(Vec<u8>, SignatureAlgorithm), X509CertificateError> {
916 let algorithm = self.signature_algorithm()?;
917
918 Ok((self.try_sign(message)?.into(), algorithm))
919 }
920
921 fn key_algorithm(&self) -> Option<KeyAlgorithm> {
922 self.signing_cert.key_algorithm()
923 }
924
925 fn public_key_data(&self) -> Bytes {
926 self.signing_cert.public_key_data()
927 }
928
929 fn signature_algorithm(&self) -> Result<SignatureAlgorithm, X509CertificateError> {
930 if let Some(algorithm) = self.signing_cert.signature_algorithm() {
931 Ok(algorithm)
932 } else {
933 Err(X509CertificateError::UnknownSignatureAlgorithm(format!(
934 "{}",
935 self.signing_cert.signature_algorithm_oid()
936 )))
937 }
938 }
939
940 fn private_key_data(&self) -> Option<Zeroizing<Vec<u8>>> {
941 None
943 }
944
945 fn rsa_primes(
946 &self,
947 ) -> Result<Option<(Zeroizing<Vec<u8>>, Zeroizing<Vec<u8>>)>, X509CertificateError> {
948 Ok(None)
950 }
951}
952
953impl KeyInfoSigner for InitiatorClient {}
954
955impl PublicKeyPeerDecrypt for InitiatorClient {
956 fn decrypt(&self, _ciphertext: &[u8]) -> Result<Vec<u8>, RemoteSignError> {
957 Err(RemoteSignError::Crypto(
958 "a remote signer cannot be used to perform signing".into(),
959 ))
960 }
961}
962
963impl PrivateKey for InitiatorClient {
964 fn as_key_info_signer(&self) -> &dyn KeyInfoSigner {
965 self
966 }
967
968 fn to_public_key_peer_decrypt(
969 &self,
970 ) -> Result<Box<dyn PublicKeyPeerDecrypt>, AppleCodesignError> {
971 Err(
972 RemoteSignError::ClientState("cannot use remote signing initiator for decryption")
973 .into(),
974 )
975 }
976
977 fn finish(&self) -> Result<(), AppleCodesignError> {
978 Ok(self
980 .client
981 .borrow_mut()
982 .send_goodbye(Some("signing operations completed".into()))?)
983 }
984}
985
986pub struct SigningClient<'key> {
987 client: RefCell<PairedClient>,
988 signing_key: &'key dyn KeyInfoSigner,
989 signing_cert: CapturedX509Certificate,
990 certificates: Vec<CapturedX509Certificate>,
991}
992
993impl<'key> SigningClient<'key> {
994 fn send_signing_certificate(
995 &self,
996 mut client: RefMut<PairedClient>,
997 ) -> Result<(), RemoteSignError> {
998 client.send_encrypted_message(
999 PeerMessageType::SigningCertificate,
1000 Some(PeerPayload::SigningCertificate(PeerSigningCertificate {
1001 certificates: vec![PeerCertificate {
1002 certificate: STANDARD_ENGINE.encode(self.signing_cert.encode_der()?),
1003 chain: self
1004 .certificates
1005 .iter()
1006 .map(|cert| {
1007 let der = cert.encode_der()?;
1008
1009 Ok(STANDARD_ENGINE.encode(der))
1010 })
1011 .collect::<Result<Vec<_>, RemoteSignError>>()?,
1012 }],
1013 })),
1014 )?;
1015
1016 wait_for_expected_server_message(&mut client.ws, ServerMessageType::MessageSent)?;
1017
1018 Ok(())
1019 }
1020
1021 fn handle_sign_request(
1022 &self,
1023 mut client: RefMut<PairedClient>,
1024 request: PeerSignRequest,
1025 ) -> Result<(), RemoteSignError> {
1026 let message = STANDARD_ENGINE.decode(&request.message)?;
1027
1028 warn!(
1029 "creating signature for remote message: {}",
1030 &request.message
1031 );
1032 let signature = self
1033 .signing_key
1034 .try_sign(&message)
1035 .map_err(|e| RemoteSignError::Crypto(format!("when creating signature: {e}")))?;
1036 let algorithm = self.signing_key.signature_algorithm()?;
1037
1038 let oid = Oid::from(algorithm);
1039 let mut oid_der = vec![];
1040 oid.encode().write_encoded(Mode::Der, &mut oid_der)?;
1041
1042 warn!("sending signature to peer");
1043 client.send_encrypted_message(
1044 PeerMessageType::Signature,
1045 Some(PeerPayload::Signature(PeerSignature {
1046 message: STANDARD_ENGINE.encode(message),
1047 signature: STANDARD_ENGINE.encode(signature),
1048 algorithm_oid: STANDARD_ENGINE.encode(oid_der),
1049 })),
1050 )?;
1051
1052 wait_for_expected_server_message(&mut client.ws, ServerMessageType::MessageSent)?;
1053 warn!("relay acknowledged signature message received");
1054
1055 Ok(())
1056 }
1057
1058 fn process_next_message(&self) -> Result<bool, RemoteSignError> {
1059 let mut client = self.client.borrow_mut();
1060
1061 warn!("waiting for server to send us a message...");
1062 let res = if let Some(res) = client.wait_for_peer_message()? {
1063 res
1064 } else {
1065 return Ok(false);
1066 };
1067
1068 match res.typ {
1069 PeerMessageType::RequestSigningCertificate => {
1070 self.send_signing_certificate(client)?;
1071 }
1072 PeerMessageType::Ping => {
1073 client.send_encrypted_message(PeerMessageType::Pong, None)?;
1074 wait_for_expected_server_message(&mut client.ws, ServerMessageType::MessageSent)?;
1075 }
1076 PeerMessageType::Pong => {}
1077 PeerMessageType::SignRequest => {
1078 self.handle_sign_request(client, res.as_sign_request()?)?;
1079 }
1080 typ => {
1081 warn!("unprocessed message: {:?}", typ);
1082 }
1083 }
1084
1085 Ok(true)
1086 }
1087
1088 pub fn run(self) -> Result<(), RemoteSignError> {
1089 while self.process_next_message()? {}
1090
1091 Ok(())
1092 }
1093}