gcrypt 0.7.0

Libgcrypt bindings for Rust
Documentation
use std::ptr;

use ffi;
use libc::c_int;

use crate::{digest::Algorithm as DigestAlgorithm, error::return_err, Result};

ffi_enum_wrapper! {
    pub enum Algorithm: c_int {
        SimpleS2K = ffi::GCRY_KDF_SIMPLE_S2K,
        SaltedS2K = ffi::GCRY_KDF_SALTED_S2K,
        IteratedSaltedS2K = ffi::GCRY_KDF_ITERSALTED_S2K,
        Pbkdf1 = ffi::GCRY_KDF_PBKDF1,
        Pbkdf2 = ffi::GCRY_KDF_PBKDF2,
        Scrypt = ffi::GCRY_KDF_SCRYPT,
    }
}

#[inline]
pub fn derive(
    algo: Algorithm, subalgo: i32, iter: u32, secret: &[u8], salt: Option<&[u8]>, key: &mut [u8],
) -> Result<()> {
    let _ = crate::init_default();
    unsafe {
        let salt = salt.map_or((ptr::null(), 0), |s| (s.as_ptr(), s.len()));
        return_err!(ffi::gcry_kdf_derive(
            secret.as_ptr().cast(),
            secret.len(),
            algo.raw(),
            subalgo as c_int,
            salt.0.cast(),
            salt.1,
            iter.into(),
            key.len(),
            key.as_mut_ptr().cast(),
        ));
    }
    Ok(())
}

#[inline]
pub fn s2k_derive(
    digest: DigestAlgorithm, iter: u32, secret: &[u8], salt: Option<&[u8]>, key: &mut [u8],
) -> Result<()> {
    let variant = match (iter, salt.is_some()) {
        (0, true) => Algorithm::SaltedS2K,
        (_, true) => Algorithm::IteratedSaltedS2K,
        _ => Algorithm::SimpleS2K,
    };
    derive(variant, digest.raw(), iter, secret, salt, key)
}

#[inline]
pub fn pbkdf1_derive(
    digest: DigestAlgorithm, iter: u32, secret: &[u8], salt: &[u8], key: &mut [u8],
) -> Result<()> {
    derive(
        Algorithm::Pbkdf1,
        digest.raw(),
        iter,
        secret,
        Some(salt),
        key,
    )
}

#[inline]
pub fn pbkdf2_derive(
    digest: DigestAlgorithm, iter: u32, secret: &[u8], salt: &[u8], key: &mut [u8],
) -> Result<()> {
    derive(
        Algorithm::Pbkdf2,
        digest.raw(),
        iter,
        secret,
        Some(salt),
        key,
    )
}

#[inline]
pub fn scrypt_derive(n: u32, p: u32, secret: &[u8], salt: &[u8], key: &mut [u8]) -> Result<()> {
    derive(Algorithm::Scrypt, n as i32, p, secret, Some(salt), key)
}