1pub mod sizes;
2
3use super::*;
4
5use argon2::{
6 password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, Salt, SaltString},
7 Argon2,
8};
9use chacha20::cipher::{KeyIvInit, StreamCipher};
10use chacha20::XChaCha20;
11use chacha20poly1305 as ch;
12use chacha20poly1305::aead::AeadInOut as _;
13use chacha20poly1305::KeyInit as _;
14use curve25519_dalek::digest::Digest as _;
15use ed25519_dalek as ed;
16use x25519_dalek as xd;
17
18pub use chacha20poly1305::aead::Buffer;
19
20pub struct BufferWrapper<'a> {
21 buffer: &'a mut dyn CryptoSystemBuffer,
22}
23
24impl<'a> BufferWrapper<'a> {
25 pub fn new(buffer: &'a mut dyn CryptoSystemBuffer) -> Self {
26 Self { buffer }
27 }
28}
29impl<'a> AsRef<[u8]> for BufferWrapper<'a> {
30 fn as_ref(&self) -> &[u8] {
31 self.buffer.as_ref()
32 }
33}
34impl<'a> AsMut<[u8]> for BufferWrapper<'a> {
35 fn as_mut(&mut self) -> &mut [u8] {
36 self.buffer.as_mut()
37 }
38}
39impl<'a> ch::aead::Buffer for BufferWrapper<'a> {
40 fn len(&self) -> usize {
41 self.buffer.len()
42 }
43 fn is_empty(&self) -> bool {
44 self.buffer.is_empty()
45 }
46 fn extend_from_slice(&mut self, other: &[u8]) -> Result<(), ch::Error> {
47 self.buffer.extend_from_slice(other);
48 Ok(())
49 }
50 fn truncate(&mut self, len: usize) {
51 self.buffer.truncate(len)
52 }
53}
54
55const VLD0_DOMAIN_SIGN: &[u8] = b"VLD0_SIGN";
56const VLD0_DOMAIN_CRYPT: &[u8] = b"VLD0_CRYPT";
57
58const VLD0_AEAD_OVERHEAD: usize = 16;
59pub const CRYPTO_KIND_VLD0: CryptoKind = CryptoKind::new(*b"VLD0");
60pub const CRYPTO_KIND_VLD0_FOURCC: u32 = u32::from_be_bytes(*b"VLD0");
61pub use sizes::*;
62
63fn public_to_x25519_pk(public: &PublicKey) -> VeilidAPIResult<xd::PublicKey> {
64 let pk_ed = ed::VerifyingKey::from_bytes(
65 public
66 .ref_value()
67 .as_ref()
68 .try_into()
69 .map_err(VeilidAPIError::internal)?,
70 )
71 .map_err(VeilidAPIError::internal)?;
72 Ok(xd::PublicKey::from(*pk_ed.to_montgomery().as_bytes()))
73}
74fn secret_to_x25519_sk(secret: &SecretKey) -> VeilidAPIResult<xd::StaticSecret> {
75 let hash: [u8; VLD0_SIGNATURE_LENGTH] = ed::Sha512::default()
78 .chain_update(secret.ref_value().bytes())
79 .finalize()
80 .into();
81 let mut output = [0u8; VLD0_SECRET_KEY_LENGTH];
82 output.copy_from_slice(&hash[..VLD0_SECRET_KEY_LENGTH]);
83
84 Ok(xd::StaticSecret::from(output))
85}
86
87pub(crate) fn vld0_generate_keypair() -> KeyPair {
88 let mut csprng = VeilidRng {};
89 let signing_key = ed::SigningKey::generate(&mut csprng);
90 let verifying_key = signing_key.verifying_key();
91 let public_key = BarePublicKey::new(&verifying_key.to_bytes());
92 let secret_key = BareSecretKey::new(&signing_key.to_bytes());
93
94 KeyPair::new(CRYPTO_KIND_VLD0, BareKeyPair::new(public_key, secret_key))
95}
96
97pub(crate) struct CryptoSystemVLD0 {
99 registry: VeilidComponentRegistry,
100}
101
102impl CryptoSystemVLD0 {
103 #[must_use]
104 pub(crate) fn new(registry: VeilidComponentRegistry) -> Self {
105 Self { registry }
106 }
107}
108
109impl CryptoSystem for CryptoSystemVLD0 {
110 fn kind(&self) -> CryptoKind {
112 CRYPTO_KIND_VLD0
113 }
114
115 fn crypto(&self) -> VeilidComponentGuard<'_, Crypto> {
116 self.registry.lookup::<Crypto>().unwrap_or_log()
117 }
118
119 #[cfg_attr(feature = "instrument", instrument(level = "trace", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key())))]
121 fn cached_dh(&self, key: &PublicKey, secret: &SecretKey) -> VeilidAPIResult<SharedSecret> {
122 self.crypto()
123 .cached_dh_internal::<CryptoSystemVLD0>(self, key, secret)
124 }
125
126 #[cfg_attr(
128 feature = "instrument",
129 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
130 )]
131 fn random_bytes(&self, len: usize) -> Vec<u8> {
132 let mut bytes = unsafe { unaligned_u8_vec_uninit(len) };
133 random_bytes(bytes.as_mut());
134 bytes
135 }
136
137 #[cfg_attr(
138 feature = "instrument",
139 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
140 )]
141 fn hash_password(&self, password: &[u8], salt: &[u8]) -> VeilidAPIResult<String> {
142 if salt.len() < Salt::MIN_LENGTH || salt.len() > Salt::MAX_LENGTH {
143 apibail_generic!("invalid salt length");
144 }
145
146 let salt = SaltString::encode_b64(salt).map_err(VeilidAPIError::generic)?;
148
149 let argon2 = Argon2::default();
151
152 let password_hash = argon2
153 .hash_password(password, &salt)
154 .map_err(VeilidAPIError::generic)?
155 .to_string();
156 Ok(password_hash)
157 }
158 #[cfg_attr(
159 feature = "instrument",
160 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
161 )]
162 fn verify_password(&self, password: &[u8], password_hash: &str) -> VeilidAPIResult<bool> {
163 let parsed_hash = PasswordHash::new(password_hash).map_err(VeilidAPIError::generic)?;
164 let argon2 = Argon2::default();
166
167 Ok(argon2.verify_password(password, &parsed_hash).is_ok())
168 }
169
170 #[cfg_attr(
171 feature = "instrument",
172 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
173 )]
174 fn derive_shared_secret(&self, password: &[u8], salt: &[u8]) -> VeilidAPIResult<SharedSecret> {
175 if salt.len() < Salt::MIN_LENGTH || salt.len() > Salt::MAX_LENGTH {
176 apibail_generic!("invalid salt length");
177 }
178
179 let argon2 = Argon2::default();
181
182 let mut output_key_material = [0u8; VLD0_SHARED_SECRET_LENGTH];
183 argon2
184 .hash_password_into(password, salt, &mut output_key_material)
185 .map_err(VeilidAPIError::generic)?;
186 Ok(SharedSecret::new(
187 CRYPTO_KIND_VLD0,
188 BareSharedSecret::new(&output_key_material),
189 ))
190 }
191
192 #[cfg_attr(
193 feature = "instrument",
194 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
195 )]
196 fn random_nonce(&self) -> Nonce {
197 let mut nonce = [0u8; VLD0_NONCE_LENGTH];
198 random_bytes(&mut nonce);
199 Nonce::new(&nonce)
200 }
201
202 #[cfg_attr(
203 feature = "instrument",
204 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
205 )]
206 fn random_shared_secret(&self) -> SharedSecret {
207 let mut s = [0u8; VLD0_SHARED_SECRET_LENGTH];
208 random_bytes(&mut s);
209 SharedSecret::new(CRYPTO_KIND_VLD0, BareSharedSecret::new(&s))
210 }
211
212 #[cfg_attr(
213 feature = "instrument",
214 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
215 )]
216 fn compute_dh(&self, key: &PublicKey, secret: &SecretKey) -> VeilidAPIResult<SharedSecret> {
217 let pk_xd = public_to_x25519_pk(key)?;
218 let sk_xd = secret_to_x25519_sk(secret)?;
219
220 let dh = sk_xd.diffie_hellman(&pk_xd);
221 if !dh.was_contributory() {
222 apibail_generic!("dh was not contributory");
223 }
224 let dh_bytes = dh.to_bytes();
225
226 let mut hasher = blake3::Hasher::new();
227 hasher.update(VLD0_DOMAIN_CRYPT);
228 hasher.update(&dh_bytes);
229 let output = hasher.finalize();
230
231 Ok(SharedSecret::new(
232 CRYPTO_KIND_VLD0,
233 BareSharedSecret::new(output.as_bytes()),
234 ))
235 }
236
237 #[cfg_attr(
238 feature = "instrument",
239 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
240 )]
241 fn generate_keypair(&self) -> KeyPair {
242 vld0_generate_keypair()
243 }
244
245 #[cfg_attr(
246 feature = "instrument",
247 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
248 )]
249 fn generate_hash(&self, data: &[u8]) -> HashDigest {
250 HashDigest::new(
251 CRYPTO_KIND_VLD0,
252 BareHashDigest::new(blake3::hash(data).as_bytes()),
253 )
254 }
255
256 #[cfg_attr(
257 feature = "instrument",
258 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
259 )]
260 fn generate_hash_reader(&self, reader: &mut dyn std::io::Read) -> VeilidAPIResult<PublicKey> {
261 let mut hasher = blake3::Hasher::new();
262 std::io::copy(reader, &mut hasher).map_err(VeilidAPIError::generic)?;
263 Ok(PublicKey::new(
264 CRYPTO_KIND_VLD0,
265 BarePublicKey::new(hasher.finalize().as_bytes()),
266 ))
267 }
268
269 fn shared_secret_length(&self) -> usize {
271 VLD0_SHARED_SECRET_LENGTH
272 }
273 fn nonce_length(&self) -> usize {
274 VLD0_NONCE_LENGTH
275 }
276 fn hash_digest_length(&self) -> usize {
277 VLD0_HASH_DIGEST_LENGTH
278 }
279 fn public_key_length(&self) -> usize {
280 VLD0_PUBLIC_KEY_LENGTH
281 }
282 fn secret_key_length(&self) -> usize {
283 VLD0_SECRET_KEY_LENGTH
284 }
285 fn signature_length(&self) -> usize {
286 VLD0_SIGNATURE_LENGTH
287 }
288 fn default_salt_length(&self) -> usize {
289 16
290 }
291 fn aead_overhead(&self) -> usize {
292 VLD0_AEAD_OVERHEAD
293 }
294
295 #[cfg_attr(
296 feature = "instrument",
297 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
298 )]
299 fn validate_keypair(
300 &self,
301 public_key: &PublicKey,
302 secret_key: &SecretKey,
303 ) -> VeilidAPIResult<bool> {
304 self.check_public_key(public_key)?;
305 self.check_secret_key(secret_key)?;
306
307 let data = vec![0u8; 512];
308 let Ok(sig) = self.sign(public_key, secret_key, &data) else {
309 return Ok(false);
310 };
311 let Ok(v) = self.verify(public_key, &data, &sig) else {
312 return Ok(false);
313 };
314 Ok(v)
315 }
316
317 #[cfg_attr(
318 feature = "instrument",
319 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
320 )]
321 fn validate_hash(&self, data: &[u8], hash_digest: &HashDigest) -> VeilidAPIResult<bool> {
322 self.check_hash_digest(hash_digest)?;
323
324 let bytes = *blake3::hash(data).as_bytes();
325
326 Ok(bytes == *hash_digest.ref_value().bytes())
327 }
328
329 #[cfg_attr(
330 feature = "instrument",
331 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
332 )]
333 fn validate_hash_reader(
334 &self,
335 reader: &mut dyn std::io::Read,
336 hash_digest: &HashDigest,
337 ) -> VeilidAPIResult<bool> {
338 self.check_hash_digest(hash_digest)?;
339
340 let mut hasher = blake3::Hasher::new();
341 std::io::copy(reader, &mut hasher).map_err(VeilidAPIError::generic)?;
342 let bytes = *hasher.finalize().as_bytes();
343 Ok(bytes == *hash_digest.ref_value().bytes())
344 }
345
346 #[cfg_attr(
348 feature = "instrument",
349 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
350 )]
351 fn sign(
352 &self,
353 public_key: &PublicKey,
354 secret_key: &SecretKey,
355 data: &[u8],
356 ) -> VeilidAPIResult<Signature> {
357 self.check_public_key(public_key)?;
358 self.check_secret_key(secret_key)?;
359
360 let mut kpb = BytesMut::with_capacity(VLD0_SECRET_KEY_LENGTH + VLD0_PUBLIC_KEY_LENGTH);
361
362 kpb.extend_from_slice(secret_key.ref_value().as_ref());
363 kpb.extend_from_slice(public_key.ref_value().as_ref());
364 let keypair = ed::SigningKey::from_keypair_bytes(kpb.as_ref().try_into().unwrap_or_log())
365 .map_err(|e| VeilidAPIError::parse_error("Keypair is invalid", e))?;
366
367 let mut dig: ed::Sha512 = ed::Sha512::default();
368 dig.update(data);
369
370 let sig_bytes = keypair
371 .sign_prehashed(dig, Some(VLD0_DOMAIN_SIGN))
372 .map_err(VeilidAPIError::internal)?;
373
374 let sig = Signature::new(CRYPTO_KIND_VLD0, BareSignature::new(&sig_bytes.to_bytes()));
375
376 Ok(sig)
377 }
378
379 fn sign_in_place(
380 &self,
381 public_key: &PublicKey,
382 secret_key: &SecretKey,
383 data: &mut [u8],
384 range: Range<usize>,
385 sig_idx: usize,
386 ) -> VeilidAPIResult<()> {
387 self.check_public_key(public_key)?;
388 self.check_secret_key(secret_key)?;
389
390 let mut kpb = BytesMut::with_capacity(VLD0_SECRET_KEY_LENGTH + VLD0_PUBLIC_KEY_LENGTH);
391
392 kpb.extend_from_slice(secret_key.ref_value().as_ref());
393 kpb.extend_from_slice(public_key.ref_value().as_ref());
394 let keypair = ed::SigningKey::from_keypair_bytes(kpb.as_ref().try_into().unwrap_or_log())
395 .map_err(|e| VeilidAPIError::parse_error("Keypair is invalid", e))?;
396
397 let mut dig: ed::Sha512 = ed::Sha512::default();
398
399 dig.update(
400 data.get(range)
401 .ok_or_else(|| VeilidAPIError::internal("range is out of bounds"))?,
402 );
403
404 let sig_bytes = keypair
405 .sign_prehashed(dig, Some(VLD0_DOMAIN_SIGN))
406 .map_err(VeilidAPIError::internal)?;
407
408 data.get_mut(sig_idx..sig_idx + VLD0_SIGNATURE_LENGTH)
409 .ok_or_else(|| VeilidAPIError::internal("signature index is out of bounds"))?
410 .copy_from_slice(&sig_bytes.to_bytes());
411
412 Ok(())
413 }
414
415 #[cfg_attr(
416 feature = "instrument",
417 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
418 )]
419 fn verify(
420 &self,
421 public_key: &PublicKey,
422 data: &[u8],
423 signature: &Signature,
424 ) -> VeilidAPIResult<bool> {
425 self.check_public_key(public_key)?;
426 self.check_signature(signature)?;
427
428 let pk = ed::VerifyingKey::from_bytes(
429 public_key
430 .ref_value()
431 .as_ref()
432 .try_into()
433 .map_err(VeilidAPIError::internal)?,
434 )
435 .map_err(|e| VeilidAPIError::parse_error("Public key is invalid", e))?;
436 let sig = ed::Signature::from_bytes(
437 signature
438 .ref_value()
439 .as_ref()
440 .try_into()
441 .map_err(VeilidAPIError::internal)?,
442 );
443
444 let mut dig: ed::Sha512 = ed::Sha512::default();
445 dig.update(data);
446
447 if pk
448 .verify_prehashed_strict(dig, Some(VLD0_DOMAIN_SIGN), &sig)
449 .is_err()
450 {
451 return Ok(false);
452 }
453 Ok(true)
454 }
455
456 fn verify_in_place(
457 &self,
458 public_key: &PublicKey,
459 data: &[u8],
460 range: Range<usize>,
461 sig_idx: usize,
462 ) -> VeilidAPIResult<bool> {
463 self.check_public_key(public_key)?;
464
465 let pk = ed::VerifyingKey::from_bytes(
466 public_key
467 .ref_value()
468 .as_ref()
469 .try_into()
470 .map_err(VeilidAPIError::internal)?,
471 )
472 .map_err(|e| VeilidAPIError::parse_error("Public key is invalid", e))?;
473
474 let mut dig: ed::Sha512 = ed::Sha512::default();
475 dig.update(
476 data.get(range)
477 .ok_or_else(|| VeilidAPIError::internal("range is out of bounds"))?,
478 );
479
480 let sig = data
481 .get(sig_idx..sig_idx + VLD0_SIGNATURE_LENGTH)
482 .ok_or_else(|| VeilidAPIError::internal("signature index is out of bounds"))?;
483 let sig = ed::Signature::from_bytes(sig.try_into().unwrap_or_log());
484 if pk
485 .verify_prehashed_strict(dig, Some(VLD0_DOMAIN_SIGN), &sig)
486 .is_err()
487 {
488 return Ok(false);
489 }
490 Ok(true)
491 }
492
493 #[cfg_attr(
495 feature = "instrument",
496 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
497 )]
498 fn decrypt_in_place_aead(
499 &self,
500 body: &mut dyn CryptoSystemBuffer,
501 nonce: &Nonce,
502 shared_secret: &SharedSecret,
503 associated_data: Option<&[u8]>,
504 ) -> VeilidAPIResult<()> {
505 self.check_shared_secret(shared_secret)?;
506
507 let shared_secret_bytes: [u8; VLD0_SHARED_SECRET_LENGTH] = shared_secret
508 .ref_value()
509 .as_ref()
510 .try_into()
511 .map_err(VeilidAPIError::internal)?;
512 let nonce_bytes: [u8; VLD0_NONCE_LENGTH] = nonce
513 .as_ref()
514 .try_into()
515 .map_err(VeilidAPIError::internal)?;
516
517 let key = ch::Key::from(shared_secret_bytes);
518 let xnonce = ch::XNonce::from(nonce_bytes);
519 let aead = ch::XChaCha20Poly1305::new(&key);
520 let mut buffer = BufferWrapper::new(body);
521 aead.decrypt_in_place(
522 &xnonce,
523 associated_data.unwrap_or(b""),
524 &mut buffer as &mut dyn ch::aead::Buffer,
525 )
526 .map_err(map_to_string)
527 .map_err(VeilidAPIError::generic)
528 }
529
530 #[cfg_attr(
531 feature = "instrument",
532 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
533 )]
534 fn decrypt_aead(
535 &self,
536 body: &[u8],
537 nonce: &Nonce,
538 shared_secret: &SharedSecret,
539 associated_data: Option<&[u8]>,
540 ) -> VeilidAPIResult<Vec<u8>> {
541 self.check_nonce(nonce)?;
542 self.check_shared_secret(shared_secret)?;
543
544 let mut out = body.to_vec();
545 self.decrypt_in_place_aead(&mut out, nonce, shared_secret, associated_data)
546 .map_err(map_to_string)
547 .map_err(VeilidAPIError::generic)?;
548 Ok(out)
549 }
550
551 #[cfg_attr(
552 feature = "instrument",
553 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
554 )]
555 fn encrypt_in_place_aead(
556 &self,
557 body: &mut dyn CryptoSystemBuffer,
558 nonce: &Nonce,
559 shared_secret: &SharedSecret,
560 associated_data: Option<&[u8]>,
561 ) -> VeilidAPIResult<()> {
562 self.check_nonce(nonce)?;
563 self.check_shared_secret(shared_secret)?;
564
565 let shared_secret_bytes: [u8; VLD0_SHARED_SECRET_LENGTH] = shared_secret
566 .ref_value()
567 .as_ref()
568 .try_into()
569 .map_err(VeilidAPIError::internal)?;
570 let nonce_bytes: [u8; VLD0_NONCE_LENGTH] = nonce
571 .as_ref()
572 .try_into()
573 .map_err(VeilidAPIError::internal)?;
574
575 let key = ch::Key::from(shared_secret_bytes);
576 let xnonce = ch::XNonce::from(nonce_bytes);
577 let aead = ch::XChaCha20Poly1305::new(&key);
578
579 let mut buffer = BufferWrapper::new(body);
580 aead.encrypt_in_place(&xnonce, associated_data.unwrap_or(b""), &mut buffer)
581 .map_err(map_to_string)
582 .map_err(VeilidAPIError::generic)
583 }
584
585 #[cfg_attr(
586 feature = "instrument",
587 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
588 )]
589 fn encrypt_aead(
590 &self,
591 body: &[u8],
592 nonce: &Nonce,
593 shared_secret: &SharedSecret,
594 associated_data: Option<&[u8]>,
595 ) -> VeilidAPIResult<Vec<u8>> {
596 self.check_nonce(nonce)?;
597 self.check_shared_secret(shared_secret)?;
598
599 let mut out = body.to_vec();
600 self.encrypt_in_place_aead(&mut out, nonce, shared_secret, associated_data)
601 .map_err(map_to_string)
602 .map_err(VeilidAPIError::generic)?;
603 Ok(out)
604 }
605
606 #[cfg_attr(
608 feature = "instrument",
609 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
610 )]
611 fn crypt_in_place_no_auth(
612 &self,
613 body: &mut [u8],
614 nonce: &Nonce,
615 shared_secret: &SharedSecret,
616 ) -> VeilidAPIResult<()> {
617 self.check_nonce(nonce)?;
618 self.check_shared_secret(shared_secret)?;
619
620 let shared_secret_bytes: [u8; VLD0_SHARED_SECRET_LENGTH] = shared_secret
621 .ref_value()
622 .as_ref()
623 .try_into()
624 .map_err(VeilidAPIError::internal)?;
625 let nonce_bytes: [u8; VLD0_NONCE_LENGTH] = nonce
626 .as_ref()
627 .try_into()
628 .map_err(VeilidAPIError::internal)?;
629 let key = ch::Key::from(shared_secret_bytes);
630 let xnonce = ch::XNonce::from(nonce_bytes);
631
632 let mut cipher = <XChaCha20 as KeyIvInit>::new(&key, &xnonce);
633 cipher.apply_keystream(body);
634 Ok(())
635 }
636
637 #[cfg_attr(
638 feature = "instrument",
639 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
640 )]
641 fn crypt_b2b_no_auth(
642 &self,
643 in_buf: &[u8],
644 out_buf: &mut [u8],
645 nonce: &Nonce,
646 shared_secret: &SharedSecret,
647 ) -> VeilidAPIResult<()> {
648 self.check_nonce(nonce)?;
649 self.check_shared_secret(shared_secret)?;
650
651 let shared_secret_bytes: [u8; VLD0_SHARED_SECRET_LENGTH] = shared_secret
652 .ref_value()
653 .as_ref()
654 .try_into()
655 .map_err(VeilidAPIError::internal)?;
656 let nonce_bytes: [u8; VLD0_NONCE_LENGTH] = nonce
657 .as_ref()
658 .try_into()
659 .map_err(VeilidAPIError::internal)?;
660 let key = ch::Key::from(shared_secret_bytes);
661 let xnonce = ch::XNonce::from(nonce_bytes);
662
663 let mut cipher = <XChaCha20 as KeyIvInit>::new(&key, &xnonce);
664 cipher.apply_keystream_b2b(in_buf, out_buf);
665 Ok(())
666 }
667
668 #[cfg_attr(
669 feature = "instrument",
670 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
671 )]
672 fn crypt_no_auth_aligned_8(
673 &self,
674 in_buf: &[u8],
675 nonce: &Nonce,
676 shared_secret: &SharedSecret,
677 ) -> VeilidAPIResult<Vec<u8>> {
678 self.check_nonce(nonce)?;
679 self.check_shared_secret(shared_secret)?;
680
681 let mut out_buf = unsafe { aligned_8_u8_vec_uninit(in_buf.len()) };
682 self.crypt_b2b_no_auth(in_buf, &mut out_buf, nonce, shared_secret)?;
683 Ok(out_buf)
684 }
685
686 #[cfg_attr(
687 feature = "instrument",
688 instrument(level = "trace", target = "crypto", skip_all, fields(__VEILID_LOG_KEY = self.registry.log_key()))
689 )]
690 fn crypt_no_auth_unaligned(
691 &self,
692 in_buf: &[u8],
693 nonce: &Nonce,
694 shared_secret: &SharedSecret,
695 ) -> VeilidAPIResult<Vec<u8>> {
696 self.check_nonce(nonce)?;
697 self.check_shared_secret(shared_secret)?;
698
699 let mut out_buf = unsafe { unaligned_u8_vec_uninit(in_buf.len()) };
700 self.crypt_b2b_no_auth(in_buf, &mut out_buf, nonce, shared_secret)?;
701 Ok(out_buf)
702 }
703}