1use std::convert::TryFrom;
2use std::fs::File;
3use std::path::Path;
4
5use uuid::Uuid;
6
7use blkid_rs::{Luks2Header, LuksHeader};
8
9use crate::api::{crypt_pbkdf_algo_type, crypt_token_info, CryptDeviceHandle};
10use crate::api::{CryptDeviceType, Luks2CryptDevice, LuksCryptDevice};
11use crate::device::{
12 Error, Keyslot, Luks2FormatPbkdf, Luks2TokenHandlerBox, Luks2TokenHandlerRaw, Luks2TokenId, Result,
13};
14use crate::luks2_meta::Luks2Token;
15
16#[derive(Debug, PartialEq)]
18pub struct Luks2Params {
19 label: Option<String>,
20 subsystem: Option<String>,
21 seqid: u64,
22 header_size: u64,
23 header_offset: u64,
24 }
26
27impl Luks2Params {
28 pub(crate) fn from(header: impl Luks2Header) -> Result<Luks2Params> {
29 let label = header.label()?.map(|s| s.to_owned());
30 let subsystem = header.subsystem()?.map(|s| s.to_owned());
31 let seqid = header.seqid();
32 let header_size = header.header_size();
33 let header_offset = header.header_offset();
34 Ok(Luks2Params {
35 label,
36 subsystem,
37 seqid,
38 header_size,
39 header_offset,
40 })
41 }
42
43 pub(crate) fn from_path<P: AsRef<Path>>(path: P) -> Result<Luks2Params> {
44 let device_file = File::open(path.as_ref())?;
45 match LuksHeader::read(device_file)? {
46 LuksHeader::Luks2(v2) => Luks2Params::from(v2),
47 _ => Err(Error::InvalidLuksVersion),
48 }
49 }
50}
51
52impl LuksCryptDevice for CryptDeviceHandle<Luks2Params> {
53 fn activate(&mut self, name: &str, key: &[u8]) -> Result<u8> {
54 crate::device::luks_activate(&mut self.cd, name, key)
55 }
56
57 fn deactivate(self, name: &str) -> Result<()> {
58 crate::device::deactivate(self.cd, name)
59 }
60
61 fn destroy_keyslot(&mut self, slot: Keyslot) -> Result<()> {
62 crate::device::luks_destroy_keyslot(&mut self.cd, slot)
63 }
64
65 fn keyslot_status(&self, keyslot: Keyslot) -> raw::crypt_keyslot_info {
66 crate::device::keyslot_status(&self.cd, keyslot)
67 }
68
69 fn dump(&self) {
70 crate::device::dump(&self.cd).expect("Dump should be fine for initialised device")
71 }
72
73 fn uuid(&self) -> Uuid {
74 crate::device::uuid(&self.cd).expect("Initialised device should have UUID")
75 }
76
77 fn add_keyslot(
78 &mut self,
79 key: &[u8],
80 maybe_prev_key: Option<&[u8]>,
81 maybe_keyslot: Option<Keyslot>,
82 ) -> Result<Keyslot> {
83 crate::device::luks_add_keyslot(&mut self.cd, key, maybe_prev_key, maybe_keyslot)
84 }
85
86 fn update_keyslot(&mut self, key: &[u8], prev_key: &[u8], maybe_keyslot: Option<Keyslot>) -> Result<Keyslot> {
87 crate::device::luks_update_keyslot(&mut self.cd, key, prev_key, maybe_keyslot)
88 }
89}
90
91impl Luks2CryptDevice for CryptDeviceHandle<Luks2Params> {
92 fn register_new_token_handler<Handler: Luks2TokenHandlerRaw>() -> Result<Luks2TokenHandlerBox<Handler>> {
93 let b = Luks2TokenHandlerBox::new();
94 Self::register_token_handler(&b)?;
95 Ok(b)
96 }
97
98 fn register_token_handler<Handler: Luks2TokenHandlerRaw>(handler: &Luks2TokenHandlerBox<Handler>) -> Result<()> {
99 crate::device::luks2_register_token_handler::<Handler>(handler)
100 }
101
102 fn token_status(&mut self, token_id: Luks2TokenId) -> (crypt_token_info, Option<String>) {
103 crate::device::luks2_token_status(&mut self.cd, token_id)
104 }
105
106 fn get_token(&mut self, token_id: Luks2TokenId) -> Result<Luks2Token> {
107 let json = crate::device::luks2_token_json(&mut self.cd, token_id)?;
108 let token = Luks2Token::try_from(json.as_str()).map_err(|err| Error::InvalidJson(format!("{}", err)))?;
109 Ok(token)
110 }
111
112 fn add_token_with_id(&mut self, token: &Luks2Token, token_id: Luks2TokenId) -> Result<()> {
113 let js = String::try_from(token).map_err(|err| Error::InvalidJson(format!("{}", err)))?;
114 crate::device::luks2_token_json_allocate(&mut self.cd, js.as_str(), Some(token_id))?;
115 Ok(())
116 }
117
118 fn add_token(&mut self, token: &Luks2Token) -> Result<Luks2TokenId> {
119 let js = String::try_from(token).map_err(|err| Error::InvalidJson(format!("{}", err)))?;
120 crate::device::luks2_token_json_allocate(&mut self.cd, js.as_str(), None)
121 }
122
123 fn remove_token(&mut self, token_id: Luks2TokenId) -> Result<()> {
124 crate::device::luks2_token_remove(&mut self.cd, token_id)
125 }
126
127 fn assign_token_to_keyslot(&mut self, token_id: Luks2TokenId, keyslot_opt: Option<Keyslot>) -> Result<()> {
128 crate::device::luks2_token_assign_keyslot(&mut self.cd, token_id, keyslot_opt)
129 }
130
131 fn unassign_token_keyslot(&mut self, token_id: Luks2TokenId, keyslot_opt: Option<Keyslot>) -> Result<()> {
132 crate::device::luks2_token_unassign_keyslot(&mut self.cd, token_id, keyslot_opt)
133 }
134
135 fn token_keyslot_is_assigned(&mut self, token_id: Luks2TokenId, keyslot: Keyslot) -> Result<bool> {
136 crate::device::luks2_token_is_assigned(&mut self.cd, token_id, keyslot)
137 }
138
139 fn activate_with_token(&mut self, name: &str, token_id: Luks2TokenId) -> Result<Keyslot> {
140 crate::device::luks2_activate_by_token(&mut self.cd, Some(name), Some(token_id))
141 }
142
143 fn check_activation_with_token(&mut self, token_id: Luks2TokenId) -> Result<Keyslot> {
144 crate::device::luks2_activate_by_token(&mut self.cd, None, Some(token_id))
145 }
146
147 fn set_pbkdf_params(
148 &mut self,
149 type_: crypt_pbkdf_algo_type,
150 hash: &str,
151 time_ms: u32,
152 iterations: u32,
153 max_memory_kb: u32,
154 parallel_threads: u32,
155 ) -> Result<()> {
156 let params = Luks2FormatPbkdf {
157 type_,
158 hash,
159 time_ms,
160 iterations,
161 max_memory_kb,
162 parallel_threads,
163 flags: 0,
164 };
165 crate::device::luks2_set_pbkdf_type(&mut self.cd, ¶ms)
166 }
167}
168
169impl CryptDeviceType for CryptDeviceHandle<Luks2Params> {
170 fn device_type(&self) -> raw::crypt_device_type {
171 raw::crypt_device_type::LUKS2
172 }
173}