reach_core/communication/secrets/
mod.rs

1// SPDX-FileCopyrightText: 2023—2025 eaon <eaon@posteo.net>
2// SPDX-FileCopyrightText: 2025 Michael Goldenberg <m@mgoldenberg.net>
3// SPDX-License-Identifier: EUPL-1.2
4
5use zeroize::{Zeroize, Zeroizing};
6
7use reach_aliases::EnvelopeIdHints as WireEnvelopeIdHints;
8use reach_proc_macros::{communicable, prosted};
9
10use crate::{
11    communication::*,
12    error,
13    macros::from_generic_websocket_error,
14    memory::{
15        HintedEnvelopeId as MemoryHintedEnvelopeId, Message as MemoryMessage,
16        SharedSecretKeys as MemorySharedSecretKeys,
17    },
18    storage::{
19        ReachablePublicKeyRing as StorageReachablePublicKeyRing, Storable,
20        UnsignedReachableVerifyingKeys as StorageUnsignedReachableVerifyingKeys,
21    },
22    traits::*,
23    wire::{
24        AttestantVerifyingKeys as WireAttestantVerifyingKeys, Envelope as WireEnvelope,
25        MessageVault as WireMessageVault, MessageVaultId as WireMessageVaultId,
26        ReachableVerifyingKeys as WireReachableVerifyingKeys, Salts as WireSalts,
27    },
28};
29
30mod v0 {
31    include!(concat!(env!("OUT_DIR"), "/reach.ipc_secrets_v0.rs"));
32
33    pub mod communication {
34        include!(concat!(
35            env!("OUT_DIR"),
36            "/reach.ipc_secrets_communication_v0.rs"
37        ));
38    }
39}
40
41pub(crate) mod proto {
42    use super::v0;
43
44    pub(crate) use v0::{
45        AllReachableVerifyingKeys, GetReachablePublicKeys, HintedEnvelopeIds, Initialize,
46        Initialized, UnlockKey,
47    };
48}
49
50pub use v0::communication::{Request, Response};
51
52impl CommunicableType for Request {}
53impl CommunicableType for Response {}
54
55#[derive(Debug, Clone, Copy)]
56pub enum ErrorResponse {
57    Locked,
58    MissingVerifyingKeys,
59    Uninitialized,
60    Unsupported,
61    Internal,
62    Decode,
63}
64
65impl From<ErrorResponse> for Response {
66    fn from(value: ErrorResponse) -> Self {
67        match value {
68            ErrorResponse::Locked => Response::ErrorLocked,
69            ErrorResponse::MissingVerifyingKeys => Response::ErrorMissingVerifyingKeys,
70            ErrorResponse::Uninitialized => Response::ErrorUninitialized,
71            ErrorResponse::Unsupported => Response::ErrorUnsupported,
72            ErrorResponse::Internal => Response::ErrorInternal,
73            ErrorResponse::Decode => Response::ErrorDecode,
74        }
75    }
76}
77
78impl ErrorSubset for Response {
79    type Error = ErrorResponse;
80}
81
82#[cfg(feature = "websocket")]
83from_generic_websocket_error!(Response);
84
85pub struct SecretsCommunication {}
86
87impl CommunicableTypes for SecretsCommunication {
88    type Req = Request;
89    type Resp = Response;
90    type Variant = LocalCommunication;
91}
92
93impl CommunicableOwned<Request> for WireEnvelopeIdHints {
94    fn to_communication(self) -> Communication<Request> {
95        Communication::from(Request::EnvelopeIdHints, self.to_bytes(), None)
96    }
97
98    fn try_from_communication(
99        communication: &Communication<Request>,
100    ) -> Result<Self, error::DecodeError> {
101        Ok(WireEnvelopeIdHints::from_bytes(&communication.inner)?)
102    }
103}
104
105impl ProstCommunicable<Request> for WireEnvelope {
106    const COMMUNICATION_VARIANT: Request = Request::Envelope;
107}
108
109impl ProstCommunicable<Request> for WireMessageVault {
110    const COMMUNICATION_VARIANT: Request = Request::MessageVault;
111}
112
113#[derive(Debug)]
114#[communicable(Response::Ok, marker)]
115pub struct SecretsOk;
116
117#[derive(Debug)]
118#[prosted(proto::UnlockKey, Encode, Decode, ProstTraits)]
119pub struct UnlockKey {
120    pub passphrase: String,
121}
122
123impl ProstCommunicable<Request> for UnlockKey {
124    const COMMUNICATION_VARIANT: Request = Request::UnlockKey;
125}
126
127impl MatchResponse<Request> for UnlockKey {
128    type Resp = SecretsOk;
129}
130
131#[derive(Debug)]
132#[communicable(Request::GetReachablePublicKeys)]
133#[prosted(proto::GetReachablePublicKeys, Encode, Decode, ProstTraits)]
134pub struct GetReachablePublicKeys {
135    pub amount: u16,
136}
137
138impl MatchResponse<Request> for GetReachablePublicKeys {
139    type Resp = StorageReachablePublicKeyRing;
140}
141
142#[derive(Debug)]
143#[communicable(Request::Hello, marker)]
144pub struct Hello;
145
146impl MatchResponse<Request> for Hello {
147    type Resp = SecretsOk;
148}
149
150#[derive(Debug)]
151#[communicable(Request::Initialize)]
152#[prosted(proto::Initialize, Encode, Decode, ProstTraits)]
153pub struct Initialize {
154    pub salts: WireSalts,
155    pub attestant_verifying_keys: WireAttestantVerifyingKeys,
156}
157
158#[derive(Debug)]
159#[communicable(Response::Initialized)]
160#[prosted(proto::Initialized, Encode, Decode, ProstTraits)]
161pub struct Initialized {
162    pub passphrase: Zeroizing<String>,
163    pub unsigned_reachable_verifying_keys: StorageUnsignedReachableVerifyingKeys,
164}
165
166impl Drop for proto::Initialized {
167    fn drop(&mut self) {
168        self.passphrase.zeroize();
169    }
170}
171
172impl MatchResponse<Request> for Initialize {
173    type Resp = Initialized;
174}
175
176impl ProstCommunicable<Request> for MemorySharedSecretKeys {
177    const COMMUNICATION_VARIANT: Request = Request::SharedSecretKeys;
178}
179
180#[derive(Debug)]
181#[communicable(Response::HintedEnvelopeIds)]
182#[prosted(proto::HintedEnvelopeIds, Decode, Encode, ProstTraits)]
183pub struct HintedEnvelopeIds {
184    pub hinted_envelope_ids: Vec<MemoryHintedEnvelopeId>,
185}
186
187impl ProstCommunicable<Response> for WireMessageVaultId {
188    const COMMUNICATION_VARIANT: Response = Response::MessageVaultId;
189}
190
191impl ProstCommunicableOwned<Response> for MemoryMessage {
192    const COMMUNICATION_VARIANT: Response = Response::Message;
193}
194
195#[derive(Debug)]
196#[communicable(Request::GetUnsignedReachableVerifyingKeys, marker)]
197pub struct GetUnsignedReachableVerifyingKeys;
198
199#[derive(Debug)]
200#[communicable(Request::GenerateSigningKeys, marker)]
201pub struct GenerateSigningKeys;
202
203#[derive(Debug)]
204#[communicable(Request::AllReachableVerifyingKeys)]
205#[prosted(proto::AllReachableVerifyingKeys, Decode, Encode, ProstTraits)]
206pub struct AllReachableVerifyingKeys {
207    pub reachable_verifying_keys: Vec<WireReachableVerifyingKeys>,
208}
209
210impl Storable for AllReachableVerifyingKeys {}
211
212impl MatchResponse<Request> for AllReachableVerifyingKeys {
213    type Resp = SecretsOk;
214}
215
216impl ProstCommunicable<Response> for StorageUnsignedReachableVerifyingKeys {
217    const COMMUNICATION_VARIANT: Response = Response::UnsignedReachableVerifyingKeys;
218}