Skip to main content

veilid_core/crypto/
guard.rs

1use core::marker::PhantomData;
2use std::ops::Range;
3
4use super::*;
5
6/// Guard to access a particular cryptosystem
7#[must_use]
8pub struct CryptoSystemGuard<'a> {
9    crypto_system: Arc<dyn CryptoSystem + Send + Sync>,
10    _phantom: core::marker::PhantomData<&'a (dyn CryptoSystem + Send + Sync)>,
11}
12
13impl<'a> CryptoSystemGuard<'a> {
14    pub(super) fn new(crypto_system: Arc<dyn CryptoSystem + Send + Sync>) -> Self {
15        Self {
16            crypto_system,
17            _phantom: PhantomData,
18        }
19    }
20    pub fn as_async(self) -> AsyncCryptoSystemGuard<'a> {
21        AsyncCryptoSystemGuard { guard: self }
22    }
23    /// Get a clone of the inner Arc for use in blocking tasks
24    pub(super) fn clone_arc(&self) -> Arc<dyn CryptoSystem + Send + Sync> {
25        self.crypto_system.clone()
26    }
27}
28
29impl core::ops::Deref for CryptoSystemGuard<'_> {
30    type Target = dyn CryptoSystem + Send + Sync;
31
32    fn deref(&self) -> &Self::Target {
33        self.crypto_system.as_ref()
34    }
35}
36
37/// Async cryptosystem guard to help break up heavy blocking operations
38#[must_use]
39pub struct AsyncCryptoSystemGuard<'a> {
40    guard: CryptoSystemGuard<'a>,
41}
42
43impl AsyncCryptoSystemGuard<'_> {
44    // Accessors
45    pub fn kind(&self) -> CryptoKind {
46        self.guard.kind()
47    }
48    #[must_use]
49    pub fn crypto(&self) -> VeilidComponentGuard<'_, Crypto> {
50        self.guard.crypto()
51    }
52
53    // Cached Operations
54    pub async fn cached_dh(
55        &self,
56        key: &PublicKey,
57        secret: &SecretKey,
58    ) -> VeilidAPIResult<SharedSecret> {
59        yielding(|| self.guard.cached_dh(key, secret)).await
60    }
61
62    // Generation
63    pub async fn random_bytes(&self, len: usize) -> Bytes {
64        yielding(|| self.guard.random_bytes(len).into()).await
65    }
66
67    pub async fn hash_password(&self, password: Bytes, salt: Bytes) -> VeilidAPIResult<String> {
68        let cs = self.guard.clone_arc();
69        let salt = salt.to_vec();
70        cpu_yielding(move || cs.hash_password(&password, &salt)).await
71    }
72    pub async fn verify_password(
73        &self,
74        password: Bytes,
75        password_hash: &str,
76    ) -> VeilidAPIResult<bool> {
77        let cs = self.guard.clone_arc();
78        let password_hash = password_hash.to_string();
79        cpu_yielding(move || cs.verify_password(&password, &password_hash)).await
80    }
81    pub async fn derive_shared_secret(
82        &self,
83        password: Bytes,
84        salt: Bytes,
85    ) -> VeilidAPIResult<SharedSecret> {
86        yielding(|| self.guard.derive_shared_secret(&password, &salt)).await
87    }
88    pub async fn random_nonce(&self) -> Nonce {
89        yielding(|| self.guard.random_nonce()).await
90    }
91    pub async fn random_shared_secret(&self) -> SharedSecret {
92        yielding(|| self.guard.random_shared_secret()).await
93    }
94    pub async fn compute_dh(
95        &self,
96        key: &PublicKey,
97        secret: &SecretKey,
98    ) -> VeilidAPIResult<SharedSecret> {
99        let cs = self.guard.clone_arc();
100        let key = key.clone();
101        let secret = secret.clone();
102        cpu_yielding(move || cs.compute_dh(&key, &secret)).await
103    }
104    pub async fn generate_shared_secret(
105        &self,
106        key: &PublicKey,
107        secret: &SecretKey,
108        domain: Bytes,
109    ) -> VeilidAPIResult<SharedSecret> {
110        let dh = self.compute_dh(key, secret).await?;
111        let data = [
112            dh.ref_value().bytes().as_ref(),
113            domain.as_ref(),
114            VEILID_DOMAIN_API,
115        ]
116        .concat()
117        .into();
118        let hash = self.generate_hash(data).await;
119        Ok(SharedSecret::new(
120            hash.kind(),
121            BareSharedSecret::new(&hash.into_value()),
122        ))
123    }
124
125    pub async fn generate_keypair(&self) -> KeyPair {
126        yielding(|| self.guard.generate_keypair()).await
127    }
128
129    pub async fn generate_hash(&self, data: Bytes) -> HashDigest {
130        yielding(|| self.guard.generate_hash(&data)).await
131    }
132
133    pub async fn generate_hash_reader(
134        &self,
135        reader: &mut dyn std::io::Read,
136    ) -> VeilidAPIResult<PublicKey> {
137        yielding(|| self.guard.generate_hash_reader(reader)).await
138    }
139
140    // Validation
141    #[must_use]
142    pub fn shared_secret_length(&self) -> usize {
143        self.guard.shared_secret_length()
144    }
145    #[must_use]
146    pub fn nonce_length(&self) -> usize {
147        self.guard.nonce_length()
148    }
149    #[must_use]
150    pub fn hash_digest_length(&self) -> usize {
151        self.guard.hash_digest_length()
152    }
153    #[must_use]
154    pub fn public_key_length(&self) -> usize {
155        self.guard.public_key_length()
156    }
157    #[must_use]
158    pub fn secret_key_length(&self) -> usize {
159        self.guard.secret_key_length()
160    }
161    #[must_use]
162    pub fn signature_length(&self) -> usize {
163        self.guard.signature_length()
164    }
165    #[must_use]
166    pub fn aead_overhead(&self) -> usize {
167        self.guard.aead_overhead()
168    }
169    #[must_use]
170    pub fn default_salt_length(&self) -> usize {
171        self.guard.default_salt_length()
172    }
173    pub fn check_shared_secret(&self, secret: &SharedSecret) -> VeilidAPIResult<()> {
174        self.guard.check_shared_secret(secret)
175    }
176    pub fn check_nonce(&self, nonce: &Nonce) -> VeilidAPIResult<()> {
177        self.guard.check_nonce(nonce)
178    }
179    pub fn check_hash_digest(&self, hash: &HashDigest) -> VeilidAPIResult<()> {
180        self.guard.check_hash_digest(hash)
181    }
182    pub fn check_public_key(&self, key: &PublicKey) -> VeilidAPIResult<()> {
183        self.guard.check_public_key(key)
184    }
185    pub fn check_secret_key(&self, key: &SecretKey) -> VeilidAPIResult<()> {
186        self.guard.check_secret_key(key)
187    }
188    pub fn check_signature(&self, signature: &Signature) -> VeilidAPIResult<()> {
189        self.guard.check_signature(signature)
190    }
191    pub async fn validate_keypair(
192        &self,
193        key: &PublicKey,
194        secret: &SecretKey,
195    ) -> VeilidAPIResult<bool> {
196        yielding(|| self.guard.validate_keypair(key, secret)).await
197    }
198
199    pub async fn validate_hash(&self, data: Bytes, hash: &HashDigest) -> VeilidAPIResult<bool> {
200        yielding(|| self.guard.validate_hash(&data, hash)).await
201    }
202
203    pub async fn validate_hash_reader(
204        &self,
205        reader: &mut dyn std::io::Read,
206        hash: &HashDigest,
207    ) -> VeilidAPIResult<bool> {
208        yielding(|| self.guard.validate_hash_reader(reader, hash)).await
209    }
210
211    // Authentication
212    pub async fn sign(
213        &self,
214        public_key: &PublicKey,
215        secret: &SecretKey,
216        data: Bytes,
217    ) -> VeilidAPIResult<Signature> {
218        let cs = self.guard.clone_arc();
219        let public_key = public_key.clone();
220        let secret = secret.clone();
221        cpu_yielding(move || cs.sign(&public_key, &secret, &data)).await
222    }
223
224    pub async fn sign_in_place(
225        &self,
226        public_key: &PublicKey,
227        secret: &SecretKey,
228        mut data: BytesMut,
229        range: Range<usize>,
230        sig_idx: usize,
231    ) -> VeilidAPIResult<BytesMut> {
232        let cs = self.guard.clone_arc();
233        let public_key = public_key.clone();
234        let secret = secret.clone();
235        cpu_yielding(move || {
236            cs.sign_in_place(&public_key, &secret, &mut data, range, sig_idx)?;
237            Ok(data)
238        })
239        .await
240    }
241
242    pub async fn verify(
243        &self,
244        public_key: &PublicKey,
245        data: Bytes,
246        signature: &Signature,
247    ) -> VeilidAPIResult<bool> {
248        let cs = self.guard.clone_arc();
249        let public_key = public_key.clone();
250        let signature = signature.clone();
251        cpu_yielding(move || cs.verify(&public_key, &data, &signature)).await
252    }
253
254    pub async fn verify_in_place(
255        &self,
256        public_key: &PublicKey,
257        data: Bytes,
258        range: Range<usize>,
259        sig_idx: usize,
260    ) -> VeilidAPIResult<bool> {
261        let cs = self.guard.clone_arc();
262        let public_key = public_key.clone();
263        cpu_yielding(move || cs.verify_in_place(&public_key, &data, range, sig_idx)).await
264    }
265
266    // AEAD Encrypt/Decrypt
267    pub async fn decrypt_aead(
268        &self,
269        body: Bytes,
270        nonce: &Nonce,
271        shared_secret: &SharedSecret,
272        associated_data: Option<Bytes>,
273    ) -> VeilidAPIResult<Bytes> {
274        let cs = self.guard.clone_arc();
275        let nonce = nonce.clone();
276        let shared_secret = shared_secret.clone();
277        scaled_yielding(body.len(), 1024, 8192, move || {
278            Ok(cs
279                .decrypt_aead(&body, &nonce, &shared_secret, associated_data.as_deref())?
280                .into())
281        })
282        .await
283    }
284    pub async fn decrypt_in_place_aead(
285        &self,
286        mut body: BytesMut,
287        nonce: &Nonce,
288        shared_secret: &SharedSecret,
289        associated_data: Option<Bytes>,
290    ) -> VeilidAPIResult<BytesMut> {
291        let cs = self.guard.clone_arc();
292        let nonce = nonce.clone();
293        let shared_secret = shared_secret.clone();
294        scaled_yielding(body.len(), 1024, 8192, move || {
295            cs.decrypt_in_place_aead(
296                &mut body,
297                &nonce,
298                &shared_secret,
299                associated_data.as_deref(),
300            )?;
301
302            Ok(body)
303        })
304        .await
305    }
306
307    pub async fn encrypt_aead(
308        &self,
309        body: Bytes,
310        nonce: &Nonce,
311        shared_secret: &SharedSecret,
312        associated_data: Option<Bytes>,
313    ) -> VeilidAPIResult<Bytes> {
314        let cs = self.guard.clone_arc();
315        let nonce = nonce.clone();
316        let shared_secret = shared_secret.clone();
317        scaled_yielding(body.len(), 1024, 8192, move || {
318            Ok(cs
319                .encrypt_aead(&body, &nonce, &shared_secret, associated_data.as_deref())?
320                .into())
321        })
322        .await
323    }
324
325    pub async fn encrypt_in_place_aead(
326        &self,
327        mut body: BytesMut,
328        nonce: &Nonce,
329        shared_secret: &SharedSecret,
330        associated_data: Option<Bytes>,
331    ) -> VeilidAPIResult<BytesMut> {
332        let cs = self.guard.clone_arc();
333        let nonce = nonce.clone();
334        let shared_secret = shared_secret.clone();
335        scaled_yielding(body.len(), 1024, 8192, move || {
336            cs.encrypt_in_place_aead(
337                &mut body,
338                &nonce,
339                &shared_secret,
340                associated_data.as_deref(),
341            )?;
342
343            Ok(body)
344        })
345        .await
346    }
347
348    // NoAuth Encrypt/Decrypt
349    pub async fn crypt_b2b_no_auth(
350        &self,
351        in_buf: Bytes,
352        mut out_buf: BytesMut,
353        out_idx: usize,
354        nonce: &Nonce,
355        shared_secret: &SharedSecret,
356    ) -> VeilidAPIResult<BytesMut> {
357        let cs = self.guard.clone_arc();
358        let nonce = nonce.clone();
359        let shared_secret = shared_secret.clone();
360        scaled_yielding(in_buf.len(), 1024, 8192, move || {
361            cs.crypt_b2b_no_auth(
362                &in_buf,
363                &mut out_buf[out_idx..out_idx + in_buf.len()],
364                &nonce,
365                &shared_secret,
366            )?;
367            Ok(out_buf)
368        })
369        .await
370    }
371
372    pub async fn crypt_in_place_no_auth(
373        &self,
374        mut body: BytesMut,
375        range: Range<usize>,
376        nonce: &Nonce,
377        shared_secret: &SharedSecret,
378    ) -> VeilidAPIResult<BytesMut> {
379        let cs = self.guard.clone_arc();
380        let nonce = nonce.clone();
381        let shared_secret = shared_secret.clone();
382        scaled_yielding(body.len(), 1024, 8192, move || {
383            cs.crypt_in_place_no_auth(
384                body.as_mut()
385                    .get_mut(range)
386                    .ok_or_else(|| VeilidAPIError::internal("range is out of bounds"))?,
387                &nonce,
388                &shared_secret,
389            )?;
390            Ok(body)
391        })
392        .await
393    }
394
395    pub async fn crypt_no_auth_aligned_8(
396        &self,
397        body: Bytes,
398        nonce: &Nonce,
399        shared_secret: &SharedSecret,
400    ) -> VeilidAPIResult<Vec<u8>> {
401        let cs = self.guard.clone_arc();
402        let nonce = nonce.clone();
403        let shared_secret = shared_secret.clone();
404        scaled_yielding(body.len(), 1024, 8192, move || {
405            cs.crypt_no_auth_aligned_8(&body, &nonce, &shared_secret)
406        })
407        .await
408    }
409
410    pub async fn crypt_no_auth_unaligned(
411        &self,
412        body: Bytes,
413        nonce: &Nonce,
414        shared_secret: &SharedSecret,
415    ) -> VeilidAPIResult<Vec<u8>> {
416        let cs = self.guard.clone_arc();
417        let nonce = nonce.clone();
418        let shared_secret = shared_secret.clone();
419        scaled_yielding(body.len(), 1024, 8192, move || {
420            cs.crypt_no_auth_unaligned(&body, &nonce, &shared_secret)
421        })
422        .await
423    }
424}