libcryptsetup_rs/
format.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use std::{
6    ffi::{c_void, CString},
7    os::raw::c_uint,
8    path::PathBuf,
9    ptr, slice,
10};
11
12use libcryptsetup_rs_sys::{
13    crypt_params_integrity, crypt_params_loopaes, crypt_params_luks1, crypt_params_luks2,
14    crypt_params_plain, crypt_params_tcrypt, crypt_params_verity,
15};
16
17use crate::{
18    consts::{
19        flags::{CryptTcrypt, CryptVerity},
20        vals::EncryptionFormat,
21    },
22    device::CryptDevice,
23    err::LibcryptErr,
24    settings::{CryptPbkdfType, CryptPbkdfTypeRef},
25};
26
27pub trait CryptParams {
28    fn as_ptr(&mut self) -> *mut c_void;
29}
30
31impl CryptParams for () {
32    fn as_ptr(&mut self) -> *mut c_void {
33        ptr::null_mut()
34    }
35}
36
37/// A struct with a lifetime representing a reference to `CryptParamsLuks1`.
38pub struct CryptParamsLuks1Ref<'a> {
39    /// The struct containing data referenced from the corresponding
40    /// `CryptParamsLuks1`.
41    inner: libcryptsetup_rs_sys::crypt_params_luks1,
42    #[allow(dead_code)]
43    reference: &'a CryptParamsLuks1,
44    #[allow(dead_code)]
45    hash_cstring: CString,
46    #[allow(dead_code)]
47    data_device_cstring: Option<CString>,
48}
49
50/// A struct representing LUKS1 specific parameters.
51pub struct CryptParamsLuks1 {
52    #[allow(missing_docs)]
53    pub hash: String,
54    #[allow(missing_docs)]
55    pub data_alignment: usize,
56    #[allow(missing_docs)]
57    pub data_device: Option<PathBuf>,
58}
59
60impl<'a> TryFrom<&'a libcryptsetup_rs_sys::crypt_params_luks1> for CryptParamsLuks1 {
61    type Error = LibcryptErr;
62
63    fn try_from(v: &'a libcryptsetup_rs_sys::crypt_params_luks1) -> Result<Self, Self::Error> {
64        Ok(CryptParamsLuks1 {
65            hash: from_str_ptr_to_owned!(v.hash)?,
66            data_alignment: v.data_alignment,
67            data_device: match ptr_to_option!(v.data_device) {
68                Some(s) => Some(PathBuf::from(from_str_ptr_to_owned!(s)?)),
69                None => None,
70            },
71        })
72    }
73}
74
75impl<'a> TryInto<CryptParamsLuks1Ref<'a>> for &'a CryptParamsLuks1 {
76    type Error = LibcryptErr;
77
78    fn try_into(self) -> Result<CryptParamsLuks1Ref<'a>, Self::Error> {
79        let hash_cstring = to_cstring!(self.hash)?;
80        let data_device_cstring = match self.data_device {
81            Some(ref dd) => Some(path_to_cstring!(dd)?),
82            None => None,
83        };
84
85        let inner = libcryptsetup_rs_sys::crypt_params_luks1 {
86            hash: hash_cstring.as_ptr(),
87            data_alignment: self.data_alignment,
88            data_device: data_device_cstring
89                .as_ref()
90                .map(|dd| dd.as_ptr())
91                .unwrap_or(ptr::null()),
92        };
93        Ok(CryptParamsLuks1Ref {
94            inner,
95            reference: self,
96            hash_cstring,
97            data_device_cstring,
98        })
99    }
100}
101
102impl CryptParams for CryptParamsLuks1Ref<'_> {
103    fn as_ptr(&mut self) -> *mut c_void {
104        (&mut self.inner as *mut crypt_params_luks1).cast::<c_void>()
105    }
106}
107
108/// A struct representing a reference with a lifetime to a `CryptParamsLuks2`
109/// struct
110pub struct CryptParamsLuks2Ref<'a> {
111    #[allow(missing_docs)]
112    inner: libcryptsetup_rs_sys::crypt_params_luks2,
113    #[allow(dead_code)]
114    reference: &'a CryptParamsLuks2,
115    #[allow(dead_code)]
116    pbkdf_type: Option<Box<CryptPbkdfTypeRef<'a>>>,
117    #[allow(dead_code)]
118    integrity_params: Option<Box<CryptParamsIntegrityRef<'a>>>,
119    #[allow(dead_code)]
120    integrity_cstring_opt: Option<CString>,
121    #[allow(dead_code)]
122    data_device_cstring: Option<CString>,
123    #[allow(dead_code)]
124    label_cstring: Option<CString>,
125    #[allow(dead_code)]
126    subsystem_cstring: Option<CString>,
127}
128
129/// LUKS2-specific parameters
130pub struct CryptParamsLuks2 {
131    #[allow(missing_docs)]
132    pub pbkdf: Option<CryptPbkdfType>,
133    #[allow(missing_docs)]
134    pub integrity: Option<String>,
135    #[allow(missing_docs)]
136    pub integrity_params: Option<CryptParamsIntegrity>,
137    #[allow(missing_docs)]
138    pub data_alignment: crate::size_t,
139    #[allow(missing_docs)]
140    pub data_device: Option<PathBuf>,
141    #[allow(missing_docs)]
142    pub sector_size: u32,
143    #[allow(missing_docs)]
144    pub label: Option<String>,
145    #[allow(missing_docs)]
146    pub subsystem: Option<String>,
147}
148
149impl<'a> TryFrom<&'a libcryptsetup_rs_sys::crypt_params_luks2> for CryptParamsLuks2 {
150    type Error = LibcryptErr;
151
152    fn try_from(v: &'a libcryptsetup_rs_sys::crypt_params_luks2) -> Result<Self, Self::Error> {
153        Ok(CryptParamsLuks2 {
154            pbkdf: match ptr_to_option_with_reference!(v.pbkdf) {
155                Some(reference) => Some(CryptPbkdfType::try_from(reference)?),
156                None => None,
157            },
158            integrity: match ptr_to_option!(v.integrity) {
159                Some(ptr) => Some(from_str_ptr_to_owned!(ptr)?),
160                None => None,
161            },
162            integrity_params: match ptr_to_option_with_reference!(v.integrity_params) {
163                Some(ptr) => Some(CryptParamsIntegrity::try_from(ptr)?),
164                None => None,
165            },
166            data_alignment: v.data_alignment,
167            data_device: match ptr_to_option!(v.data_device) {
168                Some(ptr) => Some(PathBuf::from(from_str_ptr_to_owned!(ptr)?)),
169                None => None,
170            },
171            sector_size: v.sector_size,
172            label: match ptr_to_option!(v.label) {
173                Some(ptr) => Some(from_str_ptr_to_owned!(ptr)?),
174                None => None,
175            },
176            subsystem: match ptr_to_option!(v.subsystem) {
177                Some(ptr) => Some(from_str_ptr_to_owned!(ptr)?),
178                None => None,
179            },
180        })
181    }
182}
183
184impl<'a> TryInto<CryptParamsLuks2Ref<'a>> for &'a CryptParamsLuks2 {
185    type Error = LibcryptErr;
186
187    fn try_into(self) -> Result<CryptParamsLuks2Ref<'a>, Self::Error> {
188        let pbkdf_type: Option<Box<CryptPbkdfTypeRef<'a>>> = match self.pbkdf {
189            Some(ref pbkdf) => Some(Box::new(pbkdf.try_into()?)),
190            None => None,
191        };
192        let integrity_params: Option<Box<CryptParamsIntegrityRef<'a>>> = match self.integrity_params
193        {
194            Some(ref integrity) => Some(Box::new(integrity.try_into()?)),
195            None => None,
196        };
197
198        let integrity_cstring_opt = match self.integrity {
199            Some(ref intg) => Some(to_cstring!(intg)?),
200            None => None,
201        };
202        let data_device_cstring = match self.data_device {
203            Some(ref dd) => Some(path_to_cstring!(dd)?),
204            None => None,
205        };
206        let label_cstring = match self.label {
207            Some(ref label) => Some(to_cstring!(label)?),
208            None => None,
209        };
210        let subsystem_cstring = match self.subsystem {
211            Some(ref subsystem) => Some(to_cstring!(subsystem)?),
212            None => None,
213        };
214
215        let inner = libcryptsetup_rs_sys::crypt_params_luks2 {
216            pbkdf: pbkdf_type
217                .as_ref()
218                .map(|pt| &pt.inner as *const _)
219                .unwrap_or(ptr::null()),
220            integrity: integrity_cstring_opt
221                .as_ref()
222                .map(|cs| cs.as_ptr())
223                .unwrap_or(ptr::null()),
224            integrity_params: integrity_params
225                .as_ref()
226                .map(|ip| &ip.inner as *const _)
227                .unwrap_or(ptr::null()),
228            data_alignment: self.data_alignment,
229            data_device: data_device_cstring
230                .as_ref()
231                .map(|dd| dd.as_ptr())
232                .unwrap_or(ptr::null()),
233            sector_size: self.sector_size,
234            label: label_cstring
235                .as_ref()
236                .map(|l| l.as_ptr())
237                .unwrap_or(ptr::null()),
238            subsystem: subsystem_cstring
239                .as_ref()
240                .map(|s| s.as_ptr())
241                .unwrap_or(ptr::null()),
242        };
243        Ok(CryptParamsLuks2Ref {
244            inner,
245            reference: self,
246            pbkdf_type,
247            integrity_params,
248            integrity_cstring_opt,
249            data_device_cstring,
250            label_cstring,
251            subsystem_cstring,
252        })
253    }
254}
255
256impl CryptParams for CryptParamsLuks2Ref<'_> {
257    fn as_ptr(&mut self) -> *mut c_void {
258        (&mut self.inner as *mut crypt_params_luks2).cast::<c_void>()
259    }
260}
261
262/// Reference to parameters specific to Verity
263pub struct CryptParamsVerityRef<'a> {
264    /// C representation of the struct to use with FFI
265    inner: libcryptsetup_rs_sys::crypt_params_verity,
266    #[allow(dead_code)]
267    reference: &'a CryptParamsVerity,
268    #[allow(dead_code)]
269    hash_name_cstring: CString,
270    #[allow(dead_code)]
271    data_device_cstring: CString,
272    #[allow(dead_code)]
273    hash_device_cstring: CString,
274    #[allow(dead_code)]
275    fec_device_cstring: CString,
276}
277
278/// Parameters specific to Verity
279pub struct CryptParamsVerity {
280    #[allow(missing_docs)]
281    pub hash_name: String,
282    #[allow(missing_docs)]
283    pub data_device: PathBuf,
284    #[allow(missing_docs)]
285    pub hash_device: PathBuf,
286    #[allow(missing_docs)]
287    pub fec_device: PathBuf,
288    #[allow(missing_docs)]
289    pub salt: Vec<u8>,
290    #[allow(missing_docs)]
291    pub hash_type: u32,
292    #[allow(missing_docs)]
293    pub data_block_size: u32,
294    #[allow(missing_docs)]
295    pub hash_block_size: u32,
296    #[allow(missing_docs)]
297    pub data_size: u64,
298    #[allow(missing_docs)]
299    pub hash_area_offset: u64,
300    #[allow(missing_docs)]
301    pub fec_area_offset: u64,
302    #[allow(missing_docs)]
303    pub fec_roots: u32,
304    #[allow(missing_docs)]
305    pub flags: CryptVerity,
306}
307
308impl<'a> TryFrom<&'a libcryptsetup_rs_sys::crypt_params_verity> for CryptParamsVerity {
309    type Error = LibcryptErr;
310
311    fn try_from(v: &'a libcryptsetup_rs_sys::crypt_params_verity) -> Result<Self, Self::Error> {
312        Ok(CryptParamsVerity {
313            hash_name: from_str_ptr_to_owned!(v.hash_name)?,
314            data_device: PathBuf::from(from_str_ptr_to_owned!(v.data_device)?),
315            hash_device: PathBuf::from(from_str_ptr_to_owned!(v.hash_device)?),
316            fec_device: PathBuf::from(from_str_ptr_to_owned!(v.fec_device)?),
317            salt: Vec::from(unsafe {
318                std::slice::from_raw_parts(v.salt.cast::<u8>(), v.salt_size as usize)
319            }),
320            hash_type: v.hash_type,
321            data_block_size: v.data_block_size,
322            hash_block_size: v.hash_block_size,
323            data_size: v.data_size,
324            hash_area_offset: v.hash_area_offset,
325            fec_area_offset: v.fec_area_offset,
326            fec_roots: v.fec_roots,
327            flags: CryptVerity::from_bits(v.flags).ok_or(LibcryptErr::InvalidConversion)?,
328        })
329    }
330}
331
332impl<'a> TryInto<CryptParamsVerityRef<'a>> for &'a CryptParamsVerity {
333    type Error = LibcryptErr;
334
335    fn try_into(self) -> Result<CryptParamsVerityRef<'a>, Self::Error> {
336        let hash_name_cstring = to_cstring!(self.hash_name)?;
337        let data_device_cstring = path_to_cstring!(self.data_device)?;
338        let hash_device_cstring = path_to_cstring!(self.hash_device)?;
339        let fec_device_cstring = path_to_cstring!(self.fec_device)?;
340        Ok(CryptParamsVerityRef {
341            inner: libcryptsetup_rs_sys::crypt_params_verity {
342                hash_name: hash_name_cstring.as_ptr(),
343                data_device: data_device_cstring.as_ptr(),
344                hash_device: hash_device_cstring.as_ptr(),
345                fec_device: fec_device_cstring.as_ptr(),
346                salt: self.salt.as_ptr().cast::<libc::c_char>(),
347                salt_size: self.salt.len() as u32,
348                hash_type: self.hash_type,
349                data_block_size: self.data_block_size,
350                hash_block_size: self.hash_block_size,
351                data_size: self.data_size,
352                hash_area_offset: self.hash_area_offset,
353                fec_area_offset: self.fec_area_offset,
354                fec_roots: self.fec_roots,
355                flags: self.flags.bits(),
356            },
357            reference: self,
358            hash_name_cstring,
359            data_device_cstring,
360            hash_device_cstring,
361            fec_device_cstring,
362        })
363    }
364}
365
366impl CryptParams for CryptParamsVerityRef<'_> {
367    fn as_ptr(&mut self) -> *mut c_void {
368        (&mut self.inner as *mut crypt_params_verity).cast::<c_void>()
369    }
370}
371
372/// C-compatible reference to a `CryptParamsLoopaes` struct
373pub struct CryptParamsLoopaesRef<'a> {
374    /// C representation of the struct to use with FFI
375    inner: libcryptsetup_rs_sys::crypt_params_loopaes,
376    #[allow(dead_code)]
377    reference: &'a CryptParamsLoopaes,
378    #[allow(dead_code)]
379    hash_cstring: CString,
380}
381
382/// Parameters for formatting a loop AES device
383pub struct CryptParamsLoopaes {
384    #[allow(missing_docs)]
385    pub hash: String,
386    #[allow(missing_docs)]
387    pub offset: u64,
388    #[allow(missing_docs)]
389    pub skip: u64,
390}
391
392impl<'a> TryFrom<&'a libcryptsetup_rs_sys::crypt_params_loopaes> for CryptParamsLoopaes {
393    type Error = LibcryptErr;
394
395    fn try_from(v: &'a libcryptsetup_rs_sys::crypt_params_loopaes) -> Result<Self, Self::Error> {
396        Ok(CryptParamsLoopaes {
397            hash: from_str_ptr_to_owned!(v.hash)?,
398            offset: v.offset,
399            skip: v.skip,
400        })
401    }
402}
403
404impl<'a> TryInto<CryptParamsLoopaesRef<'a>> for &'a CryptParamsLoopaes {
405    type Error = LibcryptErr;
406
407    fn try_into(self) -> Result<CryptParamsLoopaesRef<'a>, Self::Error> {
408        let hash_cstring = to_cstring!(self.hash)?;
409        Ok(CryptParamsLoopaesRef {
410            inner: libcryptsetup_rs_sys::crypt_params_loopaes {
411                hash: hash_cstring.as_ptr(),
412                offset: self.offset,
413                skip: self.skip,
414            },
415            reference: self,
416            hash_cstring,
417        })
418    }
419}
420
421impl CryptParams for CryptParamsLoopaesRef<'_> {
422    fn as_ptr(&mut self) -> *mut c_void {
423        (&mut self.inner as *mut crypt_params_loopaes).cast::<c_void>()
424    }
425}
426
427/// A struct representing a reference with a lifetime to a `CryptParamsIntegrity`
428/// struct
429pub struct CryptParamsIntegrityRef<'a> {
430    #[allow(missing_docs)]
431    inner: libcryptsetup_rs_sys::crypt_params_integrity,
432    #[allow(dead_code)]
433    reference: &'a CryptParamsIntegrity,
434    #[allow(dead_code)]
435    integrity_cstring: CString,
436    #[allow(dead_code)]
437    journal_integrity_cstring: CString,
438    #[allow(dead_code)]
439    journal_crypt_cstring: CString,
440}
441
442/// Parameters for integrity checking
443pub struct CryptParamsIntegrity {
444    #[allow(missing_docs)]
445    pub journal_size: u64,
446    #[allow(missing_docs)]
447    pub journal_watermark: c_uint,
448    #[allow(missing_docs)]
449    pub journal_commit_time: c_uint,
450    #[allow(missing_docs)]
451    pub interleave_sectors: u32,
452    #[allow(missing_docs)]
453    pub tag_size: u32,
454    #[allow(missing_docs)]
455    pub sector_size: u32,
456    #[allow(missing_docs)]
457    pub buffer_sectors: u32,
458    #[allow(missing_docs)]
459    pub integrity: String,
460    #[allow(missing_docs)]
461    pub integrity_key_size: u32,
462    #[allow(missing_docs)]
463    pub journal_integrity: String,
464    #[allow(missing_docs)]
465    pub journal_integrity_key: Vec<u8>,
466    #[allow(missing_docs)]
467    pub journal_crypt: String,
468    #[allow(missing_docs)]
469    pub journal_crypt_key: Vec<u8>,
470}
471
472impl<'a> TryInto<CryptParamsIntegrityRef<'a>> for &'a CryptParamsIntegrity {
473    type Error = LibcryptErr;
474
475    fn try_into(self) -> Result<CryptParamsIntegrityRef<'a>, Self::Error> {
476        let integrity_cstring = to_cstring!(self.integrity)?;
477        let journal_integrity_cstring = to_cstring!(self.journal_integrity)?;
478        let journal_crypt_cstring = to_cstring!(self.journal_crypt)?;
479        let inner = libcryptsetup_rs_sys::crypt_params_integrity {
480            journal_size: self.journal_size,
481            journal_watermark: self.journal_watermark,
482            journal_commit_time: self.journal_commit_time,
483            interleave_sectors: self.interleave_sectors,
484            tag_size: self.tag_size,
485            sector_size: self.sector_size,
486            buffer_sectors: self.buffer_sectors,
487            integrity: integrity_cstring.as_ptr(),
488            integrity_key_size: self.integrity_key_size,
489            journal_integrity: journal_integrity_cstring.as_ptr(),
490            journal_integrity_key: to_byte_ptr!(self.journal_integrity_key),
491            journal_integrity_key_size: self.journal_integrity_key.len() as u32,
492            journal_crypt: journal_crypt_cstring.as_ptr(),
493            journal_crypt_key: to_byte_ptr!(self.journal_crypt_key),
494            journal_crypt_key_size: self.journal_crypt_key.len() as u32,
495        };
496        Ok(CryptParamsIntegrityRef {
497            inner,
498            reference: self,
499            integrity_cstring,
500            journal_integrity_cstring,
501            journal_crypt_cstring,
502        })
503    }
504}
505
506impl<'a> TryFrom<&'a libcryptsetup_rs_sys::crypt_params_integrity> for CryptParamsIntegrity {
507    type Error = LibcryptErr;
508
509    fn try_from(v: &'a libcryptsetup_rs_sys::crypt_params_integrity) -> Result<Self, Self::Error> {
510        Ok(CryptParamsIntegrity {
511            journal_size: v.journal_size,
512            journal_watermark: v.journal_watermark,
513            journal_commit_time: v.journal_commit_time,
514            interleave_sectors: v.interleave_sectors,
515            tag_size: v.tag_size,
516            sector_size: v.sector_size,
517            buffer_sectors: v.buffer_sectors,
518            integrity: from_str_ptr_to_owned!(v.integrity)?,
519            integrity_key_size: v.integrity_key_size,
520            journal_integrity: from_str_ptr_to_owned!(v.journal_integrity)?,
521            journal_integrity_key: Vec::from(unsafe {
522                std::slice::from_raw_parts(
523                    v.journal_integrity_key.cast::<u8>(),
524                    v.journal_integrity_key_size as usize,
525                )
526            }),
527            journal_crypt: from_str_ptr_to_owned!(v.journal_crypt)?,
528            journal_crypt_key: Vec::from(unsafe {
529                std::slice::from_raw_parts(
530                    v.journal_crypt_key.cast::<u8>(),
531                    v.journal_crypt_key_size as usize,
532                )
533            }),
534        })
535    }
536}
537
538impl CryptParams for CryptParamsIntegrityRef<'_> {
539    fn as_ptr(&mut self) -> *mut c_void {
540        (&mut self.inner as *mut crypt_params_integrity).cast::<c_void>()
541    }
542}
543
544/// Represents a reference to a `CryptParamsPlain` struct
545pub struct CryptParamsPlainRef<'a> {
546    /// C FFI-compatible field
547    inner: libcryptsetup_rs_sys::crypt_params_plain,
548    #[allow(dead_code)]
549    reference: &'a CryptParamsPlain,
550    #[allow(dead_code)]
551    hash_cstring: CString,
552}
553
554/// Struct representing plain cryptsetup format parameters
555pub struct CryptParamsPlain {
556    /// Password hash function
557    pub hash: String,
558    /// Offset in sectors
559    pub offset: u64,
560    /// Sector size in bytes
561    pub sector_size: u32,
562    /// Size of mapped device
563    pub size: u64,
564    /// IV offset
565    pub skip: u64,
566}
567
568impl<'a> TryInto<CryptParamsPlainRef<'a>> for &'a CryptParamsPlain {
569    type Error = LibcryptErr;
570
571    fn try_into(self) -> Result<CryptParamsPlainRef<'a>, Self::Error> {
572        let hash_cstring = to_cstring!(self.hash)?;
573        Ok(CryptParamsPlainRef {
574            inner: libcryptsetup_rs_sys::crypt_params_plain {
575                hash: hash_cstring.as_ptr(),
576                offset: self.offset,
577                sector_size: self.sector_size,
578                size: self.size,
579                skip: self.skip,
580            },
581            reference: self,
582            hash_cstring,
583        })
584    }
585}
586
587impl<'a> TryFrom<&'a libcryptsetup_rs_sys::crypt_params_plain> for CryptParamsPlain {
588    type Error = LibcryptErr;
589
590    fn try_from(v: &'a libcryptsetup_rs_sys::crypt_params_plain) -> Result<Self, Self::Error> {
591        Ok(CryptParamsPlain {
592            hash: from_str_ptr_to_owned!(v.hash)?,
593            offset: v.offset,
594            sector_size: v.sector_size,
595            size: v.size,
596            skip: v.skip,
597        })
598    }
599}
600
601impl CryptParams for CryptParamsPlainRef<'_> {
602    fn as_ptr(&mut self) -> *mut c_void {
603        (&mut self.inner as *mut crypt_params_plain).cast::<c_void>()
604    }
605}
606
607/// Reference to a `CryptParamsTcrypt` struct
608pub struct CryptParamsTcryptRef<'a> {
609    /// FFI compatible representation of `CryptParamsTcrypt`
610    inner: libcryptsetup_rs_sys::crypt_params_tcrypt,
611    #[allow(dead_code)]
612    reference: &'a CryptParamsTcrypt,
613    #[allow(dead_code)]
614    keyfiles_cstrings: Vec<CString>,
615    #[allow(dead_code)]
616    keyfiles_ptrs: Vec<*const libc::c_char>,
617    #[allow(dead_code)]
618    hash_name_cstring: CString,
619    #[allow(dead_code)]
620    cipher_cstring: CString,
621    #[allow(dead_code)]
622    mode_cstring: CString,
623}
624
625/// Parameters for tcrypt operations
626pub struct CryptParamsTcrypt {
627    #[allow(missing_docs)]
628    pub passphrase: Option<Vec<u8>>,
629    #[allow(missing_docs)]
630    pub keyfiles: Option<Vec<PathBuf>>,
631    #[allow(missing_docs)]
632    pub hash_name: String,
633    #[allow(missing_docs)]
634    pub cipher: String,
635    #[allow(missing_docs)]
636    pub mode: String,
637    #[allow(missing_docs)]
638    pub key_size: usize,
639    #[allow(missing_docs)]
640    pub flags: CryptTcrypt,
641    #[allow(missing_docs)]
642    pub veracrypt_pim: u32,
643}
644
645impl<'a> TryInto<CryptParamsTcryptRef<'a>> for &'a CryptParamsTcrypt {
646    type Error = LibcryptErr;
647
648    fn try_into(self) -> Result<CryptParamsTcryptRef<'a>, Self::Error> {
649        let mut keyfiles_cstrings = Vec::new();
650        if let Some(ref keyfiles) = self.keyfiles {
651            for keyfile in keyfiles.iter() {
652                keyfiles_cstrings.push(path_to_cstring!(keyfile)?);
653            }
654        }
655        let mut keyfiles_ptrs: Vec<*const libc::c_char> =
656            keyfiles_cstrings.iter().map(|cs| cs.as_ptr()).collect();
657        let hash_name_cstring = to_cstring!(self.hash_name)?;
658        let cipher_cstring = to_cstring!(self.cipher)?;
659        let mode_cstring = to_cstring!(self.mode)?;
660        Ok(CryptParamsTcryptRef {
661            inner: libcryptsetup_rs_sys::crypt_params_tcrypt {
662                passphrase: match self.passphrase {
663                    Some(ref pass) => pass.as_ptr().cast::<libc::c_char>(),
664                    None => std::ptr::null(),
665                },
666                passphrase_size: match self.passphrase {
667                    Some(ref pass) => pass.len(),
668                    None => 0,
669                },
670                keyfiles: keyfiles_ptrs.as_mut_ptr(),
671                keyfiles_count: keyfiles_cstrings.len() as u32,
672                hash_name: hash_name_cstring.as_ptr(),
673                cipher: cipher_cstring.as_ptr(),
674                mode: mode_cstring.as_ptr(),
675                flags: self.flags.bits(),
676                key_size: self.key_size,
677                veracrypt_pim: self.veracrypt_pim,
678            },
679            reference: self,
680            keyfiles_cstrings,
681            keyfiles_ptrs,
682            hash_name_cstring,
683            cipher_cstring,
684            mode_cstring,
685        })
686    }
687}
688
689impl<'a> TryFrom<&'a libcryptsetup_rs_sys::crypt_params_tcrypt> for CryptParamsTcrypt {
690    type Error = LibcryptErr;
691
692    fn try_from(v: &'a libcryptsetup_rs_sys::crypt_params_tcrypt) -> Result<Self, Self::Error> {
693        let mut keyfiles = Vec::new();
694        let keyfiles_ptrs = unsafe { slice::from_raw_parts(v.keyfiles, v.keyfiles_count as usize) };
695        for keyfile_ptr in keyfiles_ptrs {
696            keyfiles.push(PathBuf::from(from_str_ptr_to_owned!(*keyfile_ptr)?));
697        }
698        Ok(CryptParamsTcrypt {
699            passphrase: ptr_to_option!(v.passphrase).map(|p| {
700                unsafe { slice::from_raw_parts(p.cast::<u8>(), v.passphrase_size) }.to_vec()
701            }),
702            keyfiles: if keyfiles.is_empty() {
703                None
704            } else {
705                Some(keyfiles)
706            },
707            hash_name: from_str_ptr_to_owned!(v.hash_name)?,
708            cipher: from_str_ptr_to_owned!(v.cipher)?,
709            mode: from_str_ptr_to_owned!(v.mode)?,
710            flags: CryptTcrypt::from_bits(v.flags).ok_or(LibcryptErr::InvalidConversion)?,
711            key_size: v.key_size,
712            veracrypt_pim: v.veracrypt_pim,
713        })
714    }
715}
716
717impl CryptParams for CryptParamsTcryptRef<'_> {
718    fn as_ptr(&mut self) -> *mut c_void {
719        (&mut self.inner as *mut crypt_params_tcrypt).cast::<c_void>()
720    }
721}
722
723/// Handle for format operations on a device
724pub struct CryptFormatHandle<'a> {
725    reference: &'a mut CryptDevice,
726}
727
728impl<'a> CryptFormatHandle<'a> {
729    pub(crate) fn new(reference: &'a mut CryptDevice) -> Self {
730        CryptFormatHandle { reference }
731    }
732
733    /// Get the formatting type
734    pub fn get_type(&mut self) -> Result<EncryptionFormat, LibcryptErr> {
735        EncryptionFormat::from_ptr(ptr_to_result!(mutex!(
736            libcryptsetup_rs_sys::crypt_get_type(self.reference.as_ptr())
737        ))?)
738    }
739
740    /// Get the default formatting type
741    pub fn get_default_type() -> Result<EncryptionFormat, LibcryptErr> {
742        EncryptionFormat::from_ptr(ptr_to_result!(mutex!(
743            libcryptsetup_rs_sys::crypt_get_default_type()
744        ))?)
745    }
746}
747
748#[cfg(test)]
749mod test {
750    use super::EncryptionFormat;
751
752    #[test]
753    fn test_encryption_format_partialeq() {
754        #[allow(clippy::eq_op)]
755        {
756            assert_eq!(EncryptionFormat::Luks1, EncryptionFormat::Luks1);
757        }
758        assert_ne!(EncryptionFormat::Luks1, EncryptionFormat::Luks2);
759    }
760
761    #[test]
762    fn test_encryption_format_from_ptr() {
763        for format in &[
764            EncryptionFormat::Integrity,
765            EncryptionFormat::Tcrypt,
766            EncryptionFormat::Verity,
767            EncryptionFormat::Luks2,
768            EncryptionFormat::Loopaes,
769            EncryptionFormat::Luks1,
770            EncryptionFormat::Plain,
771        ] {
772            assert_eq!(
773                EncryptionFormat::from_ptr(format.as_ptr()).unwrap(),
774                *format
775            );
776        }
777    }
778}