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: Option<CString>,
274    #[allow(dead_code)]
275    fec_device_cstring: Option<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: Option<PathBuf>,
286    #[allow(missing_docs)]
287    pub fec_device: Option<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: match ptr_to_option!(v.hash_device) {
316                Some(s) => Some(PathBuf::from(from_str_ptr_to_owned!(s)?)),
317                None => None,
318            },
319            fec_device: match ptr_to_option!(v.fec_device) {
320                Some(s) => Some(PathBuf::from(from_str_ptr_to_owned!(s)?)),
321                None => None,
322            },
323            salt: Vec::from(unsafe {
324                std::slice::from_raw_parts(v.salt.cast::<u8>(), v.salt_size as usize)
325            }),
326            hash_type: v.hash_type,
327            data_block_size: v.data_block_size,
328            hash_block_size: v.hash_block_size,
329            data_size: v.data_size,
330            hash_area_offset: v.hash_area_offset,
331            fec_area_offset: v.fec_area_offset,
332            fec_roots: v.fec_roots,
333            flags: CryptVerity::from_bits(v.flags).ok_or(LibcryptErr::InvalidConversion)?,
334        })
335    }
336}
337
338impl<'a> TryInto<CryptParamsVerityRef<'a>> for &'a CryptParamsVerity {
339    type Error = LibcryptErr;
340
341    fn try_into(self) -> Result<CryptParamsVerityRef<'a>, Self::Error> {
342        let hash_name_cstring = to_cstring!(self.hash_name)?;
343        let data_device_cstring = path_to_cstring!(self.data_device)?;
344        let hash_device_cstring = match self.hash_device {
345            Some(ref hash_device) => Some(path_to_cstring!(hash_device)?),
346            None => None,
347        };
348        let fec_device_cstring = match self.fec_device {
349            Some(ref fec_device) => Some(path_to_cstring!(fec_device)?),
350            None => None,
351        };
352        Ok(CryptParamsVerityRef {
353            inner: libcryptsetup_rs_sys::crypt_params_verity {
354                hash_name: hash_name_cstring.as_ptr(),
355                data_device: data_device_cstring.as_ptr(),
356                hash_device: hash_device_cstring
357                    .as_ref()
358                    .map(|hd| hd.as_ptr())
359                    .unwrap_or(ptr::null()),
360                fec_device: fec_device_cstring
361                    .as_ref()
362                    .map(|fd| fd.as_ptr())
363                    .unwrap_or(ptr::null()),
364                salt: self.salt.as_ptr().cast::<libc::c_char>(),
365                salt_size: self.salt.len() as u32,
366                hash_type: self.hash_type,
367                data_block_size: self.data_block_size,
368                hash_block_size: self.hash_block_size,
369                data_size: self.data_size,
370                hash_area_offset: self.hash_area_offset,
371                fec_area_offset: self.fec_area_offset,
372                fec_roots: self.fec_roots,
373                flags: self.flags.bits(),
374            },
375            reference: self,
376            hash_name_cstring,
377            data_device_cstring,
378            hash_device_cstring,
379            fec_device_cstring,
380        })
381    }
382}
383
384impl CryptParams for CryptParamsVerityRef<'_> {
385    fn as_ptr(&mut self) -> *mut c_void {
386        (&mut self.inner as *mut crypt_params_verity).cast::<c_void>()
387    }
388}
389
390/// C-compatible reference to a `CryptParamsLoopaes` struct
391pub struct CryptParamsLoopaesRef<'a> {
392    /// C representation of the struct to use with FFI
393    inner: libcryptsetup_rs_sys::crypt_params_loopaes,
394    #[allow(dead_code)]
395    reference: &'a CryptParamsLoopaes,
396    #[allow(dead_code)]
397    hash_cstring: CString,
398}
399
400/// Parameters for formatting a loop AES device
401pub struct CryptParamsLoopaes {
402    #[allow(missing_docs)]
403    pub hash: String,
404    #[allow(missing_docs)]
405    pub offset: u64,
406    #[allow(missing_docs)]
407    pub skip: u64,
408}
409
410impl<'a> TryFrom<&'a libcryptsetup_rs_sys::crypt_params_loopaes> for CryptParamsLoopaes {
411    type Error = LibcryptErr;
412
413    fn try_from(v: &'a libcryptsetup_rs_sys::crypt_params_loopaes) -> Result<Self, Self::Error> {
414        Ok(CryptParamsLoopaes {
415            hash: from_str_ptr_to_owned!(v.hash)?,
416            offset: v.offset,
417            skip: v.skip,
418        })
419    }
420}
421
422impl<'a> TryInto<CryptParamsLoopaesRef<'a>> for &'a CryptParamsLoopaes {
423    type Error = LibcryptErr;
424
425    fn try_into(self) -> Result<CryptParamsLoopaesRef<'a>, Self::Error> {
426        let hash_cstring = to_cstring!(self.hash)?;
427        Ok(CryptParamsLoopaesRef {
428            inner: libcryptsetup_rs_sys::crypt_params_loopaes {
429                hash: hash_cstring.as_ptr(),
430                offset: self.offset,
431                skip: self.skip,
432            },
433            reference: self,
434            hash_cstring,
435        })
436    }
437}
438
439impl CryptParams for CryptParamsLoopaesRef<'_> {
440    fn as_ptr(&mut self) -> *mut c_void {
441        (&mut self.inner as *mut crypt_params_loopaes).cast::<c_void>()
442    }
443}
444
445/// A struct representing a reference with a lifetime to a `CryptParamsIntegrity`
446/// struct
447pub struct CryptParamsIntegrityRef<'a> {
448    #[allow(missing_docs)]
449    inner: libcryptsetup_rs_sys::crypt_params_integrity,
450    #[allow(dead_code)]
451    reference: &'a CryptParamsIntegrity,
452    #[allow(dead_code)]
453    integrity_cstring: CString,
454    #[allow(dead_code)]
455    journal_integrity_cstring: CString,
456    #[allow(dead_code)]
457    journal_crypt_cstring: CString,
458}
459
460/// Parameters for integrity checking
461pub struct CryptParamsIntegrity {
462    #[allow(missing_docs)]
463    pub journal_size: u64,
464    #[allow(missing_docs)]
465    pub journal_watermark: c_uint,
466    #[allow(missing_docs)]
467    pub journal_commit_time: c_uint,
468    #[allow(missing_docs)]
469    pub interleave_sectors: u32,
470    #[allow(missing_docs)]
471    pub tag_size: u32,
472    #[allow(missing_docs)]
473    pub sector_size: u32,
474    #[allow(missing_docs)]
475    pub buffer_sectors: u32,
476    #[allow(missing_docs)]
477    pub integrity: String,
478    #[allow(missing_docs)]
479    pub integrity_key_size: u32,
480    #[allow(missing_docs)]
481    pub journal_integrity: String,
482    #[allow(missing_docs)]
483    pub journal_integrity_key: Vec<u8>,
484    #[allow(missing_docs)]
485    pub journal_crypt: String,
486    #[allow(missing_docs)]
487    pub journal_crypt_key: Vec<u8>,
488}
489
490impl<'a> TryInto<CryptParamsIntegrityRef<'a>> for &'a CryptParamsIntegrity {
491    type Error = LibcryptErr;
492
493    fn try_into(self) -> Result<CryptParamsIntegrityRef<'a>, Self::Error> {
494        let integrity_cstring = to_cstring!(self.integrity)?;
495        let journal_integrity_cstring = to_cstring!(self.journal_integrity)?;
496        let journal_crypt_cstring = to_cstring!(self.journal_crypt)?;
497        let inner = libcryptsetup_rs_sys::crypt_params_integrity {
498            journal_size: self.journal_size,
499            journal_watermark: self.journal_watermark,
500            journal_commit_time: self.journal_commit_time,
501            interleave_sectors: self.interleave_sectors,
502            tag_size: self.tag_size,
503            sector_size: self.sector_size,
504            buffer_sectors: self.buffer_sectors,
505            integrity: integrity_cstring.as_ptr(),
506            integrity_key_size: self.integrity_key_size,
507            journal_integrity: journal_integrity_cstring.as_ptr(),
508            journal_integrity_key: to_byte_ptr!(self.journal_integrity_key),
509            journal_integrity_key_size: self.journal_integrity_key.len() as u32,
510            journal_crypt: journal_crypt_cstring.as_ptr(),
511            journal_crypt_key: to_byte_ptr!(self.journal_crypt_key),
512            journal_crypt_key_size: self.journal_crypt_key.len() as u32,
513        };
514        Ok(CryptParamsIntegrityRef {
515            inner,
516            reference: self,
517            integrity_cstring,
518            journal_integrity_cstring,
519            journal_crypt_cstring,
520        })
521    }
522}
523
524impl<'a> TryFrom<&'a libcryptsetup_rs_sys::crypt_params_integrity> for CryptParamsIntegrity {
525    type Error = LibcryptErr;
526
527    fn try_from(v: &'a libcryptsetup_rs_sys::crypt_params_integrity) -> Result<Self, Self::Error> {
528        Ok(CryptParamsIntegrity {
529            journal_size: v.journal_size,
530            journal_watermark: v.journal_watermark,
531            journal_commit_time: v.journal_commit_time,
532            interleave_sectors: v.interleave_sectors,
533            tag_size: v.tag_size,
534            sector_size: v.sector_size,
535            buffer_sectors: v.buffer_sectors,
536            integrity: from_str_ptr_to_owned!(v.integrity)?,
537            integrity_key_size: v.integrity_key_size,
538            journal_integrity: from_str_ptr_to_owned!(v.journal_integrity)?,
539            journal_integrity_key: Vec::from(unsafe {
540                std::slice::from_raw_parts(
541                    v.journal_integrity_key.cast::<u8>(),
542                    v.journal_integrity_key_size as usize,
543                )
544            }),
545            journal_crypt: from_str_ptr_to_owned!(v.journal_crypt)?,
546            journal_crypt_key: Vec::from(unsafe {
547                std::slice::from_raw_parts(
548                    v.journal_crypt_key.cast::<u8>(),
549                    v.journal_crypt_key_size as usize,
550                )
551            }),
552        })
553    }
554}
555
556impl CryptParams for CryptParamsIntegrityRef<'_> {
557    fn as_ptr(&mut self) -> *mut c_void {
558        (&mut self.inner as *mut crypt_params_integrity).cast::<c_void>()
559    }
560}
561
562/// Represents a reference to a `CryptParamsPlain` struct
563pub struct CryptParamsPlainRef<'a> {
564    /// C FFI-compatible field
565    inner: libcryptsetup_rs_sys::crypt_params_plain,
566    #[allow(dead_code)]
567    reference: &'a CryptParamsPlain,
568    #[allow(dead_code)]
569    hash_cstring: CString,
570}
571
572/// Struct representing plain cryptsetup format parameters
573pub struct CryptParamsPlain {
574    /// Password hash function
575    pub hash: String,
576    /// Offset in sectors
577    pub offset: u64,
578    /// Sector size in bytes
579    pub sector_size: u32,
580    /// Size of mapped device
581    pub size: u64,
582    /// IV offset
583    pub skip: u64,
584}
585
586impl<'a> TryInto<CryptParamsPlainRef<'a>> for &'a CryptParamsPlain {
587    type Error = LibcryptErr;
588
589    fn try_into(self) -> Result<CryptParamsPlainRef<'a>, Self::Error> {
590        let hash_cstring = to_cstring!(self.hash)?;
591        Ok(CryptParamsPlainRef {
592            inner: libcryptsetup_rs_sys::crypt_params_plain {
593                hash: hash_cstring.as_ptr(),
594                offset: self.offset,
595                sector_size: self.sector_size,
596                size: self.size,
597                skip: self.skip,
598            },
599            reference: self,
600            hash_cstring,
601        })
602    }
603}
604
605impl<'a> TryFrom<&'a libcryptsetup_rs_sys::crypt_params_plain> for CryptParamsPlain {
606    type Error = LibcryptErr;
607
608    fn try_from(v: &'a libcryptsetup_rs_sys::crypt_params_plain) -> Result<Self, Self::Error> {
609        Ok(CryptParamsPlain {
610            hash: from_str_ptr_to_owned!(v.hash)?,
611            offset: v.offset,
612            sector_size: v.sector_size,
613            size: v.size,
614            skip: v.skip,
615        })
616    }
617}
618
619impl CryptParams for CryptParamsPlainRef<'_> {
620    fn as_ptr(&mut self) -> *mut c_void {
621        (&mut self.inner as *mut crypt_params_plain).cast::<c_void>()
622    }
623}
624
625/// Reference to a `CryptParamsTcrypt` struct
626pub struct CryptParamsTcryptRef<'a> {
627    /// FFI compatible representation of `CryptParamsTcrypt`
628    inner: libcryptsetup_rs_sys::crypt_params_tcrypt,
629    #[allow(dead_code)]
630    reference: &'a CryptParamsTcrypt,
631    #[allow(dead_code)]
632    keyfiles_cstrings: Vec<CString>,
633    #[allow(dead_code)]
634    keyfiles_ptrs: Vec<*const libc::c_char>,
635    #[allow(dead_code)]
636    hash_name_cstring: CString,
637    #[allow(dead_code)]
638    cipher_cstring: CString,
639    #[allow(dead_code)]
640    mode_cstring: CString,
641}
642
643/// Parameters for tcrypt operations
644pub struct CryptParamsTcrypt {
645    #[allow(missing_docs)]
646    pub passphrase: Option<Vec<u8>>,
647    #[allow(missing_docs)]
648    pub keyfiles: Option<Vec<PathBuf>>,
649    #[allow(missing_docs)]
650    pub hash_name: String,
651    #[allow(missing_docs)]
652    pub cipher: String,
653    #[allow(missing_docs)]
654    pub mode: String,
655    #[allow(missing_docs)]
656    pub key_size: usize,
657    #[allow(missing_docs)]
658    pub flags: CryptTcrypt,
659    #[allow(missing_docs)]
660    pub veracrypt_pim: u32,
661}
662
663impl<'a> TryInto<CryptParamsTcryptRef<'a>> for &'a CryptParamsTcrypt {
664    type Error = LibcryptErr;
665
666    fn try_into(self) -> Result<CryptParamsTcryptRef<'a>, Self::Error> {
667        let mut keyfiles_cstrings = Vec::new();
668        if let Some(ref keyfiles) = self.keyfiles {
669            for keyfile in keyfiles.iter() {
670                keyfiles_cstrings.push(path_to_cstring!(keyfile)?);
671            }
672        }
673        let mut keyfiles_ptrs: Vec<*const libc::c_char> =
674            keyfiles_cstrings.iter().map(|cs| cs.as_ptr()).collect();
675        let hash_name_cstring = to_cstring!(self.hash_name)?;
676        let cipher_cstring = to_cstring!(self.cipher)?;
677        let mode_cstring = to_cstring!(self.mode)?;
678        Ok(CryptParamsTcryptRef {
679            inner: libcryptsetup_rs_sys::crypt_params_tcrypt {
680                passphrase: match self.passphrase {
681                    Some(ref pass) => pass.as_ptr().cast::<libc::c_char>(),
682                    None => std::ptr::null(),
683                },
684                passphrase_size: match self.passphrase {
685                    Some(ref pass) => pass.len(),
686                    None => 0,
687                },
688                keyfiles: keyfiles_ptrs.as_mut_ptr(),
689                keyfiles_count: keyfiles_cstrings.len() as u32,
690                hash_name: hash_name_cstring.as_ptr(),
691                cipher: cipher_cstring.as_ptr(),
692                mode: mode_cstring.as_ptr(),
693                flags: self.flags.bits(),
694                key_size: self.key_size,
695                veracrypt_pim: self.veracrypt_pim,
696            },
697            reference: self,
698            keyfiles_cstrings,
699            keyfiles_ptrs,
700            hash_name_cstring,
701            cipher_cstring,
702            mode_cstring,
703        })
704    }
705}
706
707impl<'a> TryFrom<&'a libcryptsetup_rs_sys::crypt_params_tcrypt> for CryptParamsTcrypt {
708    type Error = LibcryptErr;
709
710    fn try_from(v: &'a libcryptsetup_rs_sys::crypt_params_tcrypt) -> Result<Self, Self::Error> {
711        let mut keyfiles = Vec::new();
712        let keyfiles_ptrs = unsafe { slice::from_raw_parts(v.keyfiles, v.keyfiles_count as usize) };
713        for keyfile_ptr in keyfiles_ptrs {
714            keyfiles.push(PathBuf::from(from_str_ptr_to_owned!(*keyfile_ptr)?));
715        }
716        Ok(CryptParamsTcrypt {
717            passphrase: ptr_to_option!(v.passphrase).map(|p| {
718                unsafe { slice::from_raw_parts(p.cast::<u8>(), v.passphrase_size) }.to_vec()
719            }),
720            keyfiles: if keyfiles.is_empty() {
721                None
722            } else {
723                Some(keyfiles)
724            },
725            hash_name: from_str_ptr_to_owned!(v.hash_name)?,
726            cipher: from_str_ptr_to_owned!(v.cipher)?,
727            mode: from_str_ptr_to_owned!(v.mode)?,
728            flags: CryptTcrypt::from_bits(v.flags).ok_or(LibcryptErr::InvalidConversion)?,
729            key_size: v.key_size,
730            veracrypt_pim: v.veracrypt_pim,
731        })
732    }
733}
734
735impl CryptParams for CryptParamsTcryptRef<'_> {
736    fn as_ptr(&mut self) -> *mut c_void {
737        (&mut self.inner as *mut crypt_params_tcrypt).cast::<c_void>()
738    }
739}
740
741/// Handle for format operations on a device
742pub struct CryptFormatHandle<'a> {
743    reference: &'a mut CryptDevice,
744}
745
746impl<'a> CryptFormatHandle<'a> {
747    pub(crate) fn new(reference: &'a mut CryptDevice) -> Self {
748        CryptFormatHandle { reference }
749    }
750
751    /// Get the formatting type
752    pub fn get_type(&mut self) -> Result<EncryptionFormat, LibcryptErr> {
753        EncryptionFormat::from_ptr(ptr_to_result!(mutex!(
754            libcryptsetup_rs_sys::crypt_get_type(self.reference.as_ptr())
755        ))?)
756    }
757
758    /// Get the default formatting type
759    pub fn get_default_type() -> Result<EncryptionFormat, LibcryptErr> {
760        EncryptionFormat::from_ptr(ptr_to_result!(mutex!(
761            libcryptsetup_rs_sys::crypt_get_default_type()
762        ))?)
763    }
764}
765
766#[cfg(test)]
767mod test {
768    use super::EncryptionFormat;
769
770    #[test]
771    fn test_encryption_format_partialeq() {
772        #[allow(clippy::eq_op)]
773        {
774            assert_eq!(EncryptionFormat::Luks1, EncryptionFormat::Luks1);
775        }
776        assert_ne!(EncryptionFormat::Luks1, EncryptionFormat::Luks2);
777    }
778
779    #[test]
780    fn test_encryption_format_from_ptr() {
781        for format in &[
782            EncryptionFormat::Integrity,
783            EncryptionFormat::Tcrypt,
784            EncryptionFormat::Verity,
785            EncryptionFormat::Luks2,
786            EncryptionFormat::Loopaes,
787            EncryptionFormat::Luks1,
788            EncryptionFormat::Plain,
789        ] {
790            assert_eq!(
791                EncryptionFormat::from_ptr(format.as_ptr()).unwrap(),
792                *format
793            );
794        }
795    }
796}