1use std::ptr;
6
7use crate::{consts::flags::CryptActivate, device::CryptDevice, err::LibcryptErr};
8
9use libc::{c_char, c_int, c_uint, c_void};
10
11pub enum CryptTokenInfo {
13 Invalid,
15 Inactive,
17 Internal(String),
19 InternalUnknown(String),
21 External(String),
23 ExternalUnknown(String),
25}
26
27impl CryptTokenInfo {
28 pub fn from_status(code: c_uint, type_: Option<String>) -> Result<Self, LibcryptErr> {
30 Ok(match code {
31 libcryptsetup_rs_sys::crypt_token_info_CRYPT_TOKEN_INVALID => CryptTokenInfo::Invalid,
32 libcryptsetup_rs_sys::crypt_token_info_CRYPT_TOKEN_INACTIVE => CryptTokenInfo::Inactive,
33 libcryptsetup_rs_sys::crypt_token_info_CRYPT_TOKEN_INTERNAL => {
34 CryptTokenInfo::Internal(type_.ok_or(LibcryptErr::InvalidConversion)?)
35 }
36 libcryptsetup_rs_sys::crypt_token_info_CRYPT_TOKEN_INTERNAL_UNKNOWN => {
37 CryptTokenInfo::InternalUnknown(type_.ok_or(LibcryptErr::InvalidConversion)?)
38 }
39 libcryptsetup_rs_sys::crypt_token_info_CRYPT_TOKEN_EXTERNAL => {
40 CryptTokenInfo::External(type_.ok_or(LibcryptErr::InvalidConversion)?)
41 }
42 libcryptsetup_rs_sys::crypt_token_info_CRYPT_TOKEN_EXTERNAL_UNKNOWN => {
43 CryptTokenInfo::ExternalUnknown(type_.ok_or(LibcryptErr::InvalidConversion)?)
44 }
45 _ => return Err(LibcryptErr::InvalidConversion),
46 })
47 }
48}
49
50#[allow(clippy::from_over_into)]
51impl Into<u32> for CryptTokenInfo {
52 fn into(self) -> u32 {
53 match self {
54 CryptTokenInfo::Invalid => libcryptsetup_rs_sys::crypt_token_info_CRYPT_TOKEN_INVALID,
55 CryptTokenInfo::Inactive => libcryptsetup_rs_sys::crypt_token_info_CRYPT_TOKEN_INACTIVE,
56 CryptTokenInfo::Internal(_) => {
57 libcryptsetup_rs_sys::crypt_token_info_CRYPT_TOKEN_INTERNAL
58 }
59 CryptTokenInfo::InternalUnknown(_) => {
60 libcryptsetup_rs_sys::crypt_token_info_CRYPT_TOKEN_INTERNAL_UNKNOWN
61 }
62 CryptTokenInfo::External(_) => {
63 libcryptsetup_rs_sys::crypt_token_info_CRYPT_TOKEN_EXTERNAL
64 }
65 CryptTokenInfo::ExternalUnknown(_) => {
66 libcryptsetup_rs_sys::crypt_token_info_CRYPT_TOKEN_EXTERNAL_UNKNOWN
67 }
68 }
69 }
70}
71
72pub enum TokenInput<'a> {
74 AddToken(&'a serde_json::Value),
76 ReplaceToken(c_uint, &'a serde_json::Value),
78 RemoveToken(c_uint),
80}
81
82pub struct CryptLuks2TokenHandle<'a> {
84 reference: &'a mut CryptDevice,
85}
86
87impl<'a> CryptLuks2TokenHandle<'a> {
88 pub(crate) fn new(reference: &'a mut CryptDevice) -> Self {
89 CryptLuks2TokenHandle { reference }
90 }
91
92 pub fn json_get(&mut self, token: c_uint) -> Result<serde_json::Value, LibcryptErr> {
94 let mut ptr: *const c_char = std::ptr::null();
95 errno_int_success!(mutex!(libcryptsetup_rs_sys::crypt_token_json_get(
96 self.reference.as_ptr(),
97 token as c_int,
98 &mut ptr as *mut _,
99 )))
100 .and_then(|_| from_str_ptr!(ptr))
101 .and_then(|s| serde_json::from_str(s).map_err(LibcryptErr::JsonError))
102 }
103
104 pub fn json_set(&mut self, input: TokenInput<'_>) -> Result<c_uint, LibcryptErr> {
106 let (token, json) = match input {
107 TokenInput::AddToken(json) => (libcryptsetup_rs_sys::CRYPT_ANY_TOKEN, Some(json)),
108 TokenInput::ReplaceToken(token, json) => (token as i32, Some(json)),
109 TokenInput::RemoveToken(token) => (token as i32, None),
110 };
111 let json_cstring = match json {
112 Some(j) => Some(
113 serde_json::to_string(j)
114 .map_err(LibcryptErr::JsonError)
115 .and_then(|s| to_cstring!(s))?,
116 ),
117 None => None,
118 };
119 errno_int_success!(mutex!(libcryptsetup_rs_sys::crypt_token_json_set(
120 self.reference.as_ptr(),
121 token,
122 json_cstring
123 .as_ref()
124 .map(|cs| cs.as_ptr())
125 .unwrap_or(ptr::null()),
126 )))
127 .map(|rc| rc as c_uint)
128 }
129
130 pub fn status(&mut self, token: c_uint) -> Result<CryptTokenInfo, LibcryptErr> {
132 let mut ptr: *const c_char = std::ptr::null();
133 let code = mutex!(libcryptsetup_rs_sys::crypt_token_status(
134 self.reference.as_ptr(),
135 token as c_int,
136 &mut ptr as *mut _,
137 ));
138 CryptTokenInfo::from_status(
139 code,
140 match ptr_to_option!(ptr) {
141 Some(p) => Some(from_str_ptr_to_owned!(p)?),
142 None => None,
143 },
144 )
145 }
146
147 pub fn luks2_keyring_set(
149 &mut self,
150 token: Option<c_uint>,
151 key_description: &str,
152 ) -> Result<c_uint, LibcryptErr> {
153 let description_cstring = to_cstring!(key_description)?;
154 errno_int_success!(mutex!(libcryptsetup_rs_sys::crypt_token_luks2_keyring_set(
155 self.reference.as_ptr(),
156 token
157 .map(|t| t as c_int)
158 .unwrap_or(libcryptsetup_rs_sys::CRYPT_ANY_TOKEN),
159 &libcryptsetup_rs_sys::crypt_token_params_luks2_keyring {
160 key_description: description_cstring.as_ptr(),
161 } as *const _,
162 )))
163 .map(|rc| rc as c_uint)
164 }
165
166 pub fn luks2_keyring_get(&mut self, token: c_uint) -> Result<String, LibcryptErr> {
168 let mut params = libcryptsetup_rs_sys::crypt_token_params_luks2_keyring {
169 key_description: std::ptr::null(),
170 };
171 errno_int_success!(mutex!(libcryptsetup_rs_sys::crypt_token_luks2_keyring_get(
172 self.reference.as_ptr(),
173 token as c_int,
174 &mut params as *mut _,
175 )))
176 .and_then(|_| from_str_ptr!(params.key_description).map(|s| s.to_string()))
177 }
178
179 pub fn assign_keyslot(
183 &mut self,
184 token: c_uint,
185 keyslot: Option<c_uint>,
186 ) -> Result<(), LibcryptErr> {
187 errno_int_success!(mutex!(libcryptsetup_rs_sys::crypt_token_assign_keyslot(
188 self.reference.as_ptr(),
189 token as c_int,
190 keyslot
191 .map(|k| k as c_int)
192 .unwrap_or(libcryptsetup_rs_sys::CRYPT_ANY_SLOT),
193 )))
194 .map(|_| ())
195 }
196
197 pub fn unassign_keyslot(
201 &mut self,
202 token: c_uint,
203 keyslot: Option<c_uint>,
204 ) -> Result<(), LibcryptErr> {
205 errno_int_success!(mutex!(libcryptsetup_rs_sys::crypt_token_unassign_keyslot(
206 self.reference.as_ptr(),
207 token as c_int,
208 keyslot
209 .map(|k| k as c_int)
210 .unwrap_or(libcryptsetup_rs_sys::CRYPT_ANY_SLOT),
211 )))
212 .map(|_| ())
213 }
214
215 #[allow(clippy::wrong_self_convention)]
217 pub fn is_assigned(&mut self, token: c_uint, keyslot: c_uint) -> Result<bool, LibcryptErr> {
218 let rc = mutex!(libcryptsetup_rs_sys::crypt_token_is_assigned(
219 self.reference.as_ptr(),
220 token as c_int,
221 keyslot as c_int,
222 ));
223 if rc == 0 {
224 Ok(true)
225 } else if rc == libc::ENOENT {
226 Ok(false)
227 } else {
228 Err(LibcryptErr::IOError(std::io::Error::from_raw_os_error(-rc)))
229 }
230 }
231
232 pub fn activate_by_token<T>(
234 &mut self,
235 name: Option<&str>,
236 token: Option<c_uint>,
237 usrdata: Option<&mut T>,
238 flags: CryptActivate,
239 ) -> Result<c_uint, LibcryptErr> {
240 let name_cstring_option = match name {
241 Some(n) => Some(to_cstring!(n)?),
242 None => None,
243 };
244 let usrdata_ptr = match usrdata {
245 Some(reference) => (reference as *mut T).cast::<c_void>(),
246 None => ptr::null_mut(),
247 };
248 errno_int_success!(mutex!(libcryptsetup_rs_sys::crypt_activate_by_token(
249 self.reference.as_ptr(),
250 match name_cstring_option {
251 Some(ref s) => s.as_ptr(),
252 None => std::ptr::null(),
253 },
254 token
255 .map(|t| t as c_int)
256 .unwrap_or(libcryptsetup_rs_sys::CRYPT_ANY_TOKEN),
257 usrdata_ptr,
258 flags.bits(),
259 )))
260 .map(|rc| rc as c_uint)
261 }
262}
263
264pub fn register(
266 name: &'static str,
267 open: libcryptsetup_rs_sys::crypt_token_open_func,
268 buffer_free: libcryptsetup_rs_sys::crypt_token_buffer_free_func,
269 validate: libcryptsetup_rs_sys::crypt_token_validate_func,
270 dump: libcryptsetup_rs_sys::crypt_token_dump_func,
271) -> Result<(), LibcryptErr> {
272 if name.get(name.len() - 1..) != Some("\0") {
273 return Err(LibcryptErr::NoNull(name));
274 }
275 let handler = libcryptsetup_rs_sys::crypt_token_handler {
276 name: name.as_ptr().cast::<c_char>(),
277 open,
278 buffer_free,
279 validate,
280 dump,
281 };
282 errno!(mutex!(libcryptsetup_rs_sys::crypt_token_register(
283 &handler as *const libcryptsetup_rs_sys::crypt_token_handler,
284 )))
285}