gcrypt 0.5.3

Libgcrypt bindings for Rust
Documentation
use std::ptr;

use ffi;
use libc::c_int;

use error::Result;
use digest::Algorithm as DigestAlgorithm;

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, pass: &[u8], salt: Option<&[u8]>, key: &mut [u8])
    -> Result<()> {
    let _ = ::get_token();
    unsafe {
        let salt = salt.map_or((ptr::null(), 0), |s| (s.as_ptr(), s.len()));
        return_err!(ffi::gcry_kdf_derive(
            pass.as_ptr() as *const _,
            pass.len(),
            algo.raw(),
            subalgo as c_int,
            salt.0 as *const _,
            salt.1,
            iter.into(),
            key.len(),
            key.as_mut_ptr() as *mut _
        ));
    }
    Ok(())
}

#[inline]
pub fn s2k_derive(algo: DigestAlgorithm, iter: u32, pass: &[u8], salt: Option<&[u8]>, key: &mut [u8])
    -> Result<()> {
    match (iter, salt.is_some()) {
        (x, true) if x != 0 => derive(
            Algorithm::IteratedSaltedS2K,
            algo.raw() as i32,
            iter,
            pass,
            salt,
            key,
        ),
        (_, true) => derive(
            Algorithm::SaltedS2K,
            algo.raw() as i32,
            iter,
            pass,
            salt,
            key,
        ),
        _ => derive(
            Algorithm::SimpleS2K,
            algo.raw() as i32,
            iter,
            pass,
            salt,
            key,
        ),
    }
}

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

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

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