From 3579d724a3f094c4761dc89adabd8402d9113db2 Mon Sep 17 00:00:00 2001 From: Dominik Csapak Date: Mon, 22 Jan 2024 12:50:34 +0100 Subject: [PATCH] tape: assert encryption mode when using the PoolWriter by introducing an 'assert_encryption_mode' that checks the desired state, and bails out if it's different, called directly where we previously set the encryption mode (which is now done automatically) Signed-off-by: Dominik Csapak [ TL: add drive_ prefix and fleece in comment ] Signed-off-by: Thomas Lamprecht --- pbs-tape/src/sg_tape.rs | 2 +- pbs-tape/src/sg_tape/encryption.rs | 23 ++++++++++++++++++++++- src/tape/drive/lto/mod.rs | 9 +++++++++ src/tape/drive/mod.rs | 8 ++++++++ src/tape/pool_writer/mod.rs | 4 ++++ 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/pbs-tape/src/sg_tape.rs b/pbs-tape/src/sg_tape.rs index bc0c14f0..44f30fdb 100644 --- a/pbs-tape/src/sg_tape.rs +++ b/pbs-tape/src/sg_tape.rs @@ -9,7 +9,7 @@ use endian_trait::Endian; use nix::fcntl::{fcntl, FcntlArg, OFlag}; mod encryption; -pub use encryption::{drive_set_encryption, has_encryption}; +pub use encryption::{drive_set_encryption, drive_get_encryption, has_encryption}; mod volume_statistics; use proxmox_uuid::Uuid; diff --git a/pbs-tape/src/sg_tape/encryption.rs b/pbs-tape/src/sg_tape/encryption.rs index 59648954..d460c2f7 100644 --- a/pbs-tape/src/sg_tape/encryption.rs +++ b/pbs-tape/src/sg_tape/encryption.rs @@ -57,6 +57,27 @@ pub fn drive_set_encryption(file: &mut F, key: Option<[u8; 32]>) -> bail!("got unexpected encryption mode {:?}", status.mode); } +/// Returns if encryption is enabled on the drive +pub fn drive_get_encryption(file: &mut F) -> Result { + let data = match sg_spin_data_encryption_status(file) { + Ok(data) => data, + Err(_) => { + // Assume device does not support HW encryption + return Ok(false); + } + }; + let status = decode_spin_data_encryption_status(&data)?; + match status.mode { + // these three below have all encryption enabled, and only differ in how decryption is + // handled + DataEncryptionMode::On => Ok(true), + DataEncryptionMode::Mixed => Ok(true), + DataEncryptionMode::RawRead => Ok(true), + // currently, the mode below is the only one that has encryption actually disabled + DataEncryptionMode::Off => Ok(false), + } +} + #[derive(Endian)] #[repr(C, packed)] struct SspSetDataEncryptionPage { @@ -187,7 +208,7 @@ fn sg_spin_data_encryption_caps(file: &mut F) -> Result, Err .map(|v| v.to_vec()) } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] enum DataEncryptionMode { On, Mixed, diff --git a/src/tape/drive/lto/mod.rs b/src/tape/drive/lto/mod.rs index c30b2c94..d1070d03 100644 --- a/src/tape/drive/lto/mod.rs +++ b/src/tape/drive/lto/mod.rs @@ -16,6 +16,7 @@ use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use anyhow::{bail, format_err, Error}; +use pbs_tape::sg_tape::drive_get_encryption; use proxmox_uuid::Uuid; use pbs_api_types::{ @@ -311,6 +312,14 @@ impl TapeDriver for LtoTapeHandle { self.sg_tape.set_encryption(None) } } + + fn assert_encryption_mode(&mut self, encryption_wanted: bool) -> Result<(), Error> { + let encryption_set = drive_get_encryption(self.sg_tape.file_mut())?; + if encryption_wanted != encryption_set { + bail!("Set encryption mode not what was desired (set: {encryption_set}, wanted: {encryption_wanted})"); + } + Ok(()) + } } fn run_sg_tape_cmd(subcmd: &str, args: &[&str], fd: RawFd) -> Result { diff --git a/src/tape/drive/mod.rs b/src/tape/drive/mod.rs index 90be5f9e..73886f14 100644 --- a/src/tape/drive/mod.rs +++ b/src/tape/drive/mod.rs @@ -224,6 +224,14 @@ pub trait TapeDriver { } Ok(()) } + + /// Asserts that the encryption mode is set to the given value + fn assert_encryption_mode(&mut self, encryption_wanted: bool) -> Result<(), Error> { + if encryption_wanted { + bail!("drive does not support encryption"); + } + Ok(()) + } } /// A boxed implementor of [`MediaChange`]. diff --git a/src/tape/pool_writer/mod.rs b/src/tape/pool_writer/mod.rs index 6fd4f72a..f1224bdd 100644 --- a/src/tape/pool_writer/mod.rs +++ b/src/tape/pool_writer/mod.rs @@ -270,6 +270,10 @@ impl PoolWriter { self.catalog_set.lock().unwrap().append_catalog(catalog)?; + let media_set = media.media_set_label().unwrap(); + + drive.assert_encryption_mode(media_set.encryption_key_fingerprint.is_some())?; + self.status = Some(PoolWriterState { drive, media_uuid: media_uuid.clone(),