use std::{path::Path, ptr};
use libc::{c_int, c_uint};
use crate::{device::CryptDevice, err::LibcryptErr};
consts_to_from_enum!(
CryptActivateFlag,
u32,
Readonly => libcryptsetup_rs_sys::CRYPT_ACTIVATE_READONLY,
NoUuid => libcryptsetup_rs_sys::CRYPT_ACTIVATE_NO_UUID,
Shared => libcryptsetup_rs_sys::CRYPT_ACTIVATE_SHARED,
AllowDiscards => libcryptsetup_rs_sys::CRYPT_ACTIVATE_ALLOW_DISCARDS,
Private => libcryptsetup_rs_sys::CRYPT_ACTIVATE_PRIVATE,
Corrupted => libcryptsetup_rs_sys::CRYPT_ACTIVATE_CORRUPTED,
SameCpuCrypt => libcryptsetup_rs_sys::CRYPT_ACTIVATE_SAME_CPU_CRYPT,
SubmitFromCryptCpus => libcryptsetup_rs_sys::CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS,
IgnoreCorruption => libcryptsetup_rs_sys::CRYPT_ACTIVATE_IGNORE_CORRUPTION,
RestartOnCorruption => libcryptsetup_rs_sys::CRYPT_ACTIVATE_RESTART_ON_CORRUPTION,
IgnoreZeroBlocks => libcryptsetup_rs_sys::CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS,
KeyringKey => libcryptsetup_rs_sys::CRYPT_ACTIVATE_KEYRING_KEY,
NoJournal => libcryptsetup_rs_sys::CRYPT_ACTIVATE_NO_JOURNAL,
Recovery => libcryptsetup_rs_sys::CRYPT_ACTIVATE_RECOVERY,
IgnorePersistent => libcryptsetup_rs_sys::CRYPT_ACTIVATE_IGNORE_PERSISTENT,
CheckAtMostOnce => libcryptsetup_rs_sys::CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE,
AllowUnboundKey => libcryptsetup_rs_sys::CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY,
Recalculate => libcryptsetup_rs_sys::CRYPT_ACTIVATE_RECALCULATE,
Refresh => libcryptsetup_rs_sys::CRYPT_ACTIVATE_REFRESH,
SerializeMemoryHardPbkdf => libcryptsetup_rs_sys::CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF,
NoJournalBitmap => libcryptsetup_rs_sys::CRYPT_ACTIVATE_NO_JOURNAL_BITMAP
);
bitflags_to_from_struct!(
CryptActivateFlags,
CryptActivateFlag,
u32
);
consts_to_from_enum!(
CryptDeactivateFlag,
u32,
Deferred => libcryptsetup_rs_sys::CRYPT_DEACTIVATE_DEFERRED,
Force => libcryptsetup_rs_sys::CRYPT_DEACTIVATE_FORCE
);
bitflags_to_from_struct!(
CryptDeactivateFlags,
CryptDeactivateFlag,
u32
);
pub struct CryptActivation<'a> {
reference: &'a mut CryptDevice,
}
impl<'a> CryptActivation<'a> {
pub(crate) fn new(reference: &'a mut CryptDevice) -> Self {
CryptActivation { reference }
}
pub fn activate_by_passphrase(
&mut self,
name: Option<&str>,
keyslot: Option<c_uint>,
passphrase: &[u8],
flags: CryptActivateFlags,
) -> Result<c_uint, LibcryptErr> {
let name_cstring_option = match name {
Some(n) => Some(to_cstring!(n)?),
None => None,
};
errno_int_success!(unsafe {
libcryptsetup_rs_sys::crypt_activate_by_passphrase(
self.reference.as_ptr(),
match name_cstring_option {
Some(ref cs) => cs.as_ptr(),
None => ptr::null_mut(),
},
keyslot
.map(|k| k as c_int)
.unwrap_or(libcryptsetup_rs_sys::CRYPT_ANY_SLOT),
to_byte_ptr!(passphrase),
passphrase.len(),
flags.into(),
)
})
.map(|k| k as c_uint)
}
pub fn activate_by_keyfile_device_offset(
&mut self,
name: Option<&str>,
keyslot: Option<c_uint>,
keyfile: &Path,
keyfile_size: Option<crate::size_t>,
keyfile_offset: u64,
flags: CryptActivateFlags,
) -> Result<c_uint, LibcryptErr> {
let name_cstring_option = match name {
Some(n) => Some(to_cstring!(n)?),
None => None,
};
let keyfile_cstring = path_to_cstring!(keyfile)?;
errno_int_success!(unsafe {
libcryptsetup_rs_sys::crypt_activate_by_keyfile_device_offset(
self.reference.as_ptr(),
match name_cstring_option {
Some(ref cs) => cs.as_ptr(),
None => ptr::null_mut(),
},
keyslot
.map(|k| k as c_int)
.unwrap_or(libcryptsetup_rs_sys::CRYPT_ANY_SLOT),
keyfile_cstring.as_ptr(),
match keyfile_size {
Some(i) => i,
None => std::fs::metadata(keyfile)
.map_err(LibcryptErr::IOError)?
.len() as crate::size_t,
},
keyfile_offset,
flags.into(),
)
})
.map(|k| k as c_uint)
}
pub fn activate_by_volume_key(
&mut self,
name: Option<&str>,
volume_key: Option<&[u8]>,
flags: CryptActivateFlags,
) -> Result<(), LibcryptErr> {
let name_cstring_option = match name {
Some(n) => Some(to_cstring!(n)?),
None => None,
};
let (volume_key_ptr, volume_key_len) = match volume_key {
Some(vk) => (to_byte_ptr!(vk), vk.len()),
None => (ptr::null(), 0),
};
errno!(unsafe {
libcryptsetup_rs_sys::crypt_activate_by_volume_key(
self.reference.as_ptr(),
match name_cstring_option {
Some(ref cs) => cs.as_ptr(),
None => ptr::null_mut(),
},
volume_key_ptr,
volume_key_len,
flags.into(),
)
})
}
pub fn activate_by_keyring(
&mut self,
name: Option<&str>,
key_description: &str,
keyslot: Option<c_uint>,
flags: CryptActivateFlags,
) -> Result<c_uint, LibcryptErr> {
let name_cstring_option = match name {
Some(n) => Some(to_cstring!(n)?),
None => None,
};
let description_cstring = to_cstring!(key_description)?;
errno_int_success!(unsafe {
libcryptsetup_rs_sys::crypt_activate_by_keyring(
self.reference.as_ptr(),
match name_cstring_option {
Some(ref cs) => cs.as_ptr(),
None => ptr::null_mut(),
},
description_cstring.as_ptr(),
keyslot
.map(|k| k as c_int)
.unwrap_or(libcryptsetup_rs_sys::CRYPT_ANY_SLOT),
flags.into(),
)
})
.map(|k| k as c_uint)
}
pub fn deactivate(
&mut self,
name: &str,
flags: CryptDeactivateFlags,
) -> Result<(), LibcryptErr> {
let name_cstring = to_cstring!(name)?;
errno!(unsafe {
libcryptsetup_rs_sys::crypt_deactivate_by_name(
self.reference.as_ptr(),
name_cstring.as_ptr(),
flags.into(),
)
})
}
}