libcryptsetup_rs/
context.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::{os::raw::c_int, path::Path, ptr};
6
7use crate::{
8    consts::vals::EncryptionFormat, device::CryptDevice, err::LibcryptErr, format::CryptParams,
9};
10
11use either::Either;
12use uuid::Uuid;
13
14/// Cryptographic context for device
15pub struct CryptContextHandle<'a> {
16    reference: &'a mut CryptDevice,
17}
18
19impl<'a> CryptContextHandle<'a> {
20    pub(crate) fn new(reference: &'a mut CryptDevice) -> Self {
21        CryptContextHandle { reference }
22    }
23
24    /// Format and encrypt the given device with the requested encryption
25    /// algorithm and key or key length.
26    ///
27    /// For `volume_key` parameter, either the volume key or the desired length of
28    /// the generated volume key can be specified.
29    ///
30    /// For the `volume_key` parameter, the value in `Either::Right` must be in
31    /// units of bytes. For a common key length such as 512 bits, the value passed
32    /// to the `Either::Right` variant would be `512 / 8`.
33    pub fn format<T: CryptParams>(
34        &mut self,
35        type_: EncryptionFormat,
36        cipher_and_mode: (&str, &str),
37        uuid: Option<Uuid>,
38        volume_key: Either<&[u8], usize>,
39        params: Option<&mut T>,
40    ) -> Result<(), LibcryptErr> {
41        let uuid_c_string = match uuid {
42            Some(u) => Some(to_cstring!(u.to_string())?),
43            None => None,
44        };
45        let (volume_key_ptr, volume_key_len) = match volume_key {
46            Either::Left(vk) => (to_byte_ptr!(vk), vk.len()),
47            Either::Right(len) => (ptr::null(), len),
48        };
49        let (cipher, cipher_mode) = cipher_and_mode;
50        let cipher_cstring = to_cstring!(cipher)?;
51        let cipher_mode_cstring = to_cstring!(cipher_mode)?;
52        errno!(mutex!(libcryptsetup_rs_sys::crypt_format(
53            self.reference.as_ptr(),
54            type_.as_ptr(),
55            cipher_cstring.as_ptr(),
56            cipher_mode_cstring.as_ptr(),
57            uuid_c_string
58                .as_ref()
59                .map(|cs| cs.as_ptr())
60                .unwrap_or_else(ptr::null),
61            volume_key_ptr,
62            volume_key_len,
63            params.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut()),
64        )))?;
65        Ok(())
66    }
67
68    /// Convert to new format type
69    pub fn convert<T: CryptParams>(
70        &mut self,
71        type_: EncryptionFormat,
72        params: Option<&mut T>,
73    ) -> Result<(), LibcryptErr> {
74        errno!(mutex!(libcryptsetup_rs_sys::crypt_convert(
75            self.reference.as_ptr(),
76            type_.as_ptr(),
77            params.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut()),
78        )))
79    }
80
81    /// Set UUID of crypt device
82    pub fn set_uuid(&mut self, uuid: Option<Uuid>) -> Result<(), LibcryptErr> {
83        let c_string = match uuid {
84            Some(u) => Some(to_cstring!(u.to_string())?),
85            None => None,
86        };
87        errno!(mutex!(libcryptsetup_rs_sys::crypt_set_uuid(
88            self.reference.as_ptr(),
89            c_string
90                .as_ref()
91                .map(|cs| cs.as_ptr())
92                .unwrap_or_else(ptr::null)
93        )))
94    }
95
96    /// Set LUKS2 device label
97    pub fn set_label(
98        &mut self,
99        label: Option<&str>,
100        subsystem_label: Option<&str>,
101    ) -> Result<(), LibcryptErr> {
102        let (lcstring, slcstring) = match (label, subsystem_label) {
103            (Some(l), Some(sl)) => (Some(to_cstring!(l)?), Some(to_cstring!(sl)?)),
104            (Some(l), _) => (Some(to_cstring!(l)?), None),
105            (_, Some(sl)) => (None, Some(to_cstring!(sl)?)),
106            (_, _) => (None, None),
107        };
108        errno!(mutex!(libcryptsetup_rs_sys::crypt_set_label(
109            self.reference.as_ptr(),
110            lcstring
111                .as_ref()
112                .map(|cs| cs.as_ptr())
113                .unwrap_or(ptr::null()),
114            slcstring
115                .as_ref()
116                .map(|cs| cs.as_ptr())
117                .unwrap_or(ptr::null()),
118        )))
119    }
120
121    /// Set policty on loading volume keys via kernel keyring
122    pub fn volume_key_keyring(&mut self, enable: bool) -> Result<(), LibcryptErr> {
123        errno!(mutex!(libcryptsetup_rs_sys::crypt_volume_key_keyring(
124            self.reference.as_ptr(),
125            enable as c_int
126        )))
127    }
128
129    /// Load on-disk header parameters based on provided type
130    pub fn load<T: CryptParams>(
131        &mut self,
132        type_: Option<EncryptionFormat>,
133        params: Option<&mut T>,
134    ) -> Result<(), LibcryptErr> {
135        errno!(mutex!(libcryptsetup_rs_sys::crypt_load(
136            self.reference.as_ptr(),
137            type_.map(|t| t.as_ptr()).unwrap_or(ptr::null()),
138            params.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut()),
139        )))?;
140        Ok(())
141    }
142
143    /// Repair crypt device header if invalid
144    pub fn repair<T: CryptParams>(
145        &mut self,
146        type_: EncryptionFormat,
147        params: Option<&mut T>,
148    ) -> Result<(), LibcryptErr> {
149        errno!(mutex!(libcryptsetup_rs_sys::crypt_repair(
150            self.reference.as_ptr(),
151            type_.as_ptr(),
152            params.map(|p| p.as_ptr()).unwrap_or(ptr::null_mut()),
153        )))
154    }
155
156    /// Resize crypt device
157    pub fn resize(&mut self, name: &str, new_size: u64) -> Result<(), LibcryptErr> {
158        let name_cstring = to_cstring!(name)?;
159        errno!(mutex!(libcryptsetup_rs_sys::crypt_resize(
160            self.reference.as_ptr(),
161            name_cstring.as_ptr(),
162            new_size,
163        )))
164    }
165
166    /// Suspend crypt device
167    pub fn suspend(&mut self, name: &str) -> Result<(), LibcryptErr> {
168        let name_cstring = to_cstring!(name)?;
169        errno!(mutex!(libcryptsetup_rs_sys::crypt_suspend(
170            self.reference.as_ptr(),
171            name_cstring.as_ptr()
172        )))
173    }
174
175    /// Resume crypt device using a passphrase
176    pub fn resume_by_passphrase(
177        &mut self,
178        name: &str,
179        keyslot: c_int,
180        passphrase: &str,
181    ) -> Result<c_int, LibcryptErr> {
182        let name_cstring = to_cstring!(name)?;
183        let passphrase_cstring = to_cstring!(passphrase)?;
184        errno_int_success!(mutex!(libcryptsetup_rs_sys::crypt_resume_by_passphrase(
185            self.reference.as_ptr(),
186            name_cstring.as_ptr(),
187            keyslot,
188            passphrase_cstring.as_ptr(),
189            passphrase.len() as crate::size_t,
190        )))
191    }
192
193    /// Resume crypt device using a key file at an offset on disk
194    pub fn resume_by_keyfile_device_offset(
195        &mut self,
196        name: &str,
197        keyslot: c_int,
198        keyfile: &Path,
199        keyfile_size: crate::size_t,
200        keyfile_offset: u64,
201    ) -> Result<c_int, LibcryptErr> {
202        let name_cstring = to_cstring!(name)?;
203        let keyfile_cstring = path_to_cstring!(keyfile)?;
204        errno_int_success!(mutex!(
205            libcryptsetup_rs_sys::crypt_resume_by_keyfile_device_offset(
206                self.reference.as_ptr(),
207                name_cstring.as_ptr(),
208                keyslot,
209                keyfile_cstring.as_ptr(),
210                keyfile_size,
211                keyfile_offset,
212            )
213        ))
214    }
215}