philbin 1.0.1

A pure Rust AEGIS library with SIMD and runtime CPU detection
Documentation
// Takes a closure and expands to `<T as Simd>::with_target_features(closure)`
// where T is the "best" SIMD impl returned by `SimdLevel::best()`.
macro_rules! dispatch {
  ($closure:expr) => {{
    let level = SimdLevel::best();
    match level {
      #[cfg(target_arch = "x86_64")]
      SimdLevel::Avx512(simd) => simd.with_target_features($closure),

      #[cfg(target_arch = "x86_64")]
      SimdLevel::Avx2(simd) => simd.with_target_features($closure),

      #[cfg(target_arch = "x86_64")]
      SimdLevel::Avx(simd) => simd.with_target_features($closure),

      #[cfg(target_arch = "x86_64")]
      SimdLevel::Sse2(simd) => simd.with_target_features($closure),

      #[cfg(target_arch = "aarch64")]
      SimdLevel::Neon(simd) => simd.with_target_features($closure),

      #[cfg(not(all(
        target_arch = "aarch64",
        any(target_os = "macos", target_os = "ios")
      )))]
      SimdLevel::Fallback(simd) => simd.with_target_features($closure),
    }
  }};
}

// Takes the name of an Aegis algo variant and a SIMD literal; expands to
// the fully configured and qualified name of an Aegis128L/Aegis256 struct.
//
// Valid algo names: aegis128l, aegis128x2, aegis128x4
//                   aegis256,  aegis256x2, aegis256x4
//
// Valid SIMD names are the names of structs that impl the `Simd` trait.
//
// Call example:
//   aegis_struct!(aegis128l, Avx2);
macro_rules! aegis_struct {
  (aegis128l, $simd:ident) => {
    crate::base::aegis128l::Aegis128L::<$simd, <$simd as Simd>::Block128, 32>
  };
  (aegis128x2, $simd:ident) => {
    crate::base::aegis128l::Aegis128L::<$simd, <$simd as Simd>::Block256, 64>
  };
  (aegis128x4, $simd:ident) => {
    crate::base::aegis128l::Aegis128L::<$simd, <$simd as Simd>::Block512, 128>
  };

  (aegis256, $simd:ident) => {
    crate::base::aegis256::Aegis256::<$simd, <$simd as Simd>::Block128, 16>
  };
  (aegis256x2, $simd:ident) => {
    crate::base::aegis256::Aegis256::<$simd, <$simd as Simd>::Block256, 32>
  };
  (aegis256x4, $simd:ident) => {
    crate::base::aegis256::Aegis256::<$simd, <$simd as Simd>::Block512, 64>
  };
}
#[cfg(all(test, target_arch = "x86_64"))]
pub(in crate::arch) use aegis_struct;

