wtx 0.45.0

A collection of different transport implementations and related tools focused primarily on web technologies.
Documentation
use crate::{
  crypto::{
    Aes128GcmOpenssl, Aes256GcmOpenssl, Chacha20Poly1305Openssl, CryptoError,
    aead::{Aead, NONCE_LEN, TAG_LEN, generate_nonce, split_nonce_content_tag, write_tag},
  },
  misc::SensitiveBytes,
  rng::CryptoRng,
};
use openssl::symm::{Cipher, decrypt_aead, encrypt_aead};

impl Aead for Aes128GcmOpenssl {
  type Secret = [u8; 16];

  #[inline]
  fn decrypt_in_place<'encrypted>(
    associated_data: &[u8],
    encrypted_data: &'encrypted mut [u8],
    secret: &Self::Secret,
  ) -> crate::Result<&'encrypted mut [u8]> {
    local_decrypt(
      associated_data,
      Cipher::aes_128_gcm(),
      encrypted_data,
      CryptoError::InvalidAes128GcmData,
      secret,
    )
  }

  #[inline]
  fn encrypt_parts<RNG>(
    associated_data: &[u8],
    nonce: [&mut u8; NONCE_LEN],
    plaintext: &mut [u8],
    rng: &mut RNG,
    secret: &Self::Secret,
    tag: [&mut u8; TAG_LEN],
  ) -> crate::Result<()>
  where
    RNG: CryptoRng,
  {
    local_encrypt(associated_data, Cipher::aes_128_gcm(), nonce, plaintext, rng, secret, tag)
  }
}

impl Aead for Aes256GcmOpenssl {
  type Secret = [u8; 32];

  #[inline]
  fn decrypt_in_place<'encrypted>(
    associated_data: &[u8],
    encrypted_data: &'encrypted mut [u8],
    secret: &Self::Secret,
  ) -> crate::Result<&'encrypted mut [u8]> {
    local_decrypt(
      associated_data,
      Cipher::aes_256_gcm(),
      encrypted_data,
      CryptoError::InvalidAes256GcmData,
      secret,
    )
  }

  #[inline]
  fn encrypt_parts<RNG>(
    associated_data: &[u8],
    nonce: [&mut u8; NONCE_LEN],
    plaintext: &mut [u8],
    rng: &mut RNG,
    secret: &Self::Secret,
    tag: [&mut u8; TAG_LEN],
  ) -> crate::Result<()>
  where
    RNG: CryptoRng,
  {
    local_encrypt(associated_data, Cipher::aes_256_gcm(), nonce, plaintext, rng, secret, tag)
  }
}

impl Aead for Chacha20Poly1305Openssl {
  type Secret = [u8; 32];

  #[inline]
  fn decrypt_in_place<'encrypted>(
    associated_data: &[u8],
    encrypted_data: &'encrypted mut [u8],
    secret: &Self::Secret,
  ) -> crate::Result<&'encrypted mut [u8]> {
    local_decrypt(
      associated_data,
      Cipher::chacha20_poly1305(),
      encrypted_data,
      CryptoError::InvalidChacha20Poly1305Data,
      secret,
    )
  }

  #[inline]
  fn encrypt_parts<RNG>(
    associated_data: &[u8],
    nonce: [&mut u8; NONCE_LEN],
    plaintext: &mut [u8],
    rng: &mut RNG,
    secret: &Self::Secret,
    tag: [&mut u8; TAG_LEN],
  ) -> crate::Result<()>
  where
    RNG: CryptoRng,
  {
    local_encrypt(associated_data, Cipher::chacha20_poly1305(), nonce, plaintext, rng, secret, tag)
  }
}

fn local_decrypt<'encrypted>(
  associated_data: &[u8],
  cipher: Cipher,
  encrypted_data: &'encrypted mut [u8],
  error: CryptoError,
  secret: &[u8],
) -> crate::Result<&'encrypted mut [u8]> {
  let (nonce, content, tag) = split_nonce_content_tag(encrypted_data, error)?;
  let mut decrypted = decrypt_aead(cipher, secret, Some(&nonce), associated_data, content, &tag)?;
  let decrypted_len = decrypted.len();
  content.get_mut(..decrypted_len).unwrap_or_default().copy_from_slice(&decrypted);
  drop(SensitiveBytes::new_unlocked(&mut decrypted));
  Ok(content)
}

fn local_encrypt<RNG>(
  associated_data: &[u8],
  cipher: Cipher,
  nonce: [&mut u8; NONCE_LEN],
  plaintext: &mut [u8],
  rng: &mut RNG,
  secret: &[u8],
  tag_bytes_out: [&mut u8; TAG_LEN],
) -> crate::Result<()>
where
  RNG: CryptoRng,
{
  let nonce_bytes = generate_nonce(nonce, rng);
  let mut tag = [0u8; TAG_LEN];
  let content =
    encrypt_aead(cipher, secret, Some(&nonce_bytes), associated_data, plaintext, &mut tag)?;
  plaintext.get_mut(..content.len()).unwrap_or_default().copy_from_slice(&content);
  write_tag(tag, tag_bytes_out);
  Ok(())
}