blob: 984ceda4f72fadf5fb537b837b07ff50a5a13ad0 [file] [log] [blame]
Jiyong Park86c9b082021-06-04 19:03:48 +09001/*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// `dm` module implements part of the `device-mapper` ioctl interfaces. It currently supports
18// creation and deletion of the mapper device. It doesn't support other operations like querying
19// the status of the mapper device. And there's no plan to extend the support unless it is
20// required.
21//
22// Why in-house development? [`devicemapper`](https://crates.io/crates/devicemapper) is a public
23// Rust implementation of the device mapper APIs. However, it doesn't provide any abstraction for
24// the target-specific tables. User has to manually craft the table. Ironically, the library
25// provides a lot of APIs for the features that are not required for `apkdmverity` such as listing
26// the device mapper block devices that are currently listed in the kernel. Size is an important
27// criteria for Microdroid.
28
Shikha Panwar414ea892022-10-12 13:45:52 +000029//! A library to create device mapper spec & issue ioctls.
30
31#![allow(missing_docs)]
Andrew Walbran3fcebdb2022-11-30 11:16:17 +000032#![cfg_attr(test, allow(unused))]
Jiyong Park86c9b082021-06-04 19:03:48 +090033
Jiyong Park0553ff22021-07-15 12:25:36 +090034use anyhow::{Context, Result};
Jiyong Park3c327d22021-06-08 20:51:54 +090035use data_model::DataInit;
Jiyong Park86c9b082021-06-04 19:03:48 +090036use std::fs::{File, OpenOptions};
37use std::io::Write;
38use std::mem::size_of;
39use std::os::unix::io::AsRawFd;
40use std::path::{Path, PathBuf};
Jiyong Park86c9b082021-06-04 19:03:48 +090041
Shikha Panwar27cb7e72022-10-13 20:34:45 +000042/// Exposes DmCryptTarget & related builder
43pub mod crypt;
Shikha Panwar414ea892022-10-12 13:45:52 +000044/// Expose util functions
45pub mod util;
46/// Exposes the DmVerityTarget & related builder
47pub mod verity;
Shikha Panwarb278b1c2022-10-14 12:38:32 +000048// Expose loopdevice
49pub mod loopdevice;
Shikha Panwar414ea892022-10-12 13:45:52 +000050
Jiyong Park86c9b082021-06-04 19:03:48 +090051mod sys;
Shikha Panwar27cb7e72022-10-13 20:34:45 +000052use crypt::DmCryptTarget;
Jiyong Park86c9b082021-06-04 19:03:48 +090053use sys::*;
Shikha Panwar414ea892022-10-12 13:45:52 +000054use util::*;
Shikha Panwar27cb7e72022-10-13 20:34:45 +000055use verity::DmVerityTarget;
Jiyong Park86c9b082021-06-04 19:03:48 +090056
57nix::ioctl_readwrite!(_dm_dev_create, DM_IOCTL, Cmd::DM_DEV_CREATE, DmIoctl);
Jiyong Park86c9b082021-06-04 19:03:48 +090058nix::ioctl_readwrite!(_dm_dev_suspend, DM_IOCTL, Cmd::DM_DEV_SUSPEND, DmIoctl);
59nix::ioctl_readwrite!(_dm_table_load, DM_IOCTL, Cmd::DM_TABLE_LOAD, DmIoctl);
Jiyong Park99a35b82021-06-07 10:13:44 +090060nix::ioctl_readwrite!(_dm_dev_remove, DM_IOCTL, Cmd::DM_DEV_REMOVE, DmIoctl);
Jiyong Park86c9b082021-06-04 19:03:48 +090061
Shikha Panwar414ea892022-10-12 13:45:52 +000062/// Create a new (mapper) device
Jiyong Park86c9b082021-06-04 19:03:48 +090063fn dm_dev_create(dm: &DeviceMapper, ioctl: *mut DmIoctl) -> Result<i32> {
64 // SAFETY: `ioctl` is copied into the kernel. It modifies the state in the kernel, not the
65 // state of this process in any way.
66 Ok(unsafe { _dm_dev_create(dm.0.as_raw_fd(), ioctl) }?)
67}
68
Jiyong Park86c9b082021-06-04 19:03:48 +090069fn dm_dev_suspend(dm: &DeviceMapper, ioctl: *mut DmIoctl) -> Result<i32> {
70 // SAFETY: `ioctl` is copied into the kernel. It modifies the state in the kernel, not the
71 // state of this process in any way.
72 Ok(unsafe { _dm_dev_suspend(dm.0.as_raw_fd(), ioctl) }?)
73}
74
75fn dm_table_load(dm: &DeviceMapper, ioctl: *mut DmIoctl) -> Result<i32> {
76 // SAFETY: `ioctl` is copied into the kernel. It modifies the state in the kernel, not the
77 // state of this process in any way.
78 Ok(unsafe { _dm_table_load(dm.0.as_raw_fd(), ioctl) }?)
79}
80
Jiyong Park99a35b82021-06-07 10:13:44 +090081fn dm_dev_remove(dm: &DeviceMapper, ioctl: *mut DmIoctl) -> Result<i32> {
82 // SAFETY: `ioctl` is copied into the kernel. It modifies the state in the kernel, not the
83 // state of this process in any way.
84 Ok(unsafe { _dm_dev_remove(dm.0.as_raw_fd(), ioctl) }?)
85}
86
Jiyong Park86c9b082021-06-04 19:03:48 +090087// `DmTargetSpec` is the header of the data structure for a device-mapper target. When doing the
88// ioctl, one of more `DmTargetSpec` (and its body) are appened to the `DmIoctl` struct.
89#[repr(C)]
Jiyong Park3c327d22021-06-08 20:51:54 +090090#[derive(Copy, Clone)]
Jiyong Park86c9b082021-06-04 19:03:48 +090091struct DmTargetSpec {
92 sector_start: u64,
93 length: u64, // number of 512 sectors
94 status: i32,
95 next: u32,
96 target_type: [u8; DM_MAX_TYPE_NAME],
97}
98
Jiyong Park3c327d22021-06-08 20:51:54 +090099// SAFETY: C struct is safe to be initialized from raw data
100unsafe impl DataInit for DmTargetSpec {}
101
Jiyong Park86c9b082021-06-04 19:03:48 +0900102impl DmTargetSpec {
103 fn new(target_type: &str) -> Result<Self> {
Jiyong Park3c327d22021-06-08 20:51:54 +0900104 // safe because the size of the array is the same as the size of the struct
105 let mut spec: Self = *DataInit::from_mut_slice(&mut [0; size_of::<Self>()]).unwrap();
Jiyong Park86c9b082021-06-04 19:03:48 +0900106 spec.target_type.as_mut().write_all(target_type.as_bytes())?;
107 Ok(spec)
108 }
Jiyong Park86c9b082021-06-04 19:03:48 +0900109}
110
111impl DmIoctl {
112 fn new(name: &str) -> Result<DmIoctl> {
Jiyong Park3c327d22021-06-08 20:51:54 +0900113 // safe because the size of the array is the same as the size of the struct
114 let mut data: Self = *DataInit::from_mut_slice(&mut [0; size_of::<Self>()]).unwrap();
Jiyong Park86c9b082021-06-04 19:03:48 +0900115 data.version[0] = DM_VERSION_MAJOR;
116 data.version[1] = DM_VERSION_MINOR;
117 data.version[2] = DM_VERSION_PATCHLEVEL;
118 data.data_size = size_of::<Self>() as u32;
119 data.data_start = 0;
120 data.name.as_mut().write_all(name.as_bytes())?;
121 Ok(data)
122 }
123
124 fn set_uuid(&mut self, uuid: &str) -> Result<()> {
125 let mut dst = self.uuid.as_mut();
126 dst.fill(0);
127 dst.write_all(uuid.as_bytes())?;
128 Ok(())
129 }
Jiyong Park86c9b082021-06-04 19:03:48 +0900130}
131
132/// `DeviceMapper` is the entry point for the device mapper framework. It essentially is a file
133/// handle to "/dev/mapper/control".
134pub struct DeviceMapper(File);
135
Jiyong Park5f0ebea2021-06-07 12:53:35 +0900136#[cfg(not(target_os = "android"))]
137const MAPPER_CONTROL: &str = "/dev/mapper/control";
138#[cfg(not(target_os = "android"))]
139const MAPPER_DEV_ROOT: &str = "/dev/mapper";
140
141#[cfg(target_os = "android")]
142const MAPPER_CONTROL: &str = "/dev/device-mapper";
143#[cfg(target_os = "android")]
144const MAPPER_DEV_ROOT: &str = "/dev/block/mapper";
145
Jiyong Park86c9b082021-06-04 19:03:48 +0900146impl DeviceMapper {
147 /// Constructs a new `DeviceMapper` entrypoint. This is essentially the same as opening
148 /// "/dev/mapper/control".
149 pub fn new() -> Result<DeviceMapper> {
Jiyong Park0553ff22021-07-15 12:25:36 +0900150 let f = OpenOptions::new()
151 .read(true)
152 .write(true)
153 .open(MAPPER_CONTROL)
154 .context(format!("failed to open {}", MAPPER_CONTROL))?;
Jiyong Park86c9b082021-06-04 19:03:48 +0900155 Ok(DeviceMapper(f))
156 }
157
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000158 /// Creates a (crypt) device and configure it according to the `target` specification.
159 /// The path to the generated device is "/dev/mapper/<name>".
160 pub fn create_crypt_device(&self, name: &str, target: &DmCryptTarget) -> Result<PathBuf> {
161 self.create_device(name, target.as_slice(), uuid("crypto".as_bytes())?, true)
162 }
163
164 /// Creates a (verity) device and configure it according to the `target` specification.
Jiyong Park86c9b082021-06-04 19:03:48 +0900165 /// The path to the generated device is "/dev/mapper/<name>".
Shikha Panwar414ea892022-10-12 13:45:52 +0000166 pub fn create_verity_device(&self, name: &str, target: &DmVerityTarget) -> Result<PathBuf> {
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000167 self.create_device(name, target.as_slice(), uuid("apkver".as_bytes())?, false)
168 }
169
170 /// Removes a mapper device.
171 pub fn delete_device_deferred(&self, name: &str) -> Result<()> {
172 let mut data = DmIoctl::new(name)?;
173 data.flags |= Flag::DM_DEFERRED_REMOVE;
174 dm_dev_remove(self, &mut data)
175 .context(format!("failed to remove device with name {}", &name))?;
176 Ok(())
177 }
178
179 fn create_device(
180 &self,
181 name: &str,
182 target: &[u8],
183 uid: String,
184 writable: bool,
185 ) -> Result<PathBuf> {
Jiyong Park86c9b082021-06-04 19:03:48 +0900186 // Step 1: create an empty device
Chris Wailes68c39f82021-07-27 16:03:44 -0700187 let mut data = DmIoctl::new(name)?;
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000188 data.set_uuid(&uid)?;
Chris Wailes68c39f82021-07-27 16:03:44 -0700189 dm_dev_create(self, &mut data)
Jiyong Park0553ff22021-07-15 12:25:36 +0900190 .context(format!("failed to create an empty device with name {}", &name))?;
Jiyong Park86c9b082021-06-04 19:03:48 +0900191
192 // Step 2: load table onto the device
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000193 let payload_size = size_of::<DmIoctl>() + target.len();
Jiyong Park86c9b082021-06-04 19:03:48 +0900194
Chris Wailes68c39f82021-07-27 16:03:44 -0700195 let mut data = DmIoctl::new(name)?;
Jiyong Park86c9b082021-06-04 19:03:48 +0900196 data.data_size = payload_size as u32;
197 data.data_start = size_of::<DmIoctl>() as u32;
198 data.target_count = 1;
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000199
200 if !writable {
201 data.flags |= Flag::DM_READONLY_FLAG;
202 }
Jiyong Park86c9b082021-06-04 19:03:48 +0900203
204 let mut payload = Vec::with_capacity(payload_size);
Jiyong Park3c327d22021-06-08 20:51:54 +0900205 payload.extend_from_slice(data.as_slice());
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000206 payload.extend_from_slice(target);
Chris Wailes68c39f82021-07-27 16:03:44 -0700207 dm_table_load(self, payload.as_mut_ptr() as *mut DmIoctl)
Jiyong Park0553ff22021-07-15 12:25:36 +0900208 .context("failed to load table")?;
Jiyong Park86c9b082021-06-04 19:03:48 +0900209
210 // Step 3: activate the device (note: the term 'suspend' might be misleading, but it
211 // actually activates the table. See include/uapi/linux/dm-ioctl.h
Chris Wailes68c39f82021-07-27 16:03:44 -0700212 let mut data = DmIoctl::new(name)?;
213 dm_dev_suspend(self, &mut data).context("failed to activate")?;
Jiyong Park86c9b082021-06-04 19:03:48 +0900214
215 // Step 4: wait unti the device is created and return the device path
Chris Wailes9b866f02022-11-16 15:17:16 -0800216 let path = Path::new(MAPPER_DEV_ROOT).join(name);
Jiyong Park86c9b082021-06-04 19:03:48 +0900217 wait_for_path(&path)?;
218 Ok(path)
219 }
Jiyong Park86c9b082021-06-04 19:03:48 +0900220}
221
222/// Used to derive a UUID that uniquely identifies a device mapper device when creating it.
Shikha Panwar414ea892022-10-12 13:45:52 +0000223fn uuid(node_id: &[u8]) -> Result<String> {
Jiyong Parkf02061f2021-06-07 09:44:44 +0900224 use std::time::{SystemTime, UNIX_EPOCH};
225 use uuid::v1::{Context, Timestamp};
226 use uuid::Uuid;
227
228 let context = Context::new(0);
229 let now = SystemTime::now().duration_since(UNIX_EPOCH)?;
Charisee96113f32023-01-26 09:00:42 +0000230 let ts = Timestamp::from_unix(context, now.as_secs(), now.subsec_nanos());
Chris Wailesc7c11442023-01-26 15:25:27 -0800231 let uuid = Uuid::new_v1(ts, node_id.try_into()?);
232 Ok(String::from(uuid.hyphenated().encode_lower(&mut Uuid::encode_buffer())))
Jiyong Park86c9b082021-06-04 19:03:48 +0900233}
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000234
235#[cfg(test)]
Andrew Walbran3fcebdb2022-11-30 11:16:17 +0000236ignorabletest::test_main!(tests::all_tests());
237
238#[cfg(test)]
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000239mod tests {
240 use super::*;
Shikha Panwar8e48a172022-11-25 19:01:28 +0000241 use crypt::{CipherType, DmCryptTargetBuilder};
Andrew Walbran3fcebdb2022-11-30 11:16:17 +0000242 use ignorabletest::{list_tests, test};
Shikha Panwar8e48a172022-11-25 19:01:28 +0000243 use rustutils::system_properties;
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000244 use std::fs::{read, File, OpenOptions};
245 use std::io::Write;
246
Shikha Panwar8e48a172022-11-25 19:01:28 +0000247 // Just a logical set of keys to make testing easy. This has no real meaning.
248 struct KeySet<'a> {
249 cipher: CipherType,
250 key: &'a [u8],
251 different_key: &'a [u8],
252 }
253
254 const KEY_SET_XTS: KeySet = KeySet {
255 cipher: CipherType::AES256XTS,
256 key: b"sixtyfourbyteslongsentencearerarebutletsgiveitatrycantbethathard",
257 different_key: b"drahtahtebtnacyrtatievigsteltuberareraecnetnesgnolsetybruofytxis",
258 };
259 const KEY_SET_HCTR2: KeySet = KeySet {
260 cipher: CipherType::AES256HCTR2,
261 key: b"thirtytwobyteslongreallylongword",
262 different_key: b"drowgnolyllaergnolsetybowtytriht",
263 };
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000264
Andrew Walbran3fcebdb2022-11-30 11:16:17 +0000265 list_tests! {all_tests: [
266 mapping_again_keeps_data_xts,
267 mapping_again_keeps_data_hctr2,
268 data_inaccessible_with_diff_key_xts,
269 data_inaccessible_with_diff_key_hctr2,
270 ]}
271
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000272 // Create a file in given temp directory with given size
273 fn prepare_tmpfile(test_dir: &Path, filename: &str, sz: u64) -> PathBuf {
274 let filepath = test_dir.join(filename);
275 let f = File::create(&filepath).unwrap();
276 f.set_len(sz).unwrap();
277 filepath
278 }
279
280 fn write_to_dev(path: &Path, data: &[u8]) {
Chris Wailes9b866f02022-11-16 15:17:16 -0800281 let mut f = OpenOptions::new().read(true).write(true).open(path).unwrap();
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000282 f.write_all(data).unwrap();
283 }
284
Shikha Panwar8e48a172022-11-25 19:01:28 +0000285 // TODO(b/250880499): delete_device() doesn't really delete it even without DM_DEFERRED_REMOVE.
286 // Hence, we have to create a new device with a different name for each test. Retrying
287 // the test on same machine without reboot will also fail.
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000288 fn delete_device(dm: &DeviceMapper, name: &str) -> Result<()> {
289 dm.delete_device_deferred(name)?;
Chris Wailes9b866f02022-11-16 15:17:16 -0800290 wait_for_path_disappears(Path::new(MAPPER_DEV_ROOT).join(name))?;
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000291 Ok(())
292 }
293
Shikha Panwar8e48a172022-11-25 19:01:28 +0000294 fn is_hctr2_supported() -> bool {
295 // hctr2 is NOT enabled in kernel 5.10 or lower. We run Microdroid tests on kernel versions
296 // 5.10 or above & therefore, we don't really care to skip test on other versions.
297 if let Some(version) = system_properties::read("ro.kernel.version")
298 .expect("Unable to read system property ro.kernel.version")
299 {
300 version != "5.10"
301 } else {
302 panic!("Could not read property: kernel.version!!");
303 }
304 }
305
Andrew Walbran3fcebdb2022-11-30 11:16:17 +0000306 test!(mapping_again_keeps_data_xts);
Shikha Panwar8e48a172022-11-25 19:01:28 +0000307 fn mapping_again_keeps_data_xts() {
308 mapping_again_keeps_data(&KEY_SET_XTS, "name1");
309 }
310
Andrew Walbran3fcebdb2022-11-30 11:16:17 +0000311 test!(mapping_again_keeps_data_hctr2, ignore_if: !is_hctr2_supported());
Shikha Panwar8e48a172022-11-25 19:01:28 +0000312 fn mapping_again_keeps_data_hctr2() {
Shikha Panwar8e48a172022-11-25 19:01:28 +0000313 mapping_again_keeps_data(&KEY_SET_HCTR2, "name2");
314 }
Andrew Walbran3fcebdb2022-11-30 11:16:17 +0000315
316 test!(data_inaccessible_with_diff_key_xts);
Shikha Panwar8e48a172022-11-25 19:01:28 +0000317 fn data_inaccessible_with_diff_key_xts() {
318 data_inaccessible_with_diff_key(&KEY_SET_XTS, "name3");
319 }
320
Andrew Walbran3fcebdb2022-11-30 11:16:17 +0000321 test!(data_inaccessible_with_diff_key_hctr2, ignore_if: !is_hctr2_supported());
Shikha Panwar8e48a172022-11-25 19:01:28 +0000322 fn data_inaccessible_with_diff_key_hctr2() {
Shikha Panwar8e48a172022-11-25 19:01:28 +0000323 data_inaccessible_with_diff_key(&KEY_SET_HCTR2, "name4");
324 }
325
326 fn mapping_again_keeps_data(keyset: &KeySet, device: &str) {
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000327 // This test creates 2 different crypt devices using same key backed by same data_device
328 // -> Write data on dev1 -> Check the data is visible & same on dev2
329 let dm = DeviceMapper::new().unwrap();
330 let inputimg = include_bytes!("../testdata/rand8k");
331 let sz = inputimg.len() as u64;
332
333 let test_dir = tempfile::TempDir::new().unwrap();
334 let backing_file = prepare_tmpfile(test_dir.path(), "storage", sz);
335 let data_device = loopdevice::attach(
336 backing_file,
337 0,
338 sz,
339 /*direct_io*/ true,
340 /*writable*/ true,
341 )
342 .unwrap();
Shikha Panwar8e48a172022-11-25 19:01:28 +0000343 let device_diff = device.to_owned() + "_diff";
344
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000345 scopeguard::defer! {
346 loopdevice::detach(&data_device).unwrap();
Shikha Panwar8e48a172022-11-25 19:01:28 +0000347 _ = delete_device(&dm, device);
348 _ = delete_device(&dm, &device_diff);
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000349 }
350
Shikha Panwar8e48a172022-11-25 19:01:28 +0000351 let target = DmCryptTargetBuilder::default()
352 .data_device(&data_device, sz)
353 .cipher(keyset.cipher)
354 .key(keyset.key)
355 .build()
356 .unwrap();
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000357
Shikha Panwar8e48a172022-11-25 19:01:28 +0000358 let mut crypt_device = dm.create_crypt_device(device, &target).unwrap();
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000359 write_to_dev(&crypt_device, inputimg);
360
361 // Recreate another device using same target spec & check if the content is the same
Shikha Panwar8e48a172022-11-25 19:01:28 +0000362 crypt_device = dm.create_crypt_device(&device_diff, &target).unwrap();
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000363
364 let crypt = read(crypt_device).unwrap();
365 assert_eq!(inputimg.len(), crypt.len()); // fail early if the size doesn't match
366 assert_eq!(inputimg, crypt.as_slice());
367 }
368
Shikha Panwar8e48a172022-11-25 19:01:28 +0000369 fn data_inaccessible_with_diff_key(keyset: &KeySet, device: &str) {
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000370 // This test creates 2 different crypt devices using different keys backed
371 // by same data_device -> Write data on dev1 -> Check the data is visible but not the same on dev2
372 let dm = DeviceMapper::new().unwrap();
373 let inputimg = include_bytes!("../testdata/rand8k");
374 let sz = inputimg.len() as u64;
375
376 let test_dir = tempfile::TempDir::new().unwrap();
377 let backing_file = prepare_tmpfile(test_dir.path(), "storage", sz);
378 let data_device = loopdevice::attach(
379 backing_file,
380 0,
381 sz,
382 /*direct_io*/ true,
383 /*writable*/ true,
384 )
385 .unwrap();
Shikha Panwar8e48a172022-11-25 19:01:28 +0000386 let device_diff = device.to_owned() + "_diff";
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000387 scopeguard::defer! {
388 loopdevice::detach(&data_device).unwrap();
Shikha Panwar8e48a172022-11-25 19:01:28 +0000389 _ = delete_device(&dm, device);
390 _ = delete_device(&dm, &device_diff);
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000391 }
392
Shikha Panwar8e48a172022-11-25 19:01:28 +0000393 let target = DmCryptTargetBuilder::default()
394 .data_device(&data_device, sz)
395 .cipher(keyset.cipher)
396 .key(keyset.key)
397 .build()
398 .unwrap();
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000399 let target2 = DmCryptTargetBuilder::default()
400 .data_device(&data_device, sz)
Shikha Panwar8e48a172022-11-25 19:01:28 +0000401 .cipher(keyset.cipher)
402 .key(keyset.different_key)
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000403 .build()
404 .unwrap();
405
Shikha Panwar8e48a172022-11-25 19:01:28 +0000406 let mut crypt_device = dm.create_crypt_device(device, &target).unwrap();
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000407
408 write_to_dev(&crypt_device, inputimg);
409
410 // Recreate the crypt device again diff key & check if the content is changed
Shikha Panwar8e48a172022-11-25 19:01:28 +0000411 crypt_device = dm.create_crypt_device(&device_diff, &target2).unwrap();
Shikha Panwar27cb7e72022-10-13 20:34:45 +0000412 let crypt = read(crypt_device).unwrap();
413 assert_ne!(inputimg, crypt.as_slice());
414 }
415}