1use std::{
6 ffi::CString,
7 os::raw::{c_int, c_uint, c_void},
8 ptr,
9};
10
11use libcryptsetup_rs_sys::{crypt_params_reencrypt, CRYPT_ANY_SLOT};
12
13use crate::{
14 consts::{
15 flags::CryptReencrypt,
16 vals::{CryptReencryptDirectionInfo, CryptReencryptInfo, CryptReencryptModeInfo},
17 },
18 device::CryptDevice,
19 err::LibcryptErr,
20 format::{CryptParams, CryptParamsLuks2, CryptParamsLuks2Ref},
21};
22
23type ReencryptProgress = unsafe extern "C" fn(size: u64, offset: u64, *mut c_void) -> c_int;
24
25pub struct CryptParamsReencryptRef<'a> {
28 #[allow(missing_docs)]
29 inner: libcryptsetup_rs_sys::crypt_params_reencrypt,
30 #[allow(dead_code)]
31 reference: &'a CryptParamsReencrypt,
32 #[allow(dead_code)]
33 luks2_params: Box<CryptParamsLuks2Ref<'a>>,
34 #[allow(dead_code)]
35 resilience_cstring: CString,
36 #[allow(dead_code)]
37 hash_cstring: CString,
38}
39
40impl CryptParamsReencryptRef<'_> {
41 fn as_ptr(&self) -> *const crypt_params_reencrypt {
42 (&self.inner as *const crypt_params_reencrypt).cast::<crypt_params_reencrypt>()
43 }
44}
45
46pub struct CryptParamsReencrypt {
48 pub mode: CryptReencryptModeInfo,
50 pub direction: CryptReencryptDirectionInfo,
52 #[allow(missing_docs)]
53 pub resilience: String,
54 #[allow(missing_docs)]
55 pub hash: String,
56 #[allow(missing_docs)]
57 pub data_shift: u64,
58 #[allow(missing_docs)]
59 pub max_hotzone_size: u64,
60 pub device_size: u64,
62 pub luks2: CryptParamsLuks2,
64 pub flags: CryptReencrypt,
66}
67
68impl<'a> TryInto<CryptParamsReencryptRef<'a>> for &'a CryptParamsReencrypt {
69 type Error = LibcryptErr;
70
71 fn try_into(self) -> Result<CryptParamsReencryptRef<'a>, Self::Error> {
72 let mut luks2_params: Box<CryptParamsLuks2Ref<'a>> = Box::new((&self.luks2).try_into()?);
73
74 let resilience_cstring = to_cstring!(self.resilience)?;
75 let hash_cstring = to_cstring!(self.hash)?;
76
77 let inner = libcryptsetup_rs_sys::crypt_params_reencrypt {
78 mode: self.mode.into(),
79 direction: self.direction.into(),
80 resilience: resilience_cstring.as_ptr(),
81 hash: hash_cstring.as_ptr(),
82 data_shift: self.data_shift,
83 max_hotzone_size: self.max_hotzone_size,
84 device_size: self.device_size,
85 luks2: luks2_params.as_ptr().cast(),
86 flags: self.flags.bits(),
87 };
88 Ok(CryptParamsReencryptRef {
89 inner,
90 reference: self,
91 luks2_params,
92 resilience_cstring,
93 hash_cstring,
94 })
95 }
96}
97
98pub struct CryptLuks2ReencryptHandle<'a> {
100 reference: &'a mut CryptDevice,
101}
102
103impl<'a> CryptLuks2ReencryptHandle<'a> {
104 pub(crate) fn new(reference: &'a mut CryptDevice) -> Self {
105 CryptLuks2ReencryptHandle { reference }
106 }
107
108 pub fn reencrypt_init_by_passphrase(
110 &mut self,
111 name: Option<&str>,
112 passphrase: &[u8],
113 keyslot_old: Option<c_uint>,
114 keyslot_new: Option<c_uint>,
115 cipher_and_mode: Option<(&str, &str)>,
116 params: CryptParamsReencrypt,
117 ) -> Result<c_int, LibcryptErr> {
118 let name_cstring = match name {
119 Some(n) => Some(to_cstring!(n)?),
120 None => None,
121 };
122 let (cipher_cstring_err, cipher_mode_cstring_err) = cipher_and_mode
123 .map(|(c, cm)| {
124 (
125 Some(to_cstring!(c)).transpose(),
126 Some(to_cstring!(cm)).transpose(),
127 )
128 })
129 .unwrap_or_else(|| (Ok(None), Ok(None)));
130 let cipher_cstring = cipher_cstring_err?;
131 let cipher_mode_cstring = cipher_mode_cstring_err?;
132 let params_reencrypt: CryptParamsReencryptRef<'_> = (¶ms).try_into()?;
133
134 errno_int_success!(mutex!(
135 libcryptsetup_rs_sys::crypt_reencrypt_init_by_passphrase(
136 self.reference.as_ptr(),
137 name_cstring
138 .as_ref()
139 .map(|cs| cs.as_ptr())
140 .unwrap_or_else(ptr::null),
141 to_byte_ptr!(passphrase),
142 passphrase.len(),
143 keyslot_old.map(|k| k as c_int).unwrap_or(CRYPT_ANY_SLOT),
144 keyslot_new.map(|k| k as c_int).unwrap_or(CRYPT_ANY_SLOT),
145 cipher_cstring
147 .as_ref()
148 .map(|s| s.as_ptr())
149 .unwrap_or_else(ptr::null),
150 cipher_mode_cstring
152 .as_ref()
153 .map(|s| s.as_ptr())
154 .unwrap_or_else(ptr::null),
155 params_reencrypt.as_ptr()
156 )
157 ))
158 }
159
160 pub fn reencrypt_init_by_keyring(
162 &mut self,
163 name: Option<&str>,
164 key_description: &str,
165 keyslot_old: Option<c_uint>,
166 keyslot_new: Option<c_uint>,
167 cipher_and_mode: Option<(&str, &str)>,
168 params: CryptParamsReencrypt,
169 ) -> Result<c_int, LibcryptErr> {
170 let name_cstring = match name {
171 Some(n) => Some(to_cstring!(n)?),
172 None => None,
173 };
174 let (cipher_cstring_err, cipher_mode_cstring_err) = cipher_and_mode
175 .map(|(c, cm)| {
176 (
177 Some(to_cstring!(c)).transpose(),
178 Some(to_cstring!(cm)).transpose(),
179 )
180 })
181 .unwrap_or_else(|| (Ok(None), Ok(None)));
182 let cipher_cstring = cipher_cstring_err?;
183 let cipher_mode_cstring = cipher_mode_cstring_err?;
184 let params_reencrypt: CryptParamsReencryptRef<'_> = (¶ms).try_into()?;
185
186 let description_cstring = to_cstring!(key_description)?;
187 errno_int_success!(mutex!(
188 libcryptsetup_rs_sys::crypt_reencrypt_init_by_keyring(
189 self.reference.as_ptr(),
190 name_cstring
191 .as_ref()
192 .map(|cs| cs.as_ptr())
193 .unwrap_or(ptr::null()),
194 description_cstring.as_ptr(),
195 keyslot_old.map(|k| k as c_int).unwrap_or(CRYPT_ANY_SLOT),
196 keyslot_new.map(|k| k as c_int).unwrap_or(CRYPT_ANY_SLOT),
197 cipher_cstring
199 .as_ref()
200 .map(|s| s.as_ptr())
201 .unwrap_or_else(ptr::null),
202 cipher_mode_cstring
204 .as_ref()
205 .map(|s| s.as_ptr())
206 .unwrap_or_else(ptr::null),
207 params_reencrypt.as_ptr(),
208 )
209 ))
210 }
211
212 pub fn reencrypt(&mut self, progress: Option<ReencryptProgress>) -> Result<(), LibcryptErr> {
214 errno!(mutex!(libcryptsetup_rs_sys::crypt_reencrypt(
215 self.reference.as_ptr(),
216 progress
217 )))
218 }
219
220 #[cfg(cryptsetup24supported)]
224 pub fn reencrypt2<T>(
225 &mut self,
226 progress: Option<ReencryptProgress>,
227 usrdata: Option<&mut T>,
228 ) -> Result<(), LibcryptErr> {
229 let usrptr = usrdata
230 .map(|data| (data as *mut T).cast::<c_void>())
231 .unwrap_or_else(ptr::null_mut);
232 errno!(mutex!(libcryptsetup_rs_sys::crypt_reencrypt_run(
233 self.reference.as_ptr(),
234 progress,
235 usrptr,
236 )))
237 }
238
239 pub fn status(
241 &mut self,
242 params: CryptParamsReencrypt,
243 ) -> Result<CryptReencryptInfo, LibcryptErr> {
244 let mut params_reencrypt: CryptParamsReencryptRef<'_> = (¶ms).try_into()?;
245 try_int_to_return!(
246 mutex!(libcryptsetup_rs_sys::crypt_reencrypt_status(
247 self.reference.as_ptr(),
248 &mut params_reencrypt.inner as *mut _,
249 )),
250 CryptReencryptInfo
251 )
252 }
253}