mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77083b1cbb | ||
|
|
21c2a04347 | ||
|
|
8f2d77c9d3 | ||
|
|
b6a4d7a6c1 | ||
|
|
f223069f0b | ||
|
|
19a5af8da9 | ||
|
|
03b73ab3f9 | ||
|
|
080a6678fb | ||
|
|
1d6f7d0bec | ||
|
|
a50d0485c9 | ||
|
|
d2a6a771a5 | ||
|
|
7568a0790f | ||
|
|
ca0ee966b8 | ||
|
|
36a7b2e6eb | ||
|
|
851f63eb03 | ||
|
|
3d679f61fc | ||
|
|
9237c5b675 | ||
|
|
d1ab6be082 | ||
|
|
d6c2bac99f |
18
CHANGELOG.md
18
CHANGELOG.md
@@ -1,6 +1,24 @@
|
||||
Release history for s390-tools (MIT version)
|
||||
--------------------------------------------
|
||||
|
||||
* __v2.42.1 (2026-05-22)__
|
||||
|
||||
For Linux kernel version: 7.0
|
||||
|
||||
Changes of existing tools:
|
||||
- cpumf/pai: Improve -m XXX argument verification
|
||||
- pvattest: Add -i -o option variant for check
|
||||
- pvattest: Show perform -i & -o option in help
|
||||
- pvebc: Disable unit logging to /boot
|
||||
- pvsecret: Add -i -o option variants
|
||||
|
||||
Bug Fixes:
|
||||
- cpumf/pai: Remove unnecessary const parameter definition
|
||||
- pv: Fix error description
|
||||
- pvebc: Fix dependency for non EBC guests
|
||||
- pvebc: Fix kernel module dependencies
|
||||
- zipl: Don't modify job->data.dump and job->data.mvdump sequentially
|
||||
|
||||
* __v2.42.0 (2026-04-30)__
|
||||
|
||||
For Linux kernel version: 7.0
|
||||
|
||||
@@ -33,7 +33,7 @@ endif
|
||||
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
|
||||
VERSION := 2
|
||||
RELEASE := 42
|
||||
PATCHLEVEL := 0
|
||||
PATCHLEVEL := 1
|
||||
DISTRELEASE := build-$(shell date +%Y%m%d)
|
||||
S390_TOOLS_RELEASE := $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
|
||||
export S390_TOOLS_RELEASE
|
||||
|
||||
24
cpumf/pai.c
24
cpumf/pai.c
@@ -894,7 +894,7 @@ static int parse_event_attr(char *cp)
|
||||
}
|
||||
|
||||
/* Parse CPU list and event specifications */
|
||||
static void parse_cpulist(int enr, const char *parm)
|
||||
static void parse_cpulist(int enr, char *parm)
|
||||
{
|
||||
unsigned int evt_attr = 0;
|
||||
cpu_set_t cmdlist, result;
|
||||
@@ -948,33 +948,27 @@ static const struct util_prg prg = {
|
||||
}
|
||||
};
|
||||
|
||||
static void record_cpus_crypto(const char *cp)
|
||||
static void record_cpus_crypto(char *cp)
|
||||
{
|
||||
if (!libcpumf_have_pai_crypto())
|
||||
errx(EXIT_FAILURE, "No support for PAI crypto counters");
|
||||
parse_cpulist(S390_EVT_PAI_CRYPTO, cp);
|
||||
}
|
||||
|
||||
static void record_cpus_nnpa(const char *cp)
|
||||
static void record_cpus_nnpa(char *cp)
|
||||
{
|
||||
if (!libcpumf_have_pai_nnpa())
|
||||
errx(EXIT_FAILURE, "No support for PAI nnpa counters");
|
||||
parse_cpulist(S390_EVT_PAI_NNPA, cp);
|
||||
}
|
||||
|
||||
/* Mapsize must be power of 2 and larger than 4. Count bits in n and
|
||||
* return 0 if input is invalid and has a bit count larger than one.
|
||||
/* Mapsize must be power of 2 and larger than 4. Return true in this case.
|
||||
*/
|
||||
static unsigned long check_mapsize(unsigned long n)
|
||||
static bool check_mapsize(unsigned long n)
|
||||
{
|
||||
int bit, cnt = 0;
|
||||
|
||||
if (n < 4)
|
||||
return 0;
|
||||
for (bit = 0; bit < __BITS_PER_LONG; ++bit)
|
||||
if (n & (1 << bit))
|
||||
++cnt;
|
||||
return cnt == 1 ? n : 0;
|
||||
return (n & (n - 1)) == 0;
|
||||
}
|
||||
|
||||
static void setprio(const char *prio)
|
||||
@@ -1040,11 +1034,11 @@ int main(int argc, char **argv)
|
||||
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
|
||||
break;
|
||||
case 'm':
|
||||
errno = 0;
|
||||
mapsize = strtoul(optarg, &slash, 0);
|
||||
mapsize = check_mapsize(mapsize);
|
||||
if (errno || !mapsize || *slash)
|
||||
if (!mapsize || *slash)
|
||||
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
|
||||
if (!check_mapsize(mapsize))
|
||||
errx(EXIT_FAILURE, "No power of 2 number for -%c", ch);
|
||||
break;
|
||||
case 'n':
|
||||
record_cpus_nnpa(optarg);
|
||||
|
||||
@@ -114,8 +114,10 @@ ifneq ($(HAVE_DRACUT),0)
|
||||
$(INSTALL) -m 755 pvebc/$(SEL_EBC_MODDIR)/module-setup.sh \
|
||||
pvebc/$(SEL_EBC_MODDIR)/override-crypttab.sh \
|
||||
pvebc/$(SEL_EBC_MODDIR)/pvebc-wrapper.sh \
|
||||
pvebc/$(SEL_EBC_MODDIR)/boot-mount.sh \
|
||||
pvebc/$(SEL_EBC_MODDIR)/sel-ebc-modules.conf \
|
||||
$(DESTDIR)$(DRACUTMODDIR)/$(SEL_EBC_MODDIR)
|
||||
$(INSTALL) -m 644 pvebc/$(SEL_EBC_MODDIR)/boot.mount \
|
||||
$(INSTALL) -m 644 pvebc/$(SEL_EBC_MODDIR)/sel-ebc-boot-mount.service \
|
||||
pvebc/$(SEL_EBC_MODDIR)/sel-ebc-override-crypttab.service \
|
||||
pvebc/$(SEL_EBC_MODDIR)/sel-ebc-paes-enforce.service \
|
||||
pvebc/$(SEL_EBC_MODDIR)/sel-ebc-pvebc.service \
|
||||
|
||||
@@ -90,11 +90,11 @@ pub enum Error {
|
||||
#[error("Input does not contain an attestation request")]
|
||||
NoArcb,
|
||||
|
||||
#[error("The attestation request has an unknown version (.0)")]
|
||||
#[error("The attestation request has an unknown version {0}")]
|
||||
BinArcbInvVersion(u32),
|
||||
|
||||
#[error(
|
||||
"The attestation request encrypted sice is to0 small (.0). Request probably tampered with."
|
||||
"The attestation request encrypted sice is to0 small {0}. Request probably tampered with."
|
||||
)]
|
||||
BinArcbSeaSmall(u32),
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ Create an attestation measurement request
|
||||
|
||||
- **perform**
|
||||
<ul>
|
||||
Send the attestation request to the Ultravisor
|
||||
Send the attestation request to the Ultravisor (s390x only.)
|
||||
</ul>
|
||||
|
||||
- **verify**
|
||||
@@ -150,11 +150,11 @@ Print help (see a summary with '-h').
|
||||
### Synopsis
|
||||
`pvattest perform [OPTIONS] [IN] [OUT]`
|
||||
### Description
|
||||
Send the attestation request to the Ultravisor. Run a measurement of this system
|
||||
through ’/dev/uv’. This device must be accessible and the attestation
|
||||
Ultravisor facility must be present. The input must be an attestation request
|
||||
created with ’pvattest create’. Output will contain the original request and
|
||||
the response from the Ultravisor.
|
||||
Send the attestation request to the Ultravisor (s390x only.) Run a measurement
|
||||
of this system through ’/dev/uv’. This device must be accessible and the
|
||||
attestation Ultravisor facility must be present. The input must be an
|
||||
attestation request created with ’pvattest create’. Output will contain the
|
||||
original request and the response from the Ultravisor. Only available on s390x.
|
||||
### Arguments
|
||||
|
||||
`<IN>`
|
||||
@@ -171,6 +171,18 @@ Write the result to FILE.
|
||||
|
||||
### Options
|
||||
|
||||
`-i`, `--input <FILE>`
|
||||
<ul>
|
||||
Specify the request to be sent.
|
||||
</ul>
|
||||
|
||||
|
||||
`-o`, `--output <FILE>`
|
||||
<ul>
|
||||
Write the result to FILE.
|
||||
</ul>
|
||||
|
||||
|
||||
`-u`, `--user-data <File>`
|
||||
<ul>
|
||||
Provide up to 256 bytes of user input User-data is arbitrary user-defined data
|
||||
@@ -256,7 +268,7 @@ Print help (see a summary with '-h').
|
||||
|
||||
## pvattest check
|
||||
### Synopsis
|
||||
`pvattest check [OPTIONS] <IN> <OUT>`
|
||||
`pvattest check [OPTIONS] [IN] [OUT]`
|
||||
### Description
|
||||
Check if the attestation result matches defined policies. After the attestation
|
||||
verification, check whether the attestation result complies with user-defined
|
||||
@@ -277,6 +289,18 @@ Specify the output file for the check result.
|
||||
|
||||
### Options
|
||||
|
||||
`-i`, `--input <FILE>`
|
||||
<ul>
|
||||
Specify the attestation response to check whether the policies are validated.
|
||||
</ul>
|
||||
|
||||
|
||||
`-o`, `--output <FILE>`
|
||||
<ul>
|
||||
Specify the output file for the check result.
|
||||
</ul>
|
||||
|
||||
|
||||
`--format <FORMAT>`
|
||||
<ul>
|
||||
Define the output format.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVATTEST-CHECK" "1" "2025-03-12" "s390-tools" "Attestation Manual"
|
||||
.TH "PVATTEST-CHECK" "1" "2026-05-19" "s390-tools" "Attestation Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -11,7 +11,7 @@ pvattest-check \- Check if the attestation result matches defined policies
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.fam C
|
||||
pvattest check [OPTIONS] <IN> <OUT>
|
||||
pvattest check [OPTIONS] [IN] [OUT]
|
||||
.fam C
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
@@ -31,6 +31,18 @@ Specify the output file for the check result.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.PP
|
||||
\-i, \-\-input <FILE>
|
||||
.RS 4
|
||||
Specify the attestation response to check whether the policies are validated.
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\-o, \-\-output <FILE>
|
||||
.RS 4
|
||||
Specify the output file for the check result.
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\-\-format <FORMAT>
|
||||
.RS 4
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVATTEST-CREATE" "1" "2026-02-12" "s390-tools" "Attestation Manual"
|
||||
.TH "PVATTEST-CREATE" "1" "2026-05-20" "s390-tools" "Attestation Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -21,6 +21,7 @@ Workstation. To avoid compromising the attestation do not publish the
|
||||
attestation request protection key and shred it after verification. Every
|
||||
\fBcreate\fR will generate a new, random protection key.
|
||||
.SH OPTIONS
|
||||
|
||||
.PP
|
||||
\-k, \-\-host\-key\-document <FILE>
|
||||
.RS 4
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVATTEST-PERFORM" "1" "2025-03-12" "s390-tools" "Attestation Manual"
|
||||
.TH "PVATTEST-PERFORM" "1" "2026-05-19" "s390-tools" "Attestation Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
pvattest-perform \- Send the attestation request to the Ultravisor
|
||||
pvattest-perform \- Send the attestation request to the Ultravisor (s390x only.)
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.fam C
|
||||
@@ -18,7 +18,8 @@ pvattest perform [OPTIONS] [IN] [OUT]
|
||||
Run a measurement of this system through ’/dev/uv’. This device must be
|
||||
accessible and the attestation Ultravisor facility must be present. The input
|
||||
must be an attestation request created with ’pvattest create’. Output will
|
||||
contain the original request and the response from the Ultravisor.
|
||||
contain the original request and the response from the Ultravisor. Only
|
||||
available on s390x.
|
||||
.SH OPTIONS
|
||||
.PP
|
||||
<IN>
|
||||
@@ -33,6 +34,18 @@ Write the result to FILE.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.PP
|
||||
\-i, \-\-input <FILE>
|
||||
.RS 4
|
||||
Specify the request to be sent.
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\-o, \-\-output <FILE>
|
||||
.RS 4
|
||||
Write the result to FILE.
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\-u, \-\-user\-data <File>
|
||||
.RS 4
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVATTEST-VERIFY" "1" "2026-02-12" "s390-tools" "Attestation Manual"
|
||||
.TH "PVATTEST-VERIFY" "1" "2026-05-20" "s390-tools" "Attestation Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -26,6 +26,7 @@ solely verifies that the Attestation measurement is correct. It does not check
|
||||
for the content of additional data or user data. See `pvattest check` for policy
|
||||
checks after you verified the Attestation measurement.
|
||||
.SH OPTIONS
|
||||
|
||||
.PP
|
||||
\-i, \-\-input <FILE>
|
||||
.RS 4
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVATTEST" "1" "2026-02-12" "s390-tools" "Attestation Manual"
|
||||
.TH "PVATTEST" "1" "2026-05-19" "s390-tools" "Attestation Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -29,7 +29,7 @@ Create an attestation measurement request
|
||||
|
||||
\fBpvattest\-perform(1)\fR
|
||||
.RS 4
|
||||
Send the attestation request to the Ultravisor
|
||||
Send the attestation request to the Ultravisor (s390x only.)
|
||||
.RE
|
||||
|
||||
.PP
|
||||
@@ -47,6 +47,7 @@ Check if the attestation result matches defined policies
|
||||
.RE
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.PP
|
||||
\-v, \-\-verbose
|
||||
.RS 4
|
||||
|
||||
@@ -113,20 +113,20 @@ pub enum AttAddFlags {
|
||||
#[derive(Args, Debug)]
|
||||
pub struct PerformAttOpt {
|
||||
/// Specify the request to be sent.
|
||||
#[arg(hide=true, short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
|
||||
pub input: Option<String>,
|
||||
#[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
|
||||
input: Option<String>,
|
||||
|
||||
/// Specify the request to be sent.
|
||||
#[arg(value_name = "IN", value_hint = ValueHint::FilePath, required_unless_present("input"), conflicts_with("input"))]
|
||||
pub input_pos: Option<String>,
|
||||
input_pos: Option<String>,
|
||||
|
||||
/// Write the result to FILE.
|
||||
#[arg(hide=true, short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
|
||||
pub output: Option<String>,
|
||||
#[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
|
||||
output: Option<String>,
|
||||
|
||||
/// Write the result to FILE.
|
||||
#[arg(value_name = "OUT", value_hint = ValueHint::FilePath, required_unless_present("output"), conflicts_with("output"))]
|
||||
pub output_pos: Option<String>,
|
||||
output_pos: Option<String>,
|
||||
|
||||
/// Provide up to 256 bytes of user input
|
||||
///
|
||||
@@ -134,7 +134,7 @@ pub struct PerformAttOpt {
|
||||
/// It is verified during the Attestation measurement verification.
|
||||
/// May be any arbitrary data, as long as it is less or equal to 256 bytes
|
||||
#[arg(short, long, value_name = "File", value_hint = ValueHint::FilePath,)]
|
||||
pub user_data: Option<String>,
|
||||
user_data: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "s390x")]
|
||||
@@ -217,12 +217,20 @@ pub enum OutputType {
|
||||
#[derive(Args, Debug)]
|
||||
pub struct CheckOpt {
|
||||
/// Specify the attestation response to check whether the policies are validated.
|
||||
#[arg(value_name = "IN", value_hint = ValueHint::FilePath,)]
|
||||
pub input: PathBuf,
|
||||
#[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
|
||||
input: Option<PathBuf>,
|
||||
|
||||
/// Specify the attestation response to check whether the policies are validated.
|
||||
#[arg(value_name = "IN", value_hint = ValueHint::FilePath, required_unless_present("input"), conflicts_with("input"))]
|
||||
input_pos: Option<PathBuf>,
|
||||
|
||||
/// Specify the output file for the check result.
|
||||
#[arg(value_name = "OUT", value_hint = ValueHint::FilePath,)]
|
||||
pub output: PathBuf,
|
||||
#[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
|
||||
output: Option<PathBuf>,
|
||||
|
||||
/// Specify the output file for the check result.
|
||||
#[arg(value_name = "OUT", value_hint = ValueHint::FilePath, required_unless_present("output"), conflicts_with("output"))]
|
||||
output_pos: Option<PathBuf>,
|
||||
|
||||
/// Define the output format.
|
||||
#[arg(long, value_enum, default_value_t)]
|
||||
@@ -300,6 +308,30 @@ pub struct CheckOpt {
|
||||
pub firmware_verify_url: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CheckOptIO<'a> {
|
||||
pub input: &'a PathBuf,
|
||||
pub output: &'a PathBuf,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a CheckOpt> for CheckOptIO<'a> {
|
||||
fn from(value: &'a CheckOpt) -> Self {
|
||||
let input = match (&value.input, &value.input_pos) {
|
||||
(None, Some(i)) => i,
|
||||
(Some(i), None) => i,
|
||||
(Some(_), Some(_)) => unreachable!(),
|
||||
(None, None) => unreachable!(),
|
||||
};
|
||||
let output = match (&value.output, &value.output_pos) {
|
||||
(None, Some(o)) => o,
|
||||
(Some(o), None) => o,
|
||||
(Some(_), Some(_)) => unreachable!(),
|
||||
(None, None) => unreachable!(),
|
||||
};
|
||||
Self { input, output }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)]
|
||||
pub enum HostKeyCheckPolicy {
|
||||
/// Check the host-key used for the attestation request.
|
||||
|
||||
@@ -12,7 +12,12 @@ use self::{
|
||||
secret_store::secret_store_check,
|
||||
secret_store::SecretStoreCheck,
|
||||
};
|
||||
use crate::{additional::AttestationResult, cli::CheckOpt, exchange::ExchangeFormatResponse};
|
||||
use crate::{
|
||||
additional::AttestationResult,
|
||||
cli::{CheckOpt, CheckOptIO},
|
||||
exchange::ExchangeFormatResponse,
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
use log::{debug, info, warn};
|
||||
use pv::{
|
||||
@@ -104,7 +109,8 @@ pub struct CheckResult<'a> {
|
||||
|
||||
/// Perform the policy checks
|
||||
pub fn check(opt: &CheckOpt) -> Result<ExitCode> {
|
||||
let mut input = open_file(&opt.input)?;
|
||||
let opt_io = CheckOptIO::from(opt);
|
||||
let mut input = open_file(opt_io.input)?;
|
||||
let inp = ExchangeFormatResponse::read(&mut input)?;
|
||||
let auth = AttestationRequest::auth_bin(inp.arcb())?;
|
||||
let att_res = AttestationResult::from_exchange(&inp, auth.flags())?;
|
||||
@@ -139,7 +145,7 @@ pub fn check(opt: &CheckOpt) -> Result<ExitCode> {
|
||||
};
|
||||
|
||||
debug!("res {res:?}");
|
||||
let output = create_file(&opt.output)?;
|
||||
let output = create_file(opt_io.output)?;
|
||||
serde_yaml::to_writer(output, &res)?;
|
||||
|
||||
match res.successful {
|
||||
|
||||
31
rust/pvebc/95sel-ebc/boot-mount.sh
Normal file
31
rust/pvebc/95sel-ebc/boot-mount.sh
Normal file
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Copyright IBM Corp.
|
||||
|
||||
set -eu
|
||||
|
||||
mntp="/boot"
|
||||
block_dev="$(blkid -L boot)"
|
||||
|
||||
if [[ -z "${block_dev}" ]]; then
|
||||
echo "Unable to find partition with label boot"
|
||||
exit 1
|
||||
elif [[ ! -b "${block_dev}" ]]; then
|
||||
echo "Unable to find block device ${block_dev}"
|
||||
exit 1
|
||||
else
|
||||
echo "Found block device ${block_dev}"
|
||||
fi
|
||||
|
||||
if [[ ! -d "${mntp}" ]]; then
|
||||
echo "Mountpoint ${mntp} does not exist, creating..."
|
||||
mkdir "${mntp}"
|
||||
else
|
||||
echo "Mountpoint ${mntp} exists"
|
||||
fi
|
||||
|
||||
echo "Mounting ${block_dev} to ${mntp}"
|
||||
mount --options ro "${block_dev}" "${mntp}"
|
||||
|
||||
exit 0
|
||||
@@ -1,28 +0,0 @@
|
||||
[Unit]
|
||||
Description=Mount /boot early in initramfs
|
||||
|
||||
# Initramfs requirement
|
||||
DefaultDependencies=no
|
||||
# Make absolutely sure this only runs in initramfs (and not post-pivot if the
|
||||
# unit ever appears there)
|
||||
ConditionPathExists=/etc/initrd-release
|
||||
ConditionKernelCommandLine=root
|
||||
|
||||
# we use /dev/disk/by-label because it identifies the boot partition system
|
||||
# independently IF set up correctly
|
||||
Requires=dev-disk-by\x2dlabel-boot.device
|
||||
|
||||
# Ordering dependencies
|
||||
After=dev-disk-by\x2dlabel-boot.device
|
||||
Before=sel-ebc-pvebc.service
|
||||
|
||||
[Mount]
|
||||
# system independent identification of boot partition requires that the label
|
||||
# boot is set for the boot partition
|
||||
What=/dev/disk/by-label/boot
|
||||
Where=/boot
|
||||
Type=auto
|
||||
Options=defaults
|
||||
|
||||
[Install]
|
||||
WantedBy=sel-ebc-pvebc.service
|
||||
@@ -23,11 +23,11 @@ depends() {
|
||||
# Called by dracut
|
||||
installkernel() {
|
||||
# kernel modules needed for opening an encrypted rfs
|
||||
instmods -c uvdevice
|
||||
instmods -c paes_s390
|
||||
instmods -c pkey_uv
|
||||
instmods -c pkey_pckmo
|
||||
instmods -c pkey
|
||||
hostonly='' instmods -c uvdevice
|
||||
hostonly='' instmods -c paes_s390
|
||||
hostonly='' instmods -c pkey_uv
|
||||
hostonly='' instmods -c pkey_pckmo
|
||||
hostonly='' instmods -c pkey
|
||||
}
|
||||
|
||||
# Called by dracut
|
||||
@@ -43,8 +43,8 @@ install() {
|
||||
"$systemdsystemunitdir/sel-ebc-paes-enforce.service"
|
||||
inst_simple "$moddir/sel-ebc-override-crypttab.service" \
|
||||
"$systemdsystemunitdir/sel-ebc-override-crypttab.service"
|
||||
inst_simple "$moddir/boot.mount" \
|
||||
"$systemdsystemunitdir/boot.mount"
|
||||
inst_simple "$moddir/sel-ebc-boot-mount.service" \
|
||||
"$systemdsystemunitdir/sel-ebc-boot-mount.service"
|
||||
|
||||
# already exisitng unit we depend on for kernel modules
|
||||
inst_simple /usr/lib/systemd/system/systemd-modules-load.service \
|
||||
@@ -58,6 +58,14 @@ install() {
|
||||
inst_simple "$moddir/override-crypttab.sh" \
|
||||
"/etc/sel-ebc/override-crypttab.sh"
|
||||
|
||||
# mount boot partition to /boot
|
||||
inst_simple "$moddir/boot-mount.sh" \
|
||||
"/etc/sel-ebc/boot-mount.sh"
|
||||
|
||||
# install kernel module dependencies
|
||||
inst_simple "$moddir/sel-ebc-modules.conf" \
|
||||
"/usr/lib/modules-load.d/sel-ebc-modules.conf"
|
||||
|
||||
# copy main application
|
||||
inst_binary "/usr/bin/pvebc"
|
||||
inst_binary "/usr/bin/pvsecret"
|
||||
@@ -72,5 +80,5 @@ install() {
|
||||
systemctl --root "$initdir" --no-reload --quiet enable sel-ebc-override-crypttab.service
|
||||
systemctl --root "$initdir" --no-reload --quiet enable sel-ebc-paes-enforce.service
|
||||
systemctl --root "$initdir" --no-reload --quiet enable systemd-modules-load.service
|
||||
systemctl --root "$initdir" --no-reload --quiet enable boot.mount
|
||||
systemctl --root "$initdir" --no-reload --quiet enable sel-ebc-boot-mount.service
|
||||
}
|
||||
|
||||
@@ -3,7 +3,20 @@
|
||||
#
|
||||
# Copyright IBM Corp.
|
||||
|
||||
set -eu
|
||||
|
||||
IBM_RSRC_DIR="/etc/sel-ebc"
|
||||
block_dev="$(blkid -L cryptroot)"
|
||||
|
||||
if [[ -z "${block_dev}" ]]; then
|
||||
echo "Unable to find partition with label cryptroot"
|
||||
exit 1
|
||||
elif [[ ! -b "${block_dev}" ]]; then
|
||||
echo "Unable to find block device ${block_dev}"
|
||||
exit 1
|
||||
else
|
||||
echo "Found block device ${block_dev}"
|
||||
fi
|
||||
|
||||
if [[ ! -f "${IBM_RSRC_DIR}/crypttab" ]]; then
|
||||
echo "Error: source file $IBM_RSRC_DIR/crypttab does not exist"
|
||||
@@ -15,6 +28,11 @@ cp "${IBM_RSRC_DIR}/crypttab" "/etc/crypttab"
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
systemctl restart systemd-cryptsetup@cryptroot_mapper.service
|
||||
udevadm trigger --subsystem-match=block --settle
|
||||
|
||||
if ! systemctl restart systemd-cryptsetup@cryptroot_mapper.service; then
|
||||
systemctl status systemd-cryptsetup@cryptroot_mapper.service
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -48,16 +48,23 @@ fi
|
||||
pvebc --toc "$EBC_TMPFS/$TOC"
|
||||
rc=$?
|
||||
if [[ $rc -ne 0 ]]; then
|
||||
echo "pvebc failed with rc=${rc}"
|
||||
exit $rc
|
||||
fi
|
||||
|
||||
# Retrieve and check for dummy LUKS passphrase
|
||||
pvsecret retrieve --inform name -o "$EBC_TMPFS/$ASR_NAME" --outform bin "$ASR_NAME"
|
||||
rc=$?
|
||||
if [[ $rc -ne 0 ]]; then
|
||||
echo "pvsecret failed with rc=${rc}"
|
||||
exit $rc
|
||||
fi
|
||||
|
||||
if [[ ! -f "$EBC_TMPFS/$ASR_NAME" ]]; then
|
||||
echo "$EBC_TMPFS/$ASR_NAME does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chmod 400 "$EBC_TMPFS/$ASR_NAME"
|
||||
|
||||
exit 0
|
||||
exit $?
|
||||
|
||||
21
rust/pvebc/95sel-ebc/sel-ebc-boot-mount.service
Normal file
21
rust/pvebc/95sel-ebc/sel-ebc-boot-mount.service
Normal file
@@ -0,0 +1,21 @@
|
||||
[Unit]
|
||||
Description=Mount a partition identified by label boot to /boot
|
||||
|
||||
# Ensure this runs before the handoff to the real root, if that's required:
|
||||
Before=sel-ebc-pvebc.service
|
||||
|
||||
# Initramfs requirement
|
||||
DefaultDependencies=no
|
||||
# Make absolutely sure this only runs in initramfs
|
||||
ConditionPathExists=/etc/initrd-release
|
||||
ConditionKernelCommandLine=rd.sel-ebc
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/bash /etc/sel-ebc/boot-mount.sh
|
||||
RemainAfterExit=yes
|
||||
# On failure immediately abort boot
|
||||
FailureAction=poweroff-immediate
|
||||
|
||||
[Install]
|
||||
RequiredBy=sel-ebc-pvebc.service
|
||||
5
rust/pvebc/95sel-ebc/sel-ebc-modules.conf
Normal file
5
rust/pvebc/95sel-ebc/sel-ebc-modules.conf
Normal file
@@ -0,0 +1,5 @@
|
||||
uvdevice
|
||||
paes_s390
|
||||
pkey_uv
|
||||
pkey_pckmo
|
||||
pkey
|
||||
@@ -4,10 +4,8 @@ Description=Override crypttab
|
||||
# boot partition contains SICS
|
||||
# Loading of kernel modules is required which are needed for protected keys
|
||||
Requires=systemd-modules-load.service
|
||||
Requires=boot.mount
|
||||
|
||||
# Ensure this runs before the handoff to the real root, if that's required:
|
||||
After=boot.mount
|
||||
After=systemd-modules-load.service
|
||||
Before=cryptsetup-pre.target
|
||||
Before=cryptsetup.target
|
||||
@@ -30,8 +28,8 @@ RemainAfterExit=yes
|
||||
FailureAction=poweroff-immediate
|
||||
# boot partition is unencrypted and contains SICS so we can get logs out this way
|
||||
# logs do not leek any sensitive information
|
||||
StandardOutput=file:/boot/sics/log
|
||||
StandardError=file:/boot/sics/log
|
||||
StandardOutput=console
|
||||
StandardError=console
|
||||
|
||||
[Install]
|
||||
RequiredBy=sel-ebc.target
|
||||
|
||||
@@ -20,8 +20,8 @@ FailureAction=poweroff-immediate
|
||||
RemainAfterExit=yes
|
||||
|
||||
# logs do not leek any sensitive information
|
||||
StandardOutput=file:/boot/sics/log
|
||||
StandardError=file:/boot/sics/log
|
||||
StandardOutput=console
|
||||
StandardError=console
|
||||
|
||||
[Install]
|
||||
RequiredBy=sel-ebc.target
|
||||
|
||||
@@ -4,14 +4,14 @@ Description=Run pvebc during early boot to process SICS
|
||||
# boot partition contains SICS
|
||||
# Loading of kernel modules is required which are needed for protected keys
|
||||
Requires=systemd-modules-load.service
|
||||
Wants=boot.mount
|
||||
Requires=sel-ebc-boot-mount.service
|
||||
|
||||
# Ensure this runs before the handoff to the real root, if that's required:
|
||||
Before=initrd-root-device.target
|
||||
Before=cryptsetup-pre.target
|
||||
Before=cryptsetup.target
|
||||
After=boot.mount
|
||||
After=systemd-modules-load.service
|
||||
After=sel-ebc-boot-mount.service
|
||||
|
||||
# Initramfs requirement
|
||||
DefaultDependencies=no
|
||||
@@ -29,8 +29,8 @@ RemainAfterExit=yes
|
||||
FailureAction=poweroff-immediate
|
||||
# boot partition is unencrypted and contains SICS so we can get logs out this way
|
||||
# logs do not leek any sensitive information
|
||||
StandardOutput=file:/boot/sics/log
|
||||
StandardError=file:/boot/sics/log
|
||||
StandardOutput=console
|
||||
StandardError=console
|
||||
|
||||
[Install]
|
||||
RequiredBy=sel-ebc.target
|
||||
|
||||
@@ -253,6 +253,28 @@ Optional. No user-data by default.
|
||||
</ul>
|
||||
|
||||
|
||||
`--policy <FILE>`
|
||||
<ul>
|
||||
Links an Add‑Secret-Request (ASR) to a policy file. This option embeds a
|
||||
PolicyReference in the ASR user data field. The PolicyReference includes the
|
||||
relative file path and the SHA‑512 hash of the policy file, allowing the
|
||||
policy’s integrity to be verified.
|
||||
|
||||
This option conflicts with --user-data, because both options use the same user
|
||||
data field in the ASR structure.
|
||||
</ul>
|
||||
|
||||
|
||||
`--toc-policy <FILE>`
|
||||
<ul>
|
||||
Adds the AES‑GCM authentication tag to a TOC policy file. This option appends
|
||||
the AES‑GCM authentication tag to the specified TOC policy file. This allows
|
||||
the TOC policy to maintain a list of all ASR MAC tags for completeness
|
||||
verification during boot. During verification, the TOC checks the MAC tags
|
||||
against this list to ensure that all expected ASRs are present and unmodified.
|
||||
</ul>
|
||||
|
||||
|
||||
`--user-sign-key <FILE>`
|
||||
<ul>
|
||||
Use the content of FILE as user signing key. Adds a signature calculated from
|
||||
@@ -407,14 +429,14 @@ Print help (see a summary with '-h').
|
||||
|
||||
## pvsecret add
|
||||
### Synopsis
|
||||
`pvsecret add [OPTIONS] <FILE>`
|
||||
`pvsecret add [OPTIONS] [INPUT]`
|
||||
### Description
|
||||
Submit an add-secret request to the Ultravisor (s390x only). Perform an
|
||||
add-secret request using a previously generated add-secret request. Only
|
||||
available on s390x.
|
||||
### Arguments
|
||||
|
||||
`<FILE>`
|
||||
`<INPUT>`
|
||||
<ul>
|
||||
Specify the request to be sent.
|
||||
</ul>
|
||||
@@ -422,6 +444,12 @@ Specify the request to be sent.
|
||||
|
||||
### Options
|
||||
|
||||
`-i`, `--input <FILE>`
|
||||
<ul>
|
||||
Specify the request to be sent.
|
||||
</ul>
|
||||
|
||||
|
||||
`-f`, `--force`
|
||||
<ul>
|
||||
Force the addition of add-secret requests. Add an add-secret request even if
|
||||
@@ -445,22 +473,27 @@ fail. Only available on s390x.
|
||||
|
||||
## pvsecret list
|
||||
### Synopsis
|
||||
`pvsecret list [OPTIONS] [FILE]`
|
||||
`pvsecret list [OPTIONS] [OUTPUT]`
|
||||
### Description
|
||||
List all ultravisor secrets (s390x only). Lists the IDs of all non-null secrets
|
||||
currently stored in the ultravisor for the currently running IBM Secure
|
||||
Execution guest. Only available on s390x.
|
||||
### Arguments
|
||||
|
||||
`<FILE>`
|
||||
`<OUTPUT>`
|
||||
<ul>
|
||||
Store the result in FILE.
|
||||
Default value: '-'
|
||||
</ul>
|
||||
|
||||
|
||||
### Options
|
||||
|
||||
`-o`, `--output <FILE>`
|
||||
<ul>
|
||||
Store the result in FILE.
|
||||
</ul>
|
||||
|
||||
|
||||
`--format <FORMAT>`
|
||||
<ul>
|
||||
Define the output format of the list.
|
||||
@@ -480,7 +513,7 @@ Print help (see a summary with '-h').
|
||||
|
||||
## pvsecret verify
|
||||
### Synopsis
|
||||
`pvsecret verify [OPTIONS] <FILE>`
|
||||
`pvsecret verify [OPTIONS] [INPUT] [OUTPUT]`
|
||||
### Description
|
||||
Verifies that the given request is an Add-Secret request by testing for some
|
||||
values to be present. If the request contains signed user-data, the signature
|
||||
@@ -520,14 +553,27 @@ The verification process works as follows:
|
||||
|
||||
### Arguments
|
||||
|
||||
`<FILE>`
|
||||
`<INPUT>`
|
||||
<ul>
|
||||
Specify the request to be checked.
|
||||
</ul>
|
||||
|
||||
|
||||
`<OUTPUT>`
|
||||
<ul>
|
||||
Store the result in FILE If the request contained abirtary user-data the output
|
||||
contains this user-data with padded zeros if available.
|
||||
</ul>
|
||||
|
||||
|
||||
### Options
|
||||
|
||||
`-i`, `--input <FILE>`
|
||||
<ul>
|
||||
Specify the request to be checked.
|
||||
</ul>
|
||||
|
||||
|
||||
`--user-cert <FILE>`
|
||||
<ul>
|
||||
Certificate containing a public key used to verify the user data signature.
|
||||
@@ -540,11 +586,10 @@ curve over a 521 bit prime field (secp521r1).
|
||||
</ul>
|
||||
|
||||
|
||||
`-o`, `--output <FILE>`
|
||||
`-o`, `--output <OUTPUT>`
|
||||
<ul>
|
||||
Store the result in FILE If the request contained abirtary user-data the output
|
||||
contains this user-data with padded zeros if available.
|
||||
Default value: '-'
|
||||
</ul>
|
||||
|
||||
|
||||
@@ -556,13 +601,13 @@ Print help (see a summary with '-h').
|
||||
|
||||
## pvsecret retrieve
|
||||
### Synopsis
|
||||
`pvsecret retrieve [OPTIONS] <ID>`
|
||||
`pvsecret retr [OPTIONS] <ID>`
|
||||
`pvsecret retrieve [OPTIONS] [INPUT] [OUTPUT]`
|
||||
`pvsecret retr [OPTIONS] [INPUT] [OUTPUT]`
|
||||
### Description
|
||||
Retrieve a secret from the UV secret store (s390x only)
|
||||
### Arguments
|
||||
|
||||
`<ID>`
|
||||
`<INPUT>`
|
||||
<ul>
|
||||
Specify the secret ID to be retrieved. Input type depends on '--inform'. If
|
||||
`yaml` (default) is specified, it must be a yaml created by the create
|
||||
@@ -574,12 +619,29 @@ retrieved.
|
||||
</ul>
|
||||
|
||||
|
||||
`<OUTPUT>`
|
||||
<ul>
|
||||
Specify the output path to place the secret value.
|
||||
</ul>
|
||||
|
||||
|
||||
### Options
|
||||
|
||||
`-i`, `--input <ID>`
|
||||
<ul>
|
||||
Specify the secret ID to be retrieved. Input type depends on '--inform'. If
|
||||
`yaml` (default) is specified, it must be a yaml created by the create
|
||||
subcommand of this tool. If `hex` is specified, it must be a 32 byte handle
|
||||
encodes in hexadecimal. Leading zeros are required. If there are multiple
|
||||
secrets in the store with the same Id there are no guarantees on which specific
|
||||
secret is retrieved. Use --inform=idx to make sure a specific secret is
|
||||
retrieved.
|
||||
</ul>
|
||||
|
||||
|
||||
`-o`, `--output <FILE>`
|
||||
<ul>
|
||||
Specify the output path to place the secret value.
|
||||
Default value: '-'
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVSECRET-ADD" "1" "2026-02-12" "s390-tools" "UV\-Secret Manual"
|
||||
.TH "PVSECRET-ADD" "1" "2026-05-21" "s390-tools" "UV\-Secret Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -11,7 +11,7 @@ pvsecret-add \- Submit an add-secret request to the Ultravisor (s390x only)
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.fam C
|
||||
pvsecret add [OPTIONS] <FILE>
|
||||
pvsecret add [OPTIONS] [INPUT]
|
||||
.fam C
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
@@ -19,12 +19,18 @@ Perform an add\-secret request using a previously generated add\-secret request.
|
||||
Only available on s390x.
|
||||
.SH OPTIONS
|
||||
.PP
|
||||
<FILE>
|
||||
<INPUT>
|
||||
.RS 4
|
||||
Specify the request to be sent.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.PP
|
||||
\-i, \-\-input <FILE>
|
||||
.RS 4
|
||||
Specify the request to be sent.
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\-f, \-\-force
|
||||
.RS 4
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVSECRET-CREATE-RETRIEVABLE" "1" "2026-02-12" "s390-tools" "UV\-Secret Manual"
|
||||
.TH "PVSECRET-CREATE-RETRIEVABLE" "1" "2026-05-20" "s390-tools" "UV\-Secret Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -29,30 +29,30 @@ the following curves: secp256r1, secp384r1, secp521r1, ed25519, or ed448.
|
||||
\fBHMAC\-SHA preprocessing\fP
|
||||
|
||||
.RS 2
|
||||
The \fBHMAC\-SHA\fP key supplied in the plain bytes file is the key \fBK_0\fP
|
||||
as of \fBFIPS\-198\-1\fP, i.e. the key \fBK\fP after any necessary
|
||||
pre\-processing. The pre\-processing must be performed by the user prior to
|
||||
creating the retrievable secret.
|
||||
.PP Pre\-processing means that if the key \fBK\fP is shorter than the block
|
||||
size of the to\-be\-used HMAC digest, then the key must be padded with binary
|
||||
zeros to the right up to the block size. The block size of SHA\-224 and
|
||||
SHA\-256 is 512 bits (64 bytes) and the bock size of SHA\-384 and SHA\-512 is
|
||||
1024 bits (128 bytes). Such padding can for example be achieved by using the
|
||||
\fBtruncate\fP command with the desired size in bytes, e.g. \fB'truncate
|
||||
\-\-size 64 <key\-file>'\fP for creating a \fBK_0\fP key for HMAC\-SHA\-224
|
||||
and HMAC\-SHA\-256.
|
||||
The \fBHMAC\-SHA\fP key supplied in the plain bytes file is the key \fBK_0\fP as
|
||||
of \fBFIPS\-198\-1\fP, i.e. the key \fBK\fP after any necessary pre\-processing.
|
||||
The pre\-processing must be performed by the user prior to creating the
|
||||
retrievable secret.
|
||||
.PP Pre\-processing means that if the key \fBK\fP is shorter than the block size
|
||||
of the to\-be\-used HMAC digest, then the key must be padded with binary zeros
|
||||
to the right up to the block size. The block size of SHA\-224 and SHA\-256 is
|
||||
512 bits (64 bytes) and the bock size of SHA\-384 and SHA\-512 is 1024 bits (128
|
||||
bytes). Such padding can for example be achieved by using the \fBtruncate\fP
|
||||
command with the desired size in bytes, e.g. \fB'truncate \-\-size 64
|
||||
<key\-file>'\fP for creating a \fBK_0\fP key for HMAC\-SHA\-224 and
|
||||
HMAC\-SHA\-256.
|
||||
.PP
|
||||
In case key \fBK\fP is longer than the block size of the to\-be\-used HMAC
|
||||
digest, then key \fBK\fP must first be hashed with the to\-be\-used HMAC
|
||||
digest, and the result must then be padded with binary zeros to the right up to
|
||||
the block size of the digest. This can be achieved by using the following
|
||||
OpenSSL command followed by the \fBtruncate\fP command: \fB'openssl sha256
|
||||
\-binary \-out <key2\-file> <key\-file>'\fP and then \fB'truncate \-\-size
|
||||
64 <key2\-file>'\fP for creating a \fBK_0\fP key for HMAC\-SHA\-256.
|
||||
digest, then key \fBK\fP must first be hashed with the to\-be\-used HMAC digest,
|
||||
and the result must then be padded with binary zeros to the right up to the
|
||||
block size of the digest. This can be achieved by using the following OpenSSL
|
||||
command followed by the \fBtruncate\fP command: \fB'openssl sha256 \-binary
|
||||
\-out <key2\-file> <key\-file>'\fP and then \fB'truncate \-\-size 64
|
||||
<key2\-file>'\fP for creating a \fBK_0\fP key for HMAC\-SHA\-256.
|
||||
.PP
|
||||
\fBATTENTION:\fP The digest used for hashing the key \fBK\fP must be the exact
|
||||
same as the later to\-be\-used HMAC digest! If the pre\-processing and the
|
||||
HMAC calculation use different digests, then a wrong MAC is calculated!
|
||||
same as the later to\-be\-used HMAC digest! If the pre\-processing and the HMAC
|
||||
calculation use different digests, then a wrong MAC is calculated!
|
||||
.RE
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVSECRET-CREATE-UPDATE-CCK" "1" "2026-02-12" "s390-tools" "UV\-Secret Manual"
|
||||
.TH "PVSECRET-CREATE-UPDATE-CCK" "1" "2026-05-20" "s390-tools" "UV\-Secret Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -18,6 +18,7 @@ pvsecret create cck \-\-secret <CCK\-FILE>
|
||||
.SH DESCRIPTION
|
||||
Insert a customer communication key into a guest.
|
||||
.SH OPTIONS
|
||||
|
||||
.PP
|
||||
\-\-secret <CCK\-FILE>
|
||||
.RS 4
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVSECRET-CREATE" "1" "2026-02-12" "s390-tools" "UV\-Secret Manual"
|
||||
.TH "PVSECRET-CREATE" "1" "2026-05-19" "s390-tools" "UV\-Secret Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -55,6 +55,7 @@ Update customer communication key
|
||||
.RE
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.PP
|
||||
\-k, \-\-host\-key\-document <FILE>
|
||||
.RS 4
|
||||
@@ -196,23 +197,23 @@ Optional. No user\-data by default.
|
||||
.PP
|
||||
\-\-policy <FILE>
|
||||
.RS 4
|
||||
Links an add\-secret request to a policy file.
|
||||
This option embeds a reference to a policy in the add\-secret request user data field. The
|
||||
reference includes the relative file path and the SHA-512 hash of the
|
||||
policy file, enabling verification of the policy file’s integrity.
|
||||
This option conflicts with \fB\-\-user\-data\fR, because both options use the
|
||||
same user data field in the add\-secret request structure.
|
||||
Links an Add‑Secret\-Request (ASR) to a policy file. This option embeds a
|
||||
PolicyReference in the ASR user data field. The PolicyReference includes the
|
||||
relative file path and the SHA‑512 hash of the policy file, allowing the
|
||||
policy’s integrity to be verified.
|
||||
|
||||
This option conflicts with \-\-user\-data, because both options use the same
|
||||
user data field in the ASR structure.
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\-\-toc\-policy <FILE>
|
||||
.RS 4
|
||||
Adds the AES\-GCM authentication tag to a table-of-contents (TOC) policy file.
|
||||
This option appends the AES\-GCM authentication tag to the specified TOC policy
|
||||
file. This allows the TOC policy to maintain a list of all add\-secret request MAC tags for
|
||||
completeness verification during boot. During verification, the TOC checks the
|
||||
AES\-GCM tags against this list to ensure that all expected add\-secret request are present and
|
||||
unmodified.
|
||||
Adds the AES‑GCM authentication tag to a TOC policy file. This option appends
|
||||
the AES‑GCM authentication tag to the specified TOC policy file. This allows
|
||||
the TOC policy to maintain a list of all ASR MAC tags for completeness
|
||||
verification during boot. During verification, the TOC checks the MAC tags
|
||||
against this list to ensure that all expected ASRs are present and unmodified.
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVSECRET-LIST" "1" "2024-12-19" "s390-tools" "UV-Secret Manual"
|
||||
.TH "PVSECRET-LIST" "1" "2026-05-21" "s390-tools" "UV\-Secret Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -11,7 +11,7 @@ pvsecret-list \- List all ultravisor secrets (s390x only)
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.fam C
|
||||
pvsecret list [OPTIONS] [FILE]
|
||||
pvsecret list [OPTIONS] [OUTPUT]
|
||||
.fam C
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
@@ -19,13 +19,18 @@ Lists the IDs of all non\-null secrets currently stored in the ultravisor for
|
||||
the currently running IBM Secure Execution guest. Only available on s390x.
|
||||
.SH OPTIONS
|
||||
.PP
|
||||
<FILE>
|
||||
<OUTPUT>
|
||||
.RS 4
|
||||
Store the result in FILE.
|
||||
[default: '-']
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.PP
|
||||
\-o, \-\-output <FILE>
|
||||
.RS 4
|
||||
Store the result in FILE.
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\-\-format <FORMAT>
|
||||
.RS 4
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVSECRET-RETRIEVE" "1" "2026-02-12" "s390-tools" "UV\-Secret Manual"
|
||||
.TH "PVSECRET-RETRIEVE" "1" "2026-05-21" "s390-tools" "UV\-Secret Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -11,8 +11,8 @@ pvsecret-retrieve \- Retrieve a secret from the UV secret store (s390x only)
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.fam C
|
||||
pvsecret retrieve [OPTIONS] <ID>
|
||||
pvsecret retr [OPTIONS] <ID>
|
||||
pvsecret retrieve [OPTIONS] [INPUT] [OUTPUT]
|
||||
pvsecret retr [OPTIONS] [INPUT] [OUTPUT]
|
||||
.fam C
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
@@ -24,7 +24,7 @@ keys the PEM name \fBIBM PROTECTED KEY\fP is used.
|
||||
|
||||
.SH OPTIONS
|
||||
.PP
|
||||
<ID>
|
||||
<INPUT>
|
||||
.RS 4
|
||||
Specify the secret ID to be retrieved. Input type depends on \fB\-\-inform\fR.
|
||||
If `yaml` (default) is specified, it must be a yaml created by the create
|
||||
@@ -35,12 +35,29 @@ secret is retrieved. Use \-\-inform=idx to make sure a specific secret is
|
||||
retrieved.
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
<OUTPUT>
|
||||
.RS 4
|
||||
Specify the output path to place the secret value.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.PP
|
||||
\-i, \-\-input <ID>
|
||||
.RS 4
|
||||
Specify the secret ID to be retrieved. Input type depends on \fB\-\-inform\fR.
|
||||
If `yaml` (default) is specified, it must be a yaml created by the create
|
||||
subcommand of this tool. If `hex` is specified, it must be a 32 byte handle
|
||||
encodes in hexadecimal. Leading zeros are required. If there are multiple
|
||||
secrets in the store with the same Id there are no guarantees on which specific
|
||||
secret is retrieved. Use \-\-inform=idx to make sure a specific secret is
|
||||
retrieved.
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\-o, \-\-output <FILE>
|
||||
.RS 4
|
||||
Specify the output path to place the secret value.
|
||||
[default: '-']
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVSECRET-VERIFY" "1" "2026-02-12" "s390-tools" "UV\-Secret Manual"
|
||||
.TH "PVSECRET-VERIFY" "1" "2026-05-21" "s390-tools" "UV\-Secret Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -11,7 +11,7 @@ pvsecret-verify \- Verify that an add-secret request is sane
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.fam C
|
||||
pvsecret verify [OPTIONS] <FILE>
|
||||
pvsecret verify [OPTIONS] [INPUT] [OUTPUT]
|
||||
.fam C
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
@@ -81,12 +81,25 @@ verify the signature of the request but the last 16 bytes
|
||||
|
||||
.SH OPTIONS
|
||||
.PP
|
||||
<FILE>
|
||||
<INPUT>
|
||||
.RS 4
|
||||
Specify the request to be checked.
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
<OUTPUT>
|
||||
.RS 4
|
||||
Store the result in FILE If the request contained abirtary user\-data the output
|
||||
contains this user\-data with padded zeros if available.
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.PP
|
||||
\-i, \-\-input <FILE>
|
||||
.RS 4
|
||||
Specify the request to be checked.
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\-\-user\-cert <FILE>
|
||||
.RS 4
|
||||
@@ -100,11 +113,10 @@ curve over a 521 bit prime field (secp521r1).
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
\-o, \-\-output <FILE>
|
||||
\-o, \-\-output <OUTPUT>
|
||||
.RS 4
|
||||
Store the result in FILE If the request contained abirtary user\-data the output
|
||||
contains this user\-data with padded zeros if available.
|
||||
[default: '-']
|
||||
.RE
|
||||
.RE
|
||||
.PP
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
|
||||
.TH "PVSECRET" "1" "2026-02-12" "s390-tools" "UV\-Secret Manual"
|
||||
.TH "PVSECRET" "1" "2026-05-20" "s390-tools" "UV\-Secret Manual"
|
||||
.nh
|
||||
.ad l
|
||||
.SH NAME
|
||||
@@ -76,6 +76,7 @@ Retrieve a secret from the UV secret store (s390x only)
|
||||
.RE
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.PP
|
||||
\-v, \-\-verbose
|
||||
.RS 4
|
||||
|
||||
@@ -6,7 +6,9 @@ use std::fmt::Display;
|
||||
|
||||
use clap::error::ErrorKind::ValueValidation;
|
||||
use clap::{ArgGroup, Args, CommandFactory, Parser, Subcommand, ValueEnum, ValueHint};
|
||||
use utils::{CertificateOptions, DeprecatedVerbosityOptions, STDOUT};
|
||||
use utils::{
|
||||
combined_path_opt, combined_path_req, CertificateOptions, DeprecatedVerbosityOptions, STDOUT,
|
||||
};
|
||||
|
||||
/// Manage secrets for IBM Secure Execution guests.
|
||||
///
|
||||
@@ -292,8 +294,12 @@ impl Display for RetrieveableSecretInpKind {
|
||||
#[derive(Args, Debug)]
|
||||
pub struct AddSecretOpt {
|
||||
/// Specify the request to be sent.
|
||||
#[arg(value_name = "FILE", value_hint = ValueHint::FilePath,)]
|
||||
pub input: String,
|
||||
#[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
|
||||
input: Option<String>,
|
||||
|
||||
/// Specify the request to be sent.
|
||||
#[arg(value_name = "INPUT", value_hint = ValueHint::FilePath, required_unless_present("input"), conflicts_with("input"))]
|
||||
input_pos: Option<String>,
|
||||
|
||||
/// Force the addition of add-secret requests.
|
||||
///
|
||||
@@ -303,6 +309,22 @@ pub struct AddSecretOpt {
|
||||
pub force: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AddSecretOptComb<'a> {
|
||||
pub input: &'a str,
|
||||
pub force: bool,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a AddSecretOpt> for AddSecretOptComb<'a> {
|
||||
fn from(value: &'a AddSecretOpt) -> Self {
|
||||
let input = combined_path_req(&value.input, &value.input_pos);
|
||||
Self {
|
||||
input,
|
||||
force: value.force,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug, Default)]
|
||||
pub enum ListSecretOutputType {
|
||||
/// Human-focused, non-parsable output format
|
||||
@@ -317,19 +339,43 @@ pub enum ListSecretOutputType {
|
||||
#[derive(Args, Debug)]
|
||||
pub struct ListSecretOpt {
|
||||
/// Store the result in FILE
|
||||
#[arg(value_name = "FILE", default_value = STDOUT, value_hint = ValueHint::FilePath,)]
|
||||
pub output: String,
|
||||
#[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
|
||||
output: Option<String>,
|
||||
|
||||
/// Store the result in FILE
|
||||
#[arg(value_name = "OUTPUT", value_hint = ValueHint::FilePath, conflicts_with("output"))]
|
||||
output_pos: Option<String>,
|
||||
|
||||
/// Define the output format of the list.
|
||||
#[arg(long, value_enum, default_value_t)]
|
||||
pub format: ListSecretOutputType,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ListSecretOptComb<'a> {
|
||||
pub output: &'a str,
|
||||
pub format: ListSecretOutputType,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ListSecretOpt> for ListSecretOptComb<'a> {
|
||||
fn from(value: &'a ListSecretOpt) -> Self {
|
||||
let output = combined_path_opt(&value.output, &value.output_pos, STDOUT);
|
||||
Self {
|
||||
output,
|
||||
format: value.format,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
pub struct VerifyOpt {
|
||||
/// Specify the request to be checked.
|
||||
#[arg(value_name = "FILE", value_hint = ValueHint::FilePath,)]
|
||||
pub input: String,
|
||||
#[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath,)]
|
||||
input: Option<String>,
|
||||
|
||||
/// Specify the request to be checked.
|
||||
#[arg(value_name = "INPUT", value_hint = ValueHint::FilePath, required_unless_present("input"), conflicts_with("input"))]
|
||||
input_pos: Option<String>,
|
||||
|
||||
/// Certificate containing a public key used to verify the user data signature.
|
||||
///
|
||||
@@ -345,8 +391,34 @@ pub struct VerifyOpt {
|
||||
///
|
||||
/// If the request contained abirtary user-data the output contains this user-data with padded
|
||||
/// zeros if available.
|
||||
#[arg(short, long, value_name = "FILE", default_value = STDOUT, value_hint = ValueHint::FilePath,)]
|
||||
pub output: String,
|
||||
#[arg(short, long, value_name = "OUTPUT", value_hint = ValueHint::FilePath,)]
|
||||
output: Option<String>,
|
||||
|
||||
/// Store the result in FILE
|
||||
///
|
||||
/// If the request contained abirtary user-data the output contains this user-data with padded
|
||||
/// zeros if available.
|
||||
#[arg(value_name = "OUTPUT", value_hint = ValueHint::FilePath, conflicts_with("output"))]
|
||||
output_pos: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VerifyOptComb<'a> {
|
||||
pub input: &'a str,
|
||||
pub user_cert: Option<&'a str>,
|
||||
pub output: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a VerifyOpt> for VerifyOptComb<'a> {
|
||||
fn from(value: &'a VerifyOpt) -> Self {
|
||||
let input = combined_path_req(&value.input, &value.input_pos);
|
||||
let output = combined_path_opt(&value.output, &value.output_pos, STDOUT);
|
||||
Self {
|
||||
input,
|
||||
user_cert: value.user_cert.as_deref(),
|
||||
output,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
@@ -358,12 +430,26 @@ pub struct RetrSecretOptions {
|
||||
/// handle encodes in hexadecimal. Leading zeros are required. If there are multiple secrets in
|
||||
/// the store with the same Id there are no guarantees on which specific secret is retrieved.
|
||||
/// Use --inform=idx to make sure a specific secret is retrieved.
|
||||
#[arg(value_name = "ID", value_hint = ValueHint::FilePath)]
|
||||
pub input: String,
|
||||
#[arg(short, long, value_name = "ID", value_hint = ValueHint::FilePath)]
|
||||
input: Option<String>,
|
||||
|
||||
/// Specify the secret ID to be retrieved.
|
||||
///
|
||||
/// Input type depends on '--inform'. If `yaml` (default) is specified, it must be a yaml
|
||||
/// created by the create subcommand of this tool. If `hex` is specified, it must be a 32 byte
|
||||
/// handle encodes in hexadecimal. Leading zeros are required. If there are multiple secrets in
|
||||
/// the store with the same Id there are no guarantees on which specific secret is retrieved.
|
||||
/// Use --inform=idx to make sure a specific secret is retrieved.
|
||||
#[arg(value_name = "INPUT", value_hint = ValueHint::FilePath, required_unless_present("input"), conflicts_with("input"))]
|
||||
input_pos: Option<String>,
|
||||
|
||||
/// Specify the output path to place the secret value
|
||||
#[arg(short, long, value_name = "FILE", default_value = STDOUT, value_hint = ValueHint::FilePath)]
|
||||
pub output: String,
|
||||
#[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath)]
|
||||
output: Option<String>,
|
||||
|
||||
/// Specify the output path to place the secret value
|
||||
#[arg(value_name = "OUTPUT", value_hint = ValueHint::FilePath, conflicts_with("output"))]
|
||||
output_pos: Option<String>,
|
||||
|
||||
/// Define input type for the Secret ID
|
||||
#[arg(long, value_enum, default_value_t)]
|
||||
@@ -400,6 +486,25 @@ pub enum RetrOutFmt {
|
||||
Bin,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RetrSecretOptionsComb<'a> {
|
||||
pub input: &'a str,
|
||||
pub output: &'a str,
|
||||
pub inform: RetrInpFmt,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a RetrSecretOptions> for RetrSecretOptionsComb<'a> {
|
||||
fn from(value: &'a RetrSecretOptions) -> Self {
|
||||
let input = combined_path_req(&value.input, &value.input_pos);
|
||||
let output = combined_path_opt(&value.output, &value.output_pos, STDOUT);
|
||||
Self {
|
||||
input,
|
||||
output,
|
||||
inform: value.inform,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
pub enum Command {
|
||||
/// Create a new add-secret request.
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
//
|
||||
// Copyright IBM Corp. 2023
|
||||
|
||||
use crate::{cli::AddSecretOpt, cmd::list::list_uvc};
|
||||
use crate::{
|
||||
cli::{AddSecretOpt, AddSecretOptComb},
|
||||
cmd::list::list_uvc,
|
||||
};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use log::warn;
|
||||
use pv::{
|
||||
@@ -13,15 +16,16 @@ use utils::get_reader_from_cli_file_arg;
|
||||
|
||||
/// Do an Add Secret UVC
|
||||
pub fn add(opt: &AddSecretOpt) -> Result<()> {
|
||||
let opt_comb = AddSecretOptComb::from(opt);
|
||||
let uv = UvDevice::open()?;
|
||||
let mut rd_in = get_reader_from_cli_file_arg(&opt.input)?;
|
||||
let mut rd_in = get_reader_from_cli_file_arg(opt_comb.input)?;
|
||||
let mut cmd =
|
||||
AddCmd::new(&mut rd_in).context(format!("Processing input file {}", opt.input))?;
|
||||
AddCmd::new(&mut rd_in).context(format!("Processing input file {}", opt_comb.input))?;
|
||||
|
||||
if let Some(id) = AddSecretRequest::bin_id(cmd.data().unwrap())? {
|
||||
if list_uvc(&uv)?.iter().any(|e| e.id() == id.as_ref()) {
|
||||
warn!("There is already a secret in the secret store with that id.");
|
||||
match opt.force {
|
||||
match opt_comb.force {
|
||||
true => warn!("'--force' specified: Adding the secret anyways."),
|
||||
false => bail!("Unable to add the secret due to duplicated IDs"),
|
||||
}
|
||||
|
||||
@@ -322,7 +322,7 @@ fn write_yaml<P: AsRef<Path>>(
|
||||
write_out(&yaml_path, secret_info, "secret information")?;
|
||||
warn!(
|
||||
"Successfully wrote secret info to '{}'",
|
||||
yaml_path.display().to_string()
|
||||
yaml_path.display()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
use std::io::ErrorKind;
|
||||
|
||||
use crate::cli::{ListSecretOpt, ListSecretOutputType};
|
||||
use crate::cli::{ListSecretOpt, ListSecretOptComb, ListSecretOutputType};
|
||||
use anyhow::{Context, Error, Result};
|
||||
use log::{info, warn};
|
||||
use pv::uv::{ListCmd, SecretList, UvDevice};
|
||||
@@ -34,11 +34,12 @@ pub fn list_uvc(uv: &UvDevice) -> Result<SecretList> {
|
||||
|
||||
/// Do a List Secrets UVC and output the list in the requested format
|
||||
pub fn list(opt: &ListSecretOpt) -> Result<()> {
|
||||
let opt_comb = ListSecretOptComb::from(opt);
|
||||
let uv = UvDevice::open()?;
|
||||
let secret_list = list_uvc(&uv)?;
|
||||
let mut wr_out = get_writer_from_cli_file_arg(&opt.output)?;
|
||||
let mut wr_out = get_writer_from_cli_file_arg(opt_comb.output)?;
|
||||
|
||||
match &opt.format {
|
||||
match opt_comb.format {
|
||||
ListSecretOutputType::Human => {
|
||||
write!(wr_out, "{secret_list}").context("Cannot generate output")?
|
||||
}
|
||||
@@ -50,10 +51,10 @@ pub fn list(opt: &ListSecretOpt) -> Result<()> {
|
||||
}
|
||||
wr_out.flush()?;
|
||||
|
||||
if opt.output != STDOUT {
|
||||
if opt_comb.output != STDOUT {
|
||||
warn!(
|
||||
"Successfully wrote the list of secrets to '{}'",
|
||||
&opt.output
|
||||
opt_comb.output
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -15,7 +15,7 @@ use pv::{
|
||||
use utils::get_writer_from_cli_file_arg;
|
||||
|
||||
use super::list::list_uvc;
|
||||
use crate::cli::{RetrInpFmt, RetrOutFmt, RetrSecretOptions};
|
||||
use crate::cli::{RetrInpFmt, RetrOutFmt, RetrSecretOptions, RetrSecretOptionsComb};
|
||||
|
||||
enum Value {
|
||||
Id(SecretId),
|
||||
@@ -31,19 +31,19 @@ impl Display for Value {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&RetrSecretOptions> for Value {
|
||||
impl TryFrom<&RetrSecretOptionsComb<'_>> for Value {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(opt: &RetrSecretOptions) -> Result<Self> {
|
||||
fn try_from(opt: &RetrSecretOptionsComb) -> Result<Self> {
|
||||
match opt.inform {
|
||||
RetrInpFmt::Yaml => match serde_yaml::from_reader(&mut open_file(&opt.input)?)? {
|
||||
RetrInpFmt::Yaml => match serde_yaml::from_reader(&mut open_file(opt.input)?)? {
|
||||
GuestSecret::Retrievable { id, .. } => Ok(Self::Id(id)),
|
||||
gs => bail!("The file contains a {gs}-secret, which is not retrievable."),
|
||||
},
|
||||
RetrInpFmt::Hex => serde_yaml::from_str(&opt.input)
|
||||
RetrInpFmt::Hex => serde_yaml::from_str(opt.input)
|
||||
.context("Cannot parse SecretId information")
|
||||
.map(Self::Id),
|
||||
RetrInpFmt::Name => Ok(Self::Id(SecretId::from_string(&opt.input))),
|
||||
RetrInpFmt::Name => Ok(Self::Id(SecretId::from_string(opt.input))),
|
||||
RetrInpFmt::Idx => opt
|
||||
.input
|
||||
.parse()
|
||||
@@ -104,8 +104,9 @@ fn retrieve(value: Value) -> Result<RetrievedSecret> {
|
||||
}
|
||||
|
||||
pub fn retr(opt: &RetrSecretOptions) -> Result<()> {
|
||||
let mut output = get_writer_from_cli_file_arg(&opt.output)?;
|
||||
let retr_secret = retrieve(opt.try_into()?)
|
||||
let opt_comb = RetrSecretOptionsComb::from(opt);
|
||||
let mut output = get_writer_from_cli_file_arg(opt_comb.output)?;
|
||||
let retr_secret = retrieve((&opt_comb).try_into()?)
|
||||
.context("Could not retrieve the secret from the UV secret store.")?;
|
||||
|
||||
let out_data = match opt.outform {
|
||||
@@ -115,7 +116,7 @@ pub fn retr(opt: &RetrSecretOptions) -> Result<()> {
|
||||
write(
|
||||
&mut output,
|
||||
out_data.value(),
|
||||
&opt.output,
|
||||
opt_comb.output,
|
||||
"IBM Protected Key",
|
||||
)?;
|
||||
Ok(())
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// Copyright IBM Corp. 2024
|
||||
|
||||
use crate::cli::VerifyOpt;
|
||||
use crate::cli::{VerifyOpt, VerifyOptComb};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use log::warn;
|
||||
use pv::misc::{read_certs, read_file};
|
||||
@@ -22,16 +22,16 @@ fn read_sgn_key(path: &str) -> Result<PKey<Public>> {
|
||||
}
|
||||
|
||||
pub fn verify(opt: &VerifyOpt) -> Result<()> {
|
||||
let mut rd_in = get_reader_from_cli_file_arg(&opt.input)?;
|
||||
let opt_comb = VerifyOptComb::from(opt);
|
||||
let mut rd_in = get_reader_from_cli_file_arg(opt_comb.input)?;
|
||||
let mut data_in = Vec::with_capacity(0x1000);
|
||||
rd_in
|
||||
.read_to_end(&mut data_in)
|
||||
.with_context(|| format!("Cannot read input file {}", opt.input))?;
|
||||
.with_context(|| format!("Cannot read input file {}", opt_comb.input))?;
|
||||
|
||||
let verify_cert = opt
|
||||
let verify_cert = opt_comb
|
||||
.user_cert
|
||||
.as_ref()
|
||||
.map(|p| read_sgn_key(p))
|
||||
.map(read_sgn_key)
|
||||
.transpose()
|
||||
.context("Cannot read user-verification certificate.")?;
|
||||
|
||||
@@ -39,9 +39,9 @@ pub fn verify(opt: &VerifyOpt) -> Result<()> {
|
||||
.context("Could not verify the the Add-secret request")?;
|
||||
|
||||
if let Some(user_data) = user_data {
|
||||
get_writer_from_cli_file_arg(&opt.output)?
|
||||
get_writer_from_cli_file_arg(opt_comb.output)?
|
||||
.write_all(&user_data)
|
||||
.with_context(|| format!("Cannot write user data to {}", opt.output))?;
|
||||
.with_context(|| format!("Cannot write user data to {}", opt_comb.output))?;
|
||||
}
|
||||
warn!("Successfully verified the request.");
|
||||
Ok(())
|
||||
|
||||
@@ -276,6 +276,29 @@ impl DeprecatedVerbosityOptions {
|
||||
)
|
||||
}
|
||||
}
|
||||
pub fn combined_path_opt<'a, N: AsRef<str>, P: AsRef<str>>(
|
||||
named: &'a Option<N>,
|
||||
positional: &'a Option<P>,
|
||||
default: &'a str,
|
||||
) -> &'a str {
|
||||
match (named, positional) {
|
||||
(None, Some(i)) => i.as_ref(),
|
||||
(Some(i), None) => i.as_ref(),
|
||||
(Some(_), Some(_)) => unreachable!(),
|
||||
(None, None) => default,
|
||||
}
|
||||
}
|
||||
pub fn combined_path_req<'a, N: AsRef<str>, P: AsRef<str>>(
|
||||
named: &'a Option<N>,
|
||||
positional: &'a Option<P>,
|
||||
) -> &'a str {
|
||||
match (named, positional) {
|
||||
(None, Some(i)) => i.as_ref(),
|
||||
(Some(i), None) => i.as_ref(),
|
||||
(Some(_), Some(_)) => unreachable!(),
|
||||
(None, None) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
@@ -16,8 +16,9 @@ pub use ::log::LevelFilter;
|
||||
|
||||
pub use crate::{
|
||||
cli::{
|
||||
get_reader_from_cli_file_arg, get_writer_from_cli_file_arg, print_cli_error, print_error,
|
||||
CertificateOptions, DeprecatedVerbosityOptions, VerbosityOptions, STDIN, STDOUT,
|
||||
combined_path_opt, combined_path_req, get_reader_from_cli_file_arg,
|
||||
get_writer_from_cli_file_arg, print_cli_error, print_error, CertificateOptions,
|
||||
DeprecatedVerbosityOptions, VerbosityOptions, STDIN, STDOUT,
|
||||
},
|
||||
exit_code::{docstring, ExitCodeDoc, ExitCodeTrait, ExitCodeVariantDoc},
|
||||
file::{AtomicFile, AtomicFileOperation},
|
||||
|
||||
@@ -34,6 +34,21 @@ All operations preserve the original base image. Logs are written to a
|
||||
temporary file, with the filename logged as the first message during runtime.
|
||||
Temporary artifacts are automatically cleaned up on completion or failure.
|
||||
|
||||
.SH Base Image Prerequisites
|
||||
The following prerequisites have to be fulfilled by the base image:
|
||||
.IP \(bu 2
|
||||
label of boot partition set to boot
|
||||
.IP \(bu 2
|
||||
label of root partition set to root
|
||||
.IP \(bu 2
|
||||
guest is to be backed by a qcow2 image
|
||||
.IP \(bu 2
|
||||
an initramfs containing the dracut module 95sel-ebc which is part of s390-tools
|
||||
.IP \(bu 2
|
||||
a boot loader specifying that initramfs and a kernel parameter line on which root is specified by label
|
||||
.IP \(bu 2
|
||||
any line starting with default= should be removed from /etc/zipl.conf
|
||||
|
||||
.SH ACTIONS
|
||||
.TP
|
||||
.B list
|
||||
|
||||
@@ -160,6 +160,8 @@ struct job_data {
|
||||
int command_line;
|
||||
int is_secure;
|
||||
int is_ldipl_dump;
|
||||
int no_compress;
|
||||
int force;
|
||||
};
|
||||
|
||||
static inline struct target *target_at(struct job_target_data *data,
|
||||
|
||||
@@ -1548,6 +1548,7 @@ get_job_from_section_data(char* data[], struct job_data* job, char* section)
|
||||
}
|
||||
else
|
||||
job->data.dump.mem = -1LL;
|
||||
job->data.dump.no_compress = job->no_compress;
|
||||
break;
|
||||
case section_mvdump:
|
||||
/* DUMP TO MULTI-VOLUME job */
|
||||
@@ -1570,6 +1571,7 @@ get_job_from_section_data(char* data[], struct job_data* job, char* section)
|
||||
(1024LL * 1024LL));
|
||||
} else
|
||||
job->data.mvdump.mem = -1LL;
|
||||
job->data.mvdump.force = job->force;
|
||||
break;
|
||||
default:
|
||||
/* Should not happen */
|
||||
@@ -2021,8 +2023,8 @@ job_get(int argc, char* argv[], struct job_data** data)
|
||||
job->noninteractive = cmdline.noninteractive;
|
||||
job->verbose = cmdline.verbose;
|
||||
job->add_files = cmdline.add_files;
|
||||
job->data.dump.no_compress = cmdline.no_compress;
|
||||
job->data.mvdump.force = cmdline.force;
|
||||
job->no_compress = cmdline.no_compress;
|
||||
job->force = cmdline.force;
|
||||
job->dry_run = cmdline.dry_run;
|
||||
job->is_secure = SECURE_BOOT_UNDEFINED;
|
||||
job->is_ldipl_dump = cmdline.is_ldipl_dump;
|
||||
|
||||
Reference in New Issue
Block a user