// Takes the name of an Aegis algo variant and expands to functions implementing
// it.
//
// Valid algo names: aegis128l, aegis128x2, aegis128x4
//                   aegis256,  aegis256x2, aegis256x4
//
// Call example:
//   gen_aegis_fns!(aegis128l);
macro_rules! gen_aegis_fns {
  ($algo:ident) => {
    use crate::arch::*;
    use crate::base::aegis::Aegis;
    use crate::easy::*;

    // AEGIS-128 variants -> Key128 / Nonce128
    // AEGIS-256 variants -> Key256 / Nonce256
    type Key = crate::facade::aegis_key_type!($algo);
    type Nonce = crate::facade::aegis_nonce_type!($algo);

    #[doc = include_str!("../rustdoc/encrypt_to_slice_detached.md")]
    pub fn encrypt_to_slice_detached<Tag: AuthTag>(
      plaintext: Plaintext,
      associated_data: AssociatedData,
      key: &Key,
      nonce: Nonce,
      ciphertext: CiphertextMut,
    ) -> Result<Tag> {
      dispatch!(|simd| {
        encrypt_to_slice_detached_impl(
          simd,
          plaintext,
          associated_data,
          key,
          nonce,
          ciphertext,
        )
      })
    }

    // `*_impl` needed to grab and pass the `S: Simd` generic param.
    #[inline(always)]
    fn encrypt_to_slice_detached_impl<S: Simd, Tag: AuthTag>(
      simd: S,
      plaintext: Plaintext,
      associated_data: AssociatedData,
      key: &Key,
      nonce: Nonce,
      ciphertext: CiphertextMut,
    ) -> Result<Tag> {
      <aegis_struct!($algo, S)>::encrypt_to_slice_detached(
        simd,
        plaintext,
        associated_data,
        key,
        nonce,
        ciphertext,
      )
    }

    #[doc = include_str!("../rustdoc/encrypt_in_place.md")]
    pub fn encrypt_in_place_detached<Tag: AuthTag>(
      buffer: PlaintextMut,
      associated_data: AssociatedData,
      key: &Key,
      nonce: Nonce,
    ) -> Result<Tag> {
      dispatch!(|simd| {
        encrypt_in_place_detached_impl(
          simd,
          buffer,
          associated_data,
          key,
          nonce,
        )
      })
    }

    // `*_impl` needed to grab and pass the `S: Simd` generic param.
    #[inline(always)]
    fn encrypt_in_place_detached_impl<S: Simd, Tag: AuthTag>(
      simd: S,
      buffer: PlaintextMut,
      associated_data: AssociatedData,
      key: &Key,
      nonce: Nonce,
    ) -> Result<Tag> {
      <aegis_struct!($algo, S)>::encrypt_in_place_detached(
        simd,
        buffer,
        associated_data,
        key,
        nonce,
      )
    }

    #[doc = include_str!("../rustdoc/decrypt_to_slice_detached.md")]
    pub fn decrypt_to_slice_detached<Tag: AuthTag>(
      ciphertext: Ciphertext,
      auth_tag: &Tag,
      associated_data: AssociatedData,
      key: &Key,
      nonce: Nonce,
      plaintext: PlaintextMut,
    ) -> Result<()> {
      dispatch!(|simd| {
        decrypt_to_slice_detached_impl(
          simd,
          ciphertext,
          auth_tag,
          associated_data,
          key,
          nonce,
          plaintext,
        )
      })
    }

    // `*_impl` needed to grab and pass the `S: Simd` generic param.
    #[inline(always)]
    fn decrypt_to_slice_detached_impl<S: Simd, Tag: AuthTag>(
      simd: S,
      ciphertext: Ciphertext,
      auth_tag: &Tag,
      associated_data: AssociatedData,
      key: &Key,
      nonce: Nonce,
      plaintext: PlaintextMut,
    ) -> Result<()> {
      <aegis_struct!($algo, S)>::decrypt_to_slice_detached(
        simd,
        ciphertext,
        auth_tag,
        associated_data,
        key,
        nonce,
        plaintext,
      )
    }

    #[doc = include_str!("../rustdoc/decrypt_in_place.md")]
    pub fn decrypt_in_place_detached<Tag: AuthTag>(
      buffer: CiphertextMut,
      auth_tag: &Tag,
      associated_data: AssociatedData,
      key: &Key,
      nonce: Nonce,
    ) -> Result<()> {
      dispatch!(|simd| {
        decrypt_in_place_detached_impl(
          simd,
          buffer,
          auth_tag,
          associated_data,
          key,
          nonce,
        )
      })
    }

    // `*_impl` needed to grab and pass the `S: Simd` generic param.
    #[inline(always)]
    fn decrypt_in_place_detached_impl<S: Simd, Tag: AuthTag>(
      simd: S,
      buffer: CiphertextMut,
      auth_tag: &Tag,
      associated_data: AssociatedData,
      key: &Key,
      nonce: Nonce,
    ) -> Result<()> {
      <aegis_struct!($algo, S)>::decrypt_in_place_detached(
        simd,
        buffer,
        auth_tag,
        associated_data,
        key,
        nonce,
      )
    }
  };
}

pub mod aegis128l {
  gen_aegis_fns!(aegis128l);
}
pub mod aegis128x2 {
  gen_aegis_fns!(aegis128x2);
}
pub mod aegis128x4 {
  gen_aegis_fns!(aegis128x4);
}

pub mod aegis256 {
  gen_aegis_fns!(aegis256);
}
pub mod aegis256x2 {
  gen_aegis_fns!(aegis256x2);
}
pub mod aegis256x4 {
  gen_aegis_fns!(aegis256x4);
}