From b11bb64732e1ebe0554b13d8351bdc64bb282904 Mon Sep 17 00:00:00 2001 From: Jakob Naucke Date: Fri, 25 Apr 2025 15:49:27 +0200 Subject: [PATCH] rust/pvimg: Add secret flag to allow CCK update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CCK will be able to be updated by an ultravisor call. For security reasons, this feature must be enabled at Secure Execution header creation time. Because this makes it possible to dump without having set a CCK earlier, the requirement to specify a CCK when creating an image with guest dump support is extended to also allow for CCK update instead. Change a CLI test for this that was a duplicate anyway. [seiden@linux.ibm.com: Allow --cck & --enable-cck-update simultaneously] Reviewed-by: Marc Hartmayer Reviewed-by: Steffen Eiden Signed-off-by: Jakob Naucke Signed-off-by: Jan Höppner --- rust/pvimg/man/pvimg-create.1 | 17 ++++++++++-- rust/pvimg/src/cli.rs | 35 ++++++++++++++++++++----- rust/pvimg/src/cmd/create.rs | 12 ++++++--- rust/pvimg/src/pv_utils/se_hdr/flags.rs | 2 ++ 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/rust/pvimg/man/pvimg-create.1 b/rust/pvimg/man/pvimg-create.1 index dd232083..844ae72f 100644 --- a/rust/pvimg/man/pvimg-create.1 +++ b/rust/pvimg/man/pvimg-create.1 @@ -3,7 +3,7 @@ .\" it under the terms of the MIT license. See LICENSE for details. .\" -.TH "PVIMG-CREATE" "1" "2024-12-19" "s390-tools" "Pvimg Manual" +.TH "PVIMG-CREATE" "1" "2025-04-24" "s390-tools" "Pvimg Manual" .nh .ad l .SH NAME @@ -139,7 +139,7 @@ Secure Execution header protection key is a randomly generated key. \-\-enable\-dump .RS 4 Enable Secure Execution guest dump support. This option requires the -\fB\-\-cck\fR option. +\fB\-\-cck\fR or \fB\-\-enable\-cck\-update\fR option. .RE .RE .PP @@ -163,6 +163,19 @@ Add\-secret requests don't have to provide the CCK\-derived extension secret .RE .RE .PP +\-\-enable\-cck\-update +.RS 4 +Enable CCK update support. Requires z17 or up. This option cannot be +used in conjunction with the \fB\-\-enable\-cck\-extension\-secret\fR option. +.RE +.RE +.PP +\-\-disable\-cck\-update +.RS 4 +Disable CCK update support (default). +.RE +.RE +.PP \-\-enable\-pckmo .RS 4 Enable the support for the DEA, TDEA, AES, and ECC PCKMO key encryption diff --git a/rust/pvimg/src/cli.rs b/rust/pvimg/src/cli.rs index 1431acba..4bab0b06 100644 --- a/rust/pvimg/src/cli.rs +++ b/rust/pvimg/src/cli.rs @@ -95,11 +95,13 @@ pub struct ComponentPaths { #[derive(Args, Debug)] #[cfg_attr(test, derive(Default))] -#[command(group(ArgGroup::new("header-flags").multiple(true).conflicts_with_all(["x_pcf", "x_scf"])))] +#[command( + group(ArgGroup::new("header-flags").multiple(true).conflicts_with_all(["x_pcf", "x_scf"])), + group(ArgGroup::new("cck-available").multiple(true)))] pub struct CreateBootImageLegacyFlags { /// Enable Secure Execution guest dump support. This option requires the - /// '--cck' option. - #[arg(long, action = clap::ArgAction::SetTrue, requires="cck", group="header-flags")] + /// '--cck' or '--enable-cck-update' option. + #[arg(long, action = clap::ArgAction::SetTrue, requires = "cck-available", group="header-flags")] pub enable_dump: Option, /// Disable Secure Execution guest dump support (default). @@ -117,6 +119,15 @@ pub struct CreateBootImageLegacyFlags { #[arg(long, action = clap::ArgAction::SetTrue, conflicts_with="enable_cck_extension_secret", group="header-flags")] pub disable_cck_extension_secret: Option, + /// Enable CCK update support. Requires z17 or up. This option cannot be + /// used in conjunction with the '--enable-cck-extension-secret' option. + #[arg(long, action = clap::ArgAction::SetTrue, conflicts_with="enable_cck_extension_secret", group="cck-available", group="header-flags")] + pub enable_cck_update: Option, + + /// Disable CCK update support (default). + #[arg(long, action = clap::ArgAction::SetTrue, conflicts_with="enable_cck_update", group="header-flags")] + pub disable_cck_update: Option, + /// Enable the support for the DEA, TDEA, AES, and ECC PCKMO key encryption /// functions (default). #[arg(long, action = clap::ArgAction::SetTrue, group="header-flags")] @@ -335,7 +346,12 @@ pub struct CreateBootImageArgs { /// /// The file must contain exactly 32 bytes of data. This option used to be /// called '--comm-key' in previous versions. - #[arg(long, value_name = "FILE", visible_alias = "comm-key")] + #[arg( + long, + value_name = "FILE", + group = "cck-available", + visible_alias = "comm-key" + )] pub cck: Option, /// Use the content of FILE as the Secure Execution header protection key. @@ -495,7 +511,8 @@ mod test { flat_map_collect(insert(mvca.clone(), vec![CliOption::new("enable-dump", ["--enable-dump"]), CliOption::new("comm-key", ["--cck", "/dev/null"])])), flat_map_collect(insert(mvca.clone(), vec![CliOption::new("enable-dump", ["--enable-dump"]), - CliOption::new("comm-key", ["--comm-key", "/dev/null"])])), + CliOption::new("comm-key", ["--comm-key", "/dev/null"]), + CliOption::new("enable-cck-update", ["--enable-cck-update"])])), flat_map_collect(insert(mvca.clone(), vec![CliOption::new("x-pcf", ["--x-pcf", "0x0"]), CliOption::new("x-scf", ["--x-scf", "0x0"])])), flat_map_collect(insert(mvca.clone(), vec![CliOption::new("x-psw", ["--x-psw", "0x0"])])), @@ -507,6 +524,9 @@ mod test { flat_map_collect(insert(mvca.clone(), vec![CliOption::new("enable-image-encryption", ["--enable-image-encryption"])])), flat_map_collect(insert(mvca.clone(), vec![CliOption::new("x-header-key", ["--x-header-key", "/dev/null"]),])), flat_map_collect(insert(mvca.clone(), vec![CliOption::new("x-header-key", ["--hdr-key", "/dev/null"]),])), + flat_map_collect(insert(mvca.clone(), vec![CliOption::new("enable-cck-update", ["--enable-cck-update"])])), + flat_map_collect(insert(mvca.clone(), vec![CliOption::new("disable-cck-update", ["--disable-cck-update"])])), + flat_map_collect(insert(mvca.clone(), vec![CliOption::new("multiple-cck", ["--disable-cck-update", "--cck", "/dev/null"])])), ]; let invalid_create_args = [ flat_map_collect(remove(mvcanv.clone(), "no-verify")), @@ -514,7 +534,7 @@ mod test { flat_map_collect(remove(mvcanv.clone(), "hkd")), flat_map_collect(remove(mvcanv, "output")), - // missing `--comm-key` + // missing both `--cck' and `--enable-cck-update' flat_map_collect(insert(mvca.clone(), vec![CliOption::new("enable-dump", ["--enable-dump"])])), // -v and -q cannot be combined @@ -535,6 +555,9 @@ mod test { flat_map_collect(insert(mvca.clone(), vec![CliOption::new("enable-image-encryption", ["--enable-image-encryption"]), CliOption::new("disable-image-encryption", ["--disable-image-encryption"])])), flat_map_collect(insert(mvca.clone(), vec![CliOption::new("x-header-key", ["--hdr-key"]),])), + flat_map_collect(insert(mvca.clone(), vec![CliOption::new("extension", ["--enable-cck-extension-secret"]), + CliOption::new("update", ["--enable-cck-update"])])), + ]; let mut genprotimg_valid_args = vec![ diff --git a/rust/pvimg/src/cmd/create.rs b/rust/pvimg/src/cmd/create.rs index f2ae5d03..40afcee7 100644 --- a/rust/pvimg/src/cmd/create.rs +++ b/rust/pvimg/src/cmd/create.rs @@ -92,6 +92,8 @@ fn parse_flags( lf.enable_cck_extension_secret, [ScfV1::CckExtensionSecretEnforcement] ), + flag_disabled!(lf.disable_cck_update, [ScfV1::CckUpdateAllowed]), + flag_enabled!(lf.enable_cck_update, [ScfV1::CckUpdateAllowed]), ] .into_iter() .flatten() @@ -217,14 +219,18 @@ mod test { let args = CreateBootImageArgs { legacy_flags: CreateBootImageLegacyFlags { enable_dump: Some(true), + enable_cck_update: Some(true), ..Default::default() }, ..Default::default() }; let parsed_flags = super::parse_flags(&args).expect("Failed to parse flags {args:?}"); - let mut exp_flags = Vec::from(PlaintextControlFlagsV1::PCKMO); - exp_flags.push(PcfV1::AllowDumping); - let pcf = PlaintextControlFlagsV1::from_flags(PcfV1::all_enabled(exp_flags)); + let mut exp_pcf = Vec::from(PlaintextControlFlagsV1::PCKMO); + exp_pcf.push(PcfV1::AllowDumping); + let pcf = PlaintextControlFlagsV1::from_flags(PcfV1::all_enabled(exp_pcf)); assert_eq!(parsed_flags.0, pcf); + let exp_scf = vec![ScfV1::CckUpdateAllowed]; + let scf = SecretControlFlagsV1::from_flags(ScfV1::all_enabled(exp_scf)); + assert_eq!(parsed_flags.1, scf); } } diff --git a/rust/pvimg/src/pv_utils/se_hdr/flags.rs b/rust/pvimg/src/pv_utils/se_hdr/flags.rs index 72ac543f..277c3bb1 100644 --- a/rust/pvimg/src/pv_utils/se_hdr/flags.rs +++ b/rust/pvimg/src/pv_utils/se_hdr/flags.rs @@ -205,6 +205,8 @@ impl ControlFlagTrait for PcfV1 {} pub enum ScfV1 { /// All add-secret requests must provide an extension secret CckExtensionSecretEnforcement = 1, + /// Whether CCK can be updated + CckUpdateAllowed = 2, } pub type SecretControlFlagsV1 = ControlFlags; impl ControlFlagTrait for ScfV1 {}