From 50d59ed558b498a1f8f0f622edfaa7f532765522 Mon Sep 17 00:00:00 2001 From: piotrpalcz Date: Tue, 19 Dec 2023 14:07:08 +0000 Subject: [PATCH] Use randomly generated key in image-rs to secure image layers in sefs Signed-off-by: piotrpalcz --- image-rs/src/snapshots/occlum/unionfs.rs | 58 ++++++++++++++++++++---- ocicrypt-rs/src/blockcipher/mod.rs | 2 +- ocicrypt-rs/src/blockcipher/rand.rs | 2 +- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/image-rs/src/snapshots/occlum/unionfs.rs b/image-rs/src/snapshots/occlum/unionfs.rs index 27d7ab96d..42af27c69 100644 --- a/image-rs/src/snapshots/occlum/unionfs.rs +++ b/image-rs/src/snapshots/occlum/unionfs.rs @@ -5,6 +5,8 @@ // This unionfs file is used for occlum only use std::fs; +use std::fs::File; +use std::io::Write; use std::path::{Path, PathBuf}; use std::sync::atomic::AtomicUsize; @@ -14,6 +16,8 @@ use fs_extra; use fs_extra::dir; use nix::mount::MsFlags; +use ocicrypt_rs::blockcipher::rand::rand_bytes; + use crate::snapshots::{MountPoint, Snapshotter}; const LD_LIB: &str = "ld-linux-x86-64.so.2"; @@ -47,6 +51,21 @@ fn create_dir(create_path: &Path) -> Result<()> { Ok(()) } +// returns randomly generted random 128 bit key +fn generate_random_key() -> String { + let mut key: [u8; 16] = [0u8; 16]; + + rand_bytes(&mut key).expect("Random fill failed"); + + let formatted_key = key + .iter() + .map(|byte| format!("{:02x}", byte)) + .collect::>() + .join("-"); + + formatted_key +} + fn create_environment(mount_path: &Path) -> Result<()> { let mut from_paths = Vec::new(); let mut copy_options = dir::CopyOptions::new(); @@ -69,7 +88,6 @@ fn create_environment(mount_path: &Path) -> Result<()> { if fs::symlink_metadata(ld_lib.as_path()).is_ok() { fs::remove_file(ld_lib)?; } - fs_extra::copy_items(&from_paths, &path_lib64, ©_options)?; from_paths.clear(); @@ -112,6 +130,7 @@ impl Snapshotter for Unionfs { fn mount(&mut self, layer_path: &[&str], mount_path: &Path) -> Result { let fs_type = String::from("sefs"); let source = Path::new(&fs_type); + let flags = MsFlags::empty(); if !mount_path.exists() { fs::create_dir_all(mount_path)?; @@ -124,18 +143,41 @@ impl Snapshotter for Unionfs { .file_name() .ok_or(anyhow!("Unknown error: file name parse fail"))?; - // For mounting trusted UnionFS at runtime of occlum, - // you can refer to https://github.com/occlum/occlum/blob/master/docs/runtime_mount.md#1-mount-trusted-unionfs-consisting-of-sefss. - // "c7-32-b3-ed-44-df-ec-7b-25-2d-9a-32-38-8d-58-61" is a hardcode key used to encrypt or decrypt the FS currently, - // and it will be replaced with dynamic key in the near future. + let key_mount_options = format!( + "dir={}", + Path::new("/images") + .join(cid) + .join("keys/sefs/lower") + .display() + ); + + let keys_mount_path = Path::new("/keys"); + nix::mount::mount( + Some(source), + keys_mount_path, + Some(fs_type.as_str()), + flags, + Some(key_mount_options.as_str()), + ) + .map_err(|e| { + anyhow!( + "failed to mount {:?} to {:?}, with error: {}", + source, + keys_mount_path, + e + ) + })?; + + let random_key = generate_random_key(); + std::fs::write(&PathBuf::from(&keys_mount_path.join("key.txt")), &random_key)?; + nix::mount::umount(keys_mount_path)?; + let options = format!( "dir={},key={}", Path::new("/images").join(cid).join("sefs/lower").display(), - "c7-32-b3-ed-44-df-ec-7b-25-2d-9a-32-38-8d-58-61" + random_key ); - let flags = MsFlags::empty(); - nix::mount::mount( Some(source), mount_path, diff --git a/ocicrypt-rs/src/blockcipher/mod.rs b/ocicrypt-rs/src/blockcipher/mod.rs index 5b625cd6e..5dbe0e273 100644 --- a/ocicrypt-rs/src/blockcipher/mod.rs +++ b/ocicrypt-rs/src/blockcipher/mod.rs @@ -12,7 +12,7 @@ use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; mod aes_ctr; use aes_ctr::AESCTRBlockCipher; -mod rand; +pub mod rand; /// Type of the cipher algorithm used to encrypt/decrypt image layers. pub type LayerCipherType = String; diff --git a/ocicrypt-rs/src/blockcipher/rand.rs b/ocicrypt-rs/src/blockcipher/rand.rs index bf22a16bf..db20ec63c 100644 --- a/ocicrypt-rs/src/blockcipher/rand.rs +++ b/ocicrypt-rs/src/blockcipher/rand.rs @@ -4,7 +4,7 @@ use anyhow::Result; /// Fill the given slice with cryptographically generated random numbers -pub(crate) fn rand_bytes(data: &mut [u8]) -> Result<()> { +pub fn rand_bytes(data: &mut [u8]) -> Result<()> { cfg_if::cfg_if! { if #[cfg(feature = "block-cipher-openssl")] { openssl::rand::rand_bytes(&mut data[..])?;