1use std::boxed::Box;
6use std::error;
7use std::ffi;
8use std::fmt::{Display, Formatter};
9use std::marker::PhantomData;
10use std::mem;
11use std::path::Path;
12use std::ptr;
13use std::result;
14use std::str;
15use std::sync::Once;
16
17use errno;
18use libc;
19use uuid::Uuid;
20
21use crate::api::crypt_status_info;
22use blkid_rs;
23use raw;
24
25pub type RawDevice = *mut raw::crypt_device;
27pub type Luks2TokenId = i32;
28
29static INIT_LOGGING: Once = Once::new();
30
31#[derive(Debug)]
32#[non_exhaustive]
33pub enum Error {
34 CryptsetupError(errno::Errno),
36 IOError(::std::io::Error),
38 BlkidError(blkid_rs::Error),
40 InvalidLuksVersion,
42 InvalidJson(String),
44}
45
46impl Display for Error {
47 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
48 match self {
49 Error::CryptsetupError(e) => write!(f, "Cryptsetup error: {}", e),
50 Error::IOError(io) => write!(f, "Underlying IO error: {}", io),
51 Error::BlkidError(e) => write!(f, "Blkid error: {}", e),
52 Error::InvalidLuksVersion => write!(f, "Invalid or unexpected LUKS version"),
53 Error::InvalidJson(msg) => write!(f, "Invalid JSON encountered: {}", msg),
54 }
55 }
56}
57
58impl error::Error for Error {
59 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
60 match &self {
61 &Error::IOError(e) => Some(e),
62 &Error::BlkidError(e) => Some(e),
63 _ => None,
64 }
65 }
66}
67
68impl From<::std::io::Error> for Error {
69 fn from(e: ::std::io::Error) -> Self {
70 Error::IOError(e)
71 }
72}
73
74impl From<blkid_rs::Error> for Error {
75 fn from(e: blkid_rs::Error) -> Self {
76 Error::BlkidError(e)
77 }
78}
79
80pub type Result<T> = result::Result<T, Error>;
81pub type Keyslot = u8;
82
83const ANY_KEYSLOT: libc::c_int = -1 as libc::c_int;
84
85fn str_from_c_str<'a>(c_str: *const libc::c_char) -> Option<&'a str> {
86 if c_str.is_null() {
87 None
88 } else {
89 unsafe { Some(ffi::CStr::from_ptr(c_str).to_str().unwrap()) }
90 }
91}
92
93macro_rules! crypt_error {
94 ($res:expr) => {
95 Err(Error::CryptsetupError(errno::Errno(-$res)))
96 };
97}
98
99macro_rules! check_crypt_error {
100 ($res:expr) => {
101 if $res != 0 {
102 crypt_error!($res)
103 } else {
104 Ok(())
105 }
106 };
107}
108
109#[allow(unused)]
111#[no_mangle]
112pub extern "C" fn cryptsetup_rs_log_callback(
113 level: raw::crypt_log_level,
114 message: *const libc::c_char,
115 usrptr: *mut libc::c_void,
116) {
117 let msg = str_from_c_str(message).unwrap();
118 match level {
119 raw::crypt_log_level::CRYPT_LOG_NORMAL => info!(target: "cryptsetup", "{}", msg.trim_end()),
120 raw::crypt_log_level::CRYPT_LOG_ERROR => error!(target: "cryptsetup", "{}", msg.trim_end()),
121 raw::crypt_log_level::CRYPT_LOG_VERBOSE => debug!(target: "cryptsetup", "{}", msg.trim_end()),
122 raw::crypt_log_level::CRYPT_LOG_DEBUG => debug!(target: "cryptsetup", "{}", msg.trim_end()),
123 raw::crypt_log_level::CRYPT_LOG_DEBUG_JSON => debug!(target: "cryptsetup", "{}", msg.trim_end()), }
125}
126
127fn init_logging() {
128 INIT_LOGGING.call_once(|| unsafe {
129 raw::crypt_set_log_callback(ptr::null_mut(), Some(cryptsetup_rs_log_callback), ptr::null_mut());
130 });
131}
132
133pub fn init<P: AsRef<Path>>(path: P) -> Result<RawDevice> {
135 init_logging();
136 let mut cd = ptr::null_mut();
137 let c_path = ffi::CString::new(path.as_ref().to_str().unwrap()).unwrap();
138
139 let res = unsafe { raw::crypt_init(&mut cd as *mut *mut raw::crypt_device, c_path.as_ptr()) };
140
141 if res != 0 {
142 crypt_error!(res)
143 } else {
144 Ok(cd)
145 }
146}
147
148pub fn init_detached_header<P1: AsRef<Path>, P2: AsRef<Path>>(header_path: P1, device_path: P2) -> Result<RawDevice> {
150 init_logging();
151 let mut cd = ptr::null_mut();
152
153 let c_header_path = ffi::CString::new(header_path.as_ref().to_str().unwrap()).unwrap();
154 let c_device_path = ffi::CString::new(device_path.as_ref().to_str().unwrap()).unwrap();
155
156 let res = unsafe {
157 raw::crypt_init_data_device(
158 &mut cd as *mut *mut raw::crypt_device,
159 c_header_path.as_ptr(),
160 c_device_path.as_ptr(),
161 )
162 };
163
164 if res != 0 {
165 crypt_error!(res)
166 } else {
167 Ok(cd)
168 }
169}
170
171pub fn init_by_name(name: &str) -> Result<RawDevice> {
173 init_logging();
174 let mut cd = ptr::null_mut();
175 let c_name = ffi::CString::new(name).unwrap();
176
177 let res = unsafe { raw::crypt_init_by_name(&mut cd as *mut *mut raw::crypt_device, c_name.as_ptr()) };
178
179 if res != 0 {
180 crypt_error!(res)
181 } else {
182 Ok(cd)
183 }
184}
185
186pub fn load(cd: &RawDevice, requested_type: raw::crypt_device_type) -> Result<()> {
191 let c_type = ffi::CString::new(requested_type.to_str()).unwrap();
192
193 let res = unsafe { raw::crypt_load(*cd, c_type.as_ptr(), ptr::null_mut()) };
194
195 check_crypt_error!(res)
196}
197
198pub fn cipher<'a>(cd: &'a RawDevice) -> Option<&'a str> {
200 let c_cipher = unsafe { raw::crypt_get_cipher(*cd) };
201 str_from_c_str(c_cipher)
202}
203
204pub fn cipher_mode<'a>(cd: &'a RawDevice) -> Option<&'a str> {
206 let c_cipher_mode = unsafe { raw::crypt_get_cipher_mode(*cd) };
207 str_from_c_str(c_cipher_mode)
208}
209
210pub fn deactivate(cd: RawDevice, name: &str) -> Result<()> {
212 let c_name = ffi::CString::new(name).expect("name to cstr");
213 let res = unsafe { raw::crypt_deactivate(cd, c_name.as_ptr()) };
214 check_crypt_error!(res)
215}
216
217pub fn device_name<'a>(cd: &'a RawDevice) -> Option<&'a str> {
219 let c_device_name = unsafe { raw::crypt_get_device_name(*cd) };
220 str_from_c_str(c_device_name)
221}
222
223pub fn dump(cd: &RawDevice) -> Result<()> {
225 let res = unsafe { raw::crypt_dump(*cd) };
226 check_crypt_error!(res)
227}
228
229pub fn free(cd: &mut RawDevice) {
231 unsafe { raw::crypt_free(*cd) }
232}
233
234pub fn status(cd: &mut RawDevice, name: &str) -> crypt_status_info {
236 let c_name = ffi::CString::new(name).unwrap();
237
238 unsafe { raw::crypt_status(*cd, c_name.as_ptr()) }
239}
240
241pub fn status_only(name: &str) -> crypt_status_info {
243 let c_name = ffi::CString::new(name).unwrap();
244
245 unsafe { raw::crypt_status(ptr::null_mut(), c_name.as_ptr()) }
246}
247
248pub fn luks_activate(cd: &mut RawDevice, name: &str, key: &[u8]) -> Result<Keyslot> {
250 let c_name = ffi::CString::new(name).unwrap();
251 let c_passphrase_len = key.len() as libc::size_t;
252 let c_passphrase = key as *const [u8] as *const libc::c_char;
254
255 let res = unsafe {
256 raw::crypt_activate_by_passphrase(*cd, c_name.as_ptr(), ANY_KEYSLOT, c_passphrase, c_passphrase_len, 0u32)
257 };
258
259 if res < 0 {
260 crypt_error!(res)
261 } else {
262 Ok(res as u8)
263 }
264}
265
266pub fn luks_add_keyslot(
269 cd: &mut RawDevice,
270 key: &[u8],
271 maybe_prev_key: Option<&[u8]>,
272 maybe_keyslot: Option<Keyslot>,
273) -> Result<Keyslot> {
274 let c_key_len = key.len() as libc::size_t;
275 let c_key = key as *const [u8] as *const libc::c_char;
276 let c_keyslot = maybe_keyslot
277 .map(|k| k as libc::c_int)
278 .unwrap_or(ANY_KEYSLOT as libc::c_int);
279
280 let res = if let Some(prev_key) = maybe_prev_key {
281 let c_prev_key_len = prev_key.len() as libc::size_t;
282 let c_prev_key = prev_key as *const [u8] as *const libc::c_char;
283
284 unsafe { raw::crypt_keyslot_add_by_passphrase(*cd, c_keyslot, c_prev_key, c_prev_key_len, c_key, c_key_len) }
285 } else {
286 unsafe {
287 raw::crypt_keyslot_add_by_volume_key(*cd, c_keyslot, ptr::null(), 0 as libc::size_t, c_key, c_key_len)
288 }
289 };
290
291 if res < 0 {
292 crypt_error!(res)
293 } else {
294 Ok(res as Keyslot)
295 }
296}
297
298pub fn luks_update_keyslot(
300 cd: &mut RawDevice,
301 key: &[u8],
302 prev_key: &[u8],
303 maybe_keyslot: Option<Keyslot>,
304) -> Result<Keyslot> {
305 let c_key_len = key.len() as libc::size_t;
306 let c_key = key as *const [u8] as *const libc::c_char;
307 let c_keyslot = maybe_keyslot
308 .map(|k| k as libc::c_int)
309 .unwrap_or(ANY_KEYSLOT as libc::c_int);
310
311 let c_prev_key_len = prev_key.len() as libc::size_t;
312 let c_prev_key = prev_key as *const [u8] as *const libc::c_char;
313
314 let res = unsafe {
315 raw::crypt_keyslot_change_by_passphrase(*cd, c_keyslot, c_keyslot, c_prev_key, c_prev_key_len, c_key, c_key_len)
316 };
317
318 if res < 0 {
319 crypt_error!(res)
320 } else {
321 Ok(res as Keyslot)
322 }
323}
324
325pub fn luks_destroy_keyslot(cd: &mut RawDevice, keyslot: Keyslot) -> Result<()> {
327 let res = unsafe { raw::crypt_keyslot_destroy(*cd, keyslot as libc::c_int) };
328 if res < 0 {
329 crypt_error!(res)
330 } else {
331 Ok(())
332 }
333}
334
335fn generic_format(
336 cd: &mut RawDevice,
337 cipher: &str,
338 cipher_mode: &str,
339 mk_bits: usize,
340 maybe_uuid: Option<&uuid::Uuid>,
341 type_: raw::crypt_device_type,
342 c_params: *mut libc::c_void,
343) -> Result<()> {
344 let c_cipher = ffi::CString::new(cipher).unwrap();
345 let c_cipher_mode = ffi::CString::new(cipher_mode).unwrap();
346 let c_uuid = maybe_uuid.map(|uuid| ffi::CString::new(uuid.hyphenated().to_string()).unwrap());
347
348 let c_luks_type = ffi::CString::new(type_.to_str()).unwrap();
349 let c_uuid_ptr = c_uuid.as_ref().map(|u| u.as_ptr()).unwrap_or(ptr::null());
350 let res = unsafe {
351 raw::crypt_format(
352 *cd,
353 c_luks_type.as_ptr(),
354 c_cipher.as_ptr(),
355 c_cipher_mode.as_ptr(),
356 c_uuid_ptr,
357 ptr::null(),
358 mk_bits / 8,
359 c_params,
360 )
361 };
362
363 check_crypt_error!(res)
364}
365
366pub fn luks1_format(
370 cd: &mut RawDevice,
371 cipher: &str,
372 cipher_mode: &str,
373 hash: &str,
374 mk_bits: usize,
375 maybe_uuid: Option<&uuid::Uuid>,
376) -> Result<()> {
377 let c_hash = ffi::CString::new(hash).unwrap();
378 let mut luks_params = raw::crypt_params_luks1 {
379 hash: c_hash.as_ptr(),
380 data_alignment: 0,
381 data_device: ptr::null(),
382 };
383 let c_luks_params: *mut raw::crypt_params_luks1 = &mut luks_params;
384 generic_format(
385 cd,
386 cipher,
387 cipher_mode,
388 mk_bits,
389 maybe_uuid,
390 raw::crypt_device_type::LUKS1,
391 c_luks_params as *mut libc::c_void,
392 )
393}
394
395pub struct Luks2FormatPbkdf<'a> {
397 pub type_: raw::crypt_pbkdf_algo_type,
398 pub hash: &'a str,
399 pub time_ms: u32,
400 pub iterations: u32,
401 pub max_memory_kb: u32,
402 pub parallel_threads: u32,
403 pub flags: u32,
404}
405
406pub struct Luks2FormatIntegrity<'a> {
408 journal_size: u64,
409 journal_watermark: u64,
410 journal_commit_time: u64,
411 interleave_sectors: u32,
412 tag_size: u32,
413 sector_size: u32,
414 buffer_sectors: u32,
415 journal_integrity_algorithm: &'a str,
416 journal_encryption_algorithm: &'a str,
417}
418
419pub fn luks2_format<'a>(
423 cd: &mut RawDevice,
424 cipher: &str,
425 cipher_mode: &str,
426 mk_bits: usize,
427 data_alignment: usize,
428 sector_size: u32,
429 label: Option<&'a str>,
430 subsystem: Option<&'a str>,
431 data_device: Option<&Path>,
432 maybe_uuid: Option<&uuid::Uuid>,
433 pbkdf: Option<&'a Luks2FormatPbkdf>,
434 integrity: Option<&'a Luks2FormatIntegrity>,
435) -> Result<()> {
436 let maybe_pbkdf = pbkdf.map(|p| {
437 let c_type = ffi::CString::new(p.type_.to_str()).unwrap();
438 let c_hash = ffi::CString::new(p.hash).unwrap();
439
440 let res = raw::crypt_pbkdf_type {
441 type_: c_type.as_ptr(),
442 hash: c_hash.as_ptr(),
443 time_ms: p.time_ms,
444 iterations: p.iterations,
445 max_memory_kb: p.max_memory_kb,
446 parallel_threads: p.parallel_threads,
447 flags: p.flags,
448 };
449
450 (res, (c_type, c_hash))
451 });
452 let maybe_integrity = integrity.map(|i| {
453 let c_journal_integrity = ffi::CString::new(i.journal_integrity_algorithm).unwrap();
454 let c_journal_crypt = ffi::CString::new(i.journal_encryption_algorithm).unwrap();
455
456 let res = raw::crypt_params_integrity {
457 journal_size: i.journal_size,
458 journal_watermark: i.journal_watermark as libc::c_uint,
459 journal_commit_time: i.journal_commit_time as libc::c_uint,
460 interleave_sectors: i.interleave_sectors,
461 tag_size: i.tag_size,
462 sector_size: i.sector_size,
463 buffer_sectors: i.buffer_sectors,
464 integrity: ptr::null(), integrity_key_size: 0, journal_integrity: c_journal_integrity.as_ptr(),
467 journal_integrity_key: ptr::null(), journal_integrity_key_size: 0, journal_crypt: c_journal_crypt.as_ptr(),
470 journal_crypt_key: ptr::null(), journal_crypt_key_size: 0, };
473
474 (res, (c_journal_integrity, c_journal_crypt))
475 });
476
477 let maybe_data_device = data_device
478 .map(|p| p.to_str())
479 .flatten()
480 .map(|s| ffi::CString::new(s).unwrap());
481 let maybe_label = label.map(|l| ffi::CString::new(l).unwrap());
482 let maybe_subsystem = subsystem.map(|s| ffi::CString::new(s).unwrap());
483
484 let mut luks2_params = raw::crypt_params_luks2 {
485 pbkdf: maybe_pbkdf
486 .as_ref()
487 .map_or(ptr::null(), |(p, _)| p as *const raw::crypt_pbkdf_type),
488 integrity: maybe_integrity.as_ref().map_or(ptr::null(), |(_, (i, _))| i.as_ptr()),
489 integrity_params: maybe_integrity
490 .as_ref()
491 .map_or(ptr::null(), |(i, _)| i as *const raw::crypt_params_integrity),
492 data_alignment,
493 data_device: maybe_data_device.as_ref().map_or(ptr::null(), |d| d.as_ptr()),
494 sector_size,
495 label: maybe_label.as_ref().map_or(ptr::null(), |l| l.as_ptr()),
496 subsystem: maybe_subsystem.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
497 };
498 let c_luks2_params: *mut raw::crypt_params_luks2 = &mut luks2_params;
499
500 let res = generic_format(
501 cd,
502 cipher,
503 cipher_mode,
504 mk_bits,
505 maybe_uuid,
506 raw::crypt_device_type::LUKS2,
507 c_luks2_params as *mut libc::c_void,
508 );
509
510 let _discard = (
511 maybe_pbkdf,
512 maybe_integrity,
513 maybe_data_device,
514 maybe_label,
515 maybe_subsystem,
516 luks2_params,
517 );
518 res
519}
520
521#[repr(i32)]
522pub enum TokenHandlerResult {
523 Success = 0,
524 Failure = 1,
525}
526
527pub struct Luks2TokenHandlerBox<H>
529where
530 H: Luks2TokenHandler + Luks2TokenHandlerRaw,
531{
532 _c_name: ffi::CString,
533 c_handler: Box<raw::crypt_token_handler>,
534 _handler: PhantomData<H>,
535}
536
537impl<H: Luks2TokenHandler + Luks2TokenHandlerRaw> Luks2TokenHandlerBox<H> {
538 pub fn new() -> Luks2TokenHandlerBox<H> {
539 let c_name = ffi::CString::new(H::name()).expect("valid name");
540 let c_handler = Box::new(raw::crypt_token_handler {
541 name: c_name.as_ptr(),
542 open: H::raw_open_func,
543 buffer_free: Some(H::raw_free_func),
544 validate: Some(H::raw_validate_func),
545 dump: Some(H::raw_dump_func),
546 });
547 Luks2TokenHandlerBox {
548 _c_name: c_name,
549 c_handler,
550 _handler: PhantomData,
551 }
552 }
553}
554
555pub trait Luks2TokenHandler {
562 fn name() -> &'static str;
564
565 fn open(cd: RawDevice, token_id: Luks2TokenId) -> (Vec<u8>, TokenHandlerResult);
567
568 fn free(buf: Vec<u8>);
570
571 fn can_validate() -> bool;
573
574 fn is_valid(cd: RawDevice, json: String) -> Option<TokenHandlerResult>;
576
577 fn dump(cd: RawDevice, json: String);
579}
580
581pub trait Luks2TokenHandlerRaw: Luks2TokenHandler {
584 extern "C" fn raw_open_func(
585 cd: *mut raw::crypt_device,
586 token: libc::c_int,
587 buffer: *mut *mut libc::c_char,
588 buffer_len: *mut libc::size_t,
589 _usrptr: *mut libc::c_void,
590 ) -> libc::c_int {
591 let (mut buf, res) = Self::open(cd, token as Luks2TokenId);
592
593 buf.shrink_to_fit();
595 assert!(buf.capacity() == buf.len());
596
597 let buf_ptr = buf.as_mut_ptr();
598 let len = buf.len();
599 mem::forget(buf);
600
601 unsafe {
602 *buffer = buf_ptr as *mut libc::c_char;
603 *buffer_len = len as libc::size_t;
604 }
605
606 res as i32 as libc::c_int
607 }
608
609 extern "C" fn raw_free_func(buffer: *mut libc::c_void, buffer_len: libc::size_t) {
610 let buf = unsafe { Vec::from_raw_parts(buffer as *mut libc::c_char as *mut u8, buffer_len, buffer_len) };
611 Self::free(buf)
612 }
613
614 extern "C" fn raw_dump_func(cd: *mut raw::crypt_device, token_json: *const libc::c_char) {
615 let json = str_from_c_str(token_json).map_or_else(|| String::new(), |s| s.to_string());
616 Self::dump(cd, json)
617 }
618
619 extern "C" fn raw_validate_func(cd: *mut raw::crypt_device, token_json: *const libc::c_char) -> libc::c_int {
620 let res = if Self::can_validate() {
621 let json = str_from_c_str(token_json).map_or_else(|| String::new(), |s| s.to_string());
622 Self::is_valid(cd, json).expect("validation result")
623 } else {
624 TokenHandlerResult::Success
625 };
626
627 res as i32 as libc::c_int
628 }
629}
630
631pub fn luks2_register_token_handler<H: Luks2TokenHandlerRaw>(handler_box: &Luks2TokenHandlerBox<H>) -> Result<()> {
636 let res = unsafe { raw::crypt_token_register(handler_box.c_handler.as_ref()) };
637 check_crypt_error!(res)
638}
639
640pub fn luks2_token_status(cd: &mut RawDevice, token_id: Luks2TokenId) -> (raw::crypt_token_info, Option<String>) {
642 let mut type_ptr: *const libc::c_char = ptr::null();
643 let res =
644 unsafe { raw::crypt_token_status(*cd, token_id as libc::c_int, &mut type_ptr as *mut *const libc::c_char) };
645
646 let token_type = if !type_ptr.is_null() {
647 str_from_c_str(type_ptr).map(|s| s.to_string())
648 } else {
649 None
650 };
651
652 (res, token_type)
653}
654
655pub fn luks2_token_json(cd: &mut RawDevice, token_id: Luks2TokenId) -> Result<String> {
657 let mut json_ptr: *const libc::c_char = ptr::null();
658 let res =
659 unsafe { raw::crypt_token_json_get(*cd, token_id as libc::c_int, &mut json_ptr as *mut *const libc::c_char) };
660
661 if res < 0 {
662 crypt_error!(res)
663 } else {
664 let json = str_from_c_str(json_ptr)
665 .map(|s| s.to_string())
666 .expect("valid json string");
667 Ok(json)
668 }
669}
670
671pub fn luks2_token_json_allocate(
675 cd: &mut RawDevice,
676 json: &str,
677 token_id: Option<Luks2TokenId>,
678) -> Result<Luks2TokenId> {
679 let c_json = ffi::CString::new(json).unwrap();
680
681 println!("BEFORE JSON ALLOCATE: {}", json);
682
683 let res = unsafe { raw::crypt_token_json_set(*cd, token_id.unwrap_or(raw::CRYPT_ANY_TOKEN), c_json.as_ptr()) };
684 let _deferred = (c_json,);
685
686 if res < 0 {
687 crypt_error!(res)
688 } else {
689 Ok(res as Luks2TokenId)
690 }
691}
692
693pub fn luks2_token_remove(cd: &mut RawDevice, token_id: Luks2TokenId) -> Result<()> {
695 let res = unsafe { raw::crypt_token_json_set(*cd, token_id, ptr::null()) };
696
697 check_crypt_error!(res)
698}
699
700pub fn luks2_token_assign_keyslot(cd: &mut RawDevice, token_id: Luks2TokenId, keyslot: Option<Keyslot>) -> Result<()> {
702 let res = unsafe {
703 raw::crypt_token_assign_keyslot(
704 *cd,
705 token_id,
706 keyslot.map_or(raw::CRYPT_ANY_SLOT, |ks| ks as libc::c_int),
707 )
708 };
709
710 check_crypt_error!(res)
711}
712
713pub fn luks2_token_unassign_keyslot(
715 cd: &mut RawDevice,
716 token_id: Luks2TokenId,
717 keyslot: Option<Keyslot>,
718) -> Result<()> {
719 let res = unsafe {
720 raw::crypt_token_unassign_keyslot(
721 *cd,
722 token_id,
723 keyslot.map_or(raw::CRYPT_ANY_SLOT, |ks| ks as libc::c_int),
724 )
725 };
726
727 check_crypt_error!(res)
728}
729
730pub fn luks2_token_is_assigned(cd: &mut RawDevice, token_id: Luks2TokenId, keyslot: Keyslot) -> Result<bool> {
732 let res = unsafe { raw::crypt_token_is_assigned(*cd, token_id, keyslot as libc::c_int) };
733
734 if res == 0 {
735 Ok(true)
736 } else if res == libc::ENOENT {
737 Ok(false)
738 } else {
739 crypt_error!(res)
740 }
741}
742
743pub fn luks2_activate_by_token(
745 cd: &mut RawDevice,
746 name: Option<&str>,
747 token_id: Option<Luks2TokenId>,
748) -> Result<Keyslot> {
749 let c_name_opt = name.and_then(|n| ffi::CString::new(n).ok());
750
751 let res = unsafe {
752 raw::crypt_activate_by_token(
753 *cd,
754 c_name_opt.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
755 token_id.unwrap_or(raw::CRYPT_ANY_TOKEN),
756 ptr::null_mut(),
757 0,
758 )
759 };
760
761 let _deferred = (c_name_opt,);
762
763 if res < 0 {
764 crypt_error!(res)
765 } else {
766 Ok(res as Keyslot)
767 }
768}
769
770pub fn luks2_set_pbkdf_type(cd: &mut RawDevice, pbkdf: &Luks2FormatPbkdf) -> Result<()> {
771 let c_type = ffi::CString::new(pbkdf.type_.to_str()).unwrap();
772 let c_hash = ffi::CString::new(pbkdf.hash).unwrap();
773
774 let c_pbkdf_type = raw::crypt_pbkdf_type {
775 type_: c_type.as_ptr(),
776 hash: c_hash.as_ptr(),
777 time_ms: pbkdf.time_ms,
778 iterations: pbkdf.iterations,
779 max_memory_kb: pbkdf.max_memory_kb,
780 parallel_threads: pbkdf.parallel_threads,
781 flags: pbkdf.flags,
782 };
783
784 let res = unsafe { raw::crypt_set_pbkdf_type(*cd, &c_pbkdf_type as *const raw::crypt_pbkdf_type) };
785
786 let _discard = (c_type, c_hash, c_pbkdf_type);
787
788 check_crypt_error!(res)
789}
790
791pub fn rng_type(cd: &RawDevice) -> raw::crypt_rng_type {
793 unsafe {
794 let res = raw::crypt_get_rng_type(*cd);
795 mem::transmute(res)
796 }
797}
798
799#[deprecated]
801pub fn set_iteration_time(cd: &mut RawDevice, iteration_time_ms: u64) {
802 unsafe {
803 #[allow(deprecated)]
804 raw::crypt_set_iteration_time(*cd, iteration_time_ms);
805 }
806}
807
808pub fn set_rng_type(cd: &mut RawDevice, rng_type: raw::crypt_rng_type) {
810 unsafe { raw::crypt_set_rng_type(*cd, rng_type) }
811}
812
813pub fn keyslot_status(cd: &RawDevice, slot: Keyslot) -> raw::crypt_keyslot_info {
815 unsafe { raw::crypt_keyslot_status(*cd, slot as libc::c_int) }
816}
817
818pub fn volume_key_size(cd: &RawDevice) -> u8 {
820 let res = unsafe { raw::crypt_get_volume_key_size(*cd) };
821 res as u8
822}
823
824pub fn uuid(cd: &RawDevice) -> Option<Uuid> {
826 let c_uuid_str = unsafe { raw::crypt_get_uuid(*cd) };
827 str_from_c_str(c_uuid_str).and_then(|uuid_str| Uuid::parse_str(uuid_str).ok())
828}