libcryptsetup_rs/
status.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
5#[cfg(cryptsetup24supported)]
6use std::ffi::CStr;
7use std::{os::raw::c_int, path::Path, ptr, str::FromStr};
8
9use crate::{
10    consts::vals::CryptStatusInfo,
11    device::CryptDevice,
12    err::LibcryptErr,
13    format::{CryptParamsIntegrity, CryptParamsVerity},
14};
15
16#[cfg(cryptsetup24supported)]
17use serde_json::Value;
18use uuid::Uuid;
19
20/// Handle for crypt device status operations
21pub struct CryptDeviceStatusHandle<'a> {
22    reference: &'a mut CryptDevice,
23}
24
25impl<'a> CryptDeviceStatusHandle<'a> {
26    pub(crate) fn new(reference: &'a mut CryptDevice) -> Self {
27        CryptDeviceStatusHandle { reference }
28    }
29
30    /// Dump text info about device to log output
31    pub fn dump(&mut self) -> Result<(), LibcryptErr> {
32        errno!(mutex!(libcryptsetup_rs_sys::crypt_dump(
33            self.reference.as_ptr()
34        )))
35    }
36
37    /// Dump text info about device to JSON output
38    #[cfg(cryptsetup24supported)]
39    pub fn dump_json(&mut self) -> Result<Value, LibcryptErr> {
40        let mut buffer = ptr::null();
41        errno!(mutex!(libcryptsetup_rs_sys::crypt_dump_json(
42            self.reference.as_ptr(),
43            &mut buffer as *mut _,
44            0,
45        )))?;
46        let json = serde_json::from_str(
47            unsafe { CStr::from_ptr(buffer) }
48                .to_str()
49                .map_err(LibcryptErr::Utf8Error)?,
50        )
51        .map_err(LibcryptErr::JsonError)?;
52        // Here one would probably expect a free call because we are receiving an allocated buffer
53        // into a pointer. Adding a free call here results in a double free error. Furthermore
54        // json-c references reference counting in its documentation. Just to ensure that we are
55        // not causing a memory leak, I ran valgrind on a test program without the free and no
56        // memory appears to be lost. This leads me to believe that we are doing the right thing
57        // here.
58        Ok(json)
59    }
60
61    /// Get cipher used by device
62    pub fn get_cipher(&mut self) -> Result<String, LibcryptErr> {
63        from_str_ptr_to_owned!(libcryptsetup_rs_sys::crypt_get_cipher(
64            self.reference.as_ptr()
65        ))
66    }
67
68    /// Get cipher mode used by device
69    pub fn get_cipher_mode(&mut self) -> Result<String, LibcryptErr> {
70        from_str_ptr_to_owned!(libcryptsetup_rs_sys::crypt_get_cipher_mode(
71            self.reference.as_ptr()
72        ))
73    }
74
75    /// Get device UUID
76    pub fn get_uuid(&mut self) -> Result<Uuid, LibcryptErr> {
77        from_str_ptr!(unsafe { libcryptsetup_rs_sys::crypt_get_uuid(self.reference.as_ptr()) })
78            .and_then(|e| Uuid::from_str(e).map_err(LibcryptErr::UuidError))
79    }
80
81    /// Get path to underlying device
82    pub fn get_device_path(&mut self) -> Result<&Path, LibcryptErr> {
83        from_str_ptr!(unsafe {
84            libcryptsetup_rs_sys::crypt_get_device_name(self.reference.as_ptr())
85        })
86        .map(Path::new)
87    }
88
89    /// Get path to detached metadata device or `None` if it is attached
90    pub fn get_metadata_device_path(&mut self) -> Result<Option<&Path>, LibcryptErr> {
91        let ptr = mutex!(libcryptsetup_rs_sys::crypt_get_metadata_device_name(
92            self.reference.as_ptr()
93        ));
94        if ptr.is_null() {
95            return Ok(None);
96        }
97        from_str_ptr!(ptr).map(|s| Some(Path::new(s)))
98    }
99
100    /// Get offset in 512-byte sectors where real data starts
101    pub fn get_data_offset(&mut self) -> u64 {
102        mutex!(libcryptsetup_rs_sys::crypt_get_data_offset(
103            self.reference.as_ptr()
104        ))
105    }
106
107    /// Get IV location offset in 512-byte sectors
108    pub fn get_iv_offset(&mut self) -> u64 {
109        mutex!(libcryptsetup_rs_sys::crypt_get_iv_offset(
110            self.reference.as_ptr()
111        ))
112    }
113
114    /// Get size in bytes of volume key
115    pub fn get_volume_key_size(&mut self) -> c_int {
116        mutex!(libcryptsetup_rs_sys::crypt_get_volume_key_size(
117            self.reference.as_ptr()
118        ))
119    }
120
121    /// Get Verity device parameters
122    pub fn get_verity_info(&mut self) -> Result<CryptParamsVerity, LibcryptErr> {
123        let mut verity = libcryptsetup_rs_sys::crypt_params_verity {
124            hash_name: std::ptr::null(),
125            data_device: std::ptr::null(),
126            hash_device: std::ptr::null(),
127            fec_device: std::ptr::null(),
128            salt: std::ptr::null(),
129            salt_size: 0,
130            hash_type: 0,
131            data_block_size: 0,
132            hash_block_size: 0,
133            data_size: 0,
134            hash_area_offset: 0,
135            fec_area_offset: 0,
136            fec_roots: 0,
137            flags: 0,
138        };
139        errno!(mutex!(libcryptsetup_rs_sys::crypt_get_verity_info(
140            self.reference.as_ptr(),
141            &mut verity as *mut _,
142        )))
143        .and_then(|_| CryptParamsVerity::try_from(&verity))
144    }
145
146    /// Get Integrity device parameters
147    pub fn get_integrity_info(&mut self) -> Result<CryptParamsIntegrity, LibcryptErr> {
148        let mut integrity = libcryptsetup_rs_sys::crypt_params_integrity {
149            journal_size: 0,
150            journal_watermark: 0,
151            journal_commit_time: 0,
152            interleave_sectors: 0,
153            tag_size: 0,
154            sector_size: 0,
155            buffer_sectors: 0,
156            integrity: std::ptr::null(),
157            integrity_key_size: 0,
158            journal_integrity: std::ptr::null(),
159            journal_integrity_key: std::ptr::null(),
160            journal_integrity_key_size: 0,
161            journal_crypt: std::ptr::null(),
162            journal_crypt_key: std::ptr::null(),
163            journal_crypt_key_size: 0,
164        };
165        errno!(mutex!(libcryptsetup_rs_sys::crypt_get_integrity_info(
166            self.reference.as_ptr(),
167            &mut integrity as *mut _,
168        )))
169        .and_then(|_| CryptParamsIntegrity::try_from(&integrity))
170    }
171}
172
173/// Get status info from device name
174pub fn status(
175    device: Option<&mut CryptDevice>,
176    name: &str,
177) -> Result<CryptStatusInfo, LibcryptErr> {
178    let name_cstring = to_cstring!(name)?;
179    try_int_to_return!(
180        mutex!(libcryptsetup_rs_sys::crypt_status(
181            match device {
182                Some(d) => d.as_ptr(),
183                None => std::ptr::null_mut(),
184            },
185            name_cstring.as_ptr(),
186        )),
187        CryptStatusInfo
188    )
189}
190
191/// Get size of encryption sectors in bytes
192pub fn get_sector_size(device: Option<&mut CryptDevice>) -> c_int {
193    mutex!(libcryptsetup_rs_sys::crypt_get_sector_size(
194        device.map(|d| d.as_ptr()).unwrap_or(ptr::null_mut()),
195    ))
196}