1use std::{
6 path::{Path, PathBuf},
7 ptr,
8};
9
10use either::Either;
11use libc::{c_int, c_uint};
12
13use crate::{
14 consts::{
15 flags::CryptVolumeKey,
16 vals::{EncryptionFormat, KeyslotInfo, KeyslotPriority},
17 },
18 device::CryptDevice,
19 err::LibcryptErr,
20 settings::CryptPbkdfType,
21};
22
23pub struct CryptKeyslotHandle<'a> {
25 reference: &'a mut CryptDevice,
26}
27
28impl<'a> CryptKeyslotHandle<'a> {
29 pub(crate) fn new(reference: &'a mut CryptDevice) -> Self {
30 CryptKeyslotHandle { reference }
31 }
32
33 pub fn add_by_passphrase(
35 &mut self,
36 keyslot: Option<c_uint>,
37 passphrase: &[u8],
38 new_passphrase: &[u8],
39 ) -> Result<c_uint, LibcryptErr> {
40 errno_int_success!(mutex!(
41 libcryptsetup_rs_sys::crypt_keyslot_add_by_passphrase(
42 self.reference.as_ptr(),
43 keyslot
44 .map(|k| k as c_int)
45 .unwrap_or(libcryptsetup_rs_sys::CRYPT_ANY_SLOT),
46 to_byte_ptr!(passphrase),
47 passphrase.len(),
48 to_byte_ptr!(new_passphrase),
49 new_passphrase.len(),
50 )
51 ))
52 .map(|k| k as c_uint)
53 }
54
55 pub fn change_by_passphrase(
57 &mut self,
58 keyslot_old: Option<c_uint>,
59 keyslot_new: Option<c_uint>,
60 passphrase: &[u8],
61 new_passphrase: &[u8],
62 ) -> Result<c_uint, LibcryptErr> {
63 errno_int_success!(mutex!(
64 libcryptsetup_rs_sys::crypt_keyslot_change_by_passphrase(
65 self.reference.as_ptr(),
66 keyslot_old
67 .map(|k| k as c_int)
68 .unwrap_or(libcryptsetup_rs_sys::CRYPT_ANY_SLOT),
69 keyslot_new
70 .map(|k| k as c_int)
71 .unwrap_or(libcryptsetup_rs_sys::CRYPT_ANY_SLOT),
72 to_byte_ptr!(passphrase),
73 passphrase.len(),
74 to_byte_ptr!(new_passphrase),
75 new_passphrase.len(),
76 )
77 ))
78 .map(|k| k as c_uint)
79 }
80
81 pub fn add_by_keyfile_device_offset(
83 &mut self,
84 keyslot: Option<c_uint>,
85 keyfile_and_size: (&Path, crate::size_t),
86 keyfile_offset: u64,
87 new_keyfile_and_size: (&Path, crate::size_t),
88 new_keyfile_offset: u64,
89 ) -> Result<c_uint, LibcryptErr> {
90 let (keyfile, keyfile_size) = keyfile_and_size;
91 let (new_keyfile, new_keyfile_size) = new_keyfile_and_size;
92 let keyfile_cstring = path_to_cstring!(keyfile)?;
93 let new_keyfile_cstring = path_to_cstring!(new_keyfile)?;
94 errno_int_success!(mutex!(
95 libcryptsetup_rs_sys::crypt_keyslot_add_by_keyfile_device_offset(
96 self.reference.as_ptr(),
97 keyslot
98 .map(|k| k as c_int)
99 .unwrap_or(libcryptsetup_rs_sys::CRYPT_ANY_SLOT),
100 keyfile_cstring.as_ptr(),
101 keyfile_size,
102 keyfile_offset,
103 new_keyfile_cstring.as_ptr(),
104 new_keyfile_size,
105 new_keyfile_offset,
106 )
107 ))
108 .map(|k| k as c_uint)
109 }
110
111 pub fn add_by_key(
113 &mut self,
114 keyslot: Option<c_uint>,
115 volume_key: Option<Either<&[u8], usize>>,
116 passphrase: &[u8],
117 flags: CryptVolumeKey,
118 ) -> Result<c_uint, LibcryptErr> {
119 let (vk_ptr, vk_len) = match volume_key {
120 Some(Either::Left(vk)) => (to_byte_ptr!(vk), vk.len()),
121 Some(Either::Right(s)) => (std::ptr::null(), s),
122 None => (std::ptr::null(), 0),
123 };
124 errno_int_success!(mutex!(libcryptsetup_rs_sys::crypt_keyslot_add_by_key(
125 self.reference.as_ptr(),
126 keyslot
127 .map(|k| k as c_int)
128 .unwrap_or(libcryptsetup_rs_sys::CRYPT_ANY_SLOT),
129 vk_ptr,
130 vk_len,
131 to_byte_ptr!(passphrase),
132 passphrase.len(),
133 flags.bits(),
134 )))
135 .map(|k| k as c_uint)
136 }
137
138 pub fn destroy(&mut self, keyslot: c_uint) -> Result<(), LibcryptErr> {
140 errno!(mutex!(libcryptsetup_rs_sys::crypt_keyslot_destroy(
141 self.reference.as_ptr(),
142 keyslot as c_int
143 )))
144 }
145
146 pub fn status(&mut self, keyslot: c_uint) -> Result<KeyslotInfo, LibcryptErr> {
148 try_int_to_return!(
149 mutex!(libcryptsetup_rs_sys::crypt_keyslot_status(
150 self.reference.as_ptr(),
151 keyslot as c_int,
152 )),
153 KeyslotInfo
154 )
155 }
156
157 pub fn get_priority(&mut self, keyslot: c_uint) -> Result<KeyslotPriority, LibcryptErr> {
159 try_int_to_return!(
160 mutex!(libcryptsetup_rs_sys::crypt_keyslot_get_priority(
161 self.reference.as_ptr(),
162 keyslot as c_int,
163 )),
164 KeyslotPriority
165 )
166 }
167
168 pub fn set_priority(
170 &mut self,
171 keyslot: c_uint,
172 priority: KeyslotPriority,
173 ) -> Result<(), LibcryptErr> {
174 errno!(mutex!(libcryptsetup_rs_sys::crypt_keyslot_set_priority(
175 self.reference.as_ptr(),
176 keyslot as c_int,
177 priority.into(),
178 )))
179 }
180
181 pub fn max_keyslots(fmt: EncryptionFormat) -> Result<c_uint, LibcryptErr> {
183 errno_int_success!(mutex!(libcryptsetup_rs_sys::crypt_keyslot_max(
184 fmt.as_ptr()
185 )))
186 .map(|k| k as c_uint)
187 }
188
189 pub fn area(&mut self, keyslot: c_uint) -> Result<(u64, u64), LibcryptErr> {
191 let mut offset = 0u64;
192 let mut length = 0u64;
193 errno!(mutex!(libcryptsetup_rs_sys::crypt_keyslot_area(
194 self.reference.as_ptr(),
195 keyslot as c_int,
196 &mut offset as *mut u64,
197 &mut length as *mut u64,
198 )))
199 .map(|_| (offset, length))
200 }
201
202 pub fn get_key_size(&mut self, keyslot: c_uint) -> Result<c_uint, LibcryptErr> {
205 errno_int_success!(mutex!(libcryptsetup_rs_sys::crypt_keyslot_get_key_size(
206 self.reference.as_ptr(),
207 keyslot as c_int,
208 )))
209 .map(|k| k as c_uint)
210 }
211
212 pub fn get_encryption(
214 &mut self,
215 keyslot: Option<c_uint>,
216 ) -> Result<(&str, crate::size_t), LibcryptErr> {
217 let mut key_size: crate::size_t = 0;
218 ptr_to_result!(mutex!(libcryptsetup_rs_sys::crypt_keyslot_get_encryption(
219 self.reference.as_ptr(),
220 keyslot
221 .map(|k| k as c_int)
222 .unwrap_or(libcryptsetup_rs_sys::CRYPT_ANY_SLOT),
223 &mut key_size as *mut crate::size_t,
224 )))
225 .and_then(|ptr| from_str_ptr!(ptr))
226 .map(|st| (st, key_size))
227 }
228
229 pub fn get_pbkdf(&mut self, keyslot: c_uint) -> Result<CryptPbkdfType, LibcryptErr> {
231 let mut type_ = libcryptsetup_rs_sys::crypt_pbkdf_type {
232 type_: ptr::null(),
233 hash: ptr::null(),
234 time_ms: 0,
235 iterations: 0,
236 max_memory_kb: 0,
237 parallel_threads: 0,
238 flags: 0,
239 };
240 errno!(mutex!(libcryptsetup_rs_sys::crypt_keyslot_get_pbkdf(
241 self.reference.as_ptr(),
242 keyslot as c_int,
243 &mut type_ as *mut _,
244 )))
245 .and_then(|_| CryptPbkdfType::try_from(type_))
246 }
247
248 pub fn set_encryption(
250 &mut self,
251 cipher: &str,
252 key_size: crate::size_t,
253 ) -> Result<(), LibcryptErr> {
254 let cipher_cstring = to_cstring!(cipher)?;
255 errno!(mutex!(libcryptsetup_rs_sys::crypt_keyslot_set_encryption(
256 self.reference.as_ptr(),
257 cipher_cstring.as_ptr(),
258 key_size,
259 )))
260 }
261
262 pub fn get_dir() -> Result<Box<Path>, LibcryptErr> {
264 ptr_to_result!(mutex!(libcryptsetup_rs_sys::crypt_get_dir()))
265 .and_then(|s| from_str_ptr_to_owned!(s))
266 .map(PathBuf::from)
267 .map(|b| b.into_boxed_path())
268 }
269}