libcryptsetup_rs/
device.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use std::{ffi::CString, path::Path, ptr};
6
7use either::Either;
8use libc::{c_char, c_int, c_void};
9
10use libcryptsetup_rs_sys::crypt_device;
11
12use crate::{
13    activate::CryptActivationHandle,
14    backup::CryptBackupHandle,
15    context::CryptContextHandle,
16    err::LibcryptErr,
17    format::CryptFormatHandle,
18    key::CryptVolumeKeyHandle,
19    keyfile::CryptKeyfileHandle,
20    keyslot::CryptKeyslotHandle,
21    luks2::{
22        flags::CryptLuks2FlagsHandle, reencrypt::CryptLuks2ReencryptHandle,
23        token::CryptLuks2TokenHandle,
24    },
25    runtime::CryptRuntimeHandle,
26    settings::CryptSettingsHandle,
27    status::CryptDeviceStatusHandle,
28    wipe::CryptWipeHandle,
29};
30
31type ConfirmCallback = unsafe extern "C" fn(msg: *const c_char, usrptr: *mut c_void) -> c_int;
32
33/// Initialization handle for devices
34pub struct CryptInit;
35
36impl CryptInit {
37    /// Initialize by device path
38    pub fn init(device_path: &Path) -> Result<CryptDevice, LibcryptErr> {
39        let mut cdevice: *mut crypt_device = ptr::null_mut();
40        let device_path_cstring = path_to_cstring!(device_path)?;
41        errno!(mutex!(libcryptsetup_rs_sys::crypt_init(
42            &mut cdevice as *mut *mut crypt_device,
43            device_path_cstring.as_ptr(),
44        )))?;
45        Ok(CryptDevice { ptr: cdevice })
46    }
47
48    /// Initialize by device path or a header path and a data device path
49    pub fn init_with_data_device(
50        device_paths: Either<&Path, (&Path, &Path)>,
51    ) -> Result<CryptDevice, LibcryptErr> {
52        let mut cdevice: *mut crypt_device = ptr::null_mut();
53        let (device_path_cstring, data_device_option) = match device_paths {
54            Either::Left(device) => (path_to_cstring!(device)?, None),
55            Either::Right((header_device, data_device)) => (
56                path_to_cstring!(header_device)?,
57                Some(path_to_cstring!(data_device)?),
58            ),
59        };
60
61        errno!(mutex!(libcryptsetup_rs_sys::crypt_init_data_device(
62            &mut cdevice as *mut *mut crypt_device,
63            device_path_cstring.as_ptr(),
64            match data_device_option {
65                Some(ref d) => d.as_ptr(),
66                None => ptr::null(),
67            },
68        )))?;
69        Ok(CryptDevice { ptr: cdevice })
70    }
71
72    /// Initialize by name and header device path
73    pub fn init_by_name_and_header(
74        name: &str,
75        header_device_path: Option<&Path>,
76    ) -> Result<CryptDevice, LibcryptErr> {
77        let mut cdevice: *mut crypt_device = ptr::null_mut();
78        let name_cstring = to_cstring!(name)?;
79
80        let mut header_device_path_cstring = CString::default();
81        if let Some(path) = header_device_path {
82            header_device_path_cstring = path_to_cstring!(path)?;
83        }
84
85        errno!(mutex!(libcryptsetup_rs_sys::crypt_init_by_name_and_header(
86            &mut cdevice as *mut *mut crypt_device,
87            name_cstring.as_ptr(),
88            if header_device_path.is_some() {
89                header_device_path_cstring.as_ptr()
90            } else {
91                ptr::null()
92            },
93        )))?;
94        Ok(CryptDevice { ptr: cdevice })
95    }
96}
97
98/// Data type that is a handle for a crypt device
99pub struct CryptDevice {
100    ptr: *mut crypt_device,
101}
102
103impl CryptDevice {
104    /// Reconstruct a `CryptDevice` object from a pointer
105    pub fn from_ptr(ptr: *mut crypt_device) -> Self {
106        CryptDevice { ptr }
107    }
108
109    /// Get a settings option handle
110    pub fn settings_handle(&mut self) -> CryptSettingsHandle<'_> {
111        CryptSettingsHandle::new(self)
112    }
113
114    /// Get a format option handle
115    pub fn format_handle(&mut self) -> CryptFormatHandle<'_> {
116        CryptFormatHandle::new(self)
117    }
118
119    /// Get a context option handle
120    pub fn context_handle(&mut self) -> CryptContextHandle<'_> {
121        CryptContextHandle::new(self)
122    }
123
124    /// Get a keyslot option handle
125    pub fn keyslot_handle(&mut self) -> CryptKeyslotHandle<'_> {
126        CryptKeyslotHandle::new(self)
127    }
128
129    /// Get a runtime attribute option handle
130    pub fn runtime_handle<'a>(&'a mut self, name: &'a str) -> CryptRuntimeHandle<'a> {
131        CryptRuntimeHandle::new(self, name)
132    }
133
134    /// Get LUKS2 flags option handle
135    pub fn luks2_flag_handle<T>(&mut self) -> CryptLuks2FlagsHandle<'_, T> {
136        CryptLuks2FlagsHandle::new(self)
137    }
138
139    /// Get activation option handle
140    pub fn activate_handle(&mut self) -> CryptActivationHandle<'_> {
141        CryptActivationHandle::new(self)
142    }
143
144    /// Get volume key option handle
145    pub fn volume_key_handle(&mut self) -> CryptVolumeKeyHandle<'_> {
146        CryptVolumeKeyHandle::new(self)
147    }
148
149    /// Get crypt device status option handle
150    pub fn status_handle(&mut self) -> CryptDeviceStatusHandle<'_> {
151        CryptDeviceStatusHandle::new(self)
152    }
153
154    /// Get crypt device backup option handle
155    pub fn backup_handle(&mut self) -> CryptBackupHandle<'_> {
156        CryptBackupHandle::new(self)
157    }
158
159    /// Get crypt device keyfile option handle
160    pub fn keyfile_handle(&mut self) -> CryptKeyfileHandle<'_> {
161        CryptKeyfileHandle::new(self)
162    }
163
164    /// Get crypt device wipe option handle
165    pub fn wipe_handle(&mut self) -> CryptWipeHandle<'_> {
166        CryptWipeHandle::new(self)
167    }
168
169    /// Get crypt device LUKS2 token option handle
170    pub fn token_handle(&mut self) -> CryptLuks2TokenHandle<'_> {
171        CryptLuks2TokenHandle::new(self)
172    }
173
174    /// Get crypt device reencryption option handle
175    pub fn reencrypt_handle(&mut self) -> CryptLuks2ReencryptHandle<'_> {
176        CryptLuks2ReencryptHandle::new(self)
177    }
178
179    /// Set the callback that prompts the user to confirm an action
180    pub fn set_confirm_callback<T>(
181        &mut self,
182        confirm: Option<ConfirmCallback>,
183        usrdata: Option<&mut T>,
184    ) {
185        mutex!(libcryptsetup_rs_sys::crypt_set_confirm_callback(
186            self.ptr,
187            confirm,
188            match usrdata {
189                Some(ud) => (ud as *mut T).cast::<c_void>(),
190                None => ptr::null_mut(),
191            },
192        ))
193    }
194
195    /// Set the device path for a data device
196    pub fn set_data_device(&mut self, device_path: &Path) -> Result<(), LibcryptErr> {
197        let device_path_cstring = path_to_cstring!(device_path)?;
198        errno!(mutex!(libcryptsetup_rs_sys::crypt_set_data_device(
199            self.ptr,
200            device_path_cstring.as_ptr()
201        )))
202    }
203
204    /// Set the offset in 512-byte sectors for the data section on a device
205    pub fn set_data_offset(&mut self, offset: u64) -> Result<(), LibcryptErr> {
206        errno!(mutex!(libcryptsetup_rs_sys::crypt_set_data_offset(
207            self.ptr, offset
208        )))
209    }
210
211    pub(crate) fn as_ptr(&mut self) -> *mut crypt_device {
212        self.ptr
213    }
214}
215
216impl Drop for CryptDevice {
217    fn drop(&mut self) {
218        mutex!(libcryptsetup_rs_sys::crypt_free(self.ptr))
219    }
220}