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: Option<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: Option<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: Option<Box<CryptParamsLuks2Ref<'a>>> = match self.luks2.as_ref() {
73 Some(l) => Some(Box::new(l.try_into()?)),
74 None => None,
75 };
76
77 let resilience_cstring = to_cstring!(self.resilience)?;
78 let hash_cstring = to_cstring!(self.hash)?;
79
80 let inner = libcryptsetup_rs_sys::crypt_params_reencrypt {
81 mode: self.mode.into(),
82 direction: self.direction.into(),
83 resilience: resilience_cstring.as_ptr(),
84 hash: hash_cstring.as_ptr(),
85 data_shift: self.data_shift,
86 max_hotzone_size: self.max_hotzone_size,
87 device_size: self.device_size,
88 luks2: luks2_params
89 .as_mut()
90 .map(|l| l.as_ptr().cast())
91 .unwrap_or(ptr::null_mut()),
92 flags: self.flags.bits(),
93 };
94 Ok(CryptParamsReencryptRef {
95 inner,
96 reference: self,
97 luks2_params,
98 resilience_cstring,
99 hash_cstring,
100 })
101 }
102}
103
104pub struct CryptLuks2ReencryptHandle<'a> {
106 reference: &'a mut CryptDevice,
107}
108
109impl<'a> CryptLuks2ReencryptHandle<'a> {
110 pub(crate) fn new(reference: &'a mut CryptDevice) -> Self {
111 CryptLuks2ReencryptHandle { reference }
112 }
113
114 pub fn reencrypt_init_by_passphrase(
116 &mut self,
117 name: Option<&str>,
118 passphrase: &[u8],
119 keyslot_old: Option<c_uint>,
120 keyslot_new: Option<c_uint>,
121 cipher_and_mode: Option<(&str, &str)>,
122 params: CryptParamsReencrypt,
123 ) -> Result<c_int, LibcryptErr> {
124 let name_cstring = match name {
125 Some(n) => Some(to_cstring!(n)?),
126 None => None,
127 };
128 let (cipher_cstring_err, cipher_mode_cstring_err) = cipher_and_mode
129 .map(|(c, cm)| {
130 (
131 Some(to_cstring!(c)).transpose(),
132 Some(to_cstring!(cm)).transpose(),
133 )
134 })
135 .unwrap_or_else(|| (Ok(None), Ok(None)));
136 let cipher_cstring = cipher_cstring_err?;
137 let cipher_mode_cstring = cipher_mode_cstring_err?;
138 let params_reencrypt: CryptParamsReencryptRef<'_> = (¶ms).try_into()?;
139
140 errno_int_success!(mutex!(
141 libcryptsetup_rs_sys::crypt_reencrypt_init_by_passphrase(
142 self.reference.as_ptr(),
143 name_cstring
144 .as_ref()
145 .map(|cs| cs.as_ptr())
146 .unwrap_or_else(ptr::null),
147 to_byte_ptr!(passphrase),
148 passphrase.len(),
149 keyslot_old.map(|k| k as c_int).unwrap_or(CRYPT_ANY_SLOT),
150 keyslot_new.map(|k| k as c_int).unwrap_or(CRYPT_ANY_SLOT),
151 cipher_cstring
153 .as_ref()
154 .map(|s| s.as_ptr())
155 .unwrap_or_else(ptr::null),
156 cipher_mode_cstring
158 .as_ref()
159 .map(|s| s.as_ptr())
160 .unwrap_or_else(ptr::null),
161 params_reencrypt.as_ptr()
162 )
163 ))
164 }
165
166 pub fn reencrypt_init_by_keyring(
168 &mut self,
169 name: Option<&str>,
170 key_description: &str,
171 keyslot_old: Option<c_uint>,
172 keyslot_new: Option<c_uint>,
173 cipher_and_mode: Option<(&str, &str)>,
174 params: CryptParamsReencrypt,
175 ) -> Result<c_int, LibcryptErr> {
176 let name_cstring = match name {
177 Some(n) => Some(to_cstring!(n)?),
178 None => None,
179 };
180 let (cipher_cstring_err, cipher_mode_cstring_err) = cipher_and_mode
181 .map(|(c, cm)| {
182 (
183 Some(to_cstring!(c)).transpose(),
184 Some(to_cstring!(cm)).transpose(),
185 )
186 })
187 .unwrap_or_else(|| (Ok(None), Ok(None)));
188 let cipher_cstring = cipher_cstring_err?;
189 let cipher_mode_cstring = cipher_mode_cstring_err?;
190 let params_reencrypt: CryptParamsReencryptRef<'_> = (¶ms).try_into()?;
191
192 let description_cstring = to_cstring!(key_description)?;
193 errno_int_success!(mutex!(
194 libcryptsetup_rs_sys::crypt_reencrypt_init_by_keyring(
195 self.reference.as_ptr(),
196 name_cstring
197 .as_ref()
198 .map(|cs| cs.as_ptr())
199 .unwrap_or(ptr::null()),
200 description_cstring.as_ptr(),
201 keyslot_old.map(|k| k as c_int).unwrap_or(CRYPT_ANY_SLOT),
202 keyslot_new.map(|k| k as c_int).unwrap_or(CRYPT_ANY_SLOT),
203 cipher_cstring
205 .as_ref()
206 .map(|s| s.as_ptr())
207 .unwrap_or_else(ptr::null),
208 cipher_mode_cstring
210 .as_ref()
211 .map(|s| s.as_ptr())
212 .unwrap_or_else(ptr::null),
213 params_reencrypt.as_ptr(),
214 )
215 ))
216 }
217
218 pub fn reencrypt(&mut self, progress: Option<ReencryptProgress>) -> Result<(), LibcryptErr> {
220 errno!(mutex!(libcryptsetup_rs_sys::crypt_reencrypt(
221 self.reference.as_ptr(),
222 progress
223 )))
224 }
225
226 #[cfg(cryptsetup24supported)]
230 pub fn reencrypt2<T>(
231 &mut self,
232 progress: Option<ReencryptProgress>,
233 usrdata: Option<&mut T>,
234 ) -> Result<(), LibcryptErr> {
235 let usrptr = usrdata
236 .map(|data| (data as *mut T).cast::<c_void>())
237 .unwrap_or_else(ptr::null_mut);
238 errno!(mutex!(libcryptsetup_rs_sys::crypt_reencrypt_run(
239 self.reference.as_ptr(),
240 progress,
241 usrptr,
242 )))
243 }
244
245 pub fn status(
247 &mut self,
248 params: CryptParamsReencrypt,
249 ) -> Result<CryptReencryptInfo, LibcryptErr> {
250 let mut params_reencrypt: CryptParamsReencryptRef<'_> = (¶ms).try_into()?;
251 try_int_to_return!(
252 mutex!(libcryptsetup_rs_sys::crypt_reencrypt_status(
253 self.reference.as_ptr(),
254 &mut params_reencrypt.inner as *mut _,
255 )),
256 CryptReencryptInfo
257 )
258 }
259}