From 7914f646dedeea489d7b01fd36f34dc824455732 Mon Sep 17 00:00:00 2001 From: ChengyuZhu6 Date: Thu, 18 Jul 2024 13:44:01 +0800 Subject: [PATCH] cdh/storage: mount block device with luks encryption Mount block device encrypted by LUKS. Signed-off-by: ChengyuZhu6 --- .../src/volume_type/blockdevice/luks/mod.rs | 87 +++++++++++++++++++ .../src/volume_type/blockdevice/mod.rs | 8 ++ 2 files changed, 95 insertions(+) create mode 100644 confidential-data-hub/storage/src/volume_type/blockdevice/luks/mod.rs diff --git a/confidential-data-hub/storage/src/volume_type/blockdevice/luks/mod.rs b/confidential-data-hub/storage/src/volume_type/blockdevice/luks/mod.rs new file mode 100644 index 000000000..e75f12a76 --- /dev/null +++ b/confidential-data-hub/storage/src/volume_type/blockdevice/luks/mod.rs @@ -0,0 +1,87 @@ +// Copyright (c) 2024 Intel +// +// SPDX-License-Identifier: Apache-2.0 +// +use super::Interpreter; +use super::{get_plaintext_key, BlockDeviceError, BlockDeviceParameters, Result}; +use async_trait::async_trait; +use log::error; +use rand::{distributions::Alphanumeric, Rng}; +use tokio::{ + fs, + io::{AsyncReadExt, AsyncWriteExt}, + process::Command, +}; + +/// LUKS encrypt storage binary +const LUKS_ENCRYPT_STORAGE_BIN: &str = "/usr/local/bin/luks-encrypt-storage"; + +async fn random_encrypt_key() -> Vec { + let mut buffer = vec![0u8; 4096]; + rand::thread_rng().fill(&mut buffer[..]); + buffer +} + +async fn create_storage_key_file( + storage_key_path: &str, + encrypt_key: Option, +) -> anyhow::Result<()> { + let mut storage_key_file = fs::File::create(storage_key_path).await?; + + let plain_key = match encrypt_key { + Some(encrypt_key) => get_plaintext_key(&encrypt_key).await?, + None => random_encrypt_key().await, + }; + + storage_key_file.write_all(&plain_key).await?; + storage_key_file.flush().await?; + Ok(()) +} + +pub(crate) struct LuksInterpreter; + +#[async_trait] +impl Interpreter for LuksInterpreter { + async fn secure_device_mount( + &self, + parameters: BlockDeviceParameters, + mount_point: &str, + ) -> Result<()> { + let random_string: String = rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(5) + .map(char::from) + .collect(); + let storage_key_path = format!("/tmp/encrypted_storage_key_{}", random_string); + create_storage_key_file(&storage_key_path, parameters.encryption_key.clone()).await?; + + let parameters = vec![ + parameters.device_id, + mount_point.to_string(), + storage_key_path, + parameters.data_integrity.clone(), + ]; + + let mut encrypt_device = Command::new(LUKS_ENCRYPT_STORAGE_BIN) + .args(parameters) + .spawn() + .map_err(|e| { + error!("luks-encrypt-storage cmd fork failed: {:?}", e); + BlockDeviceError::BlockDeviceMountFailed + })?; + + let bd_res = encrypt_device.wait().await?; + if !bd_res.success() { + let mut stderr = String::new(); + if let Some(mut err) = encrypt_device.stderr.take() { + err.read_to_string(&mut stderr).await?; + error!("BlockDevice mount failed with stderr: {:?}", stderr); + } else { + error!("BlockDevice mount failed"); + } + + return Err(BlockDeviceError::BlockDeviceMountFailed); + } + Ok(()) + } +} diff --git a/confidential-data-hub/storage/src/volume_type/blockdevice/mod.rs b/confidential-data-hub/storage/src/volume_type/blockdevice/mod.rs index 4bde0260c..4d89aae77 100644 --- a/confidential-data-hub/storage/src/volume_type/blockdevice/mod.rs +++ b/confidential-data-hub/storage/src/volume_type/blockdevice/mod.rs @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 // pub mod error; +pub mod luks; use super::SecureMount; use async_trait::async_trait; @@ -81,6 +82,13 @@ impl BlockDevice { let parameters = serde_json::to_string(options)?; let bd_parameter: BlockDeviceParameters = serde_json::from_str(¶meters)?; + match bd_parameter.encryption_type { + BlockDeviceEncryptType::LUKS => { + luks::LuksInterpreter + .secure_device_mount(bd_parameter, mount_point) + .await?; + } + } Ok(()) } }