SHA256
1
0
forked from pool/s390-tools
Dominique Leuenberger 2020-12-10 14:56:57 +00:00 committed by Git OBS Bridge
commit 26a26a5a1d
132 changed files with 4345 additions and 26154 deletions

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fd1883e12f9da16be6b081508108abd3ce8cd80168efe4cd339ba33837f8f4aa
size 1164539

3
s390-tools-2.15.1.tar.gz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8dc1180031018756ccd5acf6c26c4175bcac79e512e8a2ea8569fdf5d3f9bd6c
size 1390556

View File

@ -1,436 +0,0 @@
From d6582bbaf0f3986a42f562046dc0caa9de89c75e Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Fri, 6 Oct 2017 08:58:17 +0200
Subject: [PATCH] dasdfmt: Allow multiple device arguments
Allow the user to specify several devices as arguments to dasdfmt.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
dasdfmt/dasdfmt.8 | 5 +-
dasdfmt/dasdfmt.c | 175 ++++++++++++++++++++++++++++++------------------------
2 files changed, 100 insertions(+), 80 deletions(-)
diff --git a/dasdfmt/dasdfmt.8 b/dasdfmt/dasdfmt.8
index 99da9ed..e7fc501 100644
--- a/dasdfmt/dasdfmt.8
+++ b/dasdfmt/dasdfmt.8
@@ -11,14 +11,15 @@ dasdfmt \- formatting of DASD (ECKD) disk drives.
.br
[-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR]
.br
- [-L] [-V] [-F] [-k] [-C] [-M \fImode\fR] \fIdevice\fR
+ [-L] [-V] [-F] [-k] [-C] [-M \fImode\fR] \fIdevice\fR [\fIdevice\fR]
.SH DESCRIPTION
-\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it
+\fBdasdfmt\fR formats one or several DASD (ECKD) disk drive to prepare it
for usage with Linux for S/390.
The \fIdevice\fR is the node of the device (e.g. '/dev/dasda').
Any device node created by udev for kernel 2.6 can be used
(e.g. '/dev/dasd/0.0.b100/disc').
+It is possible to specify up to 512 devices.
.br
\fBWARNING\fR: Careless usage of \fBdasdfmt\fR can result in
diff --git a/dasdfmt/dasdfmt.c b/dasdfmt/dasdfmt.c
index b79cff0..607fd1c 100644
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -23,6 +23,7 @@
#include "dasdfmt.h"
+#define MAX_DEVICES 512
#define BUSIDSIZE 8
#define SEC_PER_DAY (60 * 60 * 24)
#define SEC_PER_HOUR (60 * 60)
@@ -463,44 +464,40 @@ static void program_interrupt_signal(int sig)
/*
* check given device name for blanks and some special characters
*/
-static void get_device_name(char *devname,
- int optind, int argc, char *argv[])
+static void get_device_name(char **devname, int numdev,
+ char argv[])
{
struct util_proc_dev_entry dev_entry;
struct stat dev_stat;
- if (optind + 1 < argc)
- ERRMSG_EXIT(EXIT_MISUSE,
- "%s: More than one device specified!\n", prog_name);
-
- if (optind >= argc)
- ERRMSG_EXIT(EXIT_MISUSE, "%s: No device specified!\n",
- prog_name);
-
- if (strlen(argv[optind]) >= PATH_MAX)
+ if (strlen(argv) >= PATH_MAX)
ERRMSG_EXIT(EXIT_MISUSE, "%s: device name too long!\n",
prog_name);
- strcpy(devname, argv[optind]);
- if (stat(devname, &dev_stat) != 0)
- ERRMSG_EXIT(EXIT_MISUSE, "%s: Could not get information for "
- "device node %s: %s\n", prog_name, devname,
- strerror(errno));
+ devname[numdev] = argv;
+ if (stat(devname[numdev], &dev_stat) != 0)
+ ERRMSG_EXIT(EXIT_MISUSE,
+ "%s: Could not get information for "
+ "device node %s: %s\n", prog_name,
+ devname[numdev], strerror(errno));
if (minor(dev_stat.st_rdev) & PARTN_MASK) {
- ERRMSG_EXIT(EXIT_MISUSE, "%s: Unable to format partition %s. "
+ ERRMSG_EXIT(EXIT_MISUSE,
+ "%s: Unable to format partition %s. "
"Please specify a device.\n", prog_name,
- devname);
+ devname[numdev]);
}
- if (util_proc_dev_get_entry(dev_stat.st_rdev, 1, &dev_entry) == 0) {
+ if (util_proc_dev_get_entry(dev_stat.st_rdev, 1,
+ &dev_entry) == 0) {
if (strncmp(dev_entry.name, "dasd", 4) != 0)
ERRMSG_EXIT(EXIT_MISUSE,
"%s: Unsupported device type '%s'.\n",
prog_name, dev_entry.name);
} else {
- printf("%s WARNING: Unable to get driver name for device node %s",
- prog_name, devname);
+ printf("%s WARNING: Unable to get driver name"
+ " for device node %s",
+ prog_name, devname[numdev]);
}
}
@@ -518,7 +515,7 @@ static void get_blocksize(const char *de
/*
* Check whether a specified blocksize matches the blocksize of the device
*/
-static void check_blocksize(dasdfmt_info_t *info, unsigned int blksize)
+static void check_blocksize(dasdfmt_info_t *info, char *dev_filename, unsigned int blksize)
{
unsigned int dev_blksize;
@@ -756,7 +753,7 @@ static void check_hashmarks(dasdfmt_info
* This function checks whether a range of tracks is in regular format
* with the specified block size.
*/
-static format_check_t check_track_format(dasdfmt_info_t *info, format_data_t *p)
+static format_check_t check_track_format(dasdfmt_info_t *info, char *dev_filename, format_data_t *p)
{
format_check_t cdata = {
.expect = {
@@ -812,7 +809,7 @@ static int process_tracks(dasdfmt_info_t
step.stop_unit = cur_trk + step_value - 1;
if (info->check) {
- cdata = check_track_format(info, &step);
+ cdata = check_track_format(info, dev_filename, &step);
if (cdata.result) {
cyl = cur_trk / heads + 1;
draw_progress(info, cyl, cylinders, 1);
@@ -858,7 +855,7 @@ static void check_disk_format(dasdfmt_in
return;
}
- check_blocksize(info, check_params->blksize);
+ check_blocksize(info, dev_filename, check_params->blksize);
check_layout(info, check_params->intensity);
/*
@@ -1188,7 +1185,7 @@ static void dasdfmt_write_labels(dasdfmt
* that the device is formatted to a certain extent. Otherwise the
* process is terminated.
*/
-static void dasdfmt_find_start(dasdfmt_info_t *info, unsigned int cylinders,
+static void dasdfmt_find_start(dasdfmt_info_t *info, char *dev_filename, unsigned int cylinders,
unsigned heads, format_data_t *format_params)
{
format_check_t cdata;
@@ -1197,11 +1194,11 @@ static void dasdfmt_find_start(dasdfmt_i
unsigned int right = (cylinders * heads) - 1;
unsigned int first = left;
- check_blocksize(info, format_params->blksize);
+ check_blocksize(info, dev_filename, format_params->blksize);
format_params->start_unit = 0;
format_params->stop_unit = 4;
- cdata = check_track_format(info, format_params);
+ cdata = check_track_format(info, dev_filename, format_params);
if (cdata.result) {
evaluate_format_error(info, &cdata, heads);
@@ -1217,7 +1214,7 @@ static void dasdfmt_find_start(dasdfmt_i
format_params->start_unit = middle;
format_params->stop_unit = middle;
- cdata = check_track_format(info, format_params);
+ cdata = check_track_format(info, dev_filename, format_params);
if (cdata.blksize != format_params->blksize) {
first = middle;
right = middle - 1;
@@ -1266,6 +1263,7 @@ static void dasdfmt_release_space(dasdfm
}
static void dasdfmt_prepare_and_format(dasdfmt_info_t *info,
+ char *dev_filename,
unsigned int cylinders,
unsigned int heads, format_data_t *p)
{
@@ -1324,7 +1322,7 @@ static void dasdfmt_prepare_and_format(d
/*
* This function will start the expand format process.
*/
-static void dasdfmt_expand_format(dasdfmt_info_t *info, unsigned int cylinders,
+static void dasdfmt_expand_format(dasdfmt_info_t *info, char *dev_filename, unsigned int cylinders,
unsigned int heads, format_data_t *p)
{
if (!(info->withoutprompt && (info->verbosity < 1)))
@@ -1351,7 +1349,7 @@ static void dasdfmt_expand_format(dasdfm
* This function will only format the first two tracks of a DASD.
* The rest of the DASD is untouched and left as is.
*/
-static void dasdfmt_quick_format(dasdfmt_info_t *info, unsigned int cylinders,
+static void dasdfmt_quick_format(dasdfmt_info_t *info, char *dev_filename, unsigned int cylinders,
unsigned int heads, format_data_t *p)
{
format_check_t cdata = { .expect = {0}, 0 };
@@ -1363,18 +1361,18 @@ static void dasdfmt_quick_format(dasdfmt
} else if (info->ese) {
printf("Skipping format check due to thin-provisioned device.\n");
} else {
- check_blocksize(info, p->blksize);
+ check_blocksize(info, dev_filename, p->blksize);
printf("Checking the format of selected tracks...\n");
/* Check device format on the first and last 3 regular tracks */
tmp.start_unit = 2;
tmp.stop_unit = 4;
- cdata = check_track_format(info, &tmp);
+ cdata = check_track_format(info, dev_filename, &tmp);
if (!cdata.result) {
tmp.start_unit = (cylinders * heads) - 3;
tmp.stop_unit = (cylinders * heads) - 1;
- cdata = check_track_format(info, &tmp);
+ cdata = check_track_format(info, dev_filename, &tmp);
}
if (cdata.result) {
evaluate_format_error(info, &cdata, heads);
@@ -1419,7 +1417,7 @@ static void do_format_dasd(dasdfmt_info_
p->stop_unit = 1;
break;
case EXPAND: /* only the end of the disk */
- dasdfmt_find_start(info, cylinders, heads, p);
+ dasdfmt_find_start(info, devname, cylinders, heads, p);
p->stop_unit = (cylinders * heads) - 1;
break;
}
@@ -1468,24 +1466,24 @@ static void do_format_dasd(dasdfmt_info_
switch (mode) {
case FULL:
- dasdfmt_prepare_and_format(info, cylinders, heads, p);
+ dasdfmt_prepare_and_format(info, devname, cylinders, heads, p);
break;
case QUICK:
dasdfmt_release_space(info);
- dasdfmt_quick_format(info, cylinders, heads, p);
+ dasdfmt_quick_format(info, devname, cylinders, heads, p);
break;
case EXPAND:
- dasdfmt_expand_format(info, cylinders, heads, p);
+ dasdfmt_expand_format(info, devname, cylinders, heads, p);
break;
}
printf("Finished formatting the device.\n");
if (!(info->writenolabel || mode == EXPAND))
- dasdfmt_write_labels(info, vlabel, cylinders, heads);
+ dasdfmt_write_labels(info, devname, vlabel, cylinders, heads);
printf("Rereading the partition table... ");
- err = dasd_reread_partition_table(dev_filename, 5);
+ err = dasd_reread_partition_table(devname, 5);
if (err != 0) {
ERRMSG("%s: error during rereading the partition "
"table: %s.\n", prog_name, strerror(err));
@@ -1508,23 +1506,88 @@ static void do_format_dasd(dasdfmt_info_t *info, char *devname,
mode = info->ese ? QUICK : FULL;
}
+void do_dasdfmt(char *dev_filename, dasdfmt_info_t info,
+ volume_label_t *orig_vlabel, format_data_t format_params)
+{
+ volume_label_t vlabel;
+ char old_volser[7];
+ char str[ERR_LENGTH];
+ unsigned int cylinders, heads; int rc;
+
+ filedes = open(dev_filename, O_RDWR);
+ if (filedes == -1)
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
+ prog_name, dev_filename, strerror(errno));
+ close(filedes);
+
+ rc = dasd_get_info(dev_filename, &info.dasd_info);
+ if (rc != 0)
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl call to retrieve "
+ "device information for %s failed (%s).\n",
+ prog_name, dev_filename, strerror(rc));
+
+ memcpy(&vlabel, orig_vlabel, sizeof(vlabel));
+ /* Either let the user specify the blksize or get it from the kernel */
+ if (!info.blksize_specified) {
+ if (!(mode == FULL ||
+ info.dasd_info.format == DASD_FORMAT_NONE)
+ || info.check)
+ get_blocksize(dev_filename, &format_params.blksize);
+ else
+ format_params = ask_user_for_blksize(format_params);
+ }
+
+ if (info.keep_volser) {
+ if (info.labelspec) {
+ ERRMSG_EXIT(EXIT_MISUSE, "%s: The -k and -l options "
+ "are mutually exclusive\n", prog_name);
+ }
+ if (!(format_params.intensity & DASD_FMT_INT_COMPAT)) {
+ printf("WARNING: VOLSER cannot be kept "
+ "when using the ldl format!\n");
+ exit(1);
+ }
+
+ if (dasdfmt_get_volser(dev_filename,
+ &info.dasd_info, old_volser) == 0)
+ vtoc_volume_label_set_volser(&vlabel, old_volser);
+ else
+ ERRMSG_EXIT(EXIT_FAILURE,
+ "%s: VOLSER not found on device %s\n",
+ prog_name, dev_filename);
+ }
+
+ check_disk(&info, dev_filename);
+
+ if (check_param(str, ERR_LENGTH, &format_params) < 0)
+ ERRMSG_EXIT(EXIT_MISUSE, "%s: %s\n", prog_name, str);
+
+ set_geo(&info, &cylinders, &heads);
+ set_label(&info, &vlabel, &format_params, cylinders);
+
+ if (info.check)
+ check_disk_format(&info, cylinders, heads, &format_params);
+ else
+ do_format_dasd(&info, dev_filename, &vlabel,
+ &format_params, cylinders, heads);
+
+}
+
int main(int argc, char *argv[])
{
dasdfmt_info_t info = {
.dasd_info = {0},
};
volume_label_t vlabel;
- char old_volser[7];
- char str[ERR_LENGTH];
+ char *dev_filename[MAX_DEVICES];
char buf[7];
char *blksize_param_str = NULL;
char *reqsize_param_str = NULL;
char *hashstep_str = NULL;
- int rc;
- unsigned int cylinders, heads;
+ int rc, numdev = 0, i;
/* Establish a handler for interrupt signals. */
signal(SIGTERM, program_interrupt_signal);
@@ -1686,59 +1751,24 @@ int main(int argc, char *argv[])
if (info.print_hashmarks)
PARSE_PARAM_INTO(info.hashstep, hashstep_str, 10, "hashstep");
- get_device_name(dev_filename, optind, argc, argv);
-
- rc = dasd_get_info(dev_filename, &info.dasd_info);
- if (rc != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl call to retrieve "
- "device information failed (%s).\n",
- prog_name, strerror(rc));
-
- info.ese = dasd_sys_ese(dev_filename);
- eval_format_mode(&info);
-
- /* Either let the user specify the blksize or get it from the kernel */
- if (!info.blksize_specified) {
- if (!(mode == FULL ||
- info.dasd_info.format == DASD_FORMAT_NONE) || info.check)
- get_blocksize(dev_filename, &format_params.blksize);
- else
- format_params = ask_user_for_blksize(format_params);
- }
-
- if (info.keep_volser) {
- if (info.labelspec) {
- ERRMSG_EXIT(EXIT_MISUSE, "%s: The -k and -l options "
- "are mutually exclusive\n", prog_name);
- }
- if (!(format_params.intensity & DASD_FMT_INT_COMPAT)) {
- printf("WARNING: VOLSER cannot be kept "
- "when using the ldl format!\n");
- exit(1);
- }
-
- if (dasdfmt_get_volser(dev_filename,
- &info.dasd_info, old_volser) == 0)
- vtoc_volume_label_set_volser(&vlabel, old_volser);
- else
- ERRMSG_EXIT(EXIT_FAILURE,
- "%s: VOLSER not found on device %s\n",
- prog_name, dev_filename);
+ while (optind < argc) {
+ if (optind >= argc)
+ ERRMSG_EXIT(EXIT_MISUSE, "%s: No device specified!\n",
+ prog_name);
+
+ info.ese = dasd_sys_ese(dev_filename[numdev]);
+ eval_format_mode(&info);
+
+ get_device_name(dev_filename, numdev, argv[optind]);
+ optind++;
+ numdev++;
}
- check_disk(&info, dev_filename);
-
- if (check_param(str, ERR_LENGTH, &format_params) < 0)
- ERRMSG_EXIT(EXIT_MISUSE, "%s: %s\n", prog_name, str);
-
- set_geo(&info, &cylinders, &heads);
- set_label(&info, &vlabel, &format_params, cylinders);
-
- if (info.check)
- check_disk_format(&info, cylinders, heads, &format_params);
- else
- do_format_dasd(&info, dev_filename, &vlabel,
- &format_params, cylinders, heads);
+ if (!numdev)
+ ERRMSG_EXIT(EXIT_MISUSE, "%s: No device specified!\n",
+ prog_name);
+ for (i = 0; i < numdev; i++)
+ do_dasdfmt(dev_filename[i], info, &vlabel, format_params);
return 0;
}
--
1.7.12.4

View File

@ -1,21 +1,6 @@
From c261ec990a8259f2540089827309b918e1c31590 Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Fri, 22 Nov 2013 15:34:22 +0100
Subject: [PATCH] dumpconf: Use compatible sysconfig layout
SUSE is quite restrictive on how the sysconfig
should look like.
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
etc/sysconfig/dumpconf | 134 ++++++++++++++++++++++++++++++++++---------------
1 file changed, 93 insertions(+), 41 deletions(-)
diff --git a/etc/sysconfig/dumpconf b/etc/sysconfig/dumpconf
index a3639cf..76f9040 100644
--- a/etc/sysconfig/dumpconf
+++ b/etc/sysconfig/dumpconf
@@ -1,61 +1,113 @@
--- a/etc/sysconfig/dumpconf 2020-10-15 09:56:15.000000000 -0400
+++ b/etc/sysconfig/dumpconf 2020-10-27 18:47:23.267333389 -0400
@@ -1,71 +1,137 @@
+## Path: System/Dumpconf
+## Description: Configures the actions which should be performed after a kernel panic
+## Type: list(stop,dump,vmcmd,reipl,dump_reipl)
@ -26,7 +11,7 @@ index a3639cf..76f9040 100644
-#
-# Configures the actions which should be performed after a kernel panic
-# and on PSW restart.
+# Define the action that should be taken if a panic happens.
+# Define the action that should be taken if a kernel panic happens.
#
# The following actions are supported:
#
@ -67,16 +52,16 @@ index a3639cf..76f9040 100644
-# Dump on CCW device (DASD) and re-IPL after dump is complete.
-# The re-IPL device, as specified under "/sys/firmware/reipl", is used.
-# The activation of dumpconf is delayed by 5 minutes.
+## Type: list(ccw,fcp)
+## Type: list(ccw,fcp,nvme)
+## Default: ""
+## ServiceRestart: dumpconf
+#
+# Define the type, ccw for DASD and fcp for zFCP.
#
-# ON_PANIC=dump_reipl
-# DUMP_TYPE=ccw
-# DEVICE=0.0.4e13
-# DELAY_MINUTES=5
+# Define the type, ccw for DASD, fcp for zFCP, or nvme for NVMe Disk.
+#
+DUMP_TYPE=""
+## Type: string
@ -100,68 +85,99 @@ index a3639cf..76f9040 100644
+## Type: string
+## Default: ""
+## ServiceRestart: dumpconf
+#
#
-# Dump on nvme device (NVMe Disk)
+# Define the WWPN for a zFCP dump device.
#
-# Use VMDUMP
-# ON_PANIC=dump
-# DUMP_TYPE=nvme
-# FID=0x00000300
-# NSID=0x00000001
-# BOOTPROG=3
-# BR_LBA=0
+# For example: WWPN=0x5005076303004711
#
-# ON_PANIC=vmcmd
-# VMCMD_1="MESSAGE * Starting VMDUMP"
-# VMCMD_2="VMDUMP"
-# VMCMD_3="IPL 4711"
+#
+WWPN=""
+## Type: string
+## Default: ""
+## ServiceRestart: dumpconf
+#
#
-# Use VMDUMP
+# Define the LUN for a zFCP dump device.
+#
#
-# ON_PANIC=vmcmd
-# VMCMD_1="MESSAGE * Starting VMDUMP"
-# VMCMD_2="VMDUMP"
-# VMCMD_3="IPL 4711"
+# For example: LUN=0x4711000000000000
+#
+LUN=""
+
+## Type: integer(0:30)
+## Default: "0"
+## ServiceRestart: dumpconf
+#
#
-# Stop Linux (default)
+# Define the Boot program selector for a zFCP dump device.
+#
#
-# ON_PANIC=stop
+# A decimal value between 0 and 30 specifying the program to be loaded from
+# the FCP-I/O device.
+#
+BOOTPROG="0"
+
+## Type: string
+## Default: "0"
+## ServiceRestart: dumpconf
+#
+# Define the Boot record logical block address for a zFCP dump device.
#
-# Stop Linux (default)
+# The hexadecimal digits designating the logical-block address of the boot record of the FCP-I/O device.
+# It must be a value from 0-FFFFFFFF FFFFFFFF. For values longer than 8 hex characters at least one separator
+# blank is required after the 8th character.
#
-# ON_PANIC=stop
+BR_LBA="0"
+## Type: string
+## Default: ""
+## Default: "0"
+## ServiceRestart: dumpconf
#
-# Re-IPL Linux
-# The re-IPL device, as specified under "/sys/firmware/reipl", is used.
-# Since the DELAY_MINUTES keyword is omitted, there is no delay and
-# dumpconf becomes active immediately during system startup.
+# Define the Boot record logical block address for a zFCP dump device.
#
-# ON_PANIC=reipl
+# The hexadecimal digits designating the logical-block address of the boot record of the FCP-I/O device.
+# It must be a value from 0-FFFFFFFF FFFFFFFF. For values longer than 8 hex characters at least one separator
+# blank is required after the 8th character.
+#
+BR_LBA="0"
+
+## Type: string
+## Default: ""
+## ServiceRestart: dumpconf
+#
+# Define the Function ID for NVMe dump device.
+#
+# The hexadecimal digits designating the Function ID for the NMVe disk.
+#
+# For example: FID=0x00000300
+#
+FID=""
+
+## Type: string
+## Default: ""
+## ServiceRestart: dumpconf
+#
+# Define the Namespace ID for the NVMe dump device
+#
+# The hexadecimal digits designating the Namespace ID for the NMVe disk.
+#
+# For example: NSID=0x00000001
+#
+NSID=""
+
+## Type: string
+## Default: ""
+## ServiceRestart: dumpconf
+#
+# VMCMD_<X>
+# Specifies a CP command, <X> is a number from one to eight. You can
+# specify up to eight CP commands that are executed in case of a kernel
+# panic. Note that VM commands, device adresses, and VM guest names
+# must be uppercase.
#
-# ON_PANIC=reipl
+#
+VMCMD_1=""
+VMCMD_2=""
+VMCMD_3=""
@ -170,6 +186,3 @@ index a3639cf..76f9040 100644
+VMCMD_6=""
+VMCMD_7=""
+VMCMD_8=""
--
1.8.1.4

View File

@ -1,11 +0,0 @@
--- a/zdev/dracut/95zdev/module-setup.sh 2019-01-10 11:39:08.000000000 -0500
+++ b/zdev/dracut/95zdev/module-setup.sh 2019-01-14 13:28:33.983461097 -0500
@@ -32,7 +32,7 @@
installkernel() {
# Add modules for all device types supported by chzdev (required for
# auto-configuration)
- instmods lcs qeth qeth_l2 qeth_l3 dasd_mod dasd_eckd_mod dasd_fba_mod \
+ instmods ctcm lcs qeth qeth_l2 qeth_l3 dasd_mod dasd_eckd_mod dasd_fba_mod \
dasd_diag_mod zfcp
}

View File

@ -1,442 +0,0 @@
Subject: [PATCH] [BZ 184585] cpumf/data: Add new deflate counters for IBM z15
From: Thomas Richter <tmricht@linux.ibm.com>
Description: lscpumf: New z15 CPU-MF counters not available
Symptom: Command lscpumf -c does not show the new
deflate counters on IBM z15.
Problem: The new counter names have not been published
in document SA23-2261-06 by the time te code was
release.
Solution: Add the definition for the new deflate counters.
Reproduction: Run command lscpumf -c and check for counters
rf7, rfc, r107 and r108.
Upstream-ID: 5d2871d626de6c2b3ab6b12783b87a8b3564cb56
Problem-ID: 184585
Upstream-Description:
cpumf/data: Add new deflate counters for IBM z15
Add support for new deflate counters:
- Counter 247: cycles CPU spent obtaining access to Deflate unit
- Counter 252: cycles CPU is using Deflate unit
- Counter 264: Increments by one for every DEFLATE CONVERSION CALL
instruction executed.
- Counter 265: Increments by one for every DEFLATE CONVERSION CALL
instruction executed that ended in Condition Codes
0, 1 or 2.
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
---
cpumf/Makefile | 3
cpumf/data/cpum-cf-extended-z15.ctr | 376 ++++++++++++++++++++++++++++++++++++
cpumf/data/cpum-cf-hw-counter.map | 5
3 files changed, 380 insertions(+), 4 deletions(-)
--- a/cpumf/Makefile
+++ b/cpumf/Makefile
@@ -9,7 +9,8 @@ DATA_FILES = cpum-cf-hw-counter.map \
cpum-cf-csvn-12345.ctr cpum-cf-csvn-6.ctr \
cpum-cf-extended-z10.ctr cpum-cf-extended-z196.ctr \
cpum-cf-extended-zEC12.ctr cpum-sf-modes.ctr \
- cpum-cf-extended-z13.ctr cpum-cf-extended-z14.ctr
+ cpum-cf-extended-z13.ctr cpum-cf-extended-z14.ctr \
+ cpum-cf-extended-z15.ctr
LIB_FILES = bin/cpumf_helper
USRBIN_SCRIPTS = bin/lscpumf
USRSBIN_SCRIPTS = bin/chcpumf
--- /dev/null
+++ b/cpumf/data/cpum-cf-extended-z15.ctr
@@ -0,0 +1,376 @@
+# Counter decriptions for the
+# IBM z14 extended counter and MT-diagnostic counter set
+#
+# Notes for transactional-execution mode symbolic names:
+# TX .. transactional-execution mode
+# NC .. nonconstrained
+# C .. constrained
+#
+# Undefined counters in the extended counter set:
+# 142
+# 158-161
+# 176-223
+# 227-231
+# 233-242
+# 246-255
+# Undefined counters in the MT-diagnostic counter set:
+# 450-495
+#
+#
+# Extended Counter Set
+# ---------------------------------------------------------------------
+Counter:128 Name:L1D_RO_EXCL_WRITES
+Short-Description:L1D Read-only Exclusive Writes
+Description:
+A directory write to the Level-1 Data cache where the line was
+originally in a Read-Only state in the cache but has been updated
+to be in the Exclusive state that allows stores to the cache line
+.
+Counter:129 Name:DTLB2_WRITES
+Short-Description:DTLB2 Writes
+Description:
+A translation has been written into The Translation Lookaside
+Buffer 2 (TLB2) and the request was made by the data cache
+.
+Counter:130 Name:DTLB2_MISSES
+Short-Description:DTLB2 Misses
+Description:
+A TLB2 miss is in progress for a request made by the data cache.
+Incremented by one for every TLB2 miss in progress for the Level-1
+Data cache on this cycle
+.
+Counter:131 Name:DTLB2_HPAGE_WRITES
+Short-Description:DTLB2 One-Megabyte Page Writes
+Description:
+A translation entry was written into the Combined Region and Segment
+Table Entry array in the Level-2 TLB for a one-megabyte page
+.
+Counter:132 Name:DTLB2_GPAGE_WRITES
+Short-Description:DTLB2 Two-Gigabyte Page Writes
+Description:
+A translation entry for a two-gigabyte page was written into the
+Level-2 TLB
+.
+Counter:133 Name:L1D_L2D_SOURCED_WRITES
+Short-Description:L1D L2D Sourced Writes
+Description:
+A directory write to the Level-1 Data cache directory where the
+returned cache line was sourced from the Level-2 Data cache
+.
+Counter:134 Name:ITLB2_WRITES
+Short-Description:ITLB2 Writes
+Description:
+A translation entry has been written into the Translation Lookaside
+Buffer 2 (TLB2) and the request was made by the instruction cache
+.
+Counter:135 Name:ITLB2_MISSES
+Short-Description:ITLB2 Misses
+Description:
+A TLB2 miss is in progress for a request made by the instruction cache.
+Incremented by one for every TLB2 miss in progress for the Level-1
+Instruction cache in a cycle
+.
+Counter:136 Name:L1I_L2I_SOURCED_WRITES
+Short-Description:L1I L2I Sourced Writes
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache line was sourced from the Level-2 Instruction cache
+.
+Counter:137 Name:TLB2_PTE_WRITES
+Short-Description:TLB2 PTE Writes
+Description:
+A translation entry was written into the Page Table Entry array in the
+Level-2 TLB
+.
+Counter:138 Name:TLB2_CRSTE_WRITES
+Short-Description:TLB2 CRSTE Writes
+Description:
+Translation entries were written into the Combined Region and Segment
+Table Entry array and the Page Table Entry array in the Level-2 TLB
+.
+Counter:139 Name:TLB2_ENGINES_BUSY
+Short-Description:TLB2 Engines Busy
+Description:
+The number of Level-2 TLB translation engines busy in a cycle
+.
+Counter:140 Name:TX_C_TEND
+Short-Description:Completed TEND instructions in constrained TX mode
+Description:
+A TEND instruction has completed in a constrained transactional-execution
+mode
+.
+Counter:141 Name:TX_NC_TEND
+Short-Description:Completed TEND instructions in non-constrained TX mode
+Description:
+A TEND instruction has completed in a non-constrained
+transactional-execution mode
+.
+Counter:143 Name:L1C_TLB2_MISSES
+Short-Description:L1C TLB2 Misses
+Description:
+Increments by one for any cycle where a level-1 cache or level-2 TLB miss
+is in progress
+.
+Counter:144 Name:L1D_ONCHIP_L3_SOURCED_WRITES
+Short-Description:L1D On-Chip L3 Sourced Writes
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from an On-Chip Level-3 cache without intervention
+.
+Counter:145 Name:L1D_ONCHIP_MEMORY_SOURCED_WRITES
+Short-Description:L1D On-Chip Memory Sourced Writes
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from On-Chip memory
+.
+Counter:146 Name:L1D_ONCHIP_L3_SOURCED_WRITES_IV
+Short-Description:L1D On-Chip L3 Sourced Writes with Intervention
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from an On-Chip Level-3 cache with intervention
+.
+Counter:147 Name:L1D_ONCLUSTER_L3_SOURCED_WRITES
+Short-Description:L1D On-Cluster L3 Sourced Writes
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from On-Cluster Level-3 cache withountervention
+.
+Counter:148 Name:L1D_ONCLUSTER_MEMORY_SOURCED_WRITES
+Short-Description:L1D On-Cluster Memory Sourced Writes
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from an On-Cluster memory
+.
+Counter:149 Name:L1D_ONCLUSTER_L3_SOURCED_WRITES_IV
+Short-Description:L1D On-Cluster L3 Sourced Writes with Intervention
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from an On-Cluster Level-3 cache with intervention
+.
+Counter:150 Name:L1D_OFFCLUSTER_L3_SOURCED_WRITES
+Short-Description:L1D Off-Cluster L3 Sourced Writes
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from an Off-Cluster Level-3 cache without
+intervention
+.
+Counter:151 Name:L1D_OFFCLUSTER_MEMORY_SOURCED_WRITES
+Short-Description:L1D Off-Cluster Memory Sourced Writes
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from Off-Cluster memory
+.
+Counter:152 Name:L1D_OFFCLUSTER_L3_SOURCED_WRITES_IV
+Short-Description:L1D Off-Cluster L3 Sourced Writes with Intervention
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from an Off-Cluster Level-3 cache with intervention
+.
+Counter:153 Name:L1D_OFFDRAWER_L3_SOURCED_WRITES
+Short-Description:L1D Off-Drawer L3 Sourced Writes
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from an Off-Drawer Level-3 cache without
+intervention
+.
+Counter:154 Name:L1D_OFFDRAWER_MEMORY_SOURCED_WRITES
+Short-Description:L1D Off-Drawer Memory Sourced Writes
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from Off-Drawer memory
+.
+Counter:155 Name:L1D_OFFDRAWER_L3_SOURCED_WRITES_IV
+Short-Description:L1D Off-Drawer L3 Sourced Writes with Intervention
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from an Off-Drawer Level-3 cache with intervention
+.
+Counter:156 Name:L1D_ONDRAWER_L4_SOURCED_WRITES
+Short-Description:L1D On-Drawer L4 Sourced Writes
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from On-Drawer Level-4 cache
+.
+Counter:157 Name:L1D_OFFDRAWER_L4_SOURCED_WRITES
+Short-Description:L1D Off-Drawer L4 Sourced Writes
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from Off-Drawer Level-4 cache
+.
+Counter:158 Name:L1D_ONCHIP_L3_SOURCED_WRITES_RO
+Short-Description:L1D On-Chip L3 Sourced Writes read-only
+Description:
+A directory write to the Level-1 Data cache directory where the returned
+cache line was sourced from On-Chip L3 but a read-only invalidate was
+done to remove other copies of the cache line
+.
+Counter:162 Name:L1I_ONCHIP_L3_SOURCED_WRITES
+Short-Description:L1I On-Chip L3 Sourced Writes
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache ine was sourced from an On-Chip Level-3 cache without
+intervention
+.
+Counter:163 Name:L1I_ONCHIP_MEMORY_SOURCED_WRITES
+Short-Description:L1I On-Chip Memory Sourced Writes
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache ine was sourced from On-Chip memory
+.
+Counter:164 Name:L1I_ONCHIP_L3_SOURCED_WRITES_IV
+Short-Description:L1I On-Chip L3 Sourced Writes with Intervention
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache ine was sourced from an On-Chip Level-3 cache with
+intervention
+.
+Counter:165 Name:L1I_ONCLUSTER_L3_SOURCED_WRITES
+Short-Description:L1I On-Cluster L3 Sourced Writes
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache line was sourced from an On-Cluster Level-3 cache without
+intervention
+.
+Counter:166 Name:L1I_ONCLUSTER_MEMORY_SOURCED_WRITES
+Short-Description:L1I On-Cluster Memory Sourced Writes
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache line was sourced from an On-Cluster memory
+.
+Counter:167 Name:L1I_ONCLUSTER_L3_SOURCED_WRITES_IV
+Short-Description:L1I On-Cluster L3 Sourced Writes with Intervention
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache line was sourced from On-Cluster Level-3 cache with
+intervention
+.
+Counter:168 Name:L1I_OFFCLUSTER_L3_SOURCED_WRITES
+Short-Description:L1I Off-Cluster L3 Sourced Writes
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache line was sourced from an Off-Cluster Level-3 cache without
+intervention
+.
+Counter:169 Name:L1I_OFFCLUSTER_MEMORY_SOURCED_WRITES
+Short-Description:L1I Off-Cluster Memory Sourced Writes
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache line was sourced from Off-Cluster memory
+.
+Counter:170 Name:L1I_OFFCLUSTER_L3_SOURCED_WRITES_IV
+Short-Description:L1I Off-Cluster L3 Sourced Writes with Intervention
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache line was sourced from an Off-Cluster Level-3 cache with
+intervention
+.
+Counter:171 Name:L1I_OFFDRAWER_L3_SOURCED_WRITES
+Short-Description:L1I Off-Drawer L3 Sourced Writes
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache line was sourced from an Off-Drawer Level-3 cache without
+intervention
+.
+Counter:172 Name:L1I_OFFDRAWER_MEMORY_SOURCED_WRITES
+Short-Description:L1I Off-Drawer Memory Sourced Writes
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache line was sourced from Off-Drawer memory
+.
+Counter:173 Name:L1I_OFFDRAWER_L3_SOURCED_WRITES_IV
+Short-Description:L1I Off-Drawer L3 Sourced Writes with Intervention
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache line was sourced from an Off-Drawer Level-3 cache with
+intervention
+.
+Counter:174 Name:L1I_ONDRAWER_L4_SOURCED_WRITES
+Short-Description:L1I On-Drawer L4 Sourced Writes
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache line was sourced from On-Drawer Level-4 cache
+.
+Counter:175 Name:L1I_OFFDRAWER_L4_SOURCED_WRITES
+Short-Description:L1I Off-Drawer L4 Sourced Writes
+Description:
+A directory write to the Level-1 Instruction cache directory where the
+returned cache line was sourced from Off-Drawer Level-4 cache
+.
+Counter:224 Name:BCD_DFP_EXECUTION_SLOTS
+Short-Description:BCD DFP Execution Slots
+Description:
+Count of floating point execution slots used for finished Binary Coded
+Decimal to Decimal Floating Point conversions. Instructions: CDZT,
+CXZT, CZDT, CZXT
+.
+Counter:225 Name:VX_BCD_EXECUTION_SLOTS
+Short-Description:VX BCD Execution Slots
+Description:
+Count of floating point execution slots used for finished vector arithmetic
+Binary Coded Decimal instructions. Instructions: VAP, VSP, VMPVMSP, VDP,
+VSDP, VRP, VLIP, VSRP, VPSOPVCP, VTP, VPKZ, VUPKZ, VCVB, VCVBG, VCVDVCVDG
+.
+Counter:226 Name:DECIMAL_INSTRUCTIONS
+Short-Description:Decimal Instructions
+Description:
+Decimal instructions dispatched. Instructions: CVB, CVD, AP, CP, DP, ED,
+EDMK, MP, SRP, SP, ZAP
+.
+Counter:232 Name:LAST_HOST_TRANSLATIONS
+Short-Description:Last host translation done
+Description:
+Last Host Translation done
+.
+Counter:243 Name:TX_NC_TABORT
+Short-Description:Aborted transactions in non-constrained TX mode
+Description:
+A transaction abort has occurred in a non-constrained
+transactional-execution mode
+.
+Counter:244 Name:TX_C_TABORT_NO_SPECIAL
+Short-Description:Aborted transactions in constrained TX mode not using special completion logic
+Description:
+A transaction abort has occurred in a constrained transactional-execution
+mode and the CPU is not using any special logic to allow the transaction
+to complete
+.
+Counter:245 Name:TX_C_TABORT_SPECIAL
+Short-Description:Aborted transactions in constrained TX mode using special completion logic
+Description:
+A transaction abort has occurred in a constrained transactional-execution
+mode and the CPU is using special logic to allow the transaction to
+complete
+.
+Counter:247 Name:DFLT_ACCESS
+Short-Description:Cycles CPU spent obtaining access to Deflate unit
+Description:
+Cycles CPU spent obtaining access to Deflate unit
+.
+Counter:252 Name:DFLT_CYCLES
+Short-Description:Cycles CPU is using Deflate unit
+Description:
+Cycles CPU is using Deflate unit
+.
+Counter:264 Name:DFLT_CC
+Short-Description:Increments by one for every DEFLATE CONVERSION CALL instruction executed
+Description:
+Increments by one for every DEFLATE CONVERSION CALL instruction executed
+.
+Counter:265 Name:DFLT_CCERROR
+Short-Description:Increments by one for every DEFLATE CONVERSION CALL instruction executed that ended in Condition Codes 0, 1 or 2
+Description:
+Increments by one for every DEFLATE CONVERSION CALL instruction executed that ended in Condition Codes 0, 1 or 2
+.
+#
+# MT-diagnostic counter set
+# ---------------------------------------------------------------------
+Counter:448 Name:MT_DIAG_CYCLES_ONE_THR_ACTIVE
+Short-Description:Cycle count with one thread active
+Description:
+Cycle count with one thread active
+.
+Counter:449 Name:MT_DIAG_CYCLES_TWO_THR_ACTIVE
+Short-Description:Cycle count with two threads active
+Description:
+Cycle count with two threads active
+.
--- a/cpumf/data/cpum-cf-hw-counter.map
+++ b/cpumf/data/cpum-cf-hw-counter.map
@@ -28,7 +28,6 @@
2965 => 'cpum-cf-extended-z13.ctr',
3906 => 'cpum-cf-extended-z14.ctr',
3907 => 'cpum-cf-extended-z14.ctr',
- # Identical with z14
- 8561 => 'cpum-cf-extended-z14.ctr',
- 8562 => 'cpum-cf-extended-z14.ctr',
+ 8561 => 'cpum-cf-extended-z15.ctr',
+ 8562 => 'cpum-cf-extended-z15.ctr',
};

View File

@ -1,63 +0,0 @@
Subject: [PATCH] [BZ 184396] zipl: Add missing options to help output
From: Stefan Haberland <sth@linux.ibm.com>
Description: zipl: fix secure boot config handling
Symptom: The config file parsing for secure boot worked not as
it was expected to be. For example a config section
setting was not evaluated properly.
It is not possible to specify command line option -S
without other options.
Additionally the man page showed an invalid example.
Problem: The config file parsing was not implemented properly.
Solution: The hierarchy of the secure boot settings in the config
file is:
defaultboot > menu > section
Allow that --secure or -S is specified on command line
without the need to allow all options on the command
line. Also ensure that the command line option
overrules the config option and correctly ensure that
secure boot is only set for SCSI devices.
Fix man page example.
Reproduction: Run zipl with a secure= setting in a configuration
section or specify -S on command line.
Upstream-ID: dcce14923c3e9615df53773d1d8a3a22cbb23b96
Problem-ID: 184396
Upstream-Description:
zipl: Add missing options to help output
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
---
zipl/src/zipl.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
--- a/zipl/src/zipl.c
+++ b/zipl/src/zipl.c
@@ -68,6 +68,8 @@ static const char* usage_text[] = {
"-P, --parameters PARMLINE Use specified kernel PARMLINE",
"-T, --tape TAPEDEV Install bootloader on tape device TAPEDEV",
"-s, --segment SEGMENT,ADDR Install a segment from file SEGMENT",
+"-k, --kdump=auto Install a kdump kernel that can be used as a",
+" stand-alone dump tool",
"-d, --dumpto DUMPDEV[,SIZE] Install a system dump record on tape device",
" or disk partition DUMPDEV",
"-M, --mvdump DEVLIST[,SIZE] Install a multi-volume dump record on each",
@@ -78,7 +80,12 @@ static const char* usage_text[] = {
"-n, --noninteractive Answer all confirmation questions with 'yes'",
"-V, --verbose Provide more verbose output",
"-a, --add-files Add all referenced files to bootmap file",
-" --dry-run Simulate run but don't modify IPL records"
+" --dry-run Simulate run but don't modify IPL records",
+"-S, --secure SWITCH Control the zIPL secure boot support.",
+" auto (default):",
+" Write signatures if available and supported",
+" 1: Write signatures regardless of support",
+" 0: Do not write signatures"
};

View File

@ -1,45 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: fix -Wdiscarded-qualifiers
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: bbc46edaf53c2c148b5c94a2414f6847f67f856a
Problem-ID: VS1804
Upstream-Description:
zipl: fix -Wdiscarded-qualifiers
Reported by GCC 9.2.1 when building with '-Wdiscarded-qualifiers'.
job.c: In function 'get_job_from_config_file':
job.c:1810:14: warning: assignment discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/src/job.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/zipl/src/job.c
+++ b/zipl/src/job.c
@@ -1796,7 +1796,7 @@ get_job_from_config_file(struct command_
{
struct scan_token* scan;
struct scan_token* new_scan;
- char* filename;
+ const char *filename;
char *blsdir;
char* source;
int rc, scan_size;

View File

@ -1,319 +0,0 @@
Subject: [PATCH] [BZ 184060] zipl/libc: Introduce vsnprintf
From: Philipp Rudo <prudo@linux.ibm.com>
Description: zipl/libc: Fix potential buffer overflow in printf
Symptom: Crash of the zipl boot loader during boot.
Problem: The zipl boot loaders have their own minimalistic libc
implementation. In it printf and sprintf use vsprintf for string
formatting. Per definition vsprintf assumes that the buffer it
writes to is large enough to contain the formatted string and
performs no size checks. This is problematic for the boot
loaders because the buffer they use are often allocated on the
stack. Thus even small changes to the string format can
potentially cause buffer overflows on the stack.
Solution: Implement vsnprintf and make use of it.
Reproduction: Use printf to print a string with >81 characters (exact number
depends on the stack layout/compiler used).
Upstream-ID: 6fe9e6c55c69c14971dca55551009f5060418aae
Problem-ID: 184060
Upstream-Description:
zipl/libc: Introduce vsnprintf
The zipl boot loaders have their own minimalistic libc implementation.
In it printf and sprintf use vsprintf for string formatting. Per
definition vsprintf assumes that the buffer it writes to is large enough
to contain the formatted string and performs no size checks. This is
problematic for the boot loaders because the buffer they use are often
allocated on the stack. Thus even small changes to the string format can
potentially cause buffer overflows on the stack with the well known
consequences. Protect against such errors by implementing vsnprintf.
Later patches will make use of it.
This implementation of vsnprintf only supports a small subset of format
options defined in the C standard. In particular it allows the
specifiers:
* %s (strings)
* %o (unsigned int octal)
* %u (unsigned int decimal)
* %x (unsigned int hexadecimal)
Integer specifiers (o, u, and x) always use the long form, i.e. assume the
argument to be of type 'unsigned long int'. The length modified 'l' can
be given but is ignored.
Furthermore, it is possible to provide the optional field width (aligned
to the right only) and precision as decimal integer (i.e. not via '*')
as well as the flag for zero padding integers (i.e. '0').
The implementation was heavily inspired by the implementation in
lib/vsprintf.c from the Linux kernel tree.
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
---
zipl/boot/libc.c | 248 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 248 insertions(+)
--- a/zipl/boot/libc.c
+++ b/zipl/boot/libc.c
@@ -218,6 +218,254 @@ unsigned long ebcstrtoul(char *nptr, cha
return val;
}
+static int skip_atoi(const char **c)
+{
+ int i = 0;
+
+ do {
+ i = i*10 + *((*c)++) - '0';
+ } while (isdigit(**c));
+
+ return i;
+}
+
+enum format_type {
+ FORMAT_TYPE_NONE,
+ FORMAT_TYPE_STR,
+ FORMAT_TYPE_ULONG,
+};
+
+struct printf_spec {
+ unsigned int type:8; /* format_type enum */
+ signed int field_width:24; /* width of output field */
+ unsigned int zeropad:1; /* pad numbers with zero */
+ unsigned int base:8; /* number base, 8, 10 or 16 only */
+ signed int precision:16; /* # of digits/chars */
+};
+
+#define FIELD_WIDTH_MAX ((1 << 23) - 1)
+
+static int format_decode(const char *fmt, struct printf_spec *spec)
+{
+ const char *start = fmt;
+
+ spec->type = FORMAT_TYPE_NONE;
+ while (*fmt) {
+ if (*fmt == '%')
+ break;
+ fmt++;
+ }
+
+ /* return current non-format string */
+ if (fmt != start || !*fmt)
+ return fmt - start;
+
+ /* first char is '%', skip it */
+ fmt++;
+ if (*fmt == '0') {
+ spec->zeropad = 1;
+ fmt++;
+ }
+
+ spec->field_width = -1;
+ if (isdigit(*fmt))
+ spec->field_width = skip_atoi(&fmt);
+
+ spec->precision = -1;
+ if (*fmt == '.') {
+ fmt++;
+ if (isdigit(*fmt))
+ spec->precision = skip_atoi(&fmt);
+ }
+
+ /* always use long form, i.e. ignore long qualifier */
+ if (*fmt == 'l')
+ fmt++;
+
+ switch (*fmt) {
+ case 's':
+ spec->type = FORMAT_TYPE_STR;
+ break;
+
+ case 'o':
+ spec->base = 8;
+ spec->type = FORMAT_TYPE_ULONG;
+ break;
+
+ case 'u':
+ spec->base = 10;
+ spec->type = FORMAT_TYPE_ULONG;
+ break;
+
+ case 'x':
+ spec->base = 16;
+ spec->type = FORMAT_TYPE_ULONG;
+ break;
+
+ default:
+ libc_stop(EINTERNAL);
+ }
+
+ return ++fmt - start;
+}
+
+static char *string(char *buf, char *end, const char *s,
+ struct printf_spec *spec)
+{
+ int limit = spec->precision;
+ int len = 0;
+ int spaces;
+
+ /* Copy string to buffer */
+ while (limit--) {
+ char c = *s++;
+ if (!c)
+ break;
+ if (buf < end)
+ *buf = c;
+ buf++;
+ len++;
+ }
+
+ /* right align if necessary */
+ if (len < spec->field_width && buf < end) {
+ spaces = spec->field_width - len;
+ if (spaces >= end - buf)
+ spaces = end - buf;
+ memmove(buf + spaces, buf, len);
+ memset(buf, ' ', spaces);
+ buf += spaces;
+ }
+
+ return buf;
+}
+
+static char *number(char *buf, char *end, unsigned long val,
+ struct printf_spec *spec)
+{
+ /* temporary buffer to prepare the string.
+ * Worst case: base = 8 -> 3 bits per char -> 2.67 chars per byte */
+ char tmp[3 * sizeof(val)];
+ static const char vec[] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ int field_width = spec->field_width;
+ int precision = spec->precision;
+ int len;
+
+ /* prepare string in reverse order */
+ len = 0;
+ while (val) {
+ tmp[len++] = vec[val % spec->base];
+ val /= spec->base;
+ }
+
+ if (len > precision)
+ precision = len;
+
+ field_width -= precision;
+ while (field_width-- > 0) {
+ char c = spec->zeropad ? '0' : ' ';
+ if (buf < end)
+ *buf = c;
+ buf++;
+ }
+
+ /* needed if no field width but a precision is given */
+ while (len < precision--) {
+ if (buf < end)
+ *buf = '0';
+ buf++;
+ }
+
+ while (len-- > 0) {
+ if (buf < end)
+ *buf = tmp[len];
+ buf++;
+ }
+
+ return buf;
+}
+
+/*
+ * vsnprintf - Format string and place in a buffer
+ *
+ * This funcion only supports a subset of format options defined in the
+ * C standard, i.e.
+ * specifiers:
+ * * %s (strings)
+ * * %o (unsigned int octal)
+ * * %u (unsigned int decimal)
+ * * %x (unsigned int hexadecimal)
+ *
+ * length modifier:
+ * * 'l' (ignored, see below)
+ *
+ * flag:
+ * * '0' (zero padding for integers)
+ *
+ * precision and field width as integers, i.e. _not_ by asterix '*'.
+ *
+ * The integer specifiers (o, u and, x) always use the long form, i.e.
+ * assume the argument to be of type 'unsigned long int'.
+ *
+ * Returns the number of characters the function would have generated for
+ * the given input (excluding the trailing '\0'. If the return value is
+ * greater than or equal @size the resulting string is trunctuated.
+ */
+static int vsnprintf(char *buf, unsigned long size, const char *fmt,
+ va_list args)
+{
+ struct printf_spec spec = {0};
+ char *str, *end;
+
+ str = buf;
+ end = buf + size;
+
+ /* use negative (large positive) buffer sizes as indication for
+ * unknown/unlimited buffer sizes. */
+ if (end < buf) {
+ end = ((void *)-1);
+ size = end - buf;
+ }
+
+ while (*fmt) {
+ const char *old_fmt = fmt;
+ int read = format_decode(fmt, &spec);
+ int copy;
+
+ fmt += read;
+
+ switch (spec.type) {
+ case FORMAT_TYPE_NONE:
+ copy = read;
+ if (str < end) {
+ if (copy > end - str)
+ copy = end - str;
+ memcpy(str, old_fmt, copy);
+ }
+ str += read;
+ break;
+
+ case FORMAT_TYPE_STR:
+ str = string(str, end, va_arg(args, char *), &spec);
+ break;
+
+ case FORMAT_TYPE_ULONG:
+ str = number(str, end, va_arg(args, unsigned long),
+ &spec);
+ break;
+ }
+ }
+
+ if (size) {
+ if (str < end)
+ *str = '\0';
+ else
+ end[-1] = '\0';
+ }
+ return str - buf;
+}
+
/*
* Convert string to number with given base
*/

View File

@ -1,72 +0,0 @@
Subject: [PATCH] [BZ 186940] zipl/libc: libc_stop move 'noreturn' to declaration
From: Stefan Haberland <sth@linux.ibm.com>
Description: zipl: Fix KVM IPL without bootindex
Symptom: Failed IPL on KVM when no bootindex is specified.
Problem: Without bootindex specified there is no IPL parmblock
on KVM which can be read by the stage3 loader.
Solution: In case diag308 gives a response code 0x102 the stage3
loader can safely assume that no secure IPL is required
since no IPL report block exists.
Reproduction: IPL on KVM without 'bootindex=' attached.
Upstream-ID: c9066bf5497300db5e0ba11bf111683ea225d8c8
Problem-ID: 186940
Upstream-Description:
zipl/libc: libc_stop move 'noreturn' to declaration
Commit 86856f98dbe3 ("zipl: Make use of __noreturn macro") moved the
'noreturn' attribute from declaration to definition. With this the
compiler can no longer optimize when the function is called in a
separate source file. Move the attribute back to the declaration
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
---
zipl/boot/libc.c | 3 +--
zipl/boot/libc.h | 4 +++-
2 files changed, 4 insertions(+), 3 deletions(-)
--- a/zipl/boot/libc.c
+++ b/zipl/boot/libc.c
@@ -13,7 +13,6 @@
#include <stdarg.h>
-#include "lib/zt_common.h"
#include "boot/s390.h"
#include "error.h"
@@ -501,7 +500,7 @@ void initialize(void)
/*
* Load disabled wait PSW with reason code in address field
*/
-void __noreturn libc_stop(unsigned long reason)
+void libc_stop(unsigned long reason)
{
struct psw_t psw;
--- a/zipl/boot/libc.h
+++ b/zipl/boot/libc.h
@@ -15,6 +15,8 @@
#define NULL ((void *) 0)
+#include "lib/zt_common.h"
+
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
@@ -56,7 +58,7 @@ char *strcpy(char *, const char *);
unsigned long get_zeroed_page(void);
void free_page(unsigned long);
void initialize(void);
-void libc_stop(unsigned long);
+void libc_stop(unsigned long) __noreturn;
void start(void);
void pgm_check_handler(void);
void pgm_check_handler_fn(void);

View File

@ -1,795 +0,0 @@
Subject: zkey: Separate and rework CCA host library loading
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: 95c7258ea783c5bd6aa12fc0e3d5fbe65647af03
Problem-ID: SEC1916
Upstream-Description:
zkey: Separate and rework CCA host library loading
As preparation for future changes, rework the loading of the
CCA host library so that the exported symbols are not passed
individually to the functions that use it. Pass a structure
that contains all entry points of all loaded CCA functions
instead. This will make it easier to add further CCA functions
at a later time.
Also add a version query for the CCA host library since some
future functions might be dependent on the library version.
While at it, separate the CCA related functions and definitions,
and move them into a separate source file (cca.h/cca.h).
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/Makefile | 11 +-
zkey/cca.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++
zkey/cca.h | 54 ++++++++++++
zkey/keystore.c | 26 ++---
zkey/keystore.h | 3
zkey/pkey.c | 142 --------------------------------
zkey/pkey.h | 17 ---
zkey/zkey-cryptsetup.c | 15 +--
zkey/zkey.c | 19 +---
9 files changed, 306 insertions(+), 196 deletions(-)
--- a/zkey/Makefile
+++ b/zkey/Makefile
@@ -64,18 +64,19 @@ zkey-cryptsetup-skip-jsonc:
all: $(BUILD_TARGETS)
-zkey.o: zkey.c pkey.h misc.h
+zkey.o: zkey.c pkey.h cca.h misc.h
pkey.o: pkey.c pkey.h
+cca.o: cca.c cca.h pkey.h
properties.o: check-dep-zkey properties.c properties.h
-keystore.o: keystore.c keystore.h properties.h
-zkey-cryptsetup.o: check-dep-zkey-cryptsetup zkey-cryptsetup.c pkey.h misc.h
+keystore.o: keystore.c keystore.h properties.h pkey.h cca.h
+zkey-cryptsetup.o: check-dep-zkey-cryptsetup zkey-cryptsetup.c pkey.h cca.h misc.h
zkey: LDLIBS = -ldl -lcrypto
-zkey: zkey.o pkey.o properties.o keystore.o $(libs)
+zkey: zkey.o pkey.o cca.o properties.o keystore.o $(libs)
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
zkey-cryptsetup: LDLIBS = -ldl -lcryptsetup -ljson-c
-zkey-cryptsetup: zkey-cryptsetup.o pkey.o $(libs)
+zkey-cryptsetup: zkey-cryptsetup.o pkey.o cca.o $(libs)
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
install-common:
--- /dev/null
+++ b/zkey/cca.c
@@ -0,0 +1,215 @@
+/*
+ * zkey - Generate, re-encipher, and validate secure keys
+ *
+ * Copyright IBM Corp. 2019
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <dlfcn.h>
+#include <err.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "lib/util_panic.h"
+
+#include "cca.h"
+#include "pkey.h"
+
+#define pr_verbose(verbose, fmt...) do { \
+ if (verbose) \
+ warnx(fmt); \
+ } while (0)
+
+/*
+ * Definitions for the CCA library
+ */
+#define CCA_LIBRARY_NAME "libcsulcca.so"
+#define CCA_WEB_PAGE "http://www.ibm.com/security/cryptocards"
+
+/**
+ * Prints CCA return and reason code information for certain known CCA
+ * error situations.
+ *
+ * @param return_code the CCA return code
+ * @param reason_code the CCA reason code
+ */
+static void print_CCA_error(int return_code, int reason_code)
+{
+ switch (return_code) {
+ case 8:
+ switch (reason_code) {
+ case 48:
+ warnx("The secure key has a CCA master key "
+ "verification pattern that is not valid");
+ break;
+ }
+ break;
+ case 12:
+ switch (reason_code) {
+ case 764:
+ warnx("The CCA master key is not loaded and "
+ "therefore a secure key cannot be enciphered");
+ break;
+ }
+ break;
+ }
+}
+
+/**
+ * Returns the version, release and modification number of the used CCA library.
+ *
+ * @param[in] cca the CCA library structure
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error
+ */
+static int get_cca_version(struct cca_lib *cca, bool verbose)
+{
+ unsigned char exit_data[4] = { 0, };
+ unsigned char version_data[20];
+ long return_code, reason_code;
+ long version_data_length;
+ long exit_data_len = 0;
+ char date[20];
+
+ util_assert(cca != NULL, "Internal error: cca is NULL");
+
+ memset(version_data, 0, sizeof(version_data));
+ version_data_length = sizeof(version_data);
+ cca->dll_CSUACFV(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &version_data_length, version_data);
+ pr_verbose(verbose, "CSUACFV (Cryptographic Facility Version) "
+ "returned: return_code: %ld, reason_code: %ld", return_code,
+ reason_code);
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -EIO;
+ }
+
+ version_data[sizeof(version_data) - 1] = '\0';
+ pr_verbose(verbose, "CCA Version string: %s", version_data);
+
+ if (sscanf((char *)version_data, "%u.%u.%uz%s", &cca->version.ver,
+ &cca->version.rel, &cca->version.mod, date) != 4) {
+ warnx("CCA library version is invalid: %s", version_data);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * Loads the CCA library and provides the entry point of the CSNBKTC function.
+ *
+ * @param[out] cca on return this contains the address of the CCA
+ * library and certain CCA symbols. dlclose() should
+ * be used to free the library when no longer needed.
+ * @param verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, -ELIBACC in case of library load errors
+ */
+int load_cca_library(struct cca_lib *cca, bool verbose)
+{
+ util_assert(cca != NULL, "Internal error: caa is NULL");
+
+ /* Load the CCA library */
+ cca->lib_csulcca = dlopen(CCA_LIBRARY_NAME, RTLD_GLOBAL | RTLD_NOW);
+ if (cca->lib_csulcca == NULL) {
+ pr_verbose(verbose, "%s", dlerror());
+ warnx("The command requires the IBM CCA Host Libraries and "
+ "Tools.\nFor the supported environments and downloads, "
+ "see:\n%s", CCA_WEB_PAGE);
+ return -ELIBACC;
+ }
+
+ /* Get the Cryptographic Facility Version function */
+ cca->dll_CSUACFV = (t_CSUACFV)dlsym(cca->lib_csulcca, "CSUACFV");
+
+ /* Get the Key Token Change function */
+ cca->dll_CSNBKTC = (t_CSNBKTC)dlsym(cca->lib_csulcca, "CSNBKTC");
+
+ if (cca->dll_CSUACFV == NULL ||
+ cca->dll_CSNBKTC == NULL) {
+ pr_verbose(verbose, "%s", dlerror());
+ warnx("The command requires the IBM CCA Host Libraries and "
+ "Tools.\nFor the supported environments and downloads, "
+ "see:\n%s", CCA_WEB_PAGE);
+ dlclose(cca->lib_csulcca);
+ cca->lib_csulcca = NULL;
+ return -ELIBACC;
+ }
+
+ pr_verbose(verbose, "CCA library '%s' has been loaded successfully",
+ CCA_LIBRARY_NAME);
+
+ return get_cca_version(cca, verbose);
+}
+
+/**
+ * Re-enciphers a secure key.
+ *
+ * @param[in] cca the CCA libraray structure
+ * @param[in] secure_key a buffer containing the secure key
+ * @param[in] secure_key_size the size of the secure key
+ * @param[in] method the re-enciphering method. METHOD_OLD_TO_CURRENT
+ * or METHOD_CURRENT_TO_NEW.
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, -EIO in case of an error
+ */
+int key_token_change(struct cca_lib *cca,
+ u8 *secure_key, unsigned int secure_key_size,
+ char *method, bool verbose)
+{
+ long exit_data_len = 0, rule_array_count;
+ unsigned char rule_array[2 * 8] = { 0, };
+ unsigned char exit_data[4] = { 0, };
+ long return_code, reason_code;
+
+ util_assert(cca != NULL, "Internal error: cca is NULL");
+ util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
+ util_assert(secure_key_size > 0,
+ "Internal error: secure_key_size is 0");
+ util_assert(method != NULL, "Internal error: method is NULL");
+
+ memcpy(rule_array, method, 8);
+ memcpy(rule_array + 8, "AES ", 8);
+ rule_array_count = 2;
+
+ cca->dll_CSNBKTC(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ secure_key);
+
+ pr_verbose(verbose, "CSNBKTC (Key Token Change) with '%s' returned: "
+ "return_code: %ld, reason_code: %ld", method, return_code,
+ reason_code);
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -EIO;
+ }
+
+ if (secure_key_size == 2 * SECURE_KEY_SIZE) {
+ cca->dll_CSNBKTC(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ secure_key + SECURE_KEY_SIZE);
+
+ pr_verbose(verbose, "CSNBKTC (Key Token Change) with '%s' "
+ "returned: return_code: %ld, reason_code: %ld",
+ method, return_code, reason_code);
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -EIO;
+ }
+ }
+ return 0;
+}
--- /dev/null
+++ b/zkey/cca.h
@@ -0,0 +1,54 @@
+/*
+ * zkey - Generate, re-encipher, and validate secure keys
+ *
+ * This header file defines the interface to the CCA host library.
+ *
+ * Copyright IBM Corp. 2019
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef CCA_H
+#define CCA_H
+
+#include "lib/zt_common.h"
+
+#define METHOD_OLD_TO_CURRENT "RTCMK "
+#define METHOD_CURRENT_TO_NEW "RTNMK "
+
+typedef void (*t_CSNBKTC)(long *return_code,
+ long *reason_code,
+ long *exit_data_length,
+ unsigned char *exit_data,
+ long *rule_array_count,
+ unsigned char *rule_array,
+ unsigned char *key_identifier);
+
+typedef void (*t_CSUACFV)(long *return_code,
+ long *reason_code,
+ long *exit_data_length,
+ unsigned char *exit_data,
+ long *version_data_length,
+ unsigned char *version_data);
+
+struct cca_version {
+ unsigned int ver;
+ unsigned int rel;
+ unsigned int mod;
+};
+
+struct cca_lib {
+ void *lib_csulcca;
+ t_CSNBKTC dll_CSNBKTC;
+ t_CSUACFV dll_CSUACFV;
+ struct cca_version version;
+};
+
+int load_cca_library(struct cca_lib *cca, bool verbose);
+
+int key_token_change(struct cca_lib *cca,
+ u8 *secure_key, unsigned int secure_key_size,
+ char *method, bool verbose);
+
+#endif
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -33,6 +33,7 @@
#include "keystore.h"
#include "pkey.h"
+#include "cca.h"
#include "properties.h"
struct key_filenames {
@@ -2522,7 +2523,7 @@ struct reencipher_params {
struct reencipher_info {
struct reencipher_params params;
int pkey_fd;
- t_CSNBKTC dll_CSNBKTC;
+ struct cca_lib *cca;
unsigned long num_reenciphered;
unsigned long num_failed;
unsigned long num_skipped;
@@ -2533,7 +2534,7 @@ struct reencipher_info {
*
* @param[in] keystore the keystore
* @param[in] name the name of the key
- * @param[in] dll_CSNBKTC the CCA key token change function
+ * @param[in] cca the CCA library struct
* @param[in] params reenciphering parameters
* @param[in] secure_key a buffer containing the secure key
* @param[in] secure_key_size the size of the secure key
@@ -2544,7 +2545,7 @@ struct reencipher_info {
*/
static int _keystore_perform_reencipher(struct keystore *keystore,
const char *name,
- t_CSNBKTC dll_CSNBKTC,
+ struct cca_lib *cca,
struct reencipher_params *params,
u8 *secure_key, size_t secure_key_size,
bool is_old_mk)
@@ -2584,8 +2585,7 @@ static int _keystore_perform_reencipher(
"Secure key '%s' will be re-enciphered from OLD "
"to the CURRENT CCA master key", name);
- rc = key_token_change(dll_CSNBKTC,
- secure_key, secure_key_size,
+ rc = key_token_change(cca, secure_key, secure_key_size,
METHOD_OLD_TO_CURRENT,
keystore->verbose);
if (rc != 0) {
@@ -2602,8 +2602,7 @@ static int _keystore_perform_reencipher(
if (params->inplace == -1)
params->inplace = 0;
- rc = key_token_change(dll_CSNBKTC,
- secure_key, secure_key_size,
+ rc = key_token_change(cca, secure_key, secure_key_size,
METHOD_CURRENT_TO_NEW,
keystore->verbose);
if (rc != 0) {
@@ -2696,10 +2695,9 @@ static int _keystore_process_reencipher(
if (!params.complete) {
printf("Re-enciphering key '%s'\n", name);
- rc = _keystore_perform_reencipher(keystore, name,
- info->dll_CSNBKTC, &params,
- secure_key, secure_key_size,
- is_old_mk);
+ rc = _keystore_perform_reencipher(keystore, name, info->cca,
+ &params, secure_key,
+ secure_key_size, is_old_mk);
if (rc < 0)
goto out;
if (rc > 0) {
@@ -2802,6 +2800,8 @@ out:
* @param[in] inplace if true, the key will be re-enciphere in-place
* @param[in] staged if true, the key will be re-enciphere not in-place
* @param[in] complete if true, a pending re-encipherment is completed
+ * @param[in] pkey_fd the file descriptor of /dev/pkey
+ * @param[in] cca the CCA library struct
* Note: if both from Old and toNew are FALSE, then the reencipherement mode is
* detected automatically. If both are TRUE then the key is reenciphered
* from the OLD to the NEW CCA master key.
@@ -2814,7 +2814,7 @@ int keystore_reencipher_key(struct keyst
const char *apqn_filter,
bool from_old, bool to_new, bool inplace,
bool staged, bool complete, int pkey_fd,
- t_CSNBKTC dll_CSNBKTC)
+ struct cca_lib *cca)
{
struct reencipher_info info;
int rc;
@@ -2830,7 +2830,7 @@ int keystore_reencipher_key(struct keyst
info.params.inplace = 0;
info.params.complete = complete;
info.pkey_fd = pkey_fd;
- info.dll_CSNBKTC = dll_CSNBKTC;
+ info.cca = cca;
info.num_failed = 0;
info.num_reenciphered = 0;
info.num_skipped = 0;
--- a/zkey/keystore.h
+++ b/zkey/keystore.h
@@ -14,6 +14,7 @@
#include <stdbool.h>
+#include "cca.h"
#include "pkey.h"
struct keystore {
@@ -54,7 +55,7 @@ int keystore_reencipher_key(struct keyst
const char *apqn_filter,
bool from_old, bool to_new, bool inplace,
bool staged, bool complete, int pkey_fd,
- t_CSNBKTC dll_CSNBKTC);
+ struct cca_lib *cca);
int keystore_copy_key(struct keystore *keystore, const char *name,
const char *newname, const char *volumes);
--- a/zkey/pkey.c
+++ b/zkey/pkey.c
@@ -44,57 +44,7 @@
#define MAX_CIPHER_LEN 32
-/*
- * Definitions for the CCA library
- */
-#define CCA_LIBRARY_NAME "libcsulcca.so"
-#define CCA_WEB_PAGE "http://www.ibm.com/security/cryptocards"
-
-#define DEFAULT_KEYBITS 256
-
-/**
- * Loads the CCA library and provides the entry point of the CSNBKTC function.
- *
- * @param[out] lib_csulcca on return this contains the address of the CCA
- * library. dlclose() should be used to free this
- * when no longer needed.
- * @param[out] dll_CSNBKTC on return this contains the address of the
- * CSNBKTC function.
- * @param verbose if true, verbose messages are printed
- *
- * @returns 0 on success, -ELIBACC in case of library load errors
- */
-int load_cca_library(void **lib_csulcca, t_CSNBKTC *dll_CSNBKTC, bool verbose)
-{
- util_assert(lib_csulcca != NULL, "Internal error: lib_csulcca is NULL");
- util_assert(dll_CSNBKTC != NULL, "Internal error: dll_CSNBKTC is NULL");
-
- /* Load the CCA library */
- *lib_csulcca = dlopen(CCA_LIBRARY_NAME, RTLD_GLOBAL | RTLD_NOW);
- if (*lib_csulcca == NULL) {
- pr_verbose(verbose, "%s", dlerror());
- warnx("The command requires the IBM CCA Host Libraries and "
- "Tools.\nFor the supported environments and downloads, "
- "see:\n%s", CCA_WEB_PAGE);
- return -ELIBACC;
- }
-
- /* Get the Key Token Change function */
- *dll_CSNBKTC = (t_CSNBKTC)dlsym(*lib_csulcca, "CSNBKTC");
- if (*dll_CSNBKTC == NULL) {
- pr_verbose(verbose, "%s", dlerror());
- warnx("The command requires the IBM CCA Host Libraries and "
- "Tools.\nFor the supported environments and downloads, "
- "see:\n%s", CCA_WEB_PAGE);
- dlclose(*lib_csulcca);
- *lib_csulcca = NULL;
- return -ELIBACC;
- }
-
- pr_verbose(verbose, "CCA library '%s' has been loaded successfully",
- CCA_LIBRARY_NAME);
- return 0;
-}
+#define DEFAULT_KEYBITS 256
/**
* Opens the pkey device and returns its file descriptor.
@@ -523,96 +473,6 @@ out:
}
/**
- * Prints CCA return and reason code information for certain known CCA
- * error situations.
- *
- * @param return_code the CCA return code
- * @param reason_code the CCA reason code
- */
-static void print_CCA_error(int return_code, int reason_code)
-{
- switch (return_code) {
- case 8:
- switch (reason_code) {
- case 48:
- warnx("The secure key has a CCA master key "
- "verification pattern that is not valid");
- break;
- }
- break;
- case 12:
- switch (reason_code) {
- case 764:
- warnx("The CCA master key is not loaded and "
- "therefore a secure key cannot be enciphered");
- break;
- }
- break;
- }
-}
-
-/**
- * Re-enciphers a secure key.
- *
- * @param[in] dll_CSNBKTC the address of the CCA CSNBKTC function
- * @param[in] secure_key a buffer containing the secure key
- * @param[in] secure_key_size the size of the secure key
- * @param[in] method the re-enciphering method. METHOD_OLD_TO_CURRENT
- * or METHOD_CURRENT_TO_NEW.
- * @param[in] verbose if true, verbose messages are printed
- *
- * @returns 0 on success, -EIO in case of an error
- */
-int key_token_change(t_CSNBKTC dll_CSNBKTC,
- u8 *secure_key, unsigned int secure_key_size,
- char *method, bool verbose)
-{
- long exit_data_len = 0, rule_array_count;
- unsigned char rule_array[2 * 80] = { 0, };
- unsigned char exit_data[4] = { 0, };
- long return_code, reason_code;
-
- util_assert(dll_CSNBKTC != NULL, "Internal error: dll_CSNBKTC is NULL");
- util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
- util_assert(secure_key_size > 0,
- "Internal error: secure_key_size is 0");
- util_assert(method != NULL, "Internal error: method is NULL");
-
- memcpy(rule_array, method, 8);
- memcpy(rule_array + 8, "AES ", 8);
- rule_array_count = 2;
-
- dll_CSNBKTC(&return_code, &reason_code,
- &exit_data_len, exit_data,
- &rule_array_count, rule_array,
- secure_key);
-
- pr_verbose(verbose, "CSNBKTC (Key Token Change) with '%s' returned: "
- "return_code: %ld, reason_code: %ld", method, return_code,
- reason_code);
- if (return_code != 0) {
- print_CCA_error(return_code, reason_code);
- return -EIO;
- }
-
- if (secure_key_size == 2 * SECURE_KEY_SIZE) {
- dll_CSNBKTC(&return_code, &reason_code,
- &exit_data_len, exit_data,
- &rule_array_count, rule_array,
- secure_key + SECURE_KEY_SIZE);
-
- pr_verbose(verbose, "CSNBKTC (Key Token Change) with '%s' "
- "returned: return_code: %ld, reason_code: %ld",
- method, return_code, reason_code);
- if (return_code != 0) {
- print_CCA_error(return_code, reason_code);
- return -EIO;
- }
- }
- return 0;
-}
-
-/**
* Validates an XTS secure key (the second part)
*
* @param[in] pkey_fd the pkey file descriptor
--- a/zkey/pkey.h
+++ b/zkey/pkey.h
@@ -82,23 +82,10 @@ struct pkey_verifykey {
#define PKEY_VERIFYKEY _IOWR(PKEY_IOCTL_MAGIC, 0x07, struct pkey_verifykey)
-#define METHOD_OLD_TO_CURRENT "RTCMK "
-#define METHOD_CURRENT_TO_NEW "RTNMK "
-
-typedef void (*t_CSNBKTC)(long *return_code,
- long *reason_code,
- long *exit_data_length,
- unsigned char *exit_data,
- long *rule_array_count,
- unsigned char *rule_array,
- unsigned char *key_identifier);
-
#define PAES_BLOCK_SIZE 16
#define ENC_ZERO_LEN (2 * PAES_BLOCK_SIZE)
#define VERIFICATION_PATTERN_LEN (2 * ENC_ZERO_LEN + 1)
-int load_cca_library(void **lib_csulcca, t_CSNBKTC *dll_CSNBKTC, bool verbose);
-
int open_pkey_device(bool verbose);
int generate_secure_key_random(int pkey_fd, const char *keyfile,
@@ -122,10 +109,6 @@ int validate_secure_key(int pkey_fd,
size_t *clear_key_bitsize, int *is_old_mk,
bool verbose);
-int key_token_change(t_CSNBKTC dll_CSNBKTC,
- u8 *secure_key, unsigned int secure_key_size,
- char *method, bool verbose);
-
int generate_key_verification_pattern(const char *key, size_t key_size,
char *vp, size_t vp_len, bool verbose);
--- a/zkey/zkey-cryptsetup.c
+++ b/zkey/zkey-cryptsetup.c
@@ -34,6 +34,7 @@
#include "misc.h"
#include "pkey.h"
+#include "cca.h"
/* Detect if cryptsetup 2.1 or later is available */
#ifdef CRYPT_LOG_DEBUG_JSON
@@ -101,8 +102,7 @@ static struct zkey_cryptsetup_globals {
bool batch_mode;
bool debug;
bool verbose;
- void *lib_csulcca;
- t_CSNBKTC dll_CSNBKTC;
+ struct cca_lib cca;
int pkey_fd;
struct crypt_device *cd;
} g = {
@@ -1578,7 +1578,7 @@ static int reencipher_prepare(int token)
util_print_indented(msg, 0);
free(msg);
- rc = key_token_change(g.dll_CSNBKTC, (u8 *)key, keysize,
+ rc = key_token_change(&g.cca, (u8 *)key, keysize,
is_old_mk ? METHOD_OLD_TO_CURRENT :
METHOD_CURRENT_TO_NEW,
g.verbose);
@@ -1700,7 +1700,7 @@ static int reencipher_complete(int token
goto out;
}
- rc = key_token_change(g.dll_CSNBKTC, (u8 *)key, keysize,
+ rc = key_token_change(&g.cca, (u8 *)key, keysize,
METHOD_OLD_TO_CURRENT, g.verbose);
if (rc != 0) {
warnx("Failed to re-encipher the secure volume key for "
@@ -2288,8 +2288,7 @@ int main(int argc, char *argv[])
}
if (command->need_cca_library) {
- rc = load_cca_library(&g.lib_csulcca, &g.dll_CSNBKTC,
- g.verbose);
+ rc = load_cca_library(&g.cca, g.verbose);
if (rc != 0) {
rc = EXIT_FAILURE;
goto out;
@@ -2331,8 +2330,8 @@ int main(int argc, char *argv[])
rc = command->function();
out:
- if (g.lib_csulcca)
- dlclose(g.lib_csulcca);
+ if (g.cca.lib_csulcca)
+ dlclose(g.cca.lib_csulcca);
if (g.pkey_fd >= 0)
close(g.pkey_fd);
if (g.cd)
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -27,6 +27,7 @@
#include "lib/util_prg.h"
#include "lib/zt_common.h"
+#include "cca.h"
#include "keystore.h"
#include "misc.h"
#include "pkey.h"
@@ -80,8 +81,7 @@ static struct zkey_globals {
bool force;
bool open;
bool format;
- void *lib_csulcca;
- t_CSNBKTC dll_CSNBKTC;
+ struct cca_lib cca;
int pkey_fd;
struct keystore *keystore;
} g = {
@@ -1194,8 +1194,7 @@ static int command_reencipher_file(void)
pr_verbose("Secure key will be re-enciphered from OLD to the "
"CURRENT CCA master key");
- rc = key_token_change(g.dll_CSNBKTC,
- secure_key, secure_key_size,
+ rc = key_token_change(&g.cca, secure_key, secure_key_size,
METHOD_OLD_TO_CURRENT,
g.verbose);
if (rc != 0) {
@@ -1209,8 +1208,7 @@ static int command_reencipher_file(void)
pr_verbose("Secure key will be re-enciphered from CURRENT "
"to the NEW CCA master key");
- rc = key_token_change(g.dll_CSNBKTC,
- secure_key, secure_key_size,
+ rc = key_token_change(&g.cca, secure_key, secure_key_size,
METHOD_CURRENT_TO_NEW, g.verbose);
if (rc != 0) {
warnx("Re-encipher from CURRENT to NEW CCA "
@@ -1270,7 +1268,7 @@ static int command_reencipher_repository
rc = keystore_reencipher_key(g.keystore, g.name, g.apqns, g.fromold,
g.tonew, g.inplace, g.staged, g.complete,
- g.pkey_fd, g.dll_CSNBKTC);
+ g.pkey_fd, &g.cca);
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
@@ -1867,8 +1865,7 @@ int main(int argc, char *argv[])
}
if (command->need_cca_library) {
- rc = load_cca_library(&g.lib_csulcca, &g.dll_CSNBKTC,
- g.verbose);
+ rc = load_cca_library(&g.cca, g.verbose);
if (rc != 0) {
rc = EXIT_FAILURE;
goto out;
@@ -1887,8 +1884,8 @@ int main(int argc, char *argv[])
rc = command->function();
out:
- if (g.lib_csulcca)
- dlclose(g.lib_csulcca);
+ if (g.cca.lib_csulcca)
+ dlclose(g.cca.lib_csulcca);
if (g.pkey_fd >= 0)
close(g.pkey_fd);
if (g.keystore)

View File

@ -1,70 +0,0 @@
Subject: [PATCH] [BZ 184174] zpcictl: Initiate recover after reset
From: Jan Hoeppner <hoeppner@linux.ibm.com>
Description: zpcictl: Initiate recover after reset
Symptom: If a PCI function is reset using zpcictl --reset, the function
is in an error state.
Problem: zpcictl --reset only issues a SCLP reset and leaves the PCI
function in an error state.
Solution: Initiate an OS level recovery by calling
/sys/bus/devices/<dev>/recover after the SCLP reset.
Reproduction: Call zpcictl --reset <dev>
Under z/VM check the state of the function with 'vmcp q pcif'
Upstream-ID: bc0d40c5803d4c5426b17b6d59aa0f1e46a2aacc
Problem-ID: 184174
Upstream-Description:
zpcictl: Initiate recover after reset
After a zpcitctl --reset the PCI function is currently left in an error
state. This seems unexpected, so follow the SCLP reset with an OS level
recovery using /sys/bus/devices/<dev>/recover.
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
---
zpcictl/zpcictl.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
--- a/zpcictl/zpcictl.c
+++ b/zpcictl/zpcictl.c
@@ -163,6 +163,26 @@ static unsigned int sysfs_read_value(str
return val;
}
+static void sysfs_write_value(struct zpci_device *pdev, const char *attr,
+ unsigned int val)
+{
+ char *path;
+ FILE *fp;
+
+ path = util_path_sysfs("bus/pci/devices/%s/%s", pdev->slot, attr);
+ fp = fopen(path, "w");
+ if (!fp)
+ fopen_err(path);
+ if (fprintf(fp, "%x", val) < 0) {
+ fclose(fp);
+ warnx("Could not write to file %s: %s", path, strerror(errno));
+ free(path);
+ exit(EXIT_FAILURE);
+ }
+ fclose(fp);
+ free(path);
+}
+
static void sysfs_write_data(struct zpci_report_error *report, char *slot)
{
size_t r_size;
@@ -297,6 +317,7 @@ static void sclp_issue_action(struct zpc
static void sclp_reset_device(struct zpci_device *pdev)
{
sclp_issue_action(pdev, SCLP_ERRNOTIFY_AQ_RESET);
+ sysfs_write_value(pdev, "recover", 1);
}
/*

View File

@ -1,170 +0,0 @@
Subject: [PATCH] [BZ 184396] zipl: allow stand alone secure option on command line
From: Stefan Haberland <sth@linux.ibm.com>
Description: zipl: fix secure boot config handling
Symptom: The config file parsing for secure boot worked not as
it was expected to be. For example a config section
setting was not evaluated properly.
It is not possible to specify command line option -S
without other options.
Additionally the man page showed an invalid example.
Problem: The config file parsing was not implemented properly.
Solution: The hierarchy of the secure boot settings in the config
file is:
defaultboot > menu > section
Allow that --secure or -S is specified on command line
without the need to allow all options on the command
line. Also ensure that the command line option
overrules the config option and correctly ensure that
secure boot is only set for SCSI devices.
Fix man page example.
Reproduction: Run zipl with a secure= setting in a configuration
section or specify -S on command line.
Upstream-ID: 27f6c0a167da8d08f7f3343360528528f85d661f
Problem-ID: 184396
Upstream-Description:
zipl: allow stand alone secure option on command line
Allow that --secure or -S is specified on command line without the need to
allow all options on the command line.
Also ensure that the command line option overrules the config option and
correctly ensure that secure boot is only set for SCSI devices.
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
---
zipl/src/bootmap.c | 6 ++++++
zipl/src/job.c | 52 +++++++++++++++++++++++++---------------------------
2 files changed, 31 insertions(+), 27 deletions(-)
--- a/zipl/src/bootmap.c
+++ b/zipl/src/bootmap.c
@@ -1133,6 +1133,12 @@ bootmap_create(struct job_data *job, dis
disk_get_type_name(info->type));
goto out_disk_free_info;
}
+ /* Check if secure boot was enabled only for SCSI */
+ if (job->is_secure == SECURE_BOOT_ENABLED &&
+ info->type != disk_type_scsi) {
+ error_reason("Secure boot forced for non-SCSI disk type");
+ goto out_disk_free_info;
+ }
if (verbose) {
printf("Target device information\n");
disk_print_info(info);
--- a/zipl/src/job.c
+++ b/zipl/src/job.c
@@ -72,6 +72,7 @@ struct command_line {
int add_files;
int dry_run;
int force;
+ int is_secure;
enum scan_section_type type;
};
@@ -89,6 +90,22 @@ store_option(struct command_line* cmdlin
return 0;
}
+static int
+set_secure_ipl(char *keyword, int *is_secure)
+{
+ if (strcmp(keyword, "auto") == 0) {
+ *is_secure = SECURE_BOOT_AUTO;
+ } else if (strcmp(keyword, "0") == 0) {
+ *is_secure = SECURE_BOOT_DISABLED;
+ } else if (strcmp(keyword, "1") == 0) {
+ *is_secure = SECURE_BOOT_ENABLED;
+ } else {
+ error_reason("Invalid secure boot setting '%s'",
+ keyword);
+ return -1;
+ }
+ return 0;
+}
static int
get_command_line(int argc, char* argv[], struct command_line* line)
@@ -217,9 +234,7 @@ get_command_line(int argc, char* argv[],
cmdline.menu = optarg;
break;
case 'S':
- is_keyword = 1;
- rc = store_option(&cmdline, scan_keyword_secure,
- optarg);
+ rc = set_secure_ipl(optarg, &cmdline.is_secure);
break;
case 'h':
cmdline.help = 1;
@@ -1270,27 +1285,6 @@ type_from_target(char *target, disk_type
}
static int
-set_secure_ipl(char *keyword, struct job_data *job)
-{
- if (strcmp(keyword, "auto") == 0) {
- job->is_secure = SECURE_BOOT_AUTO;
- } else if (strcmp(keyword, "0") == 0) {
- job->is_secure = SECURE_BOOT_DISABLED;
- } else if (strcmp(keyword, "1") == 0) {
- if (job->target.targettype != disk_type_scsi) {
- error_reason("Secure boot forced for non-SCSI disk type");
- return -1;
- }
- job->is_secure = SECURE_BOOT_ENABLED;
- } else {
- error_reason("Invalid secure boot setting '%s'",
- keyword);
- return -1;
- }
- return 0;
-}
-
-static int
get_job_from_section_data(char* data[], struct job_data* job, char* section)
{
int rc;
@@ -1374,7 +1368,7 @@ get_job_from_section_data(char* data[],
/* Fill in secure boot */
if (data[(int) scan_keyword_secure] != NULL) {
rc = set_secure_ipl(data[(int) scan_keyword_secure],
- job);
+ &job->is_secure);
if (rc)
return rc;
}
@@ -1538,7 +1532,7 @@ get_menu_job(struct scan_token* scan, ch
case scan_keyword_secure:
rc = set_secure_ipl(
scan[i].content.keyword.value,
- job);
+ &job->is_secure);
if (rc)
return rc;
break;
@@ -1880,7 +1874,6 @@ job_get(int argc, char* argv[], struct j
job->add_files = cmdline.add_files;
job->data.mvdump.force = cmdline.force;
job->dry_run = cmdline.dry_run;
- job->is_secure = SECURE_BOOT_AUTO;
/* Get job data from user input */
if (cmdline.help) {
job->command_line = 1;
@@ -1899,6 +1892,11 @@ job_get(int argc, char* argv[], struct j
job_free(job);
return rc;
}
+ if (cmdline.is_secure)
+ job->is_secure = cmdline.is_secure;
+ else
+ job->is_secure = job->is_secure ? : SECURE_BOOT_AUTO;
+
/* Check job data for validity */
rc = check_job_data(job);
if (rc) {

View File

@ -1,102 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: fix -Waddress-of-packed-member
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: aa09b292483eb2d79247260fccc2b456dee01e8d
Problem-ID: VS1804
Upstream-Description:
zipl: fix -Waddress-of-packed-member
Reported by GCC 9.2.1 when building with '-Waddress-of-packed-member'.
menu.c: In function 'menu_read':
menu.c:30:22: warning: taking address of packed member of 'struct boot_stage2_params' may result in an unaligned pointer value [-Waddress-of-packed-member]
30 | uint16_t *configs = __stage2_params.config;
| ^~~~~~~~~~~~~~~
menu.c: In function 'menu_list':
menu.c:83:22: warning: taking address of packed member of 'struct boot_stage2_params' may result in an unaligned pointer value [-Waddress-of-packed-member]
83 | uint16_t *configs = __stage2_params.config;
| ^~~~~~~~~~~~~~~
menu.c: In function 'menu':
menu.c:139:22: warning: taking address of packed member of 'struct boot_stage2_params' may result in an unaligned pointer value [-Waddress-of-packed-member]
139 | uint16_t *configs = __stage2_params.config;
| ^~~~~~~~~~~~~~~
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/menu.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
--- a/zipl/boot/menu.c
+++ b/zipl/boot/menu.c
@@ -27,7 +27,6 @@ static void menu_prompt(int timeout)
static int menu_read(void)
{
char *temp_area = (char *)get_zeroed_page();
- uint16_t *configs = __stage2_params.config;
int timeout, rc, i, count = 0;
char *endptr;
int value;
@@ -60,7 +59,7 @@ static int menu_read(void)
value = ebcstrtoul((char *)temp_area, &endptr, 10);
if ((endptr != temp_area) && (value < BOOT_MENU_ENTRIES - 1) &&
- (configs[value] != 0)) {
+ (__stage2_params.config[value] != 0)) {
/* valid config found - finish */
break;
} else {
@@ -80,14 +79,13 @@ out_free_page:
static int menu_list(void)
{
- uint16_t *configs = __stage2_params.config;
char *name;
int i;
for (i = 0; i < BOOT_MENU_ENTRIES; i++) {
- if (configs[i] == 0)
+ if (__stage2_params.config[i] == 0)
continue;
- name = configs[i] + ((void *)&__stage2_params);
+ name = __stage2_params.config[i] + ((void *)&__stage2_params);
printf("%s\n", name);
if (i == 0)
printf("\n");
@@ -136,7 +134,6 @@ static int menu_param(unsigned long *val
int menu(void)
{
- uint16_t *configs = __stage2_params.config;
unsigned long value = 0;
char *cmd_line_extra;
char endstring[15];
@@ -181,11 +178,11 @@ int menu(void)
boot:
/* sanity - config entry not valid */
- if (configs[value] == 0)
+ if (__stage2_params.config[value] == 0)
panic(EINTERNAL, "%s", msg_econfig);
printf("Booting %s\n",
- (char *)(configs[value] +
+ (char *)(__stage2_params.config[value] +
(void *)&__stage2_params + TEXT_OFFSET));
/* append 'BOOT_IMAGE=<num>' to parmline */

View File

@ -1,63 +0,0 @@
Subject: [PATCH] [BZ 184060] zipl/libc: Fix potential buffer overflow in printf
From: Philipp Rudo <prudo@linux.ibm.com>
Description: zipl/libc: Fix potential buffer overflow in printf
Symptom: Crash of the zipl boot loader during boot.
Problem: The zipl boot loaders have their own minimalistic libc
implementation. In it printf and sprintf use vsprintf for string
formatting. Per definition vsprintf assumes that the buffer it
writes to is large enough to contain the formatted string and
performs no size checks. This is problematic for the boot
loaders because the buffer they use are often allocated on the
stack. Thus even small changes to the string format can
potentially cause buffer overflows on the stack.
Solution: Implement vsnprintf and make use of it.
Reproduction: Use printf to print a string with >81 characters (exact number
depends on the stack layout/compiler used).
Upstream-ID: 8874b908254c47c8a6fd7a1aca2c7371c11035c4
Problem-ID: 184060
Upstream-Description:
zipl/libc: Fix potential buffer overflow in printf
Per definition vsprint assumes that the provided buffer it writes to is
large enough to contain the formatted string. As printf uses a fixed
sized buffer (81 bytes) and has no size checks the use of vsprintf can
easily cause buffer overflows. Protect against these buffer overflows by
using vsnprintf instead.
While at it fix a typo in the comment.
Reported-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
---
zipl/boot/libc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/zipl/boot/libc.c
+++ b/zipl/boot/libc.c
@@ -530,7 +530,7 @@ void sprintf(char *str, const char *fmt,
}
/*
- * Print formated string
+ * Print formatted string to console
*/
void printf(const char *fmt, ...)
{
@@ -538,7 +538,7 @@ void printf(const char *fmt, ...)
va_list va;
va_start(va, fmt);
- vsprintf(buf, fmt, va);
+ vsnprintf(buf, sizeof(buf), fmt, va);
sclp_print(buf);
va_end(va);
}

View File

@ -1,87 +0,0 @@
Subject: [PATCH] [BZ 186940] zipl/stage3: correctly handle diag308 response code
From: Stefan Haberland <sth@linux.ibm.com>
Description: zipl: Fix KVM IPL without bootindex
Symptom: Failed IPL on KVM when no bootindex is specified.
Problem: Without bootindex specified there is no IPL parmblock
on KVM which can be read by the stage3 loader.
Solution: In case diag308 gives a response code 0x102 the stage3
loader can safely assume that no secure IPL is required
since no IPL report block exists.
Reproduction: IPL on KVM without 'bootindex=' attached.
Upstream-ID: b7f1977d3f9332f82e7f388fb18076b89b83944e
Problem-ID: 186940
Upstream-Description:
zipl/stage3: correctly handle diag308 response code
In case diag308 gives a response code 0x102 the stage3 loader can
safely assume that no secure IPL is required since no IPL report
block exists.
Suggested-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Tested-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
---
include/boot/s390.h | 1 +
zipl/boot/stage3.c | 25 +++++++++++--------------
2 files changed, 12 insertions(+), 14 deletions(-)
--- a/include/boot/s390.h
+++ b/include/boot/s390.h
@@ -279,6 +279,7 @@ enum diag308_subcode {
enum diag308_rc {
DIAG308_RC_OK = 0x0001,
+ DIAG308_RC_NO_CONF = 0x0102,
};
static __always_inline unsigned long diag308(unsigned long subcode, void *addr)
--- a/zipl/boot/stage3.c
+++ b/zipl/boot/stage3.c
@@ -55,18 +55,6 @@ static inline void __noreturn start_kern
while (1);
}
-unsigned int store_ipl_parmblock(struct ipl_pl_hdr *pl_hdr)
-{
- int rc;
-
- rc = diag308(DIAG308_STORE, pl_hdr);
- if (rc == DIAG308_RC_OK &&
- pl_hdr->version <= IPL_MAX_SUPPORTED_VERSION)
- return 0;
-
- return 1;
-}
-
unsigned int
is_verified_address(unsigned long image_addr)
{
@@ -124,9 +112,18 @@ secure_boot_enabled()
unsigned int rc;
pl_hdr = (void *)get_zeroed_page();
- if (!pl_hdr || store_ipl_parmblock(pl_hdr))
+ switch (diag308(DIAG308_STORE, pl_hdr)) {
+ case DIAG308_RC_OK:
+ rc = pl_hdr->version <= IPL_MAX_SUPPORTED_VERSION &&
+ !!(pl_hdr->flags & IPL_FLAG_SECURE);
+ break;
+ case DIAG308_RC_NO_CONF:
+ rc = 0;
+ break;
+ default:
panic(ESECUREBOOT, "%s", msg_sipl_noparm);
- rc = !!(pl_hdr->flags & IPL_FLAG_SECURE);
+ break;
+ }
free_page((unsigned long) pl_hdr);
return rc;

View File

@ -1,297 +0,0 @@
Subject: zkey: Move utility functions into separate source file
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: 696e8458f0c117e3a084e1a083de89ec19baaff9
Problem-ID: SEC1916
Upstream-Description:
zkey: Move utility functions into separate source file
As preparation for future changes, move a sysfs specific functions
into a separate source file (utils.c).
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/Makefile | 5 +-
zkey/keystore.c | 69 +----------------------------------
zkey/utils.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
zkey/utils.h | 21 ++++++++++
4 files changed, 136 insertions(+), 68 deletions(-)
--- a/zkey/Makefile
+++ b/zkey/Makefile
@@ -67,12 +67,13 @@ all: $(BUILD_TARGETS)
zkey.o: zkey.c pkey.h cca.h misc.h
pkey.o: pkey.c pkey.h
cca.o: cca.c cca.h pkey.h
+utils.o: utils.h
properties.o: check-dep-zkey properties.c properties.h
-keystore.o: keystore.c keystore.h properties.h pkey.h cca.h
+keystore.o: keystore.c keystore.h properties.h pkey.h cca.h utils.h
zkey-cryptsetup.o: check-dep-zkey-cryptsetup zkey-cryptsetup.c pkey.h cca.h misc.h
zkey: LDLIBS = -ldl -lcrypto
-zkey: zkey.o pkey.o cca.o properties.o keystore.o $(libs)
+zkey: zkey.o pkey.o cca.o properties.o keystore.o utils.o $(libs)
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
zkey-cryptsetup: LDLIBS = -ldl -lcryptsetup -ljson-c
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -25,7 +25,6 @@
#include <sys/types.h>
#include "lib/util_base.h"
-#include "lib/util_file.h"
#include "lib/util_libc.h"
#include "lib/util_panic.h"
#include "lib/util_path.h"
@@ -35,6 +34,7 @@
#include "pkey.h"
#include "cca.h"
#include "properties.h"
+#include "utils.h"
struct key_filenames {
char *skey_filename;
@@ -1010,69 +1010,6 @@ free:
return rc;
}
-/**
- * Checks if the specified APQN is of type CCA and is online
- *
- * @param[in] card card number
- * @param[in] domain the domain
- *
- * @returns 1 if its a CCA card and is online, 0 if offline and -1 if its
- * not a CCA card.
- */
-static int _keystore_is_apqn_online(int card, int domain)
-{
- long int online;
- char *dev_path;
- char type[20];
- int rc = 1;
-
- dev_path = util_path_sysfs("bus/ap/devices/card%02x", card);
- if (!util_path_is_dir(dev_path)) {
- rc = 0;
- goto out;
- }
- if (util_file_read_l(&online, 10, "%s/online", dev_path) != 0) {
- rc = 0;
- goto out;
- }
- if (online == 0) {
- rc = 0;
- goto out;
- }
- if (util_file_read_line(type, sizeof(type), "%s/type", dev_path) != 0) {
- rc = 0;
- goto out;
- }
- if (strncmp(type, "CEX", 3) != 0 || strlen(type) < 5) {
- rc = 0;
- goto out;
- }
- if (type[4] != 'C') {
- rc = -1;
- goto out;
- }
- free(dev_path);
-
- dev_path = util_path_sysfs("bus/ap/devices/card%02x/%02x.%04x", card,
- card, domain);
- if (!util_path_is_dir(dev_path)) {
- rc = 0;
- goto out;
- }
- if (util_file_read_l(&online, 10, "%s/online", dev_path) != 0) {
- rc = 0;
- goto out;
- }
- if (online == 0) {
- rc = 0;
- goto out;
- }
-
-out:
- free(dev_path);
- return rc;
-}
-
struct apqn_check {
bool noonlinecheck;
bool nomsg;
@@ -1124,7 +1061,7 @@ static int _keystore_apqn_check(const ch
goto out;
}
- rc = _keystore_is_apqn_online(card, domain);
+ rc = sysfs_is_apqn_online(card, domain);
if (rc != 1) {
if (info->nomsg == 0)
warnx("The APQN %02x.%04x is %s", card, domain,
@@ -2329,7 +2266,7 @@ static int _keystore_display_apqn_status
if (sscanf(apqn_list[i], "%x.%x", &card, &domain) != 2)
continue;
- rc = _keystore_is_apqn_online(card, domain);
+ rc = sysfs_is_apqn_online(card, domain);
if (rc != 1) {
printf("WARNING: The APQN %02x.%04x associated with "
"key '%s' is %s\n", card, domain, name,
--- /dev/null
+++ b/zkey/utils.c
@@ -0,0 +1,109 @@
+/*
+ * zkey - Generate, re-encipher, and validate secure keys
+ *
+ * Copyright IBM Corp. 2019
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "lib/util_path.h"
+#include "lib/util_file.h"
+
+#include "utils.h"
+
+/**
+ * Checks if the specified card is of type CCA and is online
+ *
+ * @param[in] card card number
+ *
+ * @returns 1 if its a CCA card and is online, 0 if offline and -1 if its
+ * not a CCA card.
+ */
+int sysfs_is_card_online(int card)
+{
+ long int online;
+ char *dev_path;
+ char type[20];
+ int rc = 1;
+
+ dev_path = util_path_sysfs("bus/ap/devices/card%02x", card);
+ if (!util_path_is_dir(dev_path)) {
+ rc = 0;
+ goto out;
+ }
+ if (util_file_read_l(&online, 10, "%s/online", dev_path) != 0) {
+ rc = 0;
+ goto out;
+ }
+ if (online == 0) {
+ rc = 0;
+ goto out;
+ }
+ if (util_file_read_line(type, sizeof(type), "%s/type", dev_path) != 0) {
+ rc = 0;
+ goto out;
+ }
+ if (strncmp(type, "CEX", 3) != 0 || strlen(type) < 5) {
+ rc = 0;
+ goto out;
+ }
+ if (type[4] != 'C') {
+ rc = -1;
+ goto out;
+ }
+
+out:
+ free(dev_path);
+ return rc;
+}
+
+/**
+ * Checks if the specified APQN is of type CCA and is online
+ *
+ * @param[in] card card number
+ * @param[in] domain the domain
+ *
+ * @returns 1 if its a CCA card and is online, 0 if offline and -1 if its
+ * not a CCA card.
+ */
+int sysfs_is_apqn_online(int card, int domain)
+{
+ long int online;
+ char *dev_path;
+ int rc = 1;
+
+ rc = sysfs_is_card_online(card);
+ if (rc != 1)
+ return rc;
+
+ dev_path = util_path_sysfs("bus/ap/devices/card%02x/%02x.%04x", card,
+ card, domain);
+ if (!util_path_is_dir(dev_path)) {
+ rc = 0;
+ goto out;
+ }
+ if (util_file_read_l(&online, 10, "%s/online", dev_path) != 0) {
+ rc = 0;
+ goto out;
+ }
+ if (online == 0) {
+ rc = 0;
+ goto out;
+ }
+
+out:
+ free(dev_path);
+ return rc;
+}
+
--- /dev/null
+++ b/zkey/utils.h
@@ -0,0 +1,21 @@
+/*
+ * zkey - Generate, re-encipher, and validate secure keys
+ *
+ * This header file defines the interface to the CCA host library.
+ *
+ * Copyright IBM Corp. 2019
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include "lib/zt_common.h"
+
+int sysfs_is_card_online(int card);
+
+int sysfs_is_apqn_online(int card, int domain);
+
+#endif

View File

@ -1,51 +0,0 @@
Subject: [PATCH] [BZ 184174] zpcictl: Rename misleading sysfs_write_data
From: Jan Hoeppner <hoeppner@linux.ibm.com>
Description: zpcictl: Initiate recover after reset
Symptom: If a PCI function is reset using zpcictl --reset, the function
is in an error state.
Problem: zpcictl --reset only issues a SCLP reset and leaves the PCI
function in an error state.
Solution: Initiate an OS level recovery by calling
/sys/bus/devices/<dev>/recover after the SCLP reset.
Reproduction: Call zpcictl --reset <dev>
Under z/VM check the state of the function with 'vmcp q pcif'
Upstream-ID: d77234ddb68719819c7e8380c71dbebc555539ab
Problem-ID: 184174
Upstream-Description:
zpcictl: Rename misleading sysfs_write_data
To sysfs_report_error as it only writes to the report_error attribute.
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
---
zpcictl/zpcictl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/zpcictl/zpcictl.c
+++ b/zpcictl/zpcictl.c
@@ -183,7 +183,7 @@ static void sysfs_write_value(struct zpc
free(path);
}
-static void sysfs_write_data(struct zpci_report_error *report, char *slot)
+static void sysfs_report_error(struct zpci_report_error *report, char *slot)
{
size_t r_size;
char *path;
@@ -308,7 +308,7 @@ static void sclp_issue_action(struct zpc
sizeof(report.data.log_data));
free(sdata);
}
- sysfs_write_data(&report, pdev->slot);
+ sysfs_report_error(&report, pdev->slot);
}
/*

View File

@ -1,187 +0,0 @@
Subject: [PATCH] [BZ 184396] zipl: correct secure boot config handling
From: Stefan Haberland <sth@linux.ibm.com>
Description: zipl: fix secure boot config handling
Symptom: The config file parsing for secure boot worked not as
it was expected to be. For example a config section
setting was not evaluated properly.
It is not possible to specify command line option -S
without other options.
Additionally the man page showed an invalid example.
Problem: The config file parsing was not implemented properly.
Solution: The hierarchy of the secure boot settings in the config
file is:
defaultboot > menu > section
Allow that --secure or -S is specified on command line
without the need to allow all options on the command
line. Also ensure that the command line option
overrules the config option and correctly ensure that
secure boot is only set for SCSI devices.
Fix man page example.
Reproduction: Run zipl with a secure= setting in a configuration
section or specify -S on command line.
Upstream-ID: 6f9337d1016e00f360cf4a81d39a42df5184b3a2
Problem-ID: 184396
Upstream-Description:
zipl: correct secure boot config handling
The hierarchy of the secure boot settings in the config file should be:
defaultboot > menu > section
This patch implements this hierarchy and adds a check if a valid option is
specified and prints an error message otherwise.
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
---
zipl/include/job.h | 1 +
zipl/include/zipl.h | 1 +
zipl/src/bootmap.c | 8 +++++++-
zipl/src/job.c | 29 ++++++++++++++++++++++++++---
4 files changed, 35 insertions(+), 4 deletions(-)
--- a/zipl/include/job.h
+++ b/zipl/include/job.h
@@ -94,6 +94,7 @@ struct job_menu_entry {
char* name;
enum job_id id;
union job_menu_entry_data data;
+ int is_secure;
};
struct job_menu_data {
--- a/zipl/include/zipl.h
+++ b/zipl/include/zipl.h
@@ -57,6 +57,7 @@
#define MAX_DUMP_VOLUMES 32
+#define SECURE_BOOT_UNDEFINED -1
#define SECURE_BOOT_DISABLED 0
#define SECURE_BOOT_ENABLED 1
#define SECURE_BOOT_AUTO 2
--- a/zipl/src/bootmap.c
+++ b/zipl/src/bootmap.c
@@ -945,6 +945,7 @@ build_program_table(int fd, struct job_d
{
disk_blockptr_t* table;
int entries, component_header;
+ int is_secure;
int i;
int rc;
@@ -1016,13 +1017,18 @@ build_program_table(int fd, struct job_d
component_header_ipl;
printf("\n");
}
+ if (job->is_secure != SECURE_BOOT_UNDEFINED)
+ is_secure = job->is_secure;
+ else
+ is_secure =
+ job->data.menu.entry[i].is_secure;
rc = add_ipl_program(fd,
&job->data.menu.entry[i].data.ipl,
&table[job->data.menu.entry[i].pos],
verbose || job->command_line,
job->add_files, component_header,
info, &job->target,
- job->is_secure);
+ is_secure);
break;
case job_print_usage:
case job_print_version:
--- a/zipl/src/job.c
+++ b/zipl/src/job.c
@@ -119,6 +119,7 @@ get_command_line(int argc, char* argv[],
memset((void *) &cmdline, 0, sizeof(struct command_line));
cmdline.type = section_invalid;
is_keyword = 0;
+ cmdline.is_secure = SECURE_BOOT_UNDEFINED;
/* Process options */
do {
opt = getopt_long(argc, argv, option_string, options, NULL);
@@ -1055,6 +1056,21 @@ check_job_mvdump_data(struct job_mvdump_
return 0;
}
+static int
+check_secure_boot(struct job_data *job)
+{
+ switch (job->is_secure) {
+ case SECURE_BOOT_UNDEFINED:
+ case SECURE_BOOT_DISABLED:
+ case SECURE_BOOT_ENABLED:
+ case SECURE_BOOT_AUTO:
+ return 0;
+ default:
+ error_reason("Invalid secure boot setting '%d'",
+ job->is_secure);
+ return -1;
+ }
+}
static int
check_job_data(struct job_data* job)
@@ -1099,6 +1115,8 @@ check_job_data(struct job_data* job)
case job_mvdump:
rc = check_job_mvdump_data(&job->data.mvdump, job->name);
}
+ if (!rc)
+ rc = check_secure_boot(job);
return rc;
}
@@ -1594,6 +1612,7 @@ get_menu_job(struct scan_token* scan, ch
sizeof(struct job_menu_entry) * job->data.menu.num);
/* Fill in data */
current = 0;
+ job->data.menu.entry->is_secure = SECURE_BOOT_UNDEFINED;
for (i=index+1; (scan[i].id != scan_id_empty) &&
(scan[i].id != scan_id_section_heading) &&
(scan[i].id != scan_id_menu_heading); i++) {
@@ -1625,6 +1644,7 @@ get_menu_job(struct scan_token* scan, ch
if (temp_job == NULL)
return -1;
memset((void *) temp_job, 0, sizeof(struct job_data));
+ temp_job->is_secure = SECURE_BOOT_UNDEFINED;
rc = get_job_from_section_data(data, temp_job,
job->data.menu.entry[current].name);
if (rc) {
@@ -1637,6 +1657,8 @@ get_menu_job(struct scan_token* scan, ch
job->data.menu.entry[current].id = job_ipl;
job->data.menu.entry[current].data.ipl =
temp_job->data.ipl;
+ job->data.menu.entry[current].is_secure =
+ temp_job->is_secure;
memset((void *) &temp_job->data.ipl, 0,
sizeof(struct job_ipl_data));
break;
@@ -1874,6 +1896,7 @@ job_get(int argc, char* argv[], struct j
job->add_files = cmdline.add_files;
job->data.mvdump.force = cmdline.force;
job->dry_run = cmdline.dry_run;
+ job->is_secure = SECURE_BOOT_UNDEFINED;
/* Get job data from user input */
if (cmdline.help) {
job->command_line = 1;
@@ -1892,10 +1915,10 @@ job_get(int argc, char* argv[], struct j
job_free(job);
return rc;
}
- if (cmdline.is_secure)
+ if (cmdline.is_secure != SECURE_BOOT_UNDEFINED)
job->is_secure = cmdline.is_secure;
- else
- job->is_secure = job->is_secure ? : SECURE_BOOT_AUTO;
+ else if (job->id != job_menu && job->is_secure == SECURE_BOOT_UNDEFINED)
+ job->is_secure = SECURE_BOOT_AUTO;
/* Check job data for validity */
rc = check_job_data(job);

View File

@ -1,236 +0,0 @@
Subject: [PATCH] [BZ 184060] zipl/libc: Replace sprintf with snprintf
From: Philipp Rudo <prudo@linux.ibm.com>
Description: zipl/libc: Fix potential buffer overflow in printf
Symptom: Crash of the zipl boot loader during boot.
Problem: The zipl boot loaders have their own minimalistic libc
implementation. In it printf and sprintf use vsprintf for string
formatting. Per definition vsprintf assumes that the buffer it
writes to is large enough to contain the formatted string and
performs no size checks. This is problematic for the boot
loaders because the buffer they use are often allocated on the
stack. Thus even small changes to the string format can
potentially cause buffer overflows on the stack.
Solution: Implement vsnprintf and make use of it.
Reproduction: Use printf to print a string with >81 characters (exact number
depends on the stack layout/compiler used).
Upstream-ID: f7430027b41d5ad6220e962a179c2a5213330a44
Problem-ID: 184060
Upstream-Description:
zipl/libc: Replace sprintf with snprintf
The use of sprintf can easily result in buffer overflows as it assumes
that the buffer it writes to is large enough to contain the formatted
string. Thus replace sprintf by snprintf and update its users.
This removes the last user of vsprintf. Thus also remove vsprintf and
its dependencies.
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
---
zipl/boot/libc.c | 132 +-------------------------------------------------
zipl/boot/libc.h | 3 -
zipl/boot/menu.c | 2
zipl/boot/tape2dump.c | 2
4 files changed, 6 insertions(+), 133 deletions(-)
--- a/zipl/boot/libc.c
+++ b/zipl/boot/libc.c
@@ -126,81 +126,6 @@ int strncmp(const char *s1, const char *
}
/*
- * Convert number to string
- *
- * Parameters:
- *
- * - buf: Output buffer
- * - base: Base used for formatting (e.g. 10 or 16)
- * - val: Number to format
- * - zero: If > 0, fill with leading zeros, otherwise use blanks
- * - count: Minimum number of characters used for output string
- */
-static int num_to_str(char *buf, int base, unsigned long val, int zero,
- unsigned long count)
-{
- static const char conv_vec[] = {'0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
- unsigned long num = 0, val_work = val, in_number = 1;
- int i;
-
- /* Count number of characters needed for number */
- do {
- num++;
- val_work /= base;
- } while (val_work);
- /* Real character number overwrites count */
- if (count < num)
- count = num;
- /* Format number */
- for (i = count - 1; i >= 0; i--) {
- if (in_number) {
- buf[i] = conv_vec[val % base];
- val /= base;
- in_number = val ? 1 : 0;
- } else {
- buf[i] = zero ? '0' : ' ';
- }
- }
- buf[count] = 0;
- return count;
-}
-
-/*
- * Convert string to string with indentation
- */
-static int str_to_str(char *buf, const char *str, unsigned long count)
-{
- unsigned long size;
-
- size = strlen(str);
- if (count < size)
- count = size;
- else
- memset(buf, ' ', count - size);
- strcpy(buf + (count - size), str);
- return count;
-}
-
-/*
- * Convert string to number with given base
- */
-unsigned long strtoul(const char *nptr, char **endptr, int base)
-{
- unsigned long val = 0;
-
- while (isdigit(*nptr)) {
- if (val != 0)
- val *= base;
- val += *nptr - '0';
- nptr++;
- }
- if (endptr)
- *endptr = (char *) nptr;
- return val;
-}
-
-/*
* Convert ebcdic string to number with given base
*/
unsigned long ebcstrtoul(char *nptr, char **endptr, int base)
@@ -467,65 +392,14 @@ static int vsnprintf(char *buf, unsigned
}
/*
- * Convert string to number with given base
- */
-static int sprintf_fmt(char type, char *buf, unsigned long val, int zero,
- int count)
-{
- switch (type) {
- case 's':
- return str_to_str(buf, (const char *) val, count);
- case 'x':
- return num_to_str(buf, 16, val, zero, count);
- case 'u':
- return num_to_str(buf, 10, val, zero, count);
- default:
- libc_stop(EINTERNAL);
- }
- return 0;
-}
-
-/*
- * Print formated string (va version)
- */
-static void vsprintf(char *str, const char *fmt, va_list va)
-{
- unsigned long val, zero, count;
- char *fmt_next;
-
- do {
- if (*fmt == '%') {
- fmt++;
- if (*fmt == '0') {
- zero = 1;
- fmt++;
- } else {
- zero = 0;
- }
- /* No number found by strtoul: count=0 fmt_next=fmt */
- count = strtoul(fmt, &fmt_next, 10);
- fmt = fmt_next;
- if (*fmt == 'l')
- fmt++;
- val = va_arg(va, unsigned long);
- str += sprintf_fmt(*fmt, str, val, zero, count);
- fmt++;
- } else {
- *str++ = *fmt++;
- }
- } while (*fmt);
- *str = 0;
-}
-
-/*
- * Write formated string to string
+ * Write formatted string to buffer
*/
-void sprintf(char *str, const char *fmt, ...)
+void snprintf(char *buf, unsigned long size, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
- vsprintf(str, fmt, va);
+ vsnprintf(buf, size, fmt, va);
va_end(va);
}
--- a/zipl/boot/libc.h
+++ b/zipl/boot/libc.h
@@ -47,13 +47,12 @@ typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
void printf(const char *, ...);
-void sprintf(char *, const char *, ...);
+void snprintf(char *buf, unsigned long size, const char *fmt, ...);
void *memcpy(void *, const void *, unsigned long);
void *memmove(void *, const void *, unsigned long);
void *memset(void *, int c, unsigned long);
char *strcat(char *, const char *);
int strncmp(const char *, const char *, unsigned long);
-unsigned long strtoul(const char *, char **, int);
unsigned long ebcstrtoul(char *, char **, int);
int strlen(const char *);
char *strcpy(char *, const char *);
--- a/zipl/boot/menu.c
+++ b/zipl/boot/menu.c
@@ -189,7 +189,7 @@ boot:
(void *)&__stage2_params + TEXT_OFFSET));
/* append 'BOOT_IMAGE=<num>' to parmline */
- sprintf(endstring, " BOOT_IMAGE=%u", value);
+ snprintf(endstring, sizeof(endstring), " BOOT_IMAGE=%u", value);
if ((strlen(cmd_line_extra) + strlen(endstring)) < COMMAND_LINE_SIZE)
strcat(cmd_line_extra, endstring);
--- a/zipl/boot/tape2dump.c
+++ b/zipl/boot/tape2dump.c
@@ -186,7 +186,7 @@ static void progress_print_disp(unsigned
if (addr % (1024 * 1024 * 16) != 0)
return;
- sprintf(msg, "%08u", addr >> 20);
+ snprintf(msg, sizeof(msg), "%08u", addr >> 20);
ccw_load_display(msg);
}

View File

@ -1,143 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: remove some useless __packed___ attributes
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 2227bb8330aea1368ba234ae6f24fe0b5779d67d
Problem-ID: VS1804
Upstream-Description:
zipl: remove some useless __packed___ attributes
The __packed__ attribute is not needed for these structures as they
don't need any padding to meet the size and alignment constraints
defined in the Linux for zSeries ABI.
Reported by GCC 9.2.1 when building with '-Waddress-of-packed-member'.
stage3.c: In function 'is_verified_address':
stage3.c:241:26: warning: taking address of packed member of 'struct ipl_rb_components' may result in an unaligned pointer value [-Waddress-of-packed-member]
241 | for_each_rb_entry(comp, comps) {
| ^~~~~
stage3.c:18:15: note: in definition of macro 'for_each_rb_entry'
18 | for (entry = rb->entries; \
| ^~
CC zipl/boot/kdump3.o
CC zipl/boot/sclp_stage3.o
sclp_stage3.c: In function '__sclp_hsa_copy':
sclp_stage3.c:75:34: warning: converting a packed 'struct sdias_sccb' pointer (alignment 1) to a 'struct read_sccb' pointer (alignment 4096) may result in an unaligned pointer value [-Waddress-of-packed-member]
75 | if (sclp_hsa_copy_wait((struct read_sccb *)sccb))
| ^~~~~~~~~
In file included from sclp_stage3.c:13:
sclp_stage3.h:43:8: note: defined here
43 | struct sdias_sccb {
| ^~~~~~~~~~
In file included from sclp_stage3.c:12:
sclp.h:149:8: note: defined here
149 | struct read_sccb {
| ^~~~~~~~~
sclp_stage3.c: In function 'sclp_hsa_get_size':
sclp_stage3.c:126:34: warning: converting a packed 'struct sdias_sccb' pointer (alignment 1) to a 'struct read_sccb' pointer (alignment 4096) may result in an unaligned pointer value [-Waddress-of-packed-member]
126 | if (sclp_hsa_copy_wait((struct read_sccb *)sccb))
| ^~~~~~~~~
In file included from sclp_stage3.c:13:
sclp_stage3.h:43:8: note: defined here
43 | struct sdias_sccb {
| ^~~~~~~~~~
In file included from sclp_stage3.c:12:
sclp.h:149:8: note: defined here
149 | struct read_sccb {
| ^~~~~~~~~
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/sclp.h | 6 ++++--
zipl/boot/sclp_stage3.h | 3 ++-
zipl/boot/stage3.h | 6 ++++--
3 files changed, 10 insertions(+), 5 deletions(-)
--- a/zipl/boot/sclp.h
+++ b/zipl/boot/sclp.h
@@ -53,19 +53,21 @@ struct gds_subvector {
uint8_t key;
} __packed;
+/* Structure must not have any padding */
struct sccb_header {
uint16_t length;
uint8_t function_code;
uint8_t control_mask[3];
uint16_t response_code;
-} __packed;
+};
+/* Structure must not have any padding */
struct evbuf_header {
uint16_t length;
uint8_t type;
uint8_t flags;
uint16_t _reserved;
-} __packed;
+};
struct mto {
uint16_t length;
--- a/zipl/boot/sclp_stage3.h
+++ b/zipl/boot/sclp_stage3.h
@@ -40,10 +40,11 @@ struct sdias_evbuf {
uint16_t dbs;
} __packed;
+/* Structure must not have any padding */
struct sdias_sccb {
struct sccb_header header;
struct sdias_evbuf evbuf;
-} __packed;
+};
int sclp_hsa_copy(void *, unsigned long, unsigned long);
--- a/zipl/boot/stage3.h
+++ b/zipl/boot/stage3.h
@@ -124,11 +124,12 @@ struct ipl_rl_hdr {
} __packed;
/* IPL Report Block header */
+/* Structure must not have any padding */
struct ipl_rb_hdr {
uint32_t len;
uint8_t rbt;
uint8_t reserved1[11];
-} __packed;
+};
/* IPL Report Block types */
enum ipl_rbt {
@@ -162,12 +163,13 @@ struct ipl_rb_component_entry {
#define IPL_RB_COMPONENT_FLAG_SIGNED 0x80
#define IPL_RB_COMPONENT_FLAG_VERIFIED 0x40
+/* Structure must not have any padding */
struct ipl_rb_components {
uint32_t len;
uint8_t rbt;
uint8_t reserved1[11];
struct ipl_rb_component_entry entries[];
-} __packed;
+};
extern unsigned long long _parm_addr; /* address of parmline */
extern unsigned long long _initrd_addr; /* address of initrd */

View File

@ -1,112 +0,0 @@
Subject: zkey: Add utility function to get the serial number of a crypto card
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: a84d1c5d58fa4a0c9e087357eec009803ea06ef2
Problem-ID: SEC1916
Upstream-Description:
zkey: Add utility function to get the serial number of a crypto card
With recent changes in the zcrypt device driver, the serial number of
a crypto card can be obtained by reading the sysfs attribute 'serialnr'
of a crypto card device of type CCA-Coprocessor. The sysfs attribute
can be found under '/sys/devices/ap/cardnn/', where nn specifies the
card number in hex.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/utils.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
zkey/utils.h | 2 ++
2 files changed, 54 insertions(+)
--- a/zkey/utils.c
+++ b/zkey/utils.c
@@ -22,6 +22,11 @@
#include "utils.h"
+#define pr_verbose(verbose, fmt...) do { \
+ if (verbose) \
+ warnx(fmt); \
+ } while (0)
+
/**
* Checks if the specified card is of type CCA and is online
*
@@ -107,3 +112,50 @@ out:
return rc;
}
+/**
+ * Gets the 8 character ASCII serial number string of an card from the sysfs.
+ *
+ * @param[in] card card number
+ * @param[out] serialnr Result buffer
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 if the serial number was returned. -ENODEV if the APQN is not
+ * available, or is not a CCA card. -ENOTSUP if the serialnr sysfs
+ * attribute is not available, because the zcrypt kernel module is
+ * on an older level.
+ */
+int sysfs_get_serialnr(int card, char serialnr[9], bool verbose)
+{
+ char *dev_path;
+ int rc = 0;
+
+ if (serialnr == NULL)
+ return -EINVAL;
+
+ if (sysfs_is_card_online(card) != 1)
+ return -ENODEV;
+
+ dev_path = util_path_sysfs("bus/ap/devices/card%02x", card);
+ if (!util_path_is_dir(dev_path)) {
+ rc = -ENODEV;
+ goto out;
+ }
+ if (util_file_read_line(serialnr, 9, "%s/serialnr", dev_path) != 0) {
+ rc = -ENOTSUP;
+ goto out;
+ }
+
+ if (strlen(serialnr) == 0) {
+ rc = -ENODEV;
+ goto out;
+ }
+
+ pr_verbose(verbose, "Serial number of %02x: %s", card, serialnr);
+out:
+ if (rc != 0)
+ pr_verbose(verbose, "Failed to get serial number for "
+ "%02x: %s", card, strerror(-rc));
+
+ free(dev_path);
+ return rc;
+}
--- a/zkey/utils.h
+++ b/zkey/utils.h
@@ -18,4 +18,6 @@ int sysfs_is_card_online(int card);
int sysfs_is_apqn_online(int card, int domain);
+int sysfs_get_serialnr(int card, char serialnr[9], bool verbose);
+
#endif

View File

@ -1,119 +0,0 @@
Subject: [PATCH] [BZ 184174] zpcitctl: Exit on error in sysfs_report_error
From: Jan Hoeppner <hoeppner@linux.ibm.com>
Description: zpcictl: Initiate recover after reset
Symptom: If a PCI function is reset using zpcictl --reset, the function
is in an error state.
Problem: zpcictl --reset only issues a SCLP reset and leaves the PCI
function in an error state.
Solution: Initiate an OS level recovery by calling
/sys/bus/devices/<dev>/recover after the SCLP reset.
Reproduction: Call zpcictl --reset <dev>
Under z/VM check the state of the function with 'vmcp q pcif'
Upstream-ID: 304c3d8086bc2a9230c5404f9c9fec72de08d229
Problem-ID: 184174
Upstream-Description:
zpcitctl: Exit on error in sysfs_report_error
This also makes sure that we don't try to write to the
/sys/bus/pci/device/<dev>/recover attribute if reset failed.
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
---
zpcictl/zpcictl.c | 55 +++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 38 insertions(+), 17 deletions(-)
--- a/zpcictl/zpcictl.c
+++ b/zpcictl/zpcictl.c
@@ -97,6 +97,35 @@ static void fopen_err(char *path)
exit(EXIT_FAILURE);
}
+static void fclose_err(char *path)
+{
+ if (errno == EIO || errno == EOPNOTSUPP)
+ warnx("Unsupported operation: %s: %s", path, strerror(errno));
+ else
+ warnx("Could not close file: %s: %s", path, strerror(errno));
+ free(path);
+ exit(EXIT_FAILURE);
+
+}
+
+static void fread_err(FILE *fp, char *path)
+{
+ warnx("Could not read file: %s: %s", path, strerror(errno));
+ if (fclose(fp))
+ fclose_err(path);
+ free(path);
+ exit(EXIT_FAILURE);
+}
+
+static void fwrite_err(FILE *fp, char *path)
+{
+ warnx("Could not write to file: %s: %s", path, strerror(errno));
+ if (fclose(fp))
+ fclose_err(path);
+ free(path);
+ exit(EXIT_FAILURE);
+}
+
#define READ_CHUNK_SIZE 512
static char *collect_smart_data(struct zpci_device *pdev)
@@ -152,12 +181,10 @@ static unsigned int sysfs_read_value(str
if (!fp)
fopen_err(path);
if (fscanf(fp, "%x", &val) != 1) {
- fclose(fp);
- warnx("Could not read file %s: %s", path, strerror(errno));
- free(path);
- exit(EXIT_FAILURE);
+ fread_err(fp, path);
}
- fclose(fp);
+ if (fclose(fp))
+ fclose_err(path);
free(path);
return val;
@@ -174,12 +201,10 @@ static void sysfs_write_value(struct zpc
if (!fp)
fopen_err(path);
if (fprintf(fp, "%x", val) < 0) {
- fclose(fp);
- warnx("Could not write to file %s: %s", path, strerror(errno));
- free(path);
- exit(EXIT_FAILURE);
+ fwrite_err(fp, path);
}
- fclose(fp);
+ if (fclose(fp))
+ fclose_err(path);
free(path);
}
@@ -196,13 +221,9 @@ static void sysfs_report_error(struct zp
if (!fp)
fopen_err(path);
if (fwrite(report, 1, r_size, fp) != r_size)
- warnx("Could not write to file: %s: %s", path, strerror(errno));
- if (fclose(fp)) {
- if (errno == EIO || errno == EOPNOTSUPP)
- warnx("Unsupported operation: %s: %s", path, strerror(errno));
- else
- warnx("Could not close file: %s: %s", path, strerror(errno));
- }
+ fwrite_err(fp, path);
+ if (fclose(fp))
+ fclose_err(path);
free(path);
}

View File

@ -1,95 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: Fix entry point for stand-alone kdump
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: abe0ba7412f4398973235497754b05a199aec818
Problem-ID: VS1804
Upstream-Description:
zipl: Fix entry point for stand-alone kdump
Currently zipl doesn't differentiate between the load address and the
entry point of an image, causing stage3 to strip away the entry point at
0x10000 for stand-alone kdump. This breaks the kdump kernel as it jumps
to 0x10000 after the special handling needed for kdump has been
performed.
Fix this by differentiating between the load address and the entry point
of an image.
Fixes: d142fbd5 ("zipl: Do not strip kernel image IPL header")
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/include/boot.h | 4 ++--
zipl/src/boot.c | 10 +++++-----
zipl/src/bootmap.c | 2 +-
3 files changed, 8 insertions(+), 8 deletions(-)
--- a/zipl/include/boot.h
+++ b/zipl/include/boot.h
@@ -310,8 +310,8 @@ int boot_init_fba_stage1b(struct boot_fb
int boot_get_eckd_stage2(void** data, size_t* size, struct job_data* job);
int boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr,
address_t initrd_addr, size_t initrd_len,
- address_t load_addr, int extra_parm, uint16_t flags,
- size_t image_len);
+ address_t entry, int extra_parm, uint16_t flags,
+ address_t image_addr, size_t image_len);
int boot_get_tape_ipl(void** data, size_t* size, address_t parm_addr,
address_t initrd_addr, address_t image_addr);
int boot_get_tape_dump(void** data, size_t* size, uint64_t mem);
--- a/zipl/src/boot.c
+++ b/zipl/src/boot.c
@@ -79,14 +79,14 @@ boot_check_data(void)
int
boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr,
address_t initrd_addr, size_t initrd_len,
- address_t image_addr, int extra_parm, uint16_t flags,
- size_t image_len)
+ address_t entry, int extra_parm, uint16_t flags,
+ address_t image_addr, size_t image_len)
{
struct boot_stage3_params params;
void* data;
- if (image_addr != (image_addr & PSW_ADDRESS_MASK)) {
- error_reason("Kernel image load address to high (31 bit "
+ if (entry != (entry & PSW_ADDRESS_MASK)) {
+ error_reason("Kernel image entry point to high (31 bit "
"addressing mode)");
return -1;
}
@@ -99,7 +99,7 @@ boot_get_stage3_parms(void **buffer, siz
params.parm_addr = (uint64_t) parm_addr;
params.initrd_addr = (uint64_t) initrd_addr;
params.initrd_len = (uint64_t) initrd_len;
- params.load_psw = (uint64_t)(image_addr | PSW_LOAD);
+ params.load_psw = (uint64_t)(entry | PSW_LOAD);
params.extra_parm = (uint64_t) extra_parm;
params.flags = flags;
params.image_len = (uint64_t) image_len;
--- a/zipl/src/bootmap.c
+++ b/zipl/src/bootmap.c
@@ -646,7 +646,7 @@ add_ipl_program(int fd, struct job_ipl_d
ipl->is_kdump ? ipl->image_addr + 0x10 :
ipl->image_addr,
(info->type == disk_type_scsi) ? 0 : 1,
- flags, image_size);
+ flags, ipl->image_addr, image_size);
if (rc) {
free(table);
return rc;

View File

@ -1,70 +0,0 @@
Subject: [PATCH] [BZ 184396] zipl: fix zipl.conf man page example for secure boot
From: Stefan Haberland <sth@linux.ibm.com>
Description: zipl: fix secure boot config handling
Symptom: The config file parsing for secure boot worked not as
it was expected to be. For example a config section
setting was not evaluated properly.
It is not possible to specify command line option -S
without other options.
Additionally the man page showed an invalid example.
Problem: The config file parsing was not implemented properly.
Solution: The hierarchy of the secure boot settings in the config
file is:
defaultboot > menu > section
Allow that --secure or -S is specified on command line
without the need to allow all options on the command
line. Also ensure that the command line option
overrules the config option and correctly ensure that
secure boot is only set for SCSI devices.
Fix man page example.
Reproduction: Run zipl with a secure= setting in a configuration
section or specify -S on command line.
Upstream-ID: 299fd2b7729f35c6fe3be18964f7e5e6a365f94d
Problem-ID: 184396
Upstream-Description:
zipl: fix zipl.conf man page example for secure boot
The secure= option is not supported in the defaultboot section when a
menu is used. It should be placed in the menu section in this case.
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
---
zipl/man/zipl.conf.5 | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/zipl/man/zipl.conf.5
+++ b/zipl/man/zipl.conf.5
@@ -82,8 +82,6 @@ below).
.br
defaultmenu = menu1
.br
-secure = auto
-.br
[linux]
.br
@@ -117,6 +115,8 @@ prompt = 1
.br
timeout = 0
.br
+secure = auto
+.br
.PP
.B BootLoaderSpec configuration files
@@ -522,7 +522,7 @@ non-default memory location.
.B secure
=
.IR auto / 1 / 0
-(configuration only)
+(configuration and menu)
.IP
.B Configuration section:
.br

View File

@ -1,82 +0,0 @@
Subject: [PATCH] [BZ 184060] zipl/libc: Indicate truncated lines in printf with '...'
From: Philipp Rudo <prudo@linux.ibm.com>
Description: zipl/libc: Fix potential buffer overflow in printf
Symptom: Crash of the zipl boot loader during boot.
Problem: The zipl boot loaders have their own minimalistic libc
implementation. In it printf and sprintf use vsprintf for string
formatting. Per definition vsprintf assumes that the buffer it
writes to is large enough to contain the formatted string and
performs no size checks. This is problematic for the boot
loaders because the buffer they use are often allocated on the
stack. Thus even small changes to the string format can
potentially cause buffer overflows on the stack.
Solution: Implement vsnprintf and make use of it.
Reproduction: Use printf to print a string with >81 characters (exact number
depends on the stack layout/compiler used).
Upstream-ID: 36fed0e6c6590631c4ce1707c8fe3c3397bcce4d
Problem-ID: 184060
Upstream-Description:
zipl/libc: Indicate truncated lines in printf with '...'
Append '...' to lines exceeding the maximum line length instead of
silently truncating them.
Suggested-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
---
zipl/boot/libc.c | 10 ++++++++--
zipl/boot/libc.h | 1 +
zipl/boot/menu.h | 1 -
3 files changed, 9 insertions(+), 3 deletions(-)
--- a/zipl/boot/libc.c
+++ b/zipl/boot/libc.c
@@ -408,11 +408,17 @@ void snprintf(char *buf, unsigned long s
*/
void printf(const char *fmt, ...)
{
- char buf[81];
+ char buf[LINE_LENGTH + 1];
+ int len;
va_list va;
va_start(va, fmt);
- vsnprintf(buf, sizeof(buf), fmt, va);
+ len = vsnprintf(buf, sizeof(buf), fmt, va);
+ if (len > LINE_LENGTH) {
+ buf[LINE_LENGTH - 1] = '.';
+ buf[LINE_LENGTH - 2] = '.';
+ buf[LINE_LENGTH - 3] = '.';
+ }
sclp_print(buf);
va_end(va);
}
--- a/zipl/boot/libc.h
+++ b/zipl/boot/libc.h
@@ -40,6 +40,7 @@
#define ENOTTY 25 /* Not a typewriter */
#define MIB (1024ULL * 1024)
+#define LINE_LENGTH 80 /* max line length printed by printf */
typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;
--- a/zipl/boot/menu.h
+++ b/zipl/boot/menu.h
@@ -20,7 +20,6 @@
/* max command line length */
#define COMMAND_LINE_SIZE 896
#define BOOT_MENU_ENTRIES 63
-#define LINE_LENGTH 80
#define PARAM_SIZE 8
#define TEXT_OFFSET 4

View File

@ -1,213 +0,0 @@
Subject: zkey: Add utility function to get the mkvp of a crypto card
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: bf8872e94a2dc4810df388d1539560b00b1acf6e
Problem-ID: SEC1916
Upstream-Description:
zkey: Add utility function to get the mkvp of a crypto card
With recent changes in the zcrypt device driver, the master key verifi-
cation patterns of the AES master key of am APQN can be obtained by
reading the sysfs attribute 'mkvps' of an APQN device of type CCA-
Coprocessor. The sysfs attribute can be found under
'/sys/devices/ap/cardnn/nn.mmmm/', where nn specifies the card number
in hex, and mmmm specifies the domain number on hex.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/utils.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
zkey/utils.h | 21 ++++++++
2 files changed, 161 insertions(+)
--- a/zkey/utils.c
+++ b/zkey/utils.c
@@ -159,3 +159,143 @@ out:
free(dev_path);
return rc;
}
+
+static int parse_mk_info(char *line, struct mk_info *mk_info)
+{
+ struct mk_info_reg *mk_reg;
+ char *save;
+ char *tok;
+
+ tok = strtok_r(line, " ", &save);
+ if (tok == NULL)
+ return -EIO;
+
+ if (strcasecmp(tok, "AES") != 0)
+ return 0;
+
+ tok = strtok_r(NULL, " ", &save);
+ if (tok == NULL)
+ return -EIO;
+
+ if (strcasecmp(tok, "NEW:") == 0)
+ mk_reg = &mk_info->new_mk;
+ else if (strcasecmp(tok, "CUR:") == 0)
+ mk_reg = &mk_info->cur_mk;
+ else if (strcasecmp(tok, "OLD:") == 0)
+ mk_reg = &mk_info->old_mk;
+ else
+ return -EIO;
+
+ tok = strtok_r(NULL, " ", &save);
+ if (tok == NULL)
+ return -EIO;
+
+ if (strcasecmp(tok, "empty") == 0)
+ mk_reg->mk_state = MK_STATE_EMPTY;
+ else if (strcasecmp(tok, "partial") == 0)
+ mk_reg->mk_state = MK_STATE_PARTIAL;
+ else if (strcasecmp(tok, "full") == 0)
+ mk_reg->mk_state = MK_STATE_FULL;
+ else if (strcasecmp(tok, "valid") == 0)
+ mk_reg->mk_state = MK_STATE_VALID;
+ else if (strcasecmp(tok, "invalid") == 0)
+ mk_reg->mk_state = MK_STATE_INVALID;
+ else
+ mk_reg->mk_state = MK_STATE_UNKNOWN;
+
+ tok = strtok_r(NULL, " ", &save);
+ if (tok == NULL)
+ return -EIO;
+
+ if (sscanf(tok, "%llx", &mk_reg->mkvp) != 1)
+ return -EIO;
+
+ return 0;
+}
+
+/**
+ * Gets the master key states and verification patterns of an APQN from the
+ * sysfs.
+ *
+ * @param[in] card card number
+ * @param[in] domain the domain
+ * @param[out] mk_info structure is filled on return with master key infos
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 if the master key info was returned. -ENODEV if the APQN is not
+ * available, or is not a CCA card. -ENOTSUP if the mkvps sysfs
+ * attribute is not available, because the zcrypt kernel module is
+ * on an older level.
+ */
+int sysfs_get_mkvps(int card, int domain, struct mk_info *mk_info, bool verbose)
+{
+ char *dev_path;
+ char *p, *end;
+ char buf[100];
+ int rc = 0;
+ FILE *fp;
+
+ if (mk_info == NULL)
+ return -EINVAL;
+
+ memset(mk_info, 0, sizeof(struct mk_info));
+ mk_info->new_mk.mk_state = MK_STATE_UNKNOWN;
+ mk_info->cur_mk.mk_state = MK_STATE_UNKNOWN;
+ mk_info->old_mk.mk_state = MK_STATE_UNKNOWN;
+
+ if (sysfs_is_apqn_online(card, domain) != 1)
+ return -ENODEV;
+
+ dev_path = util_path_sysfs("bus/ap/devices/card%02x/%02x.%04x/mkvps",
+ card, card, domain);
+ if (!util_path_is_reg_file(dev_path)) {
+ rc = -ENOTSUP;
+ goto out;
+ }
+
+ fp = fopen(dev_path, "r");
+ if (fp == NULL) {
+ rc = -ENOTSUP;
+ goto out;
+ }
+
+ /*
+ * Expected contents:
+ * AES NEW: <new_mk_state> <new_mk_mkvp>
+ * AES CUR: <cur_mk_state> <cur_mk_mkvp>
+ * AES OLD: <old_mk_state> <old_mk_mkvp>
+ * with
+ * <new_mk_state>: 'empty' or 'partial' or 'full'
+ * <cur_mk_state>, <old_mk_state>: 'valid' or 'invalid'
+ * <new_mk_mkvp>, <cur_mk_mkvp>, <old_mk_mkvp:
+ * 8 byte hex string with leading 0x
+ */
+ while ((p = fgets(buf, sizeof(buf), fp)) != NULL) {
+ end = memchr(buf, '\n', sizeof(buf));
+ if (end)
+ *end = 0;
+ else
+ buf[sizeof(buf) - 1] = 0;
+
+ pr_verbose(verbose, "mkvp for %02x.%04x: %s", card, domain,
+ buf);
+
+ rc = parse_mk_info(buf, mk_info);
+ if (rc != 0)
+ break;
+ }
+
+ fclose(fp);
+
+ if (mk_info->new_mk.mk_state == MK_STATE_UNKNOWN &&
+ mk_info->cur_mk.mk_state == MK_STATE_UNKNOWN &&
+ mk_info->old_mk.mk_state == MK_STATE_UNKNOWN)
+ rc = -EIO;
+out:
+ if (rc != 0)
+ pr_verbose(verbose, "Failed to get mkvps for %02x.%04x: %s",
+ card, domain, strerror(-rc));
+
+ free(dev_path);
+ return rc;
+}
--- a/zkey/utils.h
+++ b/zkey/utils.h
@@ -20,4 +20,25 @@ int sysfs_is_apqn_online(int card, int d
int sysfs_get_serialnr(int card, char serialnr[9], bool verbose);
+#define MK_STATE_EMPTY 0
+#define MK_STATE_PARTIAL 1
+#define MK_STATE_FULL 2
+#define MK_STATE_VALID 3
+#define MK_STATE_INVALID 4
+#define MK_STATE_UNKNOWN -1
+
+struct mk_info_reg {
+ int mk_state;
+ u64 mkvp;
+};
+
+struct mk_info {
+ struct mk_info_reg new_mk;
+ struct mk_info_reg cur_mk;
+ struct mk_info_reg old_mk;
+};
+
+int sysfs_get_mkvps(int card, int domain, struct mk_info *mk_info,
+ bool verbose);
+
#endif

View File

@ -1,76 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: Fix dependency generation in zipl/boot
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 121d5d80137f270e4828f457f717e9ab365f303b
Problem-ID: VS1804
Upstream-Description:
zipl: Fix dependency generation in zipl/boot
When adding new header from zipl/include to a .c file within zipl/boot
a compiler error appears
stage3.c:16:10: fatal error: zipl.h: No such file or directory
#include "zipl.h"
^~~~~~~~
compilation terminated.
CC zipl/boot/stage3.o
This is because the rule to generate dependencies (*.o.d) does not use
the CFLAGS_BOOT. Thus it cannot find the header and fails. Note this
only applies to the dependency generation, the actual build succeeds.
To fix this rename the CFLAGS_BOOT to ALL_CFLAGS. Using ALL_CFLAGS
instead of e.g. ALL_CPPFLAGS is important to also overwrite flags given
on the commandline via OPT_FLAGS, e.g.
make V=1 OPT_FLAGS="-D__FOO__"
While at it also remove the unused and wrong '-D__ASSEMBLY__'.
Fixes: 5a6605fe ("zipl: Ensure that boot loader CFLAGS are not overwritten")
Fixes: aa913b1e ("build process: Add automatic dependency generation")
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/Makefile | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/zipl/boot/Makefile
+++ b/zipl/boot/Makefile
@@ -1,7 +1,7 @@
# Common definitions
include ../../common.mak
-CFLAGS_BOOT = $(NO_PIE_CFLAGS) -Os -g -I../include -D__ASSEMBLY__ \
+ALL_CFLAGS = $(NO_PIE_CFLAGS) -Os -g -I $(rootdir)/zipl/include \
-DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
-fno-builtin -ffreestanding -fno-asynchronous-unwind-tables \
-fno-delete-null-pointer-checks \
@@ -21,10 +21,10 @@ all: data.o data.h tape0.bin stage3.bin
%: %.S
%.o: %.S
- $(CC) $(CFLAGS_BOOT) -c -o $@ $<
+ $(CC) $(ALL_CFLAGS) -c -o $@ $<
%.o: %.c
- $(CC) $(CFLAGS_BOOT) -c -o $@ $<
+ $(CC) $(ALL_CFLAGS) -c -o $@ $<
eckd2dump_sv.exec: \
head.o stage2dump.o cio.o eckd2dump.o eckd2dump_sv.o \

View File

@ -1,197 +0,0 @@
Subject: zkey: add function to iterate over all available CCA APQNs
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: 625b81130ab2c9d184aaede2749f1fd776f51062
Problem-ID: SEC1916
Upstream-Description:
zkey: add function to iterate over all available CCA APQNs
Add a utility function to iterate over all available APQNs of
type CCA-Coprocessor. This function is required for various
future enhancements.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/utils.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
zkey/utils.h | 5 ++
2 files changed, 132 insertions(+)
--- a/zkey/utils.c
+++ b/zkey/utils.c
@@ -7,6 +7,7 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
+#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <stdbool.h>
@@ -19,8 +20,13 @@
#include "lib/util_path.h"
#include "lib/util_file.h"
+#include "lib/util_scandir.h"
+#include "lib/util_libc.h"
+#include "lib/util_rec.h"
+#include "lib/util_base.h"
#include "utils.h"
+#include "properties.h"
#define pr_verbose(verbose, fmt...) do { \
if (verbose) \
@@ -299,3 +305,124 @@ out:
free(dev_path);
return rc;
}
+
+static int scan_for_domains(int card, apqn_handler_t handler,
+ void *handler_data, bool verbose)
+{
+ struct dirent **namelist;
+ char fname[290];
+ int i, n, domain, rc = 0;
+
+ sprintf(fname, "/sys/devices/ap/card%02x/", card);
+ n = util_scandir(&namelist, alphasort, fname,
+ "[0-9a-fA-F]+\\.[0-9a-fA-F]+");
+
+ if (n < 0)
+ return -EIO;
+
+ for (i = 0; i < n; i++) {
+ if (sscanf(namelist[i]->d_name, "%x.%x", &card, &domain) != 2)
+ continue;
+
+ pr_verbose(verbose, "Found %02x.%04x", card, domain);
+
+ if (sysfs_is_apqn_online(card, domain) != 1) {
+ pr_verbose(verbose, "APQN %02x.%04x is offline or not "
+ "CCA", card, domain);
+ continue;
+ }
+
+ rc = handler(card, domain, handler_data);
+ if (rc != 0)
+ break;
+ }
+
+ util_scandir_free(namelist, n);
+ return rc;
+}
+
+
+static int scan_for_apqns(apqn_handler_t handler, void *handler_data,
+ bool verbose)
+{
+ struct dirent **namelist;
+ int i, n, card, rc = 0;
+
+ if (handler == NULL)
+ return -EINVAL;
+
+ n = util_scandir(&namelist, alphasort, "/sys/devices/ap/",
+ "card[0-9a-fA-F]+");
+ if (n < 0)
+ return -EIO;
+
+ for (i = 0; i < n; i++) {
+ if (sscanf(namelist[i]->d_name, "card%x", &card) != 1)
+ continue;
+
+ pr_verbose(verbose, "Found card %02x", card);
+
+ if (sysfs_is_card_online(card) != 1) {
+ pr_verbose(verbose, "Card %02x is offline or not CCA",
+ card);
+ continue;
+ }
+
+ rc = scan_for_domains(card, handler, handler_data, verbose);
+ if (rc != 0)
+ break;
+ }
+
+ util_scandir_free(namelist, n);
+ return rc;
+}
+
+/**
+ * Calls the handler for all APQNs specified in the apqns parameter, or of this
+ * is NULL, for all online CCA APQNs found in sysfs. In case sysfs is inspected,
+ * the cards and domains are processed in alphabetical order.
+ *
+ * @param[in] apqns a comma separated list of APQNs. If NULL is specified,
+ * or an empty string, then all online CCA APQNs are
+ * handled.
+ * @param[in] handler a handler function that is called for each APQN
+ * @param[in] handler_data private data that is passed to the handler
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 for success or a negative errno in case of an error
+ */
+int handle_apqns(const char *apqns, apqn_handler_t handler, void *handler_data,
+ bool verbose)
+{
+ int card, domain;
+ char *copy, *tok;
+ char *save;
+ int rc = 0;
+
+ if (apqns == NULL || (apqns != NULL && strlen(apqns) == 0)) {
+ rc = scan_for_apqns(handler, handler_data, verbose);
+ } else {
+ copy = util_strdup(apqns);
+ tok = strtok_r(copy, ",", &save);
+ while (tok != NULL) {
+
+ if (sscanf(tok, "%x.%x", &card, &domain) != 2) {
+ warnx("the APQN '%s' is not valid",
+ tok);
+ rc = -EINVAL;
+ break;
+ }
+
+ pr_verbose(verbose, "Specified: %02x.%04x", card,
+ domain);
+ rc = handler(card, domain, handler_data);
+ if (rc != 0)
+ break;
+
+ tok = strtok_r(NULL, ",", &save);
+ }
+ free(copy);
+ }
+
+ return rc;
+}
--- a/zkey/utils.h
+++ b/zkey/utils.h
@@ -41,4 +41,9 @@ struct mk_info {
int sysfs_get_mkvps(int card, int domain, struct mk_info *mk_info,
bool verbose);
+typedef int(*apqn_handler_t) (int card, int domain, void *handler_data);
+
+int handle_apqns(const char *apqns, apqn_handler_t handler, void *handler_data,
+ bool verbose);
+
#endif

View File

@ -1,349 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: Make use of __packed macro
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 0f7ed7d4fc86041a8646ce7abb615849e1298cca
Problem-ID: VS1804
Upstream-Description:
zipl: Make use of __packed macro
Make use of the pre-defined __packed macro throughout zipl. This
requires adding the global include dir to ALL_CFLAGS.
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/Makefile | 2 -
zipl/boot/s390.h | 2 -
zipl/include/boot.h | 52 +++++++++++++++++++++++++------------------------
zipl/include/bootmap.h | 4 ++-
zipl/src/bootmap.c | 5 ++--
zipl/src/install.c | 3 +-
6 files changed, 37 insertions(+), 31 deletions(-)
--- a/zipl/boot/Makefile
+++ b/zipl/boot/Makefile
@@ -2,7 +2,7 @@
include ../../common.mak
ALL_CFLAGS = $(NO_PIE_CFLAGS) -Os -g -I $(rootdir)/zipl/include \
- -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
+ -I $(rootdir)/include -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
-fno-builtin -ffreestanding -fno-asynchronous-unwind-tables \
-fno-delete-null-pointer-checks \
-fexec-charset=IBM1047 -m64 -mpacked-stack \
--- a/zipl/boot/s390.h
+++ b/zipl/boot/s390.h
@@ -11,7 +11,7 @@
#ifndef S390_H
#define S390_H
-#include "../../include/lib/zt_common.h"
+#include "lib/zt_common.h"
#include "libc.h"
#define __pa32(x) ((uint32_t)(unsigned long)(x))
--- a/zipl/include/boot.h
+++ b/zipl/include/boot.h
@@ -14,6 +14,8 @@
#include <sys/types.h>
+#include "lib/zt_common.h"
+
#include "disk.h"
#include "job.h"
#include "zipl.h"
@@ -51,7 +53,7 @@ struct scsi_dump_sb {
uint64_t csum_offset;
uint64_t csum_size;
uint64_t csum;
-} __attribute((packed));
+} __packed;
#define SCSI_DUMP_SB_MAGIC 0x5a46435044554d50ULL; /* ZFCPDUMP */
/* To avoid a csum entry of 0 a seed is used */
@@ -63,7 +65,7 @@ struct scsi_dump_sb {
struct scsi_dump_param {
uint64_t block;
uint64_t reserved;
-} __attribute((packed));
+} __packed;
/* ECKD dump parameter */
struct eckd_dump_param {
@@ -73,14 +75,14 @@ struct eckd_dump_param {
uint8_t num_heads;
uint8_t bpt;
char reserved[4];
-} __attribute((packed, may_alias));
+} __packed __may_alias;
/* FBA dump parameter */
struct fba_dump_param {
uint64_t start_blk;
uint64_t blockct;
-} __attribute((packed));
+} __packed;
struct boot_info_bp_dump {
union {
@@ -89,7 +91,7 @@ struct boot_info_bp_dump {
struct scsi_dump_param scsi;
} param;
uint8_t unused[16];
-} __attribute__ ((packed));
+} __packed;
/*
* Layout of block pointer for linear devices
@@ -101,7 +103,7 @@ struct linear_blockptr {
uint16_t size;
uint16_t blockct;
uint8_t reserved[4];
-} __attribute((packed));
+} __packed;
/*
* Layout of block pointer for cylinder/head/sector devices
@@ -115,7 +117,7 @@ struct eckd_blockptr {
uint16_t size;
uint8_t blockct;
uint8_t reserved[8];
-} __attribute((packed));
+} __packed;
struct boot_info_bp_ipl {
union {
@@ -123,7 +125,7 @@ struct boot_info_bp_ipl {
struct linear_blockptr lin;
} bm_ptr;
uint8_t unused[16];
-} __attribute__ ((packed));
+} __packed;
struct boot_info {
char magic[4];
@@ -135,7 +137,7 @@ struct boot_info {
struct boot_info_bp_dump dump;
struct boot_info_bp_ipl ipl;
} bp;
-} __attribute__ ((packed));
+} __packed;
struct boot_ccw0 {
uint8_t cmd;
@@ -144,21 +146,21 @@ struct boot_ccw0 {
uint8_t flags;
uint8_t pad;
uint16_t count;
-} __attribute__ ((packed));
+} __packed;
/* Boot data structures for FBA disks */
struct boot_fba_locread {
struct boot_ccw0 locate;
struct boot_ccw0 read;
-} __attribute__ ((packed));
+} __packed;
struct boot_fba_locdata {
uint8_t command;
uint8_t dummy;
uint16_t blockct;
uint32_t blocknr;
-} __attribute__ ((packed));
+} __packed;
struct boot_fba_stage0 {
uint64_t psw;
@@ -169,13 +171,13 @@ struct boot_fba_stage0 {
struct boot_fba_locdata locdata[2];
uint64_t reserved[4];
struct boot_info boot_info;
-} __attribute__ ((packed));
+} __packed;
struct boot_fba_stage1b {
struct boot_fba_locread locread[STAGE2_BLK_CNT_MAX];
struct boot_fba_locdata locdata[STAGE2_BLK_CNT_MAX];
uint8_t unused[448];
-} __attribute__ ((packed));
+} __packed;
/* Boot data structures for ECKD disks */
@@ -184,14 +186,14 @@ struct boot_eckd_ccw1 {
uint8_t flags;
uint16_t count;
uint32_t address;
-} __attribute__ ((packed));
+} __packed;
struct boot_eckd_ssrt {
struct boot_ccw0 seek;
struct boot_ccw0 search;
struct boot_ccw0 tic;
struct boot_ccw0 read;
-} __attribute__ ((packed));
+} __packed;
struct boot_eckd_seekarg {
uint16_t pad;
@@ -199,32 +201,32 @@ struct boot_eckd_seekarg {
uint16_t head;
uint8_t sec;
uint8_t pad2;
-} __attribute__ ((packed));
+} __packed;
struct boot_eckd_cdl_stage0 {
uint64_t psw;
struct boot_ccw0 read;
struct boot_ccw0 tic;
-} __attribute__ ((packed));
+} __packed;
struct boot_eckd_ldl_stage0 {
uint64_t psw;
struct boot_ccw0 read_r0;
struct boot_ccw0 read_r1;
-} __attribute__ ((packed));
+} __packed;
struct boot_eckd_stage1 {
struct boot_eckd_ssrt ssrt[2];
struct boot_ccw0 tic1b;
struct boot_eckd_seekarg seek[2];
struct boot_info boot_info;
-} __attribute__ ((packed));
+} __packed;
struct boot_eckd_stage1b {
struct boot_eckd_ssrt ssrt[STAGE2_BLK_CNT_MAX];
struct boot_eckd_seekarg seek[STAGE2_BLK_CNT_MAX];
uint8_t unused[64];
-} __attribute__ ((packed));
+} __packed;
/* Stage 2 boot menu parameter structure */
@@ -236,7 +238,7 @@ struct boot_stage2_params {
uint16_t banner;
uint16_t config[BOOT_MENU_ENTRIES + 1];
uint64_t config_kdump;
-} __attribute__ ((packed));
+} __packed;
/* Stage 3 bootloader parameter structure */
@@ -251,7 +253,7 @@ struct boot_stage3_params {
uint16_t reserved[3];
uint64_t image_len;
uint64_t image_addr;
-} __attribute__ ((packed));
+} __packed;
#define STAGE3_FLAG_SCSI 0x0001
#define STAGE3_FLAG_KDUMP 0x0002
@@ -275,7 +277,7 @@ struct mvdump_param {
uint8_t blocksize;
uint8_t bpt;
uint8_t num_heads;
-} __attribute__ ((packed));
+} __packed;
struct mvdump_parm_table {
uint64_t timestamp;
@@ -284,7 +286,7 @@ struct mvdump_parm_table {
uint8_t ssid[MAX_DUMP_VOLUMES];
unsigned char reserved[512 - sizeof(uint64_t) - sizeof(uint16_t) -
(MAX_DUMP_VOLUMES * (sizeof(struct mvdump_param) + 1))];
-} __attribute__ ((packed));
+} __packed;
void boot_get_dump_info(struct boot_info *boot_info, uint8_t dev_type,
void *param);
--- a/zipl/include/bootmap.h
+++ b/zipl/include/bootmap.h
@@ -12,6 +12,8 @@
#ifndef BOOTMAP_H
#define BOOTMAP_H
+#include "lib/zt_common.h"
+
#include "disk.h"
#include "job.h"
#include "zipl.h"
@@ -23,7 +25,7 @@ struct signature_header {
uint8_t format;
uint8_t reserved[3];
uint32_t length;
-} __attribute((packed));
+} __packed;
typedef union {
uint64_t load_address;
--- a/zipl/src/bootmap.c
+++ b/zipl/src/bootmap.c
@@ -18,6 +18,7 @@
#include <sys/stat.h>
#include <sys/types.h>
+#include "lib/zt_common.h"
#include "lib/util_part.h"
#include "lib/util_path.h"
@@ -223,7 +224,7 @@ struct component_entry {
uint8_t data[23];
uint8_t type;
component_data compdat;
-} __attribute((packed));
+} __packed;
typedef enum {
component_execute = 0x01,
@@ -263,7 +264,7 @@ struct component_header {
uint8_t magic[4];
uint8_t type;
uint8_t reserved[27];
-} __attribute((packed));
+} __packed;
typedef enum {
component_header_ipl = 0x00,
--- a/zipl/src/install.c
+++ b/zipl/src/install.c
@@ -23,6 +23,7 @@
#include <syslog.h>
#include <unistd.h>
+#include "lib/zt_common.h"
#include "lib/util_sys.h"
#include "boot.h"
@@ -89,7 +90,7 @@ update_scsi_mbr(void* bootblock, disk_bl
uint8_t program_table_pointer[16];
uint8_t reserved2[0x50];
struct boot_info boot_info;
- } __attribute__ ((packed))* mbr;
+ } __packed* mbr;
struct scsi_dump_param param;
void* buffer;

View File

@ -1,131 +0,0 @@
Subject: zkey: Add function to print the MKVPs of APQNs
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: bfc3dd018c4f0cc17f8463d8bd6be16aab8de4a4
Problem-ID: SEC1916
Upstream-Description:
zkey: Add function to print the MKVPs of APQNs
Add a utility function to print the master key verification patterns
of a set of APQNs. This allows the user to visually check which
master keys are set on which APQNs.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/utils.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
zkey/utils.h | 2 +
2 files changed, 82 insertions(+)
--- a/zkey/utils.c
+++ b/zkey/utils.c
@@ -426,3 +426,83 @@ int handle_apqns(const char *apqns, apqn
return rc;
}
+
+struct print_apqn_info {
+ struct util_rec *rec;
+ bool verbose;
+};
+
+static int print_apqn_mk_info(int card, int domain, void *handler_data)
+{
+ struct print_apqn_info *info = (struct print_apqn_info *)handler_data;
+ struct mk_info mk_info;
+ int rc;
+
+ rc = sysfs_get_mkvps(card, domain, &mk_info, info->verbose);
+ if (rc == -ENOTSUP)
+ return rc;
+
+ util_rec_set(info->rec, "APQN", "%02x.%04x", card, domain);
+
+ if (rc == 0) {
+ if (mk_info.new_mk.mk_state == MK_STATE_FULL)
+ util_rec_set(info->rec, "NEW", "%016llx",
+ mk_info.new_mk.mkvp);
+ else if (mk_info.new_mk.mk_state == MK_STATE_PARTIAL)
+ util_rec_set(info->rec, "NEW", "partially loaded");
+ else
+ util_rec_set(info->rec, "NEW", "-");
+
+ if (mk_info.cur_mk.mk_state == MK_STATE_VALID)
+ util_rec_set(info->rec, "CUR", "%016llx",
+ mk_info.cur_mk.mkvp);
+ else
+ util_rec_set(info->rec, "CUR", "-");
+
+ if (mk_info.old_mk.mk_state == MK_STATE_VALID)
+ util_rec_set(info->rec, "OLD", "%016llx",
+ mk_info.old_mk.mkvp);
+ else
+ util_rec_set(info->rec, "OLD", "-");
+ } else {
+ util_rec_set(info->rec, "NEW", "?");
+ util_rec_set(info->rec, "CUR", "?");
+ util_rec_set(info->rec, "OLD", "?");
+ }
+
+ util_rec_print(info->rec);
+
+ return 0;
+}
+
+/**
+ * Prints master key information for all specified APQNs
+ *
+ * @param[in] apqns a comma separated list of APQNs. If NULL is specified,
+ * or an empty string, then all online CCA APQNs are
+ * printed.
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 for success or a negative errno in case of an error. -ENOTSUP is
+ * returned when the mkvps sysfs attribute is not available, because
+ * the zcrypt kernel module is on an older level.
+ */
+int print_mk_info(const char *apqns, bool verbose)
+{
+ struct print_apqn_info info;
+ int rc;
+
+ info.verbose = verbose;
+ info.rec = util_rec_new_wide("-");
+
+ util_rec_def(info.rec, "APQN", UTIL_REC_ALIGN_LEFT, 11, "CARD.DOMAIN");
+ util_rec_def(info.rec, "NEW", UTIL_REC_ALIGN_LEFT, 16, "NEW MK");
+ util_rec_def(info.rec, "CUR", UTIL_REC_ALIGN_LEFT, 16, "CURRENT MK");
+ util_rec_def(info.rec, "OLD", UTIL_REC_ALIGN_LEFT, 16, "OLD MK");
+ util_rec_print_hdr(info.rec);
+
+ rc = handle_apqns(apqns, print_apqn_mk_info, &info, verbose);
+
+ util_rec_free(info.rec);
+ return rc;
+}
--- a/zkey/utils.h
+++ b/zkey/utils.h
@@ -46,4 +46,6 @@ typedef int(*apqn_handler_t) (int card,
int handle_apqns(const char *apqns, apqn_handler_t handler, void *handler_data,
bool verbose);
+int print_mk_info(const char *apqns, bool verbose);
+
#endif

View File

@ -1,188 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: define __section macro and make use of it
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 154734efc7ffeb1e51dd2be62561a364fdc6117c
Problem-ID: VS1804
Upstream-Description:
zipl: define __section macro and make use of it
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
include/lib/zt_common.h | 1 +
zipl/boot/eckd2dump_mv.c | 8 ++++----
zipl/boot/eckd2dump_sv.c | 5 +++--
zipl/boot/fba2dump.c | 4 ++--
zipl/boot/stage2.c | 4 +++-
zipl/boot/stage2dump.c | 5 +++--
zipl/boot/stage2dump.h | 3 +--
zipl/boot/tape2dump.c | 4 +++-
8 files changed, 20 insertions(+), 14 deletions(-)
--- a/include/lib/zt_common.h
+++ b/include/lib/zt_common.h
@@ -31,6 +31,7 @@
#define __packed __attribute__((packed))
#define __aligned(x) __attribute__((aligned(x)))
#define __may_alias __attribute__((may_alias))
+#define __section(x) __attribute__((__section__(#x)))
typedef unsigned long long u64;
typedef signed long long s64;
--- a/zipl/boot/eckd2dump_mv.c
+++ b/zipl/boot/eckd2dump_mv.c
@@ -9,6 +9,8 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
+#include "lib/zt_common.h"
+
#include "eckd2dump.h"
#include "error.h"
#include "stage2dump.h"
@@ -19,8 +21,7 @@
/*
* Magic number at start of dump record
*/
-uint64_t magic __attribute__((section(".stage2.head")))
- = 0x584d554c54363401ULL; /* XMULT64, version 1 */
+uint64_t __section(.stage2.head) magic = 0x584d554c54363401ULL; /* XMULT64, version 1 */
/*
* Parameter format for ECKD MV dumper (13 bytes):
@@ -59,8 +60,7 @@ struct mvdump_parm_table {
(MAX_DUMP_VOLUMES * (sizeof(struct mvdump_param) + 1))];
} __packed;
-static struct mvdump_parm_table mvdump_table
- __attribute__((section(".eckd2dump_mv.tail")));
+static struct mvdump_parm_table __section(.eckd2dump_mv.tail) mvdump_table;
static int volnr_current;
--- a/zipl/boot/eckd2dump_sv.c
+++ b/zipl/boot/eckd2dump_sv.c
@@ -9,6 +9,8 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
+#include "lib/zt_common.h"
+
#include "eckd2dump.h"
#include "error.h"
#include "stage2dump.h"
@@ -16,8 +18,7 @@
/*
* Magic number at start of dump record
*/
-uint64_t magic __attribute__((section(".stage2.head"))) =
- 0x5845434b44363401ULL; /* "XECKD64", version 1 */
+uint64_t __section(.stage2.head) magic = 0x5845434b44363401ULL; /* "XECKD64", version 1 */
/*
* ECKD parameter block passed by zipl
--- a/zipl/boot/fba2dump.c
+++ b/zipl/boot/fba2dump.c
@@ -9,6 +9,7 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
+#include "lib/zt_common.h"
#include "error.h"
#include "fba.h"
#include "stage2dump.h"
@@ -20,8 +21,7 @@
/*
* Magic number at start of dump record
*/
-uint64_t magic __attribute__((section(".stage2.head")))
- = 0x5844464241363401ULL; /* XDFBA64, version 1 */
+uint64_t __section(.stage2.head) magic = 0x5844464241363401ULL; /* XDFBA64, version 1 */
/*
* FBA dump device partition specification
--- a/zipl/boot/stage2.c
+++ b/zipl/boot/stage2.c
@@ -9,6 +9,8 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
+#include "lib/zt_common.h"
+
#include "error.h"
#include "libc.h"
#include "menu.h"
@@ -141,4 +143,4 @@ void panic_notify(unsigned long UNUSED(r
{
}
-uint64_t stage2_head __attribute__((section(".stage2.head")));
+uint64_t __section(.stage2.head) stage2_head;
--- a/zipl/boot/stage2dump.c
+++ b/zipl/boot/stage2dump.c
@@ -11,6 +11,8 @@
#include <stdarg.h>
+#include "lib/zt_common.h"
+
#include "error.h"
#include "sclp.h"
#include "stage2dump.h"
@@ -34,8 +36,7 @@ struct ipib_info {
/*
* Tail parameters
*/
-struct stage2dump_parm_tail parm_tail
- __attribute__ ((section(".stage2dump.tail"))) = {
+struct stage2dump_parm_tail parm_tail = {
.mem_upper_limit = 0xffffffffffffffffULL,
};
--- a/zipl/boot/stage2dump.h
+++ b/zipl/boot/stage2dump.h
@@ -28,8 +28,7 @@ struct stage2dump_parm_tail {
uint64_t mem_upper_limit;
} __packed;
-extern struct stage2dump_parm_tail parm_tail
- __attribute__ ((section(".stage2dump.tail")));
+extern struct stage2dump_parm_tail __section(.stage2dump.tail) parm_tail;
/*
* S390 dump format defines
--- a/zipl/boot/tape2dump.c
+++ b/zipl/boot/tape2dump.c
@@ -9,6 +9,8 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
+#include "lib/zt_common.h"
+
#include "cio.h"
#include "error.h"
#include "libc.h"
@@ -33,7 +35,7 @@ struct tape_head {
uint64_t ccw2;
} __packed;
-struct tape_head tape_head __attribute__((section(".stage2.head"))) = {
+struct tape_head __section(.stage2.head) tape_head = {
.psw = 0x0008000080002018ULL, /* Start code at 0x2018 */
.ccw1 = 0x0700000060000001ULL, /* Rewind ccw */
.ccw2 = 0x0200200020003000ULL, /* CCW to load dump tool to 0x2000 */

View File

@ -1,271 +0,0 @@
Subject: zkey: Add function to cross check APQNs for valid master keys
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: b32c0314746ddee69e59f892f105acd720d06452
Problem-ID: SEC1916
Upstream-Description:
zkey: Add function to cross check APQNs for valid master keys
Add a utility function to cross check the master keys of a set of
APQNs. It checks for valid master keys in the CURRENT and OLD
master key registers, as well as newly loaded master keys in the NEW
register. It issues information and warning messages for various
findings and also indicates improper master key setup to the caller.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/utils.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
zkey/utils.h | 3
2 files changed, 220 insertions(+)
--- a/zkey/utils.c
+++ b/zkey/utils.c
@@ -506,3 +506,220 @@ int print_mk_info(const char *apqns, boo
util_rec_free(info.rec);
return rc;
}
+
+struct cross_check_info {
+ u64 mkvp;
+ u64 new_mkvp;
+ bool key_mkvp;
+ u32 num_cur_match;
+ u32 num_old_match;
+ u32 num_new_match;
+ bool mismatch;
+ bool print_mks;
+ int num_checked;
+ bool verbose;
+};
+
+static int cross_check_mk_info(int card, int domain, void *handler_data)
+{
+ struct cross_check_info *info = (struct cross_check_info *)handler_data;
+ struct mk_info mk_info;
+ char temp[200];
+ int rc;
+
+ rc = sysfs_get_mkvps(card, domain, &mk_info, info->verbose);
+ if (rc == -ENODEV) {
+ info->print_mks = 1;
+ printf("WARNING: APQN %02x.%04x: Not available or not of "
+ "type CCA\n", card, domain);
+ return 0;
+ }
+ if (rc != 0)
+ return rc;
+
+ info->num_checked++;
+
+ if (mk_info.new_mk.mk_state == MK_STATE_PARTIAL) {
+ info->print_mks = 1;
+ sprintf(temp, "INFO: APQN %02x.%04x: The NEW master key "
+ "register is only partially loaded.", card, domain);
+ util_print_indented(temp, 0);
+ }
+
+ if (info->new_mkvp == 0 &&
+ mk_info.new_mk.mk_state == MK_STATE_FULL)
+ info->new_mkvp = mk_info.new_mk.mkvp;
+
+ if (mk_info.new_mk.mk_state == MK_STATE_FULL &&
+ mk_info.new_mk.mkvp != info->new_mkvp) {
+ info->print_mks = 1;
+ sprintf(temp, "WARNING: APQN %02x.%04x: The NEW master key "
+ "register contains a different master key than "
+ "the NEW register of other APQNs.", card,
+ domain);
+ util_print_indented(temp, 0);
+ }
+
+ if (mk_info.cur_mk.mk_state != MK_STATE_VALID) {
+ info->print_mks = 1;
+ info->mismatch = 1;
+ printf("WARNING: APQN %02x.%04x: No master key is set.\n", card,
+ domain);
+ return 0;
+ }
+
+ if (mk_info.old_mk.mk_state == MK_STATE_VALID &&
+ mk_info.old_mk.mkvp == mk_info.cur_mk.mkvp) {
+ info->print_mks = 1;
+ sprintf(temp, "INFO: APQN %02x.%04x: The OLD master key "
+ "register contains the same master key as the CURRENT "
+ "master key register.", card, domain);
+ util_print_indented(temp, 0);
+ }
+ if (mk_info.new_mk.mk_state == MK_STATE_FULL &&
+ mk_info.new_mk.mkvp == mk_info.cur_mk.mkvp) {
+ info->print_mks = 1;
+ sprintf(temp, "INFO: APQN %02x.%04x: The NEW master key "
+ "register contains the same master key as the CURRENT "
+ "master key register.", card, domain);
+ util_print_indented(temp, 0);
+ }
+ if (mk_info.new_mk.mk_state == MK_STATE_FULL &&
+ mk_info.old_mk.mk_state == MK_STATE_VALID &&
+ mk_info.new_mk.mkvp == mk_info.old_mk.mkvp) {
+ info->print_mks = 1;
+ sprintf(temp, "INFO: APQN %02x.%04x: The NEW master key "
+ "register contains the same master key as the OLD "
+ "master key register.", card, domain);
+ util_print_indented(temp, 0);
+ }
+
+ if (info->mkvp == 0)
+ info->mkvp = mk_info.cur_mk.mkvp;
+
+ if (info->key_mkvp) {
+ if (mk_info.cur_mk.mk_state == MK_STATE_VALID &&
+ mk_info.cur_mk.mkvp == info->mkvp)
+ info->num_cur_match++;
+
+ if (mk_info.old_mk.mk_state == MK_STATE_VALID &&
+ mk_info.old_mk.mkvp == info->mkvp)
+ info->num_old_match++;
+
+ if (mk_info.new_mk.mk_state == MK_STATE_FULL &&
+ mk_info.new_mk.mkvp == info->mkvp)
+ info->num_new_match++;
+ }
+
+ if (mk_info.cur_mk.mkvp != info->mkvp) {
+
+ if (info->key_mkvp) {
+ if (mk_info.old_mk.mk_state == MK_STATE_VALID &&
+ mk_info.old_mk.mkvp == info->mkvp) {
+ info->print_mks = 1;
+ sprintf(temp, "INFO: APQN %02x.%04x: The master"
+ " key has been changed to a new "
+ "master key, but the secure key has "
+ "not yet been re-enciphered.", card,
+ domain);
+ util_print_indented(temp, 0);
+ } else if (mk_info.new_mk.mk_state == MK_STATE_FULL &&
+ mk_info.new_mk.mkvp == info->mkvp) {
+ info->print_mks = 1;
+ sprintf(temp, "INFO: APQN %02x.%04x: The master"
+ " key has been changed but is not "
+ "yet been set (made active).", card,
+ domain);
+ util_print_indented(temp, 0);
+ } else {
+ info->print_mks = 1;
+ info->mismatch = 1;
+ sprintf(temp, "WARNING: APQN %02x.%04x: The "
+ "CURRENT master key register contains "
+ "a master key that is different from "
+ "the one used by the secure key.", card,
+ domain);
+ util_print_indented(temp, 0);
+ }
+ } else {
+ info->print_mks = 1;
+ info->mismatch = 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Cross checks the master key information for all specified APQNs. It checks
+ * if all specified APQNs have the same current master key, and if it matches
+ * the master key specified by the mkvp parameter (optional). If not, it prints
+ * out an information message about the APQNs that have a different master key.
+ *
+ * @param[in] apqns a comma separated list of APQNs. If NULL is specified,
+ * or an empty string, then all online CCA APQNs are
+ * checked.
+ * @param[in] mkvp The master key verification pattern of a secure key.
+ * If this is all zero, then the master keys are not
+ * matched against it.
+ * @param[in] print_mks if true, then a the full master key info of all
+ * specified APQns is printed, in case of a mismatch.
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 for success or a negative errno in case of an error. -ENODEV is
+ * returned if at least one APQN has a mismatching master key.
+ * -ENOTSUP is returned when the mkvps sysfs attribute is not
+ * available, because the zcrypt kernel module is on an older level.
+ */
+int cross_check_apqns(const char *apqns, u64 mkvp, bool print_mks, bool verbose)
+{
+ struct cross_check_info info;
+ char temp[200];
+ int rc;
+
+ memset(&info, 0, sizeof(info));
+ info.key_mkvp = mkvp != 0;
+ info.mkvp = mkvp;
+ info.verbose = verbose;
+
+ pr_verbose(verbose, "Cross checking APQNs with mkvp 0x%016llx: %s",
+ mkvp, apqns != NULL ? apqns : "ANY");
+
+ rc = handle_apqns(apqns, cross_check_mk_info, &info, verbose);
+ if (rc != 0)
+ return rc;
+
+ if (info.mismatch) {
+ if (info.key_mkvp)
+ printf("WARNING: Not all APQNs have the correct master "
+ "key (%016llx).\n", mkvp);
+ else
+ printf("WARNING: Not all APQNs have the same master "
+ "key.\n");
+
+ rc = -ENODEV;
+ }
+ if (info.num_checked == 0) {
+ printf("WARNING: None of the APQNs is available or of "
+ "type CCA\n");
+ rc = -ENODEV;
+ }
+ if (info.num_old_match > 0 && info.num_new_match > 0) {
+ sprintf(temp, "WARNING: On %u APQNs the OLD master key "
+ "register contains the master key use by the secure "
+ "key, and on %u APQNs the NEW master key register "
+ "contains the master key use by the secure key.",
+ info.num_old_match, info.num_new_match);
+ util_print_indented(temp, 0);
+ info.print_mks = 1;
+ rc = -ENODEV;
+ }
+
+ if (print_mks && info.print_mks) {
+ printf("\n");
+ print_mk_info(apqns, verbose);
+ printf("\n");
+ }
+
+ return rc;
+}
--- a/zkey/utils.h
+++ b/zkey/utils.h
@@ -48,4 +48,7 @@ int handle_apqns(const char *apqns, apqn
int print_mk_info(const char *apqns, bool verbose);
+int cross_check_apqns(const char *apqns, u64 mkvp, bool print_mks,
+ bool verbose);
+
#endif

View File

@ -1,61 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: Make use of __noreturn macro
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 86856f98dbe3f68e34b91b58e9fc92f7cdc8a0d4
Problem-ID: VS1804
Upstream-Description:
zipl: Make use of __noreturn macro
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/libc.c | 4 +++-
zipl/boot/libc.h | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
--- a/zipl/boot/libc.c
+++ b/zipl/boot/libc.c
@@ -11,6 +11,8 @@
#include <stdarg.h>
+#include "lib/zt_common.h"
+
#include "error.h"
#include "libc.h"
#include "sclp.h"
@@ -511,7 +513,7 @@ void initialize(void)
/*
* Load disabled wait PSW with reason code in address field
*/
-void libc_stop(unsigned long reason)
+void __noreturn libc_stop(unsigned long reason)
{
struct psw_t psw;
--- a/zipl/boot/libc.h
+++ b/zipl/boot/libc.h
@@ -60,7 +60,7 @@ char *strcpy(char *, const char *);
unsigned long get_zeroed_page(void);
void free_page(unsigned long);
void initialize(void);
-void libc_stop(unsigned long) __attribute__((noreturn));
+void libc_stop(unsigned long);
void start(void);
void pgm_check_handler(void);
void pgm_check_handler_fn(void);

View File

@ -1,74 +0,0 @@
Subject: zkey: Add function to obtain the mkvp of a secure key
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: ea7cc9ea606dd879e4cdfae06a6f13d8fa3afff4
Problem-ID: SEC1916
Upstream-Description:
zkey: Add function to obtain the mkvp of a secure key
A secure AES key token contains the master key verification pattern
of the master key it is encrypted with. Add a function to obtain the
master key verification pattern of a secure key token.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/pkey.c | 21 +++++++++++++++++++++
zkey/pkey.h | 4 ++++
2 files changed, 25 insertions(+)
--- a/zkey/pkey.c
+++ b/zkey/pkey.c
@@ -769,3 +769,24 @@ out:
return rc;
}
+
+int get_master_key_verification_pattern(const u8 *secure_key,
+ size_t secure_key_size, u64 *mkvp,
+ bool verbose)
+{
+ struct secaeskeytoken *token = (struct secaeskeytoken *)secure_key;
+
+ util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
+ util_assert(mkvp != NULL, "Internal error: mkvp is NULL");
+
+ if (secure_key_size < SECURE_KEY_SIZE) {
+ pr_verbose(verbose, "Size of secure key is too small: "
+ "%lu expected %lu", secure_key_size,
+ SECURE_KEY_SIZE);
+ return -EINVAL;
+ }
+
+ *mkvp = token->mkvp;
+
+ return 0;
+}
--- a/zkey/pkey.h
+++ b/zkey/pkey.h
@@ -112,4 +112,8 @@ int validate_secure_key(int pkey_fd,
int generate_key_verification_pattern(const char *key, size_t key_size,
char *vp, size_t vp_len, bool verbose);
+int get_master_key_verification_pattern(const u8 *secure_key,
+ size_t secure_key_size, u64 *mkvp,
+ bool verbose);
+
#endif

View File

@ -1,66 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: Define __noinline macro and make use of it
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 5eace91ee7bd76b8ab44291299ac313c87c9ecb8
Problem-ID: VS1804
Upstream-Description:
zipl: Define __noinline macro and make use of it
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
include/lib/zt_common.h | 1 +
libutil/util_panic_example.c | 2 +-
zipl/boot/libc.c | 2 +-
3 files changed, 3 insertions(+), 2 deletions(-)
--- a/include/lib/zt_common.h
+++ b/include/lib/zt_common.h
@@ -32,6 +32,7 @@
#define __aligned(x) __attribute__((aligned(x)))
#define __may_alias __attribute__((may_alias))
#define __section(x) __attribute__((__section__(#x)))
+#define __noinline __attribute__((__noinline__))
typedef unsigned long long u64;
typedef signed long long s64;
--- a/libutil/util_panic_example.c
+++ b/libutil/util_panic_example.c
@@ -15,10 +15,10 @@
#include <sys/resource.h>
#include <sys/time.h>
+#include "lib/zt_common.h"
#include "lib/util_panic.h"
/* Make functions noinline to have a nice backtrace */
-#define __noinline __attribute__((noinline))
/*
* Test util_panic()
--- a/zipl/boot/libc.c
+++ b/zipl/boot/libc.c
@@ -473,7 +473,7 @@ void pgm_check_handler_fn(void)
libc_stop(psw_old->addr);
}
-__attribute__ ((noinline)) void load_wait_psw(uint64_t psw_mask, struct psw_t *psw)
+void __noinline load_wait_psw(uint64_t psw_mask, struct psw_t *psw)
{
struct psw_t wait_psw = { .mask = psw_mask, .addr = 0 };
struct psw_t old_psw, *wait_psw_ptr = &wait_psw;

View File

@ -1,176 +0,0 @@
Subject: zkey: Display MKVP when validating a secure key
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: c2244a57950f4eb35e3209151dcf48de66828df1
Problem-ID: SEC1916
Upstream-Description:
zkey: Display MKVP when validating a secure key
Display the master key verification pattern of a secure key while
'zkey validate' and 'zkey-cryptsetup validate'
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/keystore.c | 20 ++++++++++++++------
zkey/zkey-cryptsetup.c | 16 +++++++++++++---
zkey/zkey.c | 14 ++++++++++++--
3 files changed, 39 insertions(+), 11 deletions(-)
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -2107,7 +2107,7 @@ static void _keystore_print_record(struc
bool validation, const char *skey_filename,
size_t secure_key_size,
size_t clear_key_bitsize, bool valid,
- bool is_old_mk, bool reenc_pending)
+ bool is_old_mk, bool reenc_pending, u64 mkvp)
{
char temp_vp[VERIFICATION_PATTERN_LEN + 2];
char *volumes_argz = NULL;
@@ -2169,10 +2169,11 @@ static void _keystore_print_record(struc
if (validation) {
if (valid)
util_rec_set(rec, REC_MASTERKEY,
- is_old_mk ? "OLD CCA master key" :
- "CURRENT CCA master key");
+ "%s CCA master key (MKVP: %016llx)",
+ is_old_mk ? "OLD" : "CURRENT", mkvp);
else
- util_rec_set(rec, REC_MASTERKEY, "(unknown)");
+ util_rec_set(rec, REC_MASTERKEY,
+ "(unknown, MKVP: %016llx)", mkvp);
}
if (volumes_argz != NULL)
util_rec_set_argz(rec, REC_VOLUMES, volumes_argz,
@@ -2350,6 +2351,7 @@ static int _keystore_process_validate(st
u8 *secure_key;
int is_old_mk;
int rc, valid;
+ u64 mkvp;
rc = _keystore_ensure_keyfiles_exist(file_names, name);
if (rc != 0)
@@ -2373,12 +2375,18 @@ static int _keystore_process_validate(st
info->num_valid++;
valid = 1;
}
+
+ rc = get_master_key_verification_pattern(secure_key, secure_key_size,
+ &mkvp, keystore->verbose);
free(secure_key);
+ if (rc)
+ goto out;
_keystore_print_record(info->rec, name, properties, 1,
file_names->skey_filename, secure_key_size,
clear_key_bitsize, valid, is_old_mk,
- _keystore_reencipher_key_exists(file_names));
+ _keystore_reencipher_key_exists(file_names),
+ mkvp);
if (valid && is_old_mk) {
util_print_indented("WARNING: The secure key is currently "
@@ -3131,7 +3139,7 @@ static int _keystore_display_key(struct
IS_XTS(secure_key_size) ? secure_key->bitsize * 2
: secure_key->bitsize,
0, 0,
- _keystore_reencipher_key_exists(file_names));
+ _keystore_reencipher_key_exists(file_names), 0);
out:
free(secure_key);
--- a/zkey/zkey-cryptsetup.c
+++ b/zkey/zkey-cryptsetup.c
@@ -1834,6 +1834,7 @@ static int command_validate(void)
char *prompt;
char *msg;
int token;
+ u64 mkvp;
int rc;
util_asprintf(&prompt, "Enter passphrase for '%s': ", g.pos_arg);
@@ -1864,6 +1865,14 @@ static int command_validate(void)
vp_tok_avail = 1;
}
+ rc = get_master_key_verification_pattern((u8 *)key, keysize,
+ &mkvp, g.verbose);
+ if (rc != 0) {
+ warnx("Failed to get the master key verification pattern: %s",
+ strerror(-rc));
+ goto out;
+ }
+
printf("Validation of secure volume key of device '%s':\n", g.pos_arg);
printf(" Status: %s\n", is_valid ? "Valid" : "Invalid");
printf(" Secure key size: %lu bytes\n", keysize);
@@ -1871,11 +1880,12 @@ static int command_validate(void)
keysize > SECURE_KEY_SIZE ? "Yes" : "No");
if (is_valid) {
printf(" Clear key size: %lu bits\n", clear_keysize);
- printf(" Enciphered with: %s CCA master key\n",
- is_old_mk ? "OLD" : "CURRENT");
+ printf(" Enciphered with: %s CCA master key (MKVP: "
+ "%016llx)\n", is_old_mk ? "OLD" : "CURRENT", mkvp);
} else {
printf(" Clear key size: (unknown)\n");
- printf(" Enciphered with: (unknown)\n");
+ printf(" Enciphered with: (unknown, MKVP: %016llx)\n",
+ mkvp);
}
if (vp_tok_avail)
print_verification_pattern(vp_tok.verification_pattern);
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -1300,6 +1300,7 @@ static int command_validate_file(void)
size_t clear_key_size;
u8 *secure_key;
int is_old_mk;
+ u64 mkvp;
int rc;
if (g.name != NULL) {
@@ -1346,14 +1347,23 @@ static int command_validate_file(void)
goto out;
}
+ rc = get_master_key_verification_pattern(secure_key, secure_key_size,
+ &mkvp, g.verbose);
+ if (rc != 0) {
+ warnx("Failed to get the master key verification pattern: %s",
+ strerror(-rc));
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+
printf("Validation of secure key in file '%s':\n", g.pos_arg);
printf(" Status: Valid\n");
printf(" Secure key size: %lu bytes\n", secure_key_size);
printf(" Clear key size: %lu bits\n", clear_key_size);
printf(" XTS type key: %s\n",
secure_key_size > SECURE_KEY_SIZE ? "Yes" : "No");
- printf(" Enciphered with: %s CCA master key\n",
- is_old_mk ? "OLD" : "CURRENT");
+ printf(" Enciphered with: %s CCA master key (MKVP: %016llx)\n",
+ is_old_mk ? "OLD" : "CURRENT", mkvp);
printf(" Verification pattern: %.*s\n", VERIFICATION_PATTERN_LEN / 2,
vp);
printf(" %.*s\n", VERIFICATION_PATTERN_LEN / 2,

View File

@ -1,49 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl/stage3: Mark start_kernel __noreturn
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: edfb6a03d862e332223eda02be46109be12c0a4e
Problem-ID: VS1804
Upstream-Description:
zipl/stage3: Mark start_kernel __noreturn
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/stage3.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/zipl/boot/stage3.c
+++ b/zipl/boot/stage3.c
@@ -175,8 +175,7 @@ static void ebcdic_to_ascii(unsigned cha
target[i] = ebc[source[i]];
}
-static void
-start_kernel(void)
+static inline void __noreturn start_kernel(void)
{
struct psw_t *psw = &S390_lowcore.program_new_psw;
unsigned long addr, code;
@@ -199,6 +198,7 @@ start_kernel(void)
: [addr] "=&d" (addr),
[code] "+&d" (code)
: [psw] "a" (psw) );
+ while (1);
}
unsigned int

View File

@ -1,91 +0,0 @@
Subject: zkey: Cross check APQNs when generating secure keys
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: a5b58038a0dbf1c3eb202a6933265f0d2e57e130
Problem-ID: SEC1916
Upstream-Description:
zkey: Cross check APQNs when generating secure keys
Perform a cross check of the APQNs when a new secure AES key is
generated. When a set of APQNs are associated to a new secure key,
these APQNs are cross checked. If a new secure key is generated
outside of the key repository, or no APQNs are associated to a secure
key generated inside the key repository, then all currently available
APQNs are cross checked. If a master key mismatch is detected, then
the key generation is rejected.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/keystore.c | 8 ++++++++
zkey/zkey.c | 11 +++++++++++
2 files changed, 19 insertions(+)
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -1685,6 +1685,14 @@ int keystore_generate_key(struct keystor
if (rc != 0)
goto out_free_key_filenames;
+ rc = cross_check_apqns(apqns, 0, true, keystore->verbose);
+ if (rc == -EINVAL)
+ goto out_free_key_filenames;
+ if (rc != 0 && rc != -ENOTSUP && noapqncheck == 0) {
+ warnx("Your master key setup is improper");
+ goto out_free_key_filenames;
+ }
+
rc = _keystore_get_card_domain(apqns, &card, &domain);
if (rc != 0)
goto out_free_key_filenames;
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -31,6 +31,7 @@
#include "keystore.h"
#include "misc.h"
#include "pkey.h"
+#include "utils.h"
/*
* Program configuration
@@ -1060,6 +1061,8 @@ static int command_generate_repository(v
*/
static int command_generate(void)
{
+ int rc;
+
if (g.pos_arg != NULL && g.name != NULL) {
warnx(" Option '--name|-N' is not valid for generating a key "
"outside of the repository");
@@ -1100,6 +1103,14 @@ static int command_generate(void)
return EXIT_FAILURE;
}
+ rc = cross_check_apqns(NULL, 0, true, g.verbose);
+ if (rc == -EINVAL)
+ return EXIT_FAILURE;
+ if (rc != 0 && rc != -ENOTSUP) {
+ warnx("Your master key setup is improper");
+ return EXIT_FAILURE;
+ }
+
return g.clearkeyfile ? command_generate_clear()
: command_generate_random();
}

View File

@ -1,41 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl/sclp: Remove duplicate macros
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: b2ae5a91ac16c5facb892dedc2dcb268eff07edf
Problem-ID: VS1804
Upstream-Description:
zipl/sclp: Remove duplicate macros
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/sclp_stage3.h | 3 ---
1 file changed, 3 deletions(-)
--- a/zipl/boot/sclp_stage3.h
+++ b/zipl/boot/sclp_stage3.h
@@ -17,9 +17,6 @@
#define SDIAS_EVSTATE_ALL_STORED 0x00
#define SDIAS_EVSTATE_PART_STORED 0x10
-#define SDIAS_EVSTATE_ALL_STORED 0x00
-#define SDIAS_EVSTATE_PART_STORED 0x10
-
struct sdias_evbuf {
struct evbuf_header header;
uint8_t event_qual;

View File

@ -1,123 +0,0 @@
Subject: zkey: Cross check APQNs when validating secure keys
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: 7f8e31e8619b32297b432a4882d78af79de37a58
Problem-ID: SEC1916
Upstream-Description:
zkey: Cross check APQNs when validating secure keys
Perform a cross check of the APQNs when a secure AES key is validated.
When a set of APQNs are associated to a secure key, these APQNs are
cross checked. If a secure key is validated outside of the key repository,
or no APQNs are associated to a secure key inside the key repository,
then all currently available APQNs are cross checked. If a master key
mismatch is detected, then an error message is issued.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/keystore.c | 34 ++++++++++++----------------------
zkey/zkey.c | 9 +++++++++
2 files changed, 21 insertions(+), 22 deletions(-)
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -2252,43 +2252,32 @@ struct validate_info {
/**
* Displays the status of the associated APQNs.
*
+ * @param[in] keystore the key store
* @param[in] properties the properties of the key
- * @param[in] name the name of the key
+ * @param[in] mkvp the master key verification pattern of the key
*
* @returns 0 in case of success, 1 if at least one of the APQNs is not
- * available
+ * available or has a master key mismatch
*/
-static int _keystore_display_apqn_status(struct properties *properties,
- const char *name)
+static int _keystore_display_apqn_status(struct keystore *keystore,
+ struct properties *properties,
+ u64 mkvp)
{
- int i, rc, card, domain, warning = 0;
- char **apqn_list;
+ int rc, warning = 0;
char *apqns;
apqns = properties_get(properties, PROP_NAME_APQNS);
if (apqns == NULL)
return 0;
- apqn_list = str_list_split(apqns);
-
- for (i = 0; apqn_list[i] != NULL; i++) {
-
- if (sscanf(apqn_list[i], "%x.%x", &card, &domain) != 2)
- continue;
- rc = sysfs_is_apqn_online(card, domain);
- if (rc != 1) {
- printf("WARNING: The APQN %02x.%04x associated with "
- "key '%s' is %s\n", card, domain, name,
- rc == -1 ? "not a CCA card" : "not online");
- warning = 1;
- }
- }
+ rc = cross_check_apqns(apqns, mkvp, true, keystore->verbose);
+ if (rc != 0 && rc != -ENOTSUP)
+ warning = 1;
if (warning)
printf("\n");
free(apqns);
- str_list_free_string_array(apqn_list);
return warning;
}
/**
@@ -2405,7 +2394,8 @@ static int _keystore_process_validate(st
info->num_warnings++;
}
if (info->noapqncheck == 0)
- if (_keystore_display_apqn_status(properties, name) != 0)
+ if (_keystore_display_apqn_status(keystore, properties,
+ mkvp) != 0)
info->num_warnings++;
if (_keystore_display_volume_status(properties, name) != 0)
info->num_warnings++;
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -1380,6 +1380,15 @@ static int command_validate_file(void)
printf(" %.*s\n", VERIFICATION_PATTERN_LEN / 2,
&vp[VERIFICATION_PATTERN_LEN / 2]);
+ rc = cross_check_apqns(NULL, mkvp, true, g.verbose);
+ if (rc == -EINVAL)
+ return EXIT_FAILURE;
+ if (rc != 0 && rc != -ENOTSUP) {
+ warnx("Your master key setup is improper");
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+
out:
free(secure_key);
return rc;

View File

@ -1,116 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: Make address/size/mask macros UL
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: ea14f5471c6fbc9a8a407aa33324db39082b4689
Problem-ID: VS1804
Upstream-Description:
zipl: Make address/size/mask macros UL
While at it also fix some white space damages.
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/stage3.h | 18 +++++++++---------
zipl/include/zipl.h | 36 ++++++++++++++++++------------------
2 files changed, 27 insertions(+), 27 deletions(-)
--- a/zipl/boot/stage3.h
+++ b/zipl/boot/stage3.h
@@ -15,12 +15,12 @@
#include "libc.h"
#include "s390.h"
-#define IPL_DEVICE 0x10404
-#define INITRD_START 0x10408
-#define INITRD_SIZE 0x10410
-#define OLDMEM_BASE 0x10418
-#define OLDMEM_SIZE 0x10420
-#define COMMAND_LINE 0x10480
+#define IPL_DEVICE 0x10404UL
+#define INITRD_START 0x10408UL
+#define INITRD_SIZE 0x10410UL
+#define OLDMEM_BASE 0x10418UL
+#define OLDMEM_SIZE 0x10420UL
+#define COMMAND_LINE 0x10480UL
#define COMMAND_LINE_SIZE 896
#define COMMAND_LINE_EXTRA 0xE000
@@ -30,11 +30,11 @@
#define IPL_FLAG_SECURE 0x40
#define DEFAULT_IMAGE_ADDR 0x10000
-#define DEFAULT_PSW_LOAD 0x0008000080010000L
-#define PSW_ADDR_MASK 0x000000007FFFFFFFL
+#define DEFAULT_PSW_LOAD 0x0008000080010000UL
+#define PSW_ADDR_MASK 0x000000007FFFFFFFUL
#define KERNEL_HEADER_SIZE 65536
-#define UNSPECIFIED_ADDRESS -1ULL
+#define UNSPECIFIED_ADDRESS -1UL
/* IPL Parameter List header */
--- a/zipl/include/zipl.h
+++ b/zipl/include/zipl.h
@@ -19,27 +19,27 @@
#define ZIPL_MAGIC_SIZE 4
#define DISK_LAYOUT_ID 0x00000001
-#define ZIPL_STAGE2_LOAD_ADDRESS 0x2000
-#define ZIPL_STAGE3_ENTRY_ADDRESS 0xa000LL
-#define DEFAULT_IMAGE_ADDRESS 0x10000LL
-#define KDUMP_IMAGE_ADDRESS 0x10010LL
-#define DEFAULT_STAGE3_ADDRESS 0xa000LL
-#define DEFAULT_STAGE3_PARAMS_ADDRESS 0x9000LL
-#define MINIMUM_ADDRESS 0x10000LL
-#define ADDRESS_LIMIT 0x80000000LL
+#define ZIPL_STAGE2_LOAD_ADDRESS 0x2000UL
+#define ZIPL_STAGE3_ENTRY_ADDRESS 0xa000UL
+#define DEFAULT_IMAGE_ADDRESS 0x10000UL
+#define KDUMP_IMAGE_ADDRESS 0x10010UL
+#define DEFAULT_STAGE3_ADDRESS 0xa000UL
+#define DEFAULT_STAGE3_PARAMS_ADDRESS 0x9000UL
+#define MINIMUM_ADDRESS 0x10000UL
+#define ADDRESS_LIMIT 0x80000000UL
#define ADDRESS_LIMIT_KDUMP 0x2000000UL /* HSA size: 32 MiB */
-#define UNSPECIFIED_ADDRESS -1ULL
-#define MAXIMUM_PARMLINE_SIZE 0x380
-#define MAXIMUM_PHYSICAL_BLOCKSIZE 0x1000
+#define UNSPECIFIED_ADDRESS -1UL
+#define MAXIMUM_PARMLINE_SIZE 0x380UL
+#define MAXIMUM_PHYSICAL_BLOCKSIZE 0x1000UL
-#define STAGE3_HEAP_SIZE 0x4000
-#define STAGE3_HEAP_ADDRESS 0x2000
-#define STAGE3_STACK_SIZE 0x1000
-#define STAGE3_STACK_ADDRESS 0xF000
+#define STAGE3_HEAP_SIZE 0x4000UL
+#define STAGE3_HEAP_ADDRESS 0x2000UL
+#define STAGE3_STACK_SIZE 0x1000UL
+#define STAGE3_STACK_ADDRESS 0xF000UL
-#define PSW_ADDRESS_MASK 0x000000007fffffffLL
-#define PSW_LOAD 0x0008000080000000LL
-#define PSW_DISABLED_WAIT 0x000a000000000000LL
+#define PSW_ADDRESS_MASK 0x000000007fffffffUL
+#define PSW_LOAD 0x0008000080000000UL
+#define PSW_DISABLED_WAIT 0x000a000000000000UL
#define BOOTMAP_FILENAME "bootmap"
#define BOOTMAP_TEMPLATE_FILENAME "bootmap_temp.XXXXXX"

View File

@ -1,85 +0,0 @@
Subject: zkey: Cross check APQNs when importing secure keys
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: d854aed4b8154e7420def8749db2106a049dd80a
Problem-ID: SEC1916
Upstream-Description:
zkey: Cross check APQNs when importing secure keys
Perform a cross check of the APQNs when an existing secure AES key is
imported into the key repository. When a set of APQNs are associated to
the imported secure key, these APQNs are cross checked. If no APQNs are
associated to imported secure key, then all currently available
APQNs are cross checked. If a master key mismatch is detected, then
the key import is rejected.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/keystore.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -1770,6 +1770,7 @@ int keystore_import_key(struct keystore
struct properties *key_props = NULL;
size_t secure_key_size;
u8 *secure_key;
+ u64 mkvp;
int rc;
util_assert(keystore != NULL, "Internal error: keystore is NULL");
@@ -1791,9 +1792,26 @@ int keystore_import_key(struct keystore
goto out_free_key_filenames;
}
+ rc = get_master_key_verification_pattern(secure_key, secure_key_size,
+ &mkvp, keystore->verbose);
+ if (rc != 0) {
+ warnx("Failed to get the master key verification pattern: %s",
+ strerror(-rc));
+ goto out_free_key;
+ }
+
+ rc = cross_check_apqns(apqns, mkvp, true, keystore->verbose);
+ if (rc == -EINVAL)
+ goto out_free_key;
+ if (rc != 0 && rc != -ENOTSUP && noapqncheck == 0) {
+ warnx("Your master key setup is improper");
+ goto out_free_key;
+ }
+
rc = write_secure_key(file_names.skey_filename, secure_key,
secure_key_size, keystore->verbose);
free(secure_key);
+ secure_key = NULL;
if (rc != 0)
goto out_free_props;
@@ -1811,6 +1829,9 @@ int keystore_import_key(struct keystore
"Successfully imported a secure key in '%s' and key info in '%s'",
file_names.skey_filename, file_names.info_filename);
+out_free_key:
+ if (secure_key != NULL)
+ free(secure_key);
out_free_props:
if (key_props != NULL)
properties_free(key_props);

View File

@ -1,52 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl/libc: Use stdint.h instead of self defined macros
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 8face3e63ed88443392bcbcd93cc0b5e29b40069
Problem-ID: VS1804
Upstream-Description:
zipl/libc: Use stdint.h instead of self defined macros
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/libc.h | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
--- a/zipl/boot/libc.h
+++ b/zipl/boot/libc.h
@@ -11,6 +11,8 @@
#ifndef LIBC_H
#define LIBC_H
+#include <stdint.h>
+
#define NULL ((void *) 0)
#define EPERM 1 /* Operation not permitted */
@@ -42,11 +44,6 @@
#define MIB (1024ULL * 1024)
#define LINE_LENGTH 80 /* max line length printed by printf */
-typedef unsigned long long uint64_t;
-typedef unsigned int uint32_t;
-typedef unsigned short uint16_t;
-typedef unsigned char uint8_t;
-
void printf(const char *, ...);
void snprintf(char *buf, unsigned long size, const char *fmt, ...);
void *memcpy(void *, const void *, unsigned long);

View File

@ -1,86 +0,0 @@
Subject: zkey: Cross check APQNs when changing APQN associations
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: 0b4cbf00412f27456d28ff7f86ec5335a39e3416
Problem-ID: SEC1916
Upstream-Description:
zkey: Cross check APQNs when changing APQN associations
Perform a cross check of the APQNs when the APQN association of a
secure AES key in the key repository is changed. When adding new APQNs,
or associating a new set of APQNs to a secure key, then the APQNs are
cross checked. If all associated APQNs are removed, then all currently
available APQNs are cross checked. If a master key mismatch is detected,
then the change is rejected.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/keystore.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -1886,7 +1886,11 @@ int keystore_change_key(struct keystore
.nomsg = 0 };
struct key_filenames file_names = { NULL, NULL, NULL };
struct properties *key_props = NULL;
+ size_t secure_key_size;
+ char *apqns_prop;
+ u8 *secure_key;
char temp[30];
+ u64 mkvp;
int rc;
util_assert(keystore != NULL, "Internal error: keystore is NULL");
@@ -1932,6 +1936,33 @@ int keystore_change_key(struct keystore
&apqn_check);
if (rc != 0)
goto out;
+
+ secure_key = read_secure_key(file_names.skey_filename,
+ &secure_key_size,
+ keystore->verbose);
+ if (secure_key == NULL) {
+ rc = -ENOENT;
+ goto out;
+ }
+
+ rc = get_master_key_verification_pattern(secure_key,
+ secure_key_size,
+ &mkvp,
+ keystore->verbose);
+ free(secure_key);
+ if (rc)
+ goto out;
+
+ apqns_prop = properties_get(key_props, PROP_NAME_APQNS);
+ rc = cross_check_apqns(apqns_prop, mkvp, true,
+ keystore->verbose);
+ free(apqns_prop);
+ if (rc == -ENOTSUP)
+ rc = 0;
+ if (rc != 0 && noapqncheck == 0) {
+ warnx("Your master key setup is improper");
+ goto out;
+ }
}
if (sector_size >= 0) {

View File

@ -1,199 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: Consolidate IMAGE macros
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: cb614ed1ee61f05fb521a7e3ac0d27eb2eb45672
Problem-ID: VS1804
Upstream-Description:
zipl: Consolidate IMAGE macros
Combine the different macros for 0x10000 and use a consistent naming
schema.
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/stage3.c | 7 ++++---
zipl/boot/stage3.h | 2 --
zipl/include/zipl.h | 8 +++++---
zipl/src/bootmap.c | 8 ++++----
zipl/src/job.c | 17 +++++++++--------
5 files changed, 22 insertions(+), 20 deletions(-)
--- a/zipl/boot/stage3.c
+++ b/zipl/boot/stage3.c
@@ -13,6 +13,7 @@
#include "s390.h"
#include "stage3.h"
#include "error.h"
+#include "zipl.h"
#define for_each_rb_entry(entry, rb) \
for (entry = rb->entries; \
@@ -272,7 +273,7 @@ void start(void)
* verified component. If it is not IPL is aborted.
*/
if (secure_boot_enabled()) {
- if (_image_addr != DEFAULT_IMAGE_ADDR ||
+ if (_image_addr != IMAGE_LOAD_ADDRESS ||
_load_psw != DEFAULT_PSW_LOAD)
panic(ESECUREBOOT, "%s", msg_sipl_inval);
@@ -283,8 +284,8 @@ void start(void)
* cut the kernel header
*/
memmove((void *)_image_addr,
- (void *)_image_addr + KERNEL_HEADER_SIZE,
- _image_len - KERNEL_HEADER_SIZE);
+ (void *)_image_addr + IMAGE_LOAD_ADDRESS,
+ _image_len - IMAGE_LOAD_ADDRESS);
/* store subchannel ID into low core and into new kernel space */
subchannel_id = S390_lowcore.subchannel_id;
--- a/zipl/boot/stage3.h
+++ b/zipl/boot/stage3.h
@@ -29,10 +29,8 @@
#define IPL_FLAG_SECURE 0x40
-#define DEFAULT_IMAGE_ADDR 0x10000
#define DEFAULT_PSW_LOAD 0x0008000080010000UL
#define PSW_ADDR_MASK 0x000000007FFFFFFFUL
-#define KERNEL_HEADER_SIZE 65536
#define UNSPECIFIED_ADDRESS -1UL
--- a/zipl/include/zipl.h
+++ b/zipl/include/zipl.h
@@ -19,13 +19,15 @@
#define ZIPL_MAGIC_SIZE 4
#define DISK_LAYOUT_ID 0x00000001
+#define IMAGE_ENTRY 0x10000UL
+#define IMAGE_ENTRY_KDUMP 0x10010UL
+
#define ZIPL_STAGE2_LOAD_ADDRESS 0x2000UL
#define ZIPL_STAGE3_ENTRY_ADDRESS 0xa000UL
-#define DEFAULT_IMAGE_ADDRESS 0x10000UL
-#define KDUMP_IMAGE_ADDRESS 0x10010UL
#define DEFAULT_STAGE3_ADDRESS 0xa000UL
#define DEFAULT_STAGE3_PARAMS_ADDRESS 0x9000UL
-#define MINIMUM_ADDRESS 0x10000UL
+#define IMAGE_LOAD_ADDRESS IMAGE_ENTRY
+
#define ADDRESS_LIMIT 0x80000000UL
#define ADDRESS_LIMIT_KDUMP 0x2000000UL /* HSA size: 32 MiB */
#define UNSPECIFIED_ADDRESS -1UL
--- a/zipl/src/bootmap.c
+++ b/zipl/src/bootmap.c
@@ -644,8 +644,8 @@ add_ipl_program(int fd, struct job_ipl_d
rc = boot_get_stage3_parms(&stage3_params, &stage3_params_size,
ipl->parm_addr, ipl->ramdisk_addr,
ramdisk_size,
- ipl->is_kdump ? ipl->image_addr + 0x10 :
- ipl->image_addr,
+ ipl->is_kdump ? IMAGE_ENTRY_KDUMP :
+ IMAGE_ENTRY,
(info->type == disk_type_scsi) ? 0 : 1,
flags, ipl->image_addr, image_size);
if (rc) {
@@ -1187,7 +1187,7 @@ bootmap_create(struct job_data *job, dis
ulong unused_size;
/* Use approximated stage 3 size as starting point */
- size = MINIMUM_ADDRESS;
+ size = IMAGE_LOAD_ADDRESS;
/* Ramdisk */
if (job->data.dump.ramdisk != NULL) {
@@ -1199,7 +1199,7 @@ bootmap_create(struct job_data *job, dis
/* Kernel */
if (stat(job->data.dump.image, &st))
goto out_misc_free_temp_dev;
- size += DIV_ROUND_UP(st.st_size - 0x10000,
+ size += DIV_ROUND_UP(st.st_size - IMAGE_LOAD_ADDRESS,
info->phy_block_size);
/* Parmfile */
size += DIV_ROUND_UP(DUMP_PARAM_MAX_LEN, info->phy_block_size);
--- a/zipl/src/job.c
+++ b/zipl/src/job.c
@@ -23,6 +23,7 @@
#include "job.h"
#include "misc.h"
#include "scan.h"
+#include "zipl.h"
/* Command line options */
static struct option options[] = {
@@ -663,12 +664,12 @@ check_component_address_data(struct comp
address_limit);
return -1;
}
- if (*cl[i].addrp < MINIMUM_ADDRESS) {
+ if (*cl[i].addrp < IMAGE_LOAD_ADDRESS) {
if (name != NULL)
error_text("Section '%s'", name);
error_reason("Component '%s' falls below available "
"address space (limit is 0x%08x)",
- cl[i].name, MINIMUM_ADDRESS);
+ cl[i].name, IMAGE_LOAD_ADDRESS);
return -1;
}
}
@@ -706,12 +707,12 @@ finalize_component_address_data(struct c
for (j = -1; j < i; j++) {
if (j < 0) {
/* Try address before first component */
- addr = MINIMUM_ADDRESS;
+ addr = IMAGE_LOAD_ADDRESS;
} else {
/* Try address after component j */
addr = *cl[j].addrp + cl[j].size;
- if (addr < MINIMUM_ADDRESS)
- addr = MINIMUM_ADDRESS;
+ if (addr < IMAGE_LOAD_ADDRESS)
+ addr = IMAGE_LOAD_ADDRESS;
}
addr = ALIGN(addr, cl[i].align);
if (addr + cl[i].size > address_limit) {
@@ -905,7 +906,7 @@ check_job_dump_images(struct job_dump_da
dump->image = misc_strdup(ZFCPDUMP_IMAGE);
if (dump->image == NULL)
return -1;
- dump->image_addr = DEFAULT_IMAGE_ADDRESS;
+ dump->image_addr = IMAGE_LOAD_ADDRESS;
/* Ramdisk is no longer required with new initramfs dump system */
if (misc_check_readable_file(ZFCPDUMP_INITRD))
@@ -1351,7 +1352,7 @@ get_job_from_section_data(char* data[],
return -1;
if (extract_address(job->data.ipl.image,
&job->data.ipl.image_addr)) {
- job->data.ipl.image_addr = DEFAULT_IMAGE_ADDRESS;
+ job->data.ipl.image_addr = IMAGE_LOAD_ADDRESS;
}
/* Fill in parmline */
rc = get_parmline(data[(int) scan_keyword_parmfile],
@@ -1406,7 +1407,7 @@ get_job_from_section_data(char* data[],
return -1;
if (extract_address(job->data.ipl_tape.image,
&job->data.ipl_tape.image_addr)) {
- job->data.ipl_tape.image_addr = DEFAULT_IMAGE_ADDRESS;
+ job->data.ipl_tape.image_addr = IMAGE_LOAD_ADDRESS;
}
/* Fill in parmline */
rc = get_parmline(data[(int) scan_keyword_parmfile],

View File

@ -1,455 +0,0 @@
Subject: zkey: Add function to select a specific CCA adapter
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: 016a0a56fcb3dd0bf8bed693e5d64873f6288995
Problem-ID: SEC1916
Upstream-Description:
zkey: Add function to select a specific CCA adapter
Some operations require the CCA host library to be used, such as
re-enciphering a secure key. The CCA host library uses a different
approach to select the APQN it operates with. To ensure that the
desired APQN is used for an operation, a utility function is added
to select a specific APQN for usage with the CCA host library.
The CCA host library allows to set environment variables to override
the default CCA APQN selection. The environment variables are inspected
during CCA host library initialization only. To select a specific
domain for CCA, the CSU_DEFAULT_DOMAIN environment variable is set,
and then the CCA host library is un-loaded and re-loaded again.
Furthermore, the 'Cryptographic Resource Allocate' verb of the CCA
host library is used together with the 'Cryptographic Facility Query
function' verb to iterate over the crypto cards known by the CCA host
library, and to identify the desired crypto card based on its serial
number. That way, a specific APQN can be selected for use with
subsequent CCA verbs.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/Makefile | 4
zkey/cca.c | 296 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
zkey/cca.h | 32 ++++++
3 files changed, 329 insertions(+), 3 deletions(-)
--- a/zkey/Makefile
+++ b/zkey/Makefile
@@ -66,7 +66,7 @@ all: $(BUILD_TARGETS)
zkey.o: zkey.c pkey.h cca.h misc.h
pkey.o: pkey.c pkey.h
-cca.o: cca.c cca.h pkey.h
+cca.o: cca.c cca.h pkey.h utils.h
utils.o: utils.h
properties.o: check-dep-zkey properties.c properties.h
keystore.o: keystore.c keystore.h properties.h pkey.h cca.h utils.h
@@ -77,7 +77,7 @@ zkey: zkey.o pkey.o cca.o properties.o k
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
zkey-cryptsetup: LDLIBS = -ldl -lcryptsetup -ljson-c
-zkey-cryptsetup: zkey-cryptsetup.o pkey.o cca.o $(libs)
+zkey-cryptsetup: zkey-cryptsetup.o pkey.o cca.o utils.o $(libs)
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
install-common:
--- a/zkey/cca.c
+++ b/zkey/cca.c
@@ -12,6 +12,7 @@
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
@@ -21,6 +22,7 @@
#include "cca.h"
#include "pkey.h"
+#include "utils.h"
#define pr_verbose(verbose, fmt...) do { \
if (verbose) \
@@ -32,6 +34,8 @@
*/
#define CCA_LIBRARY_NAME "libcsulcca.so"
#define CCA_WEB_PAGE "http://www.ibm.com/security/cryptocards"
+#define CCA_DOMAIN_ENVAR "CSU_DEFAULT_DOMAIN"
+#define CCA_ADAPTER_ENVAR "CSU_DEFAULT_ADAPTER"
/**
* Prints CCA return and reason code information for certain known CCA
@@ -136,8 +140,20 @@ int load_cca_library(struct cca_lib *cca
/* Get the Key Token Change function */
cca->dll_CSNBKTC = (t_CSNBKTC)dlsym(cca->lib_csulcca, "CSNBKTC");
+ /* Get the Cryptographic Facility Query function */
+ cca->dll_CSUACFQ = (t_CSUACFQ)dlsym(cca->lib_csulcca, "CSUACFQ");
+
+ /* Get the Cryptographic Resource Allocate function */
+ cca->dll_CSUACRA = (t_CSUACRA)dlsym(cca->lib_csulcca, "CSUACRA");
+
+ /* Cryptographic Resource Deallocate function */
+ cca->dll_CSUACRD = (t_CSUACRD)dlsym(cca->lib_csulcca, "CSUACRD");
+
if (cca->dll_CSUACFV == NULL ||
- cca->dll_CSNBKTC == NULL) {
+ cca->dll_CSNBKTC == NULL ||
+ cca->dll_CSUACFQ == NULL ||
+ cca->dll_CSUACRA == NULL ||
+ cca->dll_CSUACRD == NULL) {
pr_verbose(verbose, "%s", dlerror());
warnx("The command requires the IBM CCA Host Libraries and "
"Tools.\nFor the supported environments and downloads, "
@@ -213,3 +229,281 @@ int key_token_change(struct cca_lib *cca
}
return 0;
}
+
+/**
+ * Queries the number of adapters known by the CCA host library
+ *
+ * @param[in] cca the CCA library structure
+ * @param[out] adapters the number of adapters
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error.
+ */
+static int get_number_of_cca_adapters(struct cca_lib *cca,
+ unsigned int *adapters, bool verbose)
+{
+ long exit_data_len = 0, rule_array_count, verb_data_length = 0;
+ unsigned char rule_array[16 * 8] = { 0, };
+ unsigned char exit_data[4] = { 0, };
+ long return_code, reason_code;
+
+ util_assert(cca != NULL, "Internal error: cca is NULL");
+ util_assert(adapters != NULL, "Internal error: adapters is NULL");
+
+ memset(rule_array, 0, sizeof(rule_array));
+ memcpy(rule_array, "STATCRD2", 8);
+ rule_array_count = 1;
+
+ cca->dll_CSUACFQ(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ &verb_data_length, NULL);
+
+ pr_verbose(verbose, "CSUACFQ (Cryptographic Facility Query) returned: "
+ "return_code: %ld, reason_code: %ld", return_code,
+ reason_code);
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -EIO;
+ }
+
+ rule_array[8] = '\0';
+ if (sscanf((char *)rule_array, "%u", adapters) != 1) {
+ pr_verbose(verbose, "Unparsable output: %s", rule_array);
+ return -EIO;
+ }
+
+ pr_verbose(verbose, "Number of CCA adapters: %u", *adapters);
+ return 0;
+}
+
+/**
+ * Allocate a specific CCA adapter.
+ *
+ * @param[in] cca the CCA library structure
+ * @param[in] adapter the adapter number, starting at 1. If 0 is
+ * specified, then the AUTOSELECT option is
+ * enabled.
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error. -ENODEV is
+ * returned if the adapter is not available.
+ */
+static int allocate_cca_adapter(struct cca_lib *cca, unsigned int adapter,
+ bool verbose)
+{
+ long exit_data_len = 0, rule_array_count;
+ unsigned char rule_array[8] = { 0, };
+ unsigned char exit_data[4] = { 0, };
+ long return_code, reason_code;
+ char res_name[9];
+ long res_name_len;
+
+ util_assert(cca != NULL, "Internal error: cca is NULL");
+
+ if (adapter > 0)
+ memcpy(rule_array, "DEVICE ", 8);
+ else
+ memcpy(rule_array, "DEV-ANY ", 8);
+ rule_array_count = 1;
+
+ sprintf(res_name, "CRP%02d", adapter);
+ res_name_len = strlen(res_name);
+
+ cca->dll_CSUACRA(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ &res_name_len, (unsigned char *)res_name);
+
+ pr_verbose(verbose, "CSUACRA (Cryptographic Resource Allocate) "
+ "returned: return_code: %ld, reason_code: %ld", return_code,
+ reason_code);
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -ENODEV;
+ }
+
+ pr_verbose(verbose, "Adapter %u (%s) allocated", adapter, res_name);
+ return 0;
+}
+
+/**
+ * Deallocate a specific CCA adapter.
+ *
+ * @param[in] cca the CCA library structure
+ * @param[in] adapter the adapter number, starting at 1. If 0 is
+ * specified, then the AUTOSELECT option is
+ * disabled.
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error. -ENODEV is
+ * returned if the adapter is not available.
+ */
+static int deallocate_cca_adapter(struct cca_lib *cca, unsigned int adapter,
+ bool verbose)
+{
+ long exit_data_len = 0, rule_array_count;
+ unsigned char rule_array[8] = { 0, };
+ unsigned char exit_data[4] = { 0, };
+ long return_code, reason_code;
+ char res_name[9];
+ long res_name_len;
+
+ util_assert(cca != NULL, "Internal error: cca is NULL");
+
+ if (adapter > 0)
+ memcpy(rule_array, "DEVICE ", 8);
+ else
+ memcpy(rule_array, "DEV-ANY ", 8);
+ rule_array_count = 1;
+
+ sprintf(res_name, "CRP%02d", adapter);
+ res_name_len = strlen(res_name);
+
+ cca->dll_CSUACRD(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ &res_name_len, (unsigned char *)res_name);
+
+ pr_verbose(verbose, "CSUACRD (Cryptographic Resource Deallocate) "
+ "returned: return_code: %ld, reason_code: %ld", return_code,
+ reason_code);
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -ENODEV;
+ }
+
+ pr_verbose(verbose, "Adapter %u (%s) deallocated", adapter, res_name);
+ return 0;
+}
+
+/**
+ * Queries the serial number of the current CCA adapter
+ *
+ * @param[in] cca the CCA library structure
+ * @param[out] serialnr the buffer where the serial number is returned
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error.
+ */
+static int get_cca_adapter_serialnr(struct cca_lib *cca, char serialnr[9],
+ bool verbose)
+{
+ long exit_data_len = 0, rule_array_count, verb_data_length = 0;
+ unsigned char rule_array[16 * 8] = { 0, };
+ unsigned char exit_data[4] = { 0, };
+ long return_code, reason_code;
+
+ util_assert(cca != NULL, "Internal error: cca is NULL");
+
+ memset(rule_array, 0, sizeof(rule_array));
+ memcpy(rule_array, "STATCRD2", 8);
+ rule_array_count = 1;
+
+ cca->dll_CSUACFQ(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ &verb_data_length, NULL);
+
+ pr_verbose(verbose, "CSUACFQ (Cryptographic Facility Query) returned: "
+ "return_code: %ld, reason_code: %ld", return_code,
+ reason_code);
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -EIO;
+ }
+
+ memcpy(serialnr, rule_array+14*8, 8);
+ serialnr[8] = '\0';
+
+ pr_verbose(verbose, "Serial number of CCA adapter: %s", serialnr);
+ return 0;
+}
+
+/**
+ * Selects the specified APQN to be used for the CCA host library.
+ *
+ * @param[in] cca the CCA library structure
+ * @param[in] card the card number
+ * @param[in] domain the domain number
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error. -ENOTSUP is
+ * returned when the serialnr sysfs attribute is not available,
+ * because the zcrypt kernel module is on an older level. -ENODEV is
+ * returned if the APQN is not available.
+ */
+int select_cca_adapter(struct cca_lib *cca, int card, int domain, bool verbose)
+{
+ unsigned int adapters, adapter;
+ char adapter_serialnr[9];
+ char apqn_serialnr[9];
+ char temp[10];
+ int rc, found = 0;
+
+ util_assert(cca != NULL, "Internal error: cca is NULL");
+
+ pr_verbose(verbose, "Select %02x.%04x for the CCA host library", card,
+ domain);
+
+ rc = sysfs_get_serialnr(card, apqn_serialnr, verbose);
+ if (rc != 0) {
+ pr_verbose(verbose, "Failed to get the serial number: %s",
+ strerror(-rc));
+ return rc;
+ }
+
+ sprintf(temp, "%u", domain);
+ if (setenv(CCA_DOMAIN_ENVAR, temp, 1) != 0) {
+ rc = -errno;
+ pr_verbose(verbose, "Failed to set the %s environment variable:"
+ " %s", CCA_DOMAIN_ENVAR, strerror(-rc));
+ return rc;
+ }
+ unsetenv(CCA_ADAPTER_ENVAR);
+
+ /*
+ * Unload and reload the CCA host library so that it recognizes the
+ * changed CSU_DEFAULT_DOMAIN environment variable value.
+ */
+ if (cca->lib_csulcca != NULL)
+ dlclose(cca->lib_csulcca);
+ memset(cca, 0, sizeof(struct cca_lib));
+
+ rc = load_cca_library(cca, verbose);
+ if (rc != 0)
+ return rc;
+
+ rc = get_number_of_cca_adapters(cca, &adapters, verbose);
+ if (rc != 0)
+ return rc;
+
+ /* Disable the AUTOSELECT option */
+ rc = deallocate_cca_adapter(cca, 0, verbose);
+ if (rc != 0)
+ return rc;
+
+ for (adapter = 1; adapter <= adapters; adapter++) {
+ rc = allocate_cca_adapter(cca, adapter, verbose);
+ if (rc != 0)
+ return rc;
+
+ rc = get_cca_adapter_serialnr(cca, adapter_serialnr, verbose);
+ if (rc == 0) {
+ if (memcmp(apqn_serialnr, adapter_serialnr, 8) == 0) {
+ found = 1;
+ break;
+ }
+ }
+
+ rc = deallocate_cca_adapter(cca, adapter, verbose);
+ if (rc != 0)
+ return rc;
+ }
+
+ if (!found)
+ return -ENODEV;
+
+ pr_verbose(verbose, "Selected adapter %u (CRP%02d)", adapter, adapter);
+ return 0;
+}
--- a/zkey/cca.h
+++ b/zkey/cca.h
@@ -32,6 +32,33 @@ typedef void (*t_CSUACFV)(long *return_c
long *version_data_length,
unsigned char *version_data);
+typedef void (*t_CSUACFQ)(long *return_code,
+ long *reason_code,
+ long *exit_data_length,
+ unsigned char *exit_data,
+ long *rule_array_count,
+ unsigned char *rule_array,
+ long *verb_data_length,
+ unsigned char *verb_data);
+
+typedef void (*t_CSUACRA)(long *return_code,
+ long *reason_code,
+ long *exit_data_length,
+ unsigned char *exit_data,
+ long *rule_array_count,
+ unsigned char *rule_array,
+ long *ressource_name_length,
+ unsigned char *ressource_name);
+
+typedef void (*t_CSUACRD)(long *return_code,
+ long *reason_code,
+ long *exit_data_length,
+ unsigned char *exit_data,
+ long *rule_array_count,
+ unsigned char *rule_array,
+ long *ressource_name_length,
+ unsigned char *ressource_name);
+
struct cca_version {
unsigned int ver;
unsigned int rel;
@@ -42,6 +69,9 @@ struct cca_lib {
void *lib_csulcca;
t_CSNBKTC dll_CSNBKTC;
t_CSUACFV dll_CSUACFV;
+ t_CSUACFQ dll_CSUACFQ;
+ t_CSUACRA dll_CSUACRA;
+ t_CSUACRD dll_CSUACRD;
struct cca_version version;
};
@@ -51,4 +81,6 @@ int key_token_change(struct cca_lib *cca
u8 *secure_key, unsigned int secure_key_size,
char *method, bool verbose);
+int select_cca_adapter(struct cca_lib *cca, int card, int domain, bool verbose);
+
#endif

View File

@ -1,110 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: Consolidate STAGE{2,3} macros
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 4762e65acbc4efe7142ccb5fd2ef86073737ebd8
Problem-ID: VS1804
Upstream-Description:
zipl: Consolidate STAGE{2,3} macros
Increase consistency with the other macros by moving and renaming
the STAGE{2,3} macros in zipl.h.
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/include/zipl.h | 8 ++++----
zipl/src/boot.c | 4 ++--
zipl/src/bootmap.c | 6 +++---
3 files changed, 9 insertions(+), 9 deletions(-)
--- a/zipl/include/zipl.h
+++ b/zipl/include/zipl.h
@@ -19,13 +19,12 @@
#define ZIPL_MAGIC_SIZE 4
#define DISK_LAYOUT_ID 0x00000001
+#define STAGE3_ENTRY 0xa000UL
#define IMAGE_ENTRY 0x10000UL
#define IMAGE_ENTRY_KDUMP 0x10010UL
-#define ZIPL_STAGE2_LOAD_ADDRESS 0x2000UL
-#define ZIPL_STAGE3_ENTRY_ADDRESS 0xa000UL
-#define DEFAULT_STAGE3_ADDRESS 0xa000UL
-#define DEFAULT_STAGE3_PARAMS_ADDRESS 0x9000UL
+#define STAGE2_LOAD_ADDRESS 0x2000UL
+#define STAGE3_LOAD_ADDRESS 0xa000UL
#define IMAGE_LOAD_ADDRESS IMAGE_ENTRY
#define ADDRESS_LIMIT 0x80000000UL
@@ -38,6 +37,7 @@
#define STAGE3_HEAP_ADDRESS 0x2000UL
#define STAGE3_STACK_SIZE 0x1000UL
#define STAGE3_STACK_ADDRESS 0xF000UL
+#define STAGE3_PARAMS_ADDRESS 0x9000UL
#define PSW_ADDRESS_MASK 0x000000007fffffffUL
#define PSW_LOAD 0x0008000080000000UL
--- a/zipl/src/boot.c
+++ b/zipl/src/boot.c
@@ -195,7 +195,7 @@ boot_init_fba_stage1b(struct boot_fba_st
stage1b->locdata[i].blocknr =
(uint32_t) stage2_list[i].linear.block;
stage1b->locread[i].read.address_lo =
- ZIPL_STAGE2_LOAD_ADDRESS + i * FBA_BLK_SIZE;
+ STAGE2_LOAD_ADDRESS + i * FBA_BLK_SIZE;
}
/* Terminate CCW chain */
stage1b->locread[i - 1].read.flags &= ~CCW_FLAG_CC;
@@ -220,7 +220,7 @@ boot_init_eckd_stage1b(struct boot_eckd_
stage1b->seek[i].head = stage2_list[i].chs.head |
((stage2_list[i].chs.cyl >> 12) & 0xfff0);
stage1b->seek[i].sec = stage2_list[i].chs.sec;
- stage1b->ssrt[i].read.address_lo = ZIPL_STAGE2_LOAD_ADDRESS +
+ stage1b->ssrt[i].read.address_lo = STAGE2_LOAD_ADDRESS +
i * stage2_list[i].chs.size;
stage1b->ssrt[i].read.flags = CCW_FLAG_CC | CCW_FLAG_SLI;
}
--- a/zipl/src/bootmap.c
+++ b/zipl/src/bootmap.c
@@ -627,7 +627,7 @@ add_ipl_program(int fd, struct job_ipl_d
}
/* Add stage 3 loader to bootmap */
- rc = add_component_file(fd, ZIPL_STAGE3_PATH, DEFAULT_STAGE3_ADDRESS,
+ rc = add_component_file(fd, ZIPL_STAGE3_PATH, STAGE3_LOAD_ADDRESS,
signature_size, VOID_ADD(table, offset), 1,
info, target, &comp_loc[comp_nr]);
if (rc) {
@@ -654,7 +654,7 @@ add_ipl_program(int fd, struct job_ipl_d
}
rc = add_component_buffer(fd, stage3_params, stage3_params_size,
(component_data) (uint64_t)
- DEFAULT_STAGE3_PARAMS_ADDRESS,
+ STAGE3_PARAMS_ADDRESS,
VOID_ADD(table, offset), info,
&comp_loc[comp_nr], component_load);
free(stage3_params);
@@ -792,7 +792,7 @@ add_ipl_program(int fd, struct job_ipl_d
create_component_entry(VOID_ADD(table, offset), NULL,
component_execute,
(component_data) (uint64_t)
- (ZIPL_STAGE3_ENTRY_ADDRESS | PSW_LOAD),
+ (STAGE3_ENTRY | PSW_LOAD),
info);
/* Write component table */
rc = disk_write_block_aligned(fd, table, info->phy_block_size,

View File

@ -1,162 +0,0 @@
Subject: zkey: Add function to select a CCA adapter by mkvp
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: 1091b0bf65328aff94055a2e333aff2c737b6744
Problem-ID: SEC1916
Upstream-Description:
zkey: Add function to select a CCA adapter by mkvp
Add a utility function to select an APQN that is set up with
a specific master key for use with the CCA host library. The
selection is based on the master key verification pattern, which
is typically obtained from an existing secure AES key.
The function iterates over a set of APQNs to find one that is setup
with the desired master key in the CURRENT or OLD master key register,
and optionally has a new master key loaded. It then selects the found
APQN for use with the CCA host library.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/cca.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
zkey/cca.h | 7 ++++
2 files changed, 107 insertions(+)
--- a/zkey/cca.c
+++ b/zkey/cca.c
@@ -507,3 +507,103 @@ int select_cca_adapter(struct cca_lib *c
pr_verbose(verbose, "Selected adapter %u (CRP%02d)", adapter, adapter);
return 0;
}
+
+struct find_mkvp_info {
+ u64 mkvp;
+ unsigned int flags;
+ bool found;
+ int card;
+ int domain;
+ bool verbose;
+};
+
+static int find_mkvp(int card, int domain, void *handler_data)
+{
+ struct find_mkvp_info *info = (struct find_mkvp_info *)handler_data;
+ struct mk_info mk_info;
+ bool found = false;
+ int rc;
+
+ rc = sysfs_get_mkvps(card, domain, &mk_info, info->verbose);
+ if (rc == -ENODEV)
+ return 0;
+ if (rc != 0)
+ return rc;
+
+ if (info->flags & FLAG_SEL_CCA_MATCH_CUR_MKVP)
+ if (mk_info.cur_mk.mk_state == MK_STATE_VALID &&
+ mk_info.cur_mk.mkvp == info->mkvp)
+ found = true;
+
+ if (info->flags & FLAG_SEL_CCA_MATCH_OLD_MKVP)
+ if (mk_info.old_mk.mk_state == MK_STATE_VALID &&
+ mk_info.old_mk.mkvp == info->mkvp)
+ found = true;
+
+ if (info->flags & FLAG_SEL_CCA_NEW_MUST_BE_SET)
+ if (mk_info.new_mk.mk_state != MK_STATE_FULL)
+ found = false;
+
+
+ if (found) {
+ info->card = card;
+ info->domain = domain;
+ info->found = true;
+
+ pr_verbose(info->verbose, "%02x.%04x has the desired mkvp%s",
+ card, domain,
+ info->flags & FLAG_SEL_CCA_NEW_MUST_BE_SET ?
+ " and NEW MK set" : "");
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Selects an APQN to be used for the CCA host library that has the specified
+ * master key verification pattern
+ *
+ * @param[in] cca the CCA library structure
+ * @param[in] mkvp the master key verification pattern to search for
+ * @param[in] apqns a comma separated list of APQNs. If NULL is specified,
+ * or an empty string, then all online CCA APQNs are
+ * checked.
+ * @param[in] flags Flags that control the MKVM matching and NEW register
+ * checking. Multiple flags can be combined.
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error. -ENOTSUP is
+ * returned when the serialnr sysfs attribute is not available,
+ * because the zcrypt kernel module is on an older level. -ENODEV is
+ * returned if no APQN is available with the desired mkvp.
+ */
+int select_cca_adapter_by_mkvp(struct cca_lib *cca, u64 mkvp, const char *apqns,
+ unsigned int flags, bool verbose)
+{
+ struct find_mkvp_info info;
+ int rc;
+
+ util_assert(cca != NULL, "Internal error: cca is NULL");
+
+ pr_verbose(verbose, "Select mkvp %016llx in APQNs %s for the CCA host "
+ "library", mkvp, apqns == 0 ? "ANY" : apqns);
+
+ info.mkvp = mkvp;
+ info.flags = flags;
+ info.found = false;
+ info.card = 0;
+ info.domain = 0;
+ info.verbose = verbose;
+
+ rc = handle_apqns(apqns, find_mkvp, &info, verbose);
+ if (rc < 0)
+ return rc;
+
+ if (!info.found)
+ return -ENODEV;
+
+ rc = select_cca_adapter(cca, info.card, info.domain, verbose);
+ return rc;
+}
--- a/zkey/cca.h
+++ b/zkey/cca.h
@@ -83,4 +83,11 @@ int key_token_change(struct cca_lib *cca
int select_cca_adapter(struct cca_lib *cca, int card, int domain, bool verbose);
+#define FLAG_SEL_CCA_MATCH_CUR_MKVP 0x01
+#define FLAG_SEL_CCA_MATCH_OLD_MKVP 0x02
+#define FLAG_SEL_CCA_NEW_MUST_BE_SET 0x80
+
+int select_cca_adapter_by_mkvp(struct cca_lib *cca, u64 mkvp, const char *apqns,
+ unsigned int flags, bool verbose);
+
#endif

View File

@ -1,53 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: stfle: use uint64_t instead of u64
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 9d1baaa594d796ca9fe6bdf1282c78e4b2ff5234
Problem-ID: VS1804
Upstream-Description:
zipl: stfle: use uint64_t instead of u64
As the definition of `stfle_fac_list` in the lowcore uses uint64_t, we
should also use uint64_t for the `stfle_fac_list` parameter of the
`stfle/__stfle_asm` function.
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/s390.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/zipl/boot/s390.h
+++ b/zipl/boot/s390.h
@@ -452,7 +452,7 @@ static inline int test_facility(unsigned
return __test_facility(nr, &S390_lowcore.stfle_fac_list);
}
-static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size)
+static inline unsigned long __stfle_asm(uint64_t *stfle_fac_list, int size)
{
register unsigned long reg0 asm("0") = size - 1;
@@ -469,7 +469,7 @@ static inline unsigned long __stfle_asm(
* @stfle_fac_list: array where facility list can be stored
* @size: size of passed in array in double words
*/
-static inline void stfle(u64 *stfle_fac_list, int size)
+static inline void stfle(uint64_t *stfle_fac_list, int size)
{
unsigned long nr;

View File

@ -1,397 +0,0 @@
Subject: zkey: Select CCA adapter when re-enciphering
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: 552a915465301b768268cddc7ccb65a6d167e432
Problem-ID: SEC1916
Upstream-Description:
zkey: Select CCA adapter when re-enciphering
When re-enciphering secure AES keys, select the correct APQN for used
with the CCA host library. Re-enciphering a secure key requires the use
of the CCA host library. The APQN is selected based on the master key
verification pattern obtained from the secure key to re-encipher.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/cca.c | 19 ++++++++++++++
zkey/cca.h | 2 +
zkey/keystore.c | 57 ++++++++++++++++++++++++++++++++++++-------
zkey/zkey-cryptsetup.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++--
zkey/zkey.c | 50 ++++++++++++++++++++++++++++++++++++--
5 files changed, 179 insertions(+), 13 deletions(-)
--- a/zkey/cca.c
+++ b/zkey/cca.c
@@ -18,6 +18,8 @@
#include <sys/types.h>
#include <unistd.h>
+#include "lib/util_base.h"
+#include "lib/util_libc.h"
#include "lib/util_panic.h"
#include "cca.h"
@@ -607,3 +609,20 @@ int select_cca_adapter_by_mkvp(struct cc
rc = select_cca_adapter(cca, info.card, info.domain, verbose);
return rc;
}
+
+void print_msg_for_cca_envvars(const char *key_name)
+{
+ char *msg;
+
+ util_asprintf(&msg, "WARNING: You must set environment variables "
+ "%s and %s to the desired card and domain that is "
+ "set up with the AES master key used by this %s. "
+ "%s specifies the domain as decimal number. %s "
+ "specifies the adapter number as 'CRPnn', where "
+ "'nn' is the adapter number. See the CCA "
+ "documentation for more details.\n",
+ CCA_DOMAIN_ENVAR, CCA_ADAPTER_ENVAR, key_name,
+ CCA_DOMAIN_ENVAR, CCA_ADAPTER_ENVAR);
+ util_print_indented(msg, 0);
+ free(msg);
+}
--- a/zkey/cca.h
+++ b/zkey/cca.h
@@ -90,4 +90,6 @@ int select_cca_adapter(struct cca_lib *c
int select_cca_adapter_by_mkvp(struct cca_lib *cca, u64 mkvp, const char *apqns,
unsigned int flags, bool verbose);
+void print_msg_for_cca_envvars(const char *key_name);
+
#endif
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -2535,6 +2535,7 @@ struct reencipher_info {
* @param[in] secure_key_size the size of the secure key
* @param[in] is_old_mk if true the key is currently re-enciphered with the
* OLD master key
+ * @param[in] apqns the associated APQNs (or NULL if none)
* @returns 0 if the re-enciphering is successful, a negative errno value
* otherwise, 1 if it was skipped
*/
@@ -2543,9 +2544,18 @@ static int _keystore_perform_reencipher(
struct cca_lib *cca,
struct reencipher_params *params,
u8 *secure_key, size_t secure_key_size,
- bool is_old_mk)
+ bool is_old_mk, const char *apqns)
{
- int rc;
+ int rc, selected = 1;
+ u64 mkvp;
+
+ rc = get_master_key_verification_pattern(secure_key, secure_key_size,
+ &mkvp, keystore->verbose);
+ if (rc != 0) {
+ warnx("Failed to get the master key verification pattern: %s",
+ strerror(-rc));
+ return rc;
+ }
if (!params->from_old && !params->to_new) {
/* Autodetect reencipher mode */
@@ -2567,12 +2577,6 @@ static int _keystore_perform_reencipher(
}
if (params->from_old) {
- if (!is_old_mk) {
- printf("The secure key '%s' is already enciphered "
- "with the CURRENT CCA master key\n", name);
- return 1;
- }
-
if (params->inplace == -1)
params->inplace = 1;
@@ -2580,12 +2584,27 @@ static int _keystore_perform_reencipher(
"Secure key '%s' will be re-enciphered from OLD "
"to the CURRENT CCA master key", name);
+ rc = select_cca_adapter_by_mkvp(cca, mkvp, apqns,
+ FLAG_SEL_CCA_MATCH_OLD_MKVP,
+ keystore->verbose);
+ if (rc == -ENOTSUP) {
+ rc = 0;
+ selected = 0;
+ }
+ if (rc != 0) {
+ warnx("No APQN found that is suitable for "
+ "re-enciphering this secure AES key");
+ return rc;
+ }
+
rc = key_token_change(cca, secure_key, secure_key_size,
METHOD_OLD_TO_CURRENT,
keystore->verbose);
if (rc != 0) {
warnx("Failed to re-encipher '%s' from OLD to "
"CURRENT CCA master key", name);
+ if (!selected)
+ print_msg_for_cca_envvars("secure AES key");
return rc;
}
}
@@ -2597,12 +2616,30 @@ static int _keystore_perform_reencipher(
if (params->inplace == -1)
params->inplace = 0;
+ rc = select_cca_adapter_by_mkvp(cca, mkvp, apqns,
+ FLAG_SEL_CCA_MATCH_CUR_MKVP |
+ FLAG_SEL_CCA_NEW_MUST_BE_SET,
+ keystore->verbose);
+ if (rc == -ENOTSUP) {
+ rc = 0;
+ selected = 0;
+ }
+ if (rc != 0) {
+ util_print_indented("No APQN found that is suitable "
+ "for re-enciphering this secure "
+ "AES key and has the NEW master "
+ "key loaded", 0);
+ return rc;
+ }
+
rc = key_token_change(cca, secure_key, secure_key_size,
METHOD_CURRENT_TO_NEW,
keystore->verbose);
if (rc != 0) {
warnx("Failed to re-encipher '%s' from CURRENT to "
"NEW CCA master key", name);
+ if (!selected)
+ print_msg_for_cca_envvars("secure AES key");
return rc;
}
}
@@ -2692,7 +2729,9 @@ static int _keystore_process_reencipher(
rc = _keystore_perform_reencipher(keystore, name, info->cca,
&params, secure_key,
- secure_key_size, is_old_mk);
+ secure_key_size, is_old_mk,
+ properties_get(properties,
+ PROP_NAME_APQNS));
if (rc < 0)
goto out;
if (rc > 0) {
--- a/zkey/zkey-cryptsetup.c
+++ b/zkey/zkey-cryptsetup.c
@@ -1514,10 +1514,12 @@ static int reencipher_prepare(int token)
char *password = NULL;
size_t password_len;
char *key = NULL;
+ int selected = 1;
size_t keysize;
int is_old_mk;
char *prompt;
char *msg;
+ u64 mkvp;
int rc;
if (token >= 0) {
@@ -1578,13 +1580,42 @@ static int reencipher_prepare(int token)
util_print_indented(msg, 0);
free(msg);
+ rc = get_master_key_verification_pattern((u8 *)key, keysize, &mkvp,
+ g.verbose);
+ if (rc != 0) {
+ warnx("Failed to get the master key verification pattern: %s",
+ strerror(-rc));
+ goto out;
+ }
+
+ rc = select_cca_adapter_by_mkvp(&g.cca, mkvp, NULL,
+ is_old_mk ? FLAG_SEL_CCA_MATCH_OLD_MKVP
+ : FLAG_SEL_CCA_MATCH_CUR_MKVP |
+ FLAG_SEL_CCA_NEW_MUST_BE_SET,
+ g.verbose);
+ if (rc == -ENOTSUP) {
+ rc = 0;
+ selected = 0;
+ }
+ if (rc != 0) {
+ util_asprintf(&msg, "No APQN found that is suitable for "
+ "re-enciphering the secure AES volume key%s",
+ !is_old_mk ? " and has the NEW master key loaded"
+ : "");
+ util_print_indented(msg, 0);
+ free(msg);
+ goto out;
+ }
+
rc = key_token_change(&g.cca, (u8 *)key, keysize,
is_old_mk ? METHOD_OLD_TO_CURRENT :
METHOD_CURRENT_TO_NEW,
g.verbose);
if (rc != 0) {
warnx("Failed to re-encipher the secure volume key of device "
- "'%s'", g.pos_arg);
+ "'%s'\n", g.pos_arg);
+ if (!selected)
+ print_msg_for_cca_envvars("secure AES volume key");
rc = -EINVAL;
goto out;
}
@@ -1651,10 +1682,12 @@ static int reencipher_complete(int token
char *password = NULL;
size_t password_len;
char *key = NULL;
+ int selected = 1;
size_t keysize;
int is_old_mk;
char *prompt;
char *msg;
+ u64 mkvp;
int rc;
rc = get_reencipher_token(g.cd, token, &tok, true);
@@ -1700,11 +1733,38 @@ static int reencipher_complete(int token
goto out;
}
+ rc = get_master_key_verification_pattern((u8 *)key, keysize,
+ &mkvp, g.verbose);
+ if (rc != 0) {
+ warnx("Failed to get the master key verification "
+ "pattern: %s",
+ strerror(-rc));
+ goto out;
+ }
+
+ rc = select_cca_adapter_by_mkvp(&g.cca, mkvp, NULL,
+ FLAG_SEL_CCA_MATCH_OLD_MKVP,
+ g.verbose);
+ if (rc == -ENOTSUP) {
+ rc = 0;
+ selected = 0;
+ }
+ if (rc != 0) {
+ util_print_indented("No APQN found that is suitable "
+ "for re-enciphering the secure AES "
+ "volume key from the OLD to the "
+ "CURRENT CCA master key.", 0);
+ goto out;
+ }
+
rc = key_token_change(&g.cca, (u8 *)key, keysize,
METHOD_OLD_TO_CURRENT, g.verbose);
if (rc != 0) {
warnx("Failed to re-encipher the secure volume key for "
- "device '%s'", g.pos_arg);
+ "device '%s'\n", g.pos_arg);
+ if (!selected)
+ print_msg_for_cca_envvars(
+ "secure AES volume key");
rc = -EINVAL;
goto out;
}
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -1128,7 +1128,9 @@ static int command_reencipher_file(void)
{
size_t secure_key_size;
int rc, is_old_mk;
+ int selected = 1;
u8 *secure_key;
+ u64 mkvp;
if (g.name != NULL) {
warnx("Option '--name|-N' is not valid for "
@@ -1174,6 +1176,15 @@ static int command_reencipher_file(void)
goto out;
}
+ rc = get_master_key_verification_pattern(secure_key, secure_key_size,
+ &mkvp, g.verbose);
+ if (rc != 0) {
+ warnx("Failed to get the master key verification pattern: %s",
+ strerror(-rc));
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+
if (!g.fromold && !g.tonew) {
/* Autodetect reencipher option */
if (is_old_mk) {
@@ -1205,12 +1216,28 @@ static int command_reencipher_file(void)
pr_verbose("Secure key will be re-enciphered from OLD to the "
"CURRENT CCA master key");
+ rc = select_cca_adapter_by_mkvp(&g.cca, mkvp, NULL,
+ FLAG_SEL_CCA_MATCH_OLD_MKVP,
+ g.verbose);
+ if (rc == -ENOTSUP) {
+ rc = 0;
+ selected = 0;
+ }
+ if (rc != 0) {
+ warnx("No APQN found that is suitable for "
+ "re-enciphering the secure AES volume key");
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+
rc = key_token_change(&g.cca, secure_key, secure_key_size,
METHOD_OLD_TO_CURRENT,
g.verbose);
if (rc != 0) {
warnx("Re-encipher from OLD to CURRENT CCA "
- "master key has failed");
+ "master key has failed\n");
+ if (!selected)
+ print_msg_for_cca_envvars("secure AES key");
rc = EXIT_FAILURE;
goto out;
}
@@ -1219,11 +1246,30 @@ static int command_reencipher_file(void)
pr_verbose("Secure key will be re-enciphered from CURRENT "
"to the NEW CCA master key");
+ rc = select_cca_adapter_by_mkvp(&g.cca, mkvp, NULL,
+ FLAG_SEL_CCA_MATCH_CUR_MKVP |
+ FLAG_SEL_CCA_NEW_MUST_BE_SET,
+ g.verbose);
+ if (rc == -ENOTSUP) {
+ rc = 0;
+ selected = 0;
+ }
+ if (rc != 0) {
+ util_print_indented("No APQN found that is suitable "
+ "for re-enciphering this secure "
+ "AES key and has the NEW master "
+ "key loaded", 0);
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+
rc = key_token_change(&g.cca, secure_key, secure_key_size,
METHOD_CURRENT_TO_NEW, g.verbose);
if (rc != 0) {
warnx("Re-encipher from CURRENT to NEW CCA "
- "master key has failed");
+ "master key has failed\n");
+ if (!selected)
+ print_msg_for_cca_envvars("secure AES key");
rc = EXIT_FAILURE;
goto out;
}

View File

@ -1,42 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl/boot: fix comment in stage3.lds
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 971970989bbb1de8887d11b0ab8e4f19adbd484f
Problem-ID: VS1804
Upstream-Description:
zipl/boot: fix comment in stage3.lds
See STAGE3_STACK_ADDRESS macro.
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/stage3.lds | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/zipl/boot/stage3.lds
+++ b/zipl/boot/stage3.lds
@@ -10,7 +10,7 @@
* 0x6000-0x8fff free
* 0x9000-0x9fff Stage3 parameter
* 0xa000-0xdfff Stage3 code + data
- * 0xe000-0xffff Stack
+ * 0xf000-0xffff Stack
*/
SECTIONS

View File

@ -1,289 +0,0 @@
Subject: zkey-cryptsetup: Add --to-new and --from-old options
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
APQNs associated with a secure key have the same master key.
Display the master key verification pattern of a secure key
during the zkey validate command. This helps to better identify
which master key is the correct one, in case of master key
inconsistencies.
Select an appropriate APQN when re-enciphering a secure key.
Re-enciphering is done using the CCA host library. Special
handling is required to select an appropriate APQN for use with
the CCA host library.
Upstream-ID: a0ed6709cf3c62b1fc9dfa28358e70215c1da55a
Problem-ID: SEC1916
Upstream-Description:
zkey-cryptsetup: Add --to-new and --from-old options
To allow better control about the secure AES volume key re-enciphering
with 'zkey-cryptsetup reencipher', add options '--to-new' and '--from-old'
to specify if a re-enciphering from CURRENT to NEW, or OLD to CURRENT master
key registers is to be performed. If these options are not specified, then
it is auto-detected, based on the master key that the secure key is currently
re-enciphered with.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/zkey-cryptsetup.1 | 49 ++++++++++++++---
zkey/zkey-cryptsetup.c | 137 ++++++++++++++++++++++++++++++++++++-------------
2 files changed, 142 insertions(+), 44 deletions(-)
--- a/zkey/zkey-cryptsetup.1
+++ b/zkey/zkey-cryptsetup.1
@@ -91,6 +91,8 @@ behave in the same way as with \fBcrypts
.B zkey\-cryptsetup
.BR reencipher | re
.I device
+.RB [ \-\-to\-new | \-N ]
+.RB [ \-\-from\-old | \-O ]
.RB [ \-\-staged | \-s ]
.RB [ \-\-in\-place | \-i ]
.RB [ \-\-complete | \-c ]
@@ -128,17 +130,36 @@ register can still be used until the mas
The \fBNEW\fP register contains the new master key to be set.
The master key in the \fBNEW\fP register cannot be used until it is made
the current master key. You can pro-actively re-encipher a secure key with the
-\fBNEW\fP master key before this key is made the \fBCURRENT\fP key.
+\fBNEW\fP master key before this key is made the \fBCURRENT\fP key. Use the
+.B \-\-to-new
+option to do this.
.RE
.PP
-\fBzkey\-cryptsetup\fP automatically detects whether the secure volume key
-is currently enciphered with the master key in the \fBOLD\fP register or with
-the master key in the \fBCURRENT\fP register. If currently enciphered with the
-master key in the \fBOLD\fP register, it is re-enciphered with the master key
-in the \fBCURRENT\fP register. If it is currently enciphered with the master
-key in the \fBCURRENT\fP register, it is re-enciphered with the master key in
-the \fBNEW\fP register. If for this case the \fBNEW\fP register does not
-contain a valid master key, then the re-encipher operation fails.
+Use the
+.B \-\-from\-old
+option to re-encipher a secure volume key that is currently enciphered with
+the master key in the \fBOLD\fP register with the master key in the
+\fBCURRENT\fP register.
+.PP
+.PP
+If both the
+.B \-\-from-old
+and
+.B \-\-to-new
+options are specified, a secure volume key that is currently enciphered
+with the master key in the \fBOLD\fP register is re-enciphered with the
+master key in the \fBNEW\fP register.
+.RE
+.PP
+If both options are omitted, \fBzkey-cryptsetup\fP automatically detects whether
+the secure volume key is currently enciphered with the master key in the
+\fBOLD\fP register or with the master key in the \fBCURRENT\fP register.
+If currently enciphered with the master key in the \fBOLD\fP register,
+it is re-enciphered with the master key in the \fBCURRENT\fP register.
+If it is currently enciphered with the master key in the \fBCURRENT\fP
+register, it is re-enciphered with the master key in the \fBNEW\fP register.
+If for this case the \fBNEW\fP register does not contain a valid master key,
+then the re-encipher operation fails.
.PP
Re-enciphering a secure volume key of a volume encrypted with
\fBLUKS2\fP and the \fBpaes\fP cipher can be performed \fBin-place\fP, or in
@@ -326,6 +347,16 @@ relevance.
.
.SS "Options for the reencipher command"
.TP
+.BR \-N ", " \-\-to\-new
+Re-enciphers a secure volume key in the LUKS2 header that is currently
+enciphered with the master key in the CURRENT register with the master key in
+the NEW register.
+.TP
+.BR \-O ", " \-\-from\-old
+Re-enciphers a secure volume key in the LUKS2 header that is currently
+enciphered with the master key in the OLD register with the master key in the
+CURRENT register.
+.TP
.BR \-i ", " \-\-in-place
Forces an in-place re-enciphering of a secure volume key in the LUKS2
header. This option immediately replaces the secure volume key in the LUKS2
--- a/zkey/zkey-cryptsetup.c
+++ b/zkey/zkey-cryptsetup.c
@@ -95,6 +95,8 @@ static struct zkey_cryptsetup_globals {
long long keyfile_offset;
long long keyfile_size;
long long tries;
+ bool tonew;
+ bool fromold;
bool complete;
bool inplace;
bool staged;
@@ -163,6 +165,22 @@ static struct util_opt opt_vec[] = {
.command = COMMAND_REENCIPHER,
},
{
+ .option = {"to-new", 0, NULL, 'N'},
+ .desc = "Re-enciphers a secure volume key in the LUKS2 header "
+ "that is currently enciphered with the master key in "
+ "the CURRENT register with the master key in the NEW "
+ "register",
+ .command = COMMAND_REENCIPHER,
+ },
+ {
+ .option = {"from-old", 0, NULL, 'O'},
+ .desc = "Re-enciphers a secure volume key in the LUKS2 header "
+ "that is currently enciphered with the master key in "
+ "the OLD register with the master key in the CURRENT "
+ "register",
+ .command = COMMAND_REENCIPHER,
+ },
+ {
.option = {"staged", 0, NULL, 's'},
.desc = "Forces that the re-enciphering of a secure volume "
"key in the LUKS2 header is performed in staged mode",
@@ -1572,13 +1590,28 @@ static int reencipher_prepare(int token)
if (rc < 0)
goto out;
- util_asprintf(&msg, "The secure volume key of device '%s' is "
- "enciphered with the %s CCA master key and is being "
- "re-enciphered with the %s CCA master key.",
- g.pos_arg, is_old_mk ? "OLD" : "CURRENT",
- is_old_mk ? "CURRENT" : "NEW");
- util_print_indented(msg, 0);
- free(msg);
+ if (!g.fromold && !g.tonew) {
+ /* Autodetect reencipher mode */
+ if (is_old_mk) {
+ g.fromold = 1;
+ util_asprintf(&msg, "The secure volume key of device "
+ "'%s' is enciphered with the OLD CCA "
+ "master key and is being re-enciphered "
+ "with the CURRENT CCA master key.",
+ g.pos_arg);
+ util_print_indented(msg, 0);
+ free(msg);
+ } else {
+ g.tonew = 1;
+ util_asprintf(&msg, "The secure volume key of device "
+ "'%s' is enciphered with the CURRENT CCA "
+ "master key and is being re-enciphered "
+ "with the NEW CCA master key.",
+ g.pos_arg);
+ util_print_indented(msg, 0);
+ free(msg);
+ }
+ }
rc = get_master_key_verification_pattern((u8 *)key, keysize, &mkvp,
g.verbose);
@@ -1588,36 +1621,64 @@ static int reencipher_prepare(int token)
goto out;
}
- rc = select_cca_adapter_by_mkvp(&g.cca, mkvp, NULL,
- is_old_mk ? FLAG_SEL_CCA_MATCH_OLD_MKVP
- : FLAG_SEL_CCA_MATCH_CUR_MKVP |
- FLAG_SEL_CCA_NEW_MUST_BE_SET,
- g.verbose);
- if (rc == -ENOTSUP) {
- rc = 0;
- selected = 0;
- }
- if (rc != 0) {
- util_asprintf(&msg, "No APQN found that is suitable for "
- "re-enciphering the secure AES volume key%s",
- !is_old_mk ? " and has the NEW master key loaded"
- : "");
- util_print_indented(msg, 0);
- free(msg);
- goto out;
+ if (g.fromold) {
+ rc = select_cca_adapter_by_mkvp(&g.cca, mkvp, NULL,
+ FLAG_SEL_CCA_MATCH_OLD_MKVP,
+ g.verbose);
+ if (rc == -ENOTSUP) {
+ rc = 0;
+ selected = 0;
+ }
+ if (rc != 0) {
+ util_print_indented("No APQN found that is suitable "
+ "for re-enciphering the secure AES "
+ "volume key from the OLD to the "
+ "CURRENT CCA master key.", 0);
+ goto out;
+ }
+
+ rc = key_token_change(&g.cca, (u8 *)key, keysize,
+ METHOD_OLD_TO_CURRENT, g.verbose);
+ if (rc != 0) {
+ warnx("Failed to re-encipher the secure volume key of "
+ "device '%s'\n", g.pos_arg);
+ if (!selected)
+ print_msg_for_cca_envvars(
+ "secure AES volume key");
+ rc = -EINVAL;
+ goto out;
+ }
}
- rc = key_token_change(&g.cca, (u8 *)key, keysize,
- is_old_mk ? METHOD_OLD_TO_CURRENT :
- METHOD_CURRENT_TO_NEW,
- g.verbose);
- if (rc != 0) {
- warnx("Failed to re-encipher the secure volume key of device "
- "'%s'\n", g.pos_arg);
- if (!selected)
- print_msg_for_cca_envvars("secure AES volume key");
- rc = -EINVAL;
- goto out;
+ if (g.tonew) {
+ rc = select_cca_adapter_by_mkvp(&g.cca, mkvp, NULL,
+ FLAG_SEL_CCA_MATCH_CUR_MKVP |
+ FLAG_SEL_CCA_NEW_MUST_BE_SET,
+ g.verbose);
+ if (rc == -ENOTSUP) {
+ rc = 0;
+ selected = 0;
+ }
+ if (rc != 0) {
+ util_print_indented("No APQN found that is suitable "
+ "for re-enciphering the secure AES "
+ "volume key from the CURRENT to "
+ "the NEW CCA master key.", 0);
+ goto out;
+ }
+
+ rc = key_token_change(&g.cca, (u8 *)key, keysize,
+ METHOD_CURRENT_TO_NEW,
+ g.verbose);
+ if (rc != 0) {
+ warnx("Failed to re-encipher the secure volume key of "
+ "device '%s'\n", g.pos_arg);
+ if (!selected)
+ print_msg_for_cca_envvars(
+ "secure AES volume key");
+ rc = -EINVAL;
+ goto out;
+ }
}
rc = crypt_keyslot_add_by_key(g.cd, CRYPT_ANY_SLOT, key, keysize,
@@ -2276,6 +2337,12 @@ int main(int argc, char *argv[])
if (c == -1)
break;
switch (c) {
+ case 'N':
+ g.tonew = 1;
+ break;
+ case 'O':
+ g.fromold = 1;
+ break;
case 'c':
g.complete = 1;
break;

View File

@ -1,50 +0,0 @@
Subject: [PATCH] [FEAT VS1804] lib/zt_common: add STATIC_ASSERT macro
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: bac3f93772bdf8618c2c9677c59569d70e4a39c0
Problem-ID: VS1804
Upstream-Description:
lib/zt_common: add STATIC_ASSERT macro
Add `STATIC_ASSERT` macro that uses `_Static_assert` if available (was
introduced with gcc 4.6, see https://gcc.gnu.org/wiki/C11Status). For
example, this could be used for the verification of structure sizes at
compile time.
Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
include/lib/zt_common.h | 7 +++++++
1 file changed, 7 insertions(+)
--- a/include/lib/zt_common.h
+++ b/include/lib/zt_common.h
@@ -22,6 +22,13 @@
# define UNUSED(x) x
#endif
+#ifdef STATIC_ASSERT
+#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ >= 5)
+# define STATIC_ASSERT(test) _Static_assert((test), "(" #test ") failed");
+#else
+# define STATIC_ASSERT(test)
+#endif
+
#define RELEASE_STRING STRINGIFY (S390_TOOLS_RELEASE)
#define TOOLS_LIBDIR STRINGIFY (S390_TOOLS_LIBDIR)
#define TOOLS_SYSCONFDIR STRINGIFY (S390_TOOLS_SYSCONFDIR)

View File

@ -1,202 +0,0 @@
Subject: zkey: Display key type with list and validate commands
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: 9de85f42951e0b1a3d083363d7000b1950aebcd7
Problem-ID: SEC1717
Upstream-Description:
zkey: Display key type with list and validate commands
For the 'zkey list', 'zkey validate' and 'zkey-cryptsetup validate'
commands, display the key type.
As of today there is only one possible key type (CCA-AESDATA),
but in the future there might be additional key types.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/keystore.c | 7 +++++++
zkey/pkey.c | 39 +++++++++++++++++++++++++++++++++++++++
zkey/pkey.h | 17 +++++++++++++++++
zkey/zkey-cryptsetup.c | 2 ++
zkey/zkey.c | 2 ++
5 files changed, 67 insertions(+)
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -77,6 +77,7 @@ struct key_filenames {
#define REC_SEC_KEY_SIZE "Secure key size"
#define REC_CLR_KEY_SIZE "Clear key size"
#define REC_XTS "XTS type key"
+#define REC_KEY_TYPE "Key type"
#define REC_VOLUMES "Volumes"
#define REC_APQNS "APQNs"
#define REC_KEY_FILE "Key file name"
@@ -2140,6 +2141,7 @@ static struct util_rec *_keystore_setup_
util_rec_def(rec, REC_CLR_KEY_SIZE, UTIL_REC_ALIGN_LEFT, 20,
REC_CLR_KEY_SIZE);
util_rec_def(rec, REC_XTS, UTIL_REC_ALIGN_LEFT, 3, REC_XTS);
+ util_rec_def(rec, REC_KEY_TYPE, UTIL_REC_ALIGN_LEFT, 54, REC_KEY_TYPE);
if (validation)
util_rec_def(rec, REC_MASTERKEY, UTIL_REC_ALIGN_LEFT, 54,
REC_MASTERKEY);
@@ -2178,6 +2180,7 @@ static void _keystore_print_record(struc
char *description;
char *volume_type;
char *reencipher;
+ char *key_type;
char *creation;
char *volumes;
char *change;
@@ -2212,6 +2215,7 @@ static void _keystore_print_record(struc
reencipher = properties_get(properties, PROP_NAME_REENC_TIME);
vp = properties_get(properties, PROP_NAME_KEY_VP);
volume_type = _keystore_get_volume_type(properties);
+ key_type = properties_get(properties, PROP_NAME_KEY_TYPE);
util_rec_set(rec, REC_KEY, name);
if (validation)
@@ -2226,6 +2230,7 @@ static void _keystore_print_record(struc
util_rec_set(rec, REC_CLR_KEY_SIZE, "(unknown)");
util_rec_set(rec, REC_XTS,
IS_XTS(secure_key_size) ? "Yes" : "No");
+ util_rec_set(rec, REC_KEY_TYPE, key_type);
if (validation) {
if (valid)
util_rec_set(rec, REC_MASTERKEY,
@@ -2290,6 +2295,8 @@ static void _keystore_print_record(struc
free(vp);
if (volume_type != NULL)
free(volume_type);
+ if (key_type != NULL)
+ free(key_type);
}
struct validate_info {
--- a/zkey/pkey.c
+++ b/zkey/pkey.c
@@ -790,3 +790,42 @@ int get_master_key_verification_pattern(
return 0;
}
+
+/**
+ * Check if the specified key is a CCA AESDATA key token.
+ *
+ * @param[in] key the secure key token
+ * @param[in] key_size the size of the secure key
+ *
+ * @returns true if the key is an CCA AESDATA token type
+ */
+bool is_cca_aes_data_key(const u8 *key, size_t key_size)
+{
+ struct tokenheader *hdr = (struct tokenheader *)key;
+
+ if (key == NULL || key_size < SECURE_KEY_SIZE)
+ return false;
+
+ if (hdr->type != TOKEN_TYPE_CCA_INTERNAL)
+ return false;
+ if (hdr->version != TOKEN_VERSION_AESDATA)
+ return false;
+
+ return true;
+}
+
+/**
+ * Returns the type of the key
+ *
+ * @param[in] key the secure key token
+ * @param[in] key_size the size of the secure key
+ *
+ * @returns a static string on success, NULL in case of an error
+ */
+const char *get_key_type(const u8 *key, size_t key_size)
+{
+ if (is_cca_aes_data_key(key, key_size))
+ return KEY_TYPE_CCA_AESDATA;
+
+ return NULL;
+}
--- a/zkey/pkey.h
+++ b/zkey/pkey.h
@@ -18,6 +18,18 @@
/*
* Definitions for the /dev/pkey kernel module interface
*/
+struct tokenheader {
+ u8 type;
+ u8 res0[3];
+ u8 version;
+ u8 res1[3];
+} __packed;
+
+#define TOKEN_TYPE_NON_CCA 0x00
+#define TOKEN_TYPE_CCA_INTERNAL 0x01
+
+#define TOKEN_VERSION_AESDATA 0x04
+
struct secaeskeytoken {
u8 type; /* 0x01 for internal key token */
u8 res0[3];
@@ -82,6 +94,8 @@ struct pkey_verifykey {
#define PKEY_VERIFYKEY _IOWR(PKEY_IOCTL_MAGIC, 0x07, struct pkey_verifykey)
+#define KEY_TYPE_CCA_AESDATA "CCA-AESDATA"
+
#define PAES_BLOCK_SIZE 16
#define ENC_ZERO_LEN (2 * PAES_BLOCK_SIZE)
#define VERIFICATION_PATTERN_LEN (2 * ENC_ZERO_LEN + 1)
@@ -116,4 +130,7 @@ int get_master_key_verification_pattern(
size_t secure_key_size, u64 *mkvp,
bool verbose);
+bool is_cca_aes_data_key(const u8 *key, size_t key_size);
+const char *get_key_type(const u8 *key, size_t key_size);
+
#endif
--- a/zkey/zkey-cryptsetup.c
+++ b/zkey/zkey-cryptsetup.c
@@ -1999,6 +1999,8 @@ static int command_validate(void)
printf(" Secure key size: %lu bytes\n", keysize);
printf(" XTS type key: %s\n",
keysize > SECURE_KEY_SIZE ? "Yes" : "No");
+ printf(" Key type: %s\n",
+ get_key_type((u8 *)key, keysize));
if (is_valid) {
printf(" Clear key size: %lu bits\n", clear_keysize);
printf(" Enciphered with: %s CCA master key (MKVP: "
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -1416,6 +1416,8 @@ static int command_validate_file(void)
printf("Validation of secure key in file '%s':\n", g.pos_arg);
printf(" Status: Valid\n");
printf(" Secure key size: %lu bytes\n", secure_key_size);
+ printf(" Key type: %s\n",
+ get_key_type(secure_key, secure_key_size));
printf(" Clear key size: %lu bits\n", clear_key_size);
printf(" XTS type key: %s\n",
secure_key_size > SECURE_KEY_SIZE ? "Yes" : "No");

View File

@ -1,91 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: use STATIC_ASSERT macro for no padding verification
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: cc16e41595d6dcb942f84443f27a1b52d06d17da
Problem-ID: VS1804
Upstream-Description:
zipl: use STATIC_ASSERT macro for no padding verification
A simple comment above the struct declaration to indicate that the
structure must not have any padding is prone to error. Therefore let's
add a check for the structure size at compile time.
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/sclp.h | 2 ++
zipl/boot/sclp_stage3.h | 2 ++
zipl/boot/stage3.h | 4 ++++
3 files changed, 8 insertions(+)
--- a/zipl/boot/sclp.h
+++ b/zipl/boot/sclp.h
@@ -60,6 +60,7 @@ struct sccb_header {
uint8_t control_mask[3];
uint16_t response_code;
};
+STATIC_ASSERT(sizeof(struct sccb_header) == 2 + 1 + 3 + 2)
/* Structure must not have any padding */
struct evbuf_header {
@@ -68,6 +69,7 @@ struct evbuf_header {
uint8_t flags;
uint16_t _reserved;
};
+STATIC_ASSERT(sizeof(struct evbuf_header) == 2 + 1 + 1 + 2)
struct mto {
uint16_t length;
--- a/zipl/boot/sclp_stage3.h
+++ b/zipl/boot/sclp_stage3.h
@@ -42,6 +42,8 @@ struct sdias_sccb {
struct sccb_header header;
struct sdias_evbuf evbuf;
};
+STATIC_ASSERT(sizeof(struct sdias_sccb) ==
+ sizeof(struct sccb_header) + sizeof(struct sdias_evbuf))
int sclp_hsa_copy(void *, unsigned long, unsigned long);
--- a/zipl/boot/stage3.h
+++ b/zipl/boot/stage3.h
@@ -15,6 +15,8 @@
#include "libc.h"
#include "s390.h"
+#include "lib/zt_common.h"
+
#define IPL_DEVICE 0x10404UL
#define INITRD_START 0x10408UL
#define INITRD_SIZE 0x10410UL
@@ -128,6 +130,7 @@ struct ipl_rb_hdr {
uint8_t rbt;
uint8_t reserved1[11];
};
+STATIC_ASSERT(sizeof(struct ipl_rb_hdr) == 4 + 1 + 11)
/* IPL Report Block types */
enum ipl_rbt {
@@ -168,6 +171,7 @@ struct ipl_rb_components {
uint8_t reserved1[11];
struct ipl_rb_component_entry entries[];
};
+STATIC_ASSERT(sizeof(struct ipl_rb_components) == 4 + 1 + 11)
extern unsigned long long _parm_addr; /* address of parmline */
extern unsigned long long _initrd_addr; /* address of initrd */

View File

@ -1,331 +0,0 @@
Subject: zkey: Allow to filter list output by key type
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: 91c35543ca7fd25691487c61ec2e308f2903a6b8
Problem-ID: SEC1717
Upstream-Description:
zkey: Allow to filter list output by key type
The zkey list command now accepts option --key-type|-K type
to filter the displayed keys by key type. If not specified,
then all key types are displayed.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/keystore.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++------
zkey/keystore.h | 2 -
zkey/zkey.1 | 9 ++++-
zkey/zkey.c | 15 +++++++-
4 files changed, 112 insertions(+), 13 deletions(-)
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -315,6 +315,39 @@ static char *_keystore_get_volume_type(s
}
/**
+ * Returns the key type contained in the properties. If no key type
+ * property is contained, then 'CCA-AESDATA' is assumed (for backward
+ * compatibility).
+ *
+ * @returns a string containing the key type. Must be freed by the caller.
+ */
+static char *_keystore_get_key_type(struct properties *properties)
+{
+ char *type;
+
+ type = properties_get(properties, PROP_NAME_KEY_TYPE);
+ if (type == NULL)
+ type = util_strdup(KEY_TYPE_CCA_AESDATA);
+
+ return type;
+}
+
+/**
+ * Checks if the key type is supported.
+ *
+ * @param[in] key_type the key type
+ *
+ * @returns 1 if the key type is valid, 0 otherwise
+ */
+static int _keystore_valid_key_type(const char *key_type)
+{
+ if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) == 0)
+ return 1;
+
+ return 0;
+}
+
+/**
* Prints a message followed by a list of associated volumes, if volumes are
* associated and the volume-type matches (if specified)
*
@@ -817,6 +850,33 @@ static int _keystore_match_volume_type_p
return rc;
}
+/**
+ * Checks if the key type property matches the specified key type.
+ * If the properties do not contain a key type property, then the default
+ * key type is assumed.
+ *
+ * @param[in] properties a properties object
+ * @param[in] key_type the key type to match. Can be NULL. In this case
+ * it always matches.
+ *
+ * @returns 1 for a match, 0 for not matched
+ */
+static int _keystore_match_key_type_property(struct properties *properties,
+ const char *key_type)
+{
+ char *type;
+ int rc = 0;
+
+ if (key_type == NULL)
+ return 1;
+
+ type = _keystore_get_key_type(properties);
+ if (strcasecmp(type, key_type) == 0)
+ rc = 1;
+
+ free(type);
+ return rc;
+}
/**
* Checks if a key name matches a name filter
@@ -882,6 +942,7 @@ typedef int (*process_key_t)(struct keys
* mutliple APQN filters separated by commas.
* NULL means no APQN filter.
* @param[in] volume_type If not NULL, specifies the volume type.
+ * @param[in] key_type The key type. NULL means no key type filter.
* @param[in] process_func the callback function called for a matching key
* @param[in/out] process_private private data passed to the process_func
*
@@ -894,6 +955,7 @@ static int _keystore_process_filtered(st
const char *volume_filter,
const char *apqn_filter,
const char *volume_type,
+ const char *key_type,
process_key_t process_func,
void *process_private)
{
@@ -985,6 +1047,15 @@ static int _keystore_process_filtered(st
goto free_prop;
}
+ rc = _keystore_match_key_type_property(key_props,
+ key_type);
+ if (rc == 0) {
+ pr_verbose(keystore,
+ "Key '%s' filtered out due to key type",
+ name);
+ goto free_prop;
+ }
+
rc = process_func(keystore, name, key_props, &file_names,
process_private);
if (rc != 0) {
@@ -1193,7 +1264,7 @@ static int _keystore_volume_check(const
info->set = set;
rc = _keystore_process_filtered(info->keystore, NULL, info->volume,
- NULL, NULL,
+ NULL, NULL, NULL,
_keystore_volume_check_process, info);
out:
free((void *)info->volume);
@@ -1454,7 +1525,8 @@ static int _keystore_set_default_propert
{
int rc;
- rc = properties_set(key_props, PROP_NAME_KEY_TYPE, "CCA-AESDATA");
+ rc = properties_set(key_props, PROP_NAME_KEY_TYPE,
+ KEY_TYPE_CCA_AESDATA);
if (rc != 0)
return rc;
@@ -2498,7 +2570,7 @@ int keystore_validate_key(struct keystor
info.num_warnings = 0;
rc = _keystore_process_filtered(keystore, name_filter, NULL,
- apqn_filter, NULL,
+ apqn_filter, NULL, NULL,
_keystore_process_validate, &info);
util_rec_free(rec);
@@ -2877,7 +2949,7 @@ int keystore_reencipher_key(struct keyst
info.num_skipped = 0;
rc = _keystore_process_filtered(keystore, name_filter, NULL,
- apqn_filter, NULL,
+ apqn_filter, NULL, NULL,
_keystore_process_reencipher, &info);
if (rc != 0) {
@@ -3258,12 +3330,13 @@ out:
* mutliple APQN filters separated by commas.
* NULL means no APQN filter.
* @param[in] volume_type The volume type. NULL means no volume type filter.
+ * @param[in] key_type The key type. NULL means no key type filter.
*
* @returns 0 for success or a negative errno in case of an error
*/
int keystore_list_keys(struct keystore *keystore, const char *name_filter,
const char *volume_filter, const char *apqn_filter,
- const char *volume_type)
+ const char *volume_type, const char *key_type)
{
struct util_rec *rec;
int rc;
@@ -3276,10 +3349,16 @@ int keystore_list_keys(struct keystore *
return -EINVAL;
}
+ if (key_type != NULL &&
+ !_keystore_valid_key_type(key_type)) {
+ warnx("Invalid key-type specified");
+ return -EINVAL;
+ }
+
rec = _keystore_setup_record(0);
rc = _keystore_process_filtered(keystore, name_filter, volume_filter,
- apqn_filter, volume_type,
+ apqn_filter, volume_type, key_type,
_keystore_display_key, rec);
util_rec_free(rec);
@@ -3773,8 +3852,8 @@ int keystore_cryptsetup(struct keystore
info.process_func = _keystore_process_cryptsetup;
rc = _keystore_process_filtered(keystore, NULL, volume_filter, NULL,
- volume_type, _keystore_process_crypt,
- &info);
+ volume_type, NULL,
+ _keystore_process_crypt, &info);
str_list_free_string_array(info.volume_filter);
@@ -3834,8 +3913,8 @@ int keystore_crypttab(struct keystore *k
info.process_func = _keystore_process_crypttab;
rc = _keystore_process_filtered(keystore, NULL, volume_filter, NULL,
- volume_type, _keystore_process_crypt,
- &info);
+ volume_type, NULL,
+ _keystore_process_crypt, &info);
str_list_free_string_array(info.volume_filter);
--- a/zkey/keystore.h
+++ b/zkey/keystore.h
@@ -68,7 +68,7 @@ int keystore_remove_key(struct keystore
int keystore_list_keys(struct keystore *keystore, const char *name_filter,
const char *volume_filter, const char *apqn_filter,
- const char *volume_type);
+ const char *volume_type, const char *key_type);
int keystore_cryptsetup(struct keystore *keystore, const char *volume_filter,
bool execute, const char *volume_type,
--- a/zkey/zkey.1
+++ b/zkey/zkey.1
@@ -368,6 +368,8 @@ The exported secure key also remains in
.IR card1.domain1[,card2.domain2[,...]] ]
.RB [ \-\-volume-type | \-t
.IR type ]
+.RB [ \-\-key-type | \-K
+.IR type ]
.RB [ \-\-verbose | \-V ]
.
.PP
@@ -382,7 +384,7 @@ listed that are associated with the spec
.PP
The
.B list
-command displays the attributes of the secure keys, such as key sizes,
+command displays the attributes of the secure keys, such as key sizes, key type,
whether it is a secure key that can be used for the XTS cipher mode, the textual
description, associated cryptographic adapters (APQNs) and volumes, the
sector size, the key verification pattern, and timestamps for key creation, last
@@ -907,6 +909,11 @@ This option is only available if
.B zkey
has been compiled with LUKS2 support enabled.
This option is only used for secure keys contained in the secure key repository.
+.TP
+.BR \-K ", " \-\-key-type\~\fItype\fP
+Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP.
+Only keys with the specified key type are listed.
+This option is only used for secure keys contained in the secure key repository.
.
.
.
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -73,6 +73,7 @@ static struct zkey_globals {
long int sector_size;
char *volume_type;
char *newname;
+ char *key_type;
bool run;
bool batch_mode;
char *keyfile;
@@ -432,6 +433,15 @@ static struct util_opt opt_vec[] = {
.command = COMMAND_LIST,
},
#endif
+ {
+ .option = { "key-type", required_argument, NULL, 'K'},
+ .argument = "type",
+ .desc = "The type of the key. Possible values are '"
+ KEY_TYPE_CCA_AESDATA"'. "
+ "Use this option to list all keys with the specified "
+ "key type.",
+ .command = COMMAND_LIST,
+ },
/***********************************************************/
{
.flags = UTIL_OPT_FLAG_SECTION,
@@ -1532,7 +1542,7 @@ static int command_list(void)
int rc;
rc = keystore_list_keys(g.keystore, g.name, g.volumes, g.apqns,
- g.volume_type);
+ g.volume_type, g.key_type);
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
@@ -1853,6 +1863,9 @@ int main(int argc, char *argv[])
case 'r':
g.run = 1;
break;
+ case 'K':
+ g.key_type = optarg;
+ break;
case 'F':
g.force = 1;
break;

View File

@ -1,65 +0,0 @@
Subject: [PATCH] [FEAT VS1804] Support `lib/zt_common.h` to be used in assembler and add `_AC` macro
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 400167f5128a14ba48b0d05b7b777b42c450c73f
Problem-ID: VS1804
Upstream-Description:
Support `lib/zt_common.h` to be used in assembler and add `_AC` macro
Support `lib/zt_common.h` to be used in assembler files. In addition,
add the macro `_AC` that can be used to make constant macros usable in
both assembler and C code.
Suggested-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
include/lib/zt_common.h | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
--- a/include/lib/zt_common.h
+++ b/include/lib/zt_common.h
@@ -15,6 +15,21 @@
#define STRINGIFY_1(x) #x
#define STRINGIFY(x) STRINGIFY_1(x)
+/* Use this macro to make constant macros usable in both assembler and
+ * C code.
+ *
+ * Usage example:
+ * #define IMAGE_ENTRY _AC(0x10000, UL)
+ */
+#ifdef __ASSEMBLER__
+#define _AC(X, TYPE) X
+#else
+#define _AC(X, TYPE) X##TYPE
+#endif
+
+
+#ifndef __ASSEMBLER__
+
#ifdef UNUSED
#elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
@@ -50,4 +65,5 @@ typedef signed short int s16;
typedef unsigned char u8;
typedef signed char s8;
+#endif /* __ASSEMBLER__ */
#endif /* LIB_ZT_COMMON_H */

View File

@ -1,348 +0,0 @@
Subject: zkey: Allow to specify the key type with the generate command
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: b47007b8ac8b446eb94b06e7ed3050b3df3e80e8
Problem-ID: SEC1717
Upstream-Description:
zkey: Allow to specify the key type with the generate command
The zkey generate command allows to specify the --key-type|-K
option to specify the key type. If not specified, then the
default is CCA-AESDATA.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/keystore.c | 35 ++++++++++++++++++++++++-----------
zkey/keystore.h | 2 +-
zkey/pkey.c | 20 +++++++++++++++++---
zkey/pkey.h | 6 +++---
zkey/zkey.1 | 14 ++++++++++++++
zkey/zkey.c | 17 ++++++++++++++---
6 files changed, 73 insertions(+), 21 deletions(-)
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -1525,11 +1525,6 @@ static int _keystore_set_default_propert
{
int rc;
- rc = properties_set(key_props, PROP_NAME_KEY_TYPE,
- KEY_TYPE_CCA_AESDATA);
- if (rc != 0)
- return rc;
-
rc = properties_set(key_props, PROP_NAME_CIPHER, "paes");
if (rc != 0)
return rc;
@@ -1564,6 +1559,7 @@ static int _keystore_set_default_propert
* the sector size is not specified and the system
* default is used.
* @param[in] volume_type the type of volume
+ * @param[in] key_type the type of the key
*/
static int _keystore_create_info_file(struct keystore *keystore,
const char *name,
@@ -1572,7 +1568,8 @@ static int _keystore_create_info_file(st
const char *volumes, const char *apqns,
bool noapqncheck,
size_t sector_size,
- const char *volume_type)
+ const char *volume_type,
+ const char *key_type)
{
struct volume_check vol_check = { .keystore = keystore, .name = name,
.set = 0 };
@@ -1594,6 +1591,12 @@ static int _keystore_create_info_file(st
goto out;
}
+ rc = properties_set2(key_props, PROP_NAME_KEY_TYPE, key_type, true);
+ if (rc != 0) {
+ warnx("Invalid characters in key-type");
+ goto out;
+ }
+
rc = _keystore_change_association(key_props, PROP_NAME_VOLUMES,
volumes != NULL ? volumes : "",
"volume", _keystore_volume_check,
@@ -1731,6 +1734,7 @@ out:
* clear key contained in the file denoted here.
* if NULL, the secure key is generated by random.
* @param[in] volume_type the type of volume
+ * @param[in] key_type the type of the key
* @param[in] pkey_fd the file descriptor of /dev/pkey
*
* @returns 0 for success or a negative errno in case of an error
@@ -1740,7 +1744,7 @@ int keystore_generate_key(struct keystor
const char *apqns, bool noapqncheck,
size_t sector_size, size_t keybits, bool xts,
const char *clear_key_file, const char *volume_type,
- int pkey_fd)
+ const char *key_type, int pkey_fd)
{
struct key_filenames file_names = { NULL, NULL, NULL };
struct properties *key_props = NULL;
@@ -1749,6 +1753,12 @@ int keystore_generate_key(struct keystor
util_assert(keystore != NULL, "Internal error: keystore is NULL");
util_assert(name != NULL, "Internal error: name is NULL");
+ util_assert(key_type != NULL, "Internal error: key_type is NULL");
+
+ if (!_keystore_valid_key_type(key_type)) {
+ warnx("Invalid key-type specified");
+ return -EINVAL;
+ }
rc = _keystore_get_key_filenames(keystore, name, &file_names);
if (rc != 0)
@@ -1773,13 +1783,14 @@ int keystore_generate_key(struct keystor
if (clear_key_file == NULL)
rc = generate_secure_key_random(pkey_fd,
file_names.skey_filename,
- keybits, xts, card, domain,
+ keybits, xts, key_type,
+ card, domain,
keystore->verbose);
else
rc = generate_secure_key_clear(pkey_fd,
file_names.skey_filename,
keybits, xts, clear_key_file,
- card, domain,
+ key_type, card, domain,
keystore->verbose);
if (rc != 0)
goto out_free_props;
@@ -1790,7 +1801,8 @@ int keystore_generate_key(struct keystor
rc = _keystore_create_info_file(keystore, name, &file_names,
description, volumes, apqns,
- noapqncheck, sector_size, volume_type);
+ noapqncheck, sector_size, volume_type,
+ key_type);
if (rc != 0)
goto out_free_props;
@@ -1894,7 +1906,8 @@ int keystore_import_key(struct keystore
rc = _keystore_create_info_file(keystore, name, &file_names,
description, volumes, apqns,
- noapqncheck, sector_size, volume_type);
+ noapqncheck, sector_size, volume_type,
+ KEY_TYPE_CCA_AESDATA);
if (rc != 0)
goto out_free_props;
--- a/zkey/keystore.h
+++ b/zkey/keystore.h
@@ -32,7 +32,7 @@ int keystore_generate_key(struct keystor
const char *apqns, bool noapqncheck,
size_t sector_size, size_t keybits, bool xts,
const char *clear_key_file, const char *volume_type,
- int pkey_fd);
+ const char *key_type, int pkey_fd);
int keystore_import_key(struct keystore *keystore, const char *name,
const char *description, const char *volumes,
--- a/zkey/pkey.c
+++ b/zkey/pkey.c
@@ -278,6 +278,7 @@ out:
* @param[in] keyfile the file name of the secure key to generate
* @param[in] keybits the cryptographic size of the key in bits
* @param[in] xts if true an XTS key is generated
+ * @param[in] key_type the type of the key
* @param[in] card the card number to use (or AUTOSELECT)
* @param[in] domain the domain number to use (or AUTOSELECT)
* @param[in] verbose if true, verbose messages are printed
@@ -285,8 +286,8 @@ out:
* @returns 0 on success, a negative errno in case of an error
*/
int generate_secure_key_random(int pkey_fd, const char *keyfile,
- size_t keybits, bool xts, u16 card, u16 domain,
- bool verbose)
+ size_t keybits, bool xts, const char *key_type,
+ u16 card, u16 domain, bool verbose)
{
struct pkey_genseck gensec;
size_t secure_key_size;
@@ -295,6 +296,12 @@ int generate_secure_key_random(int pkey_
util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
util_assert(keyfile != NULL, "Internal error: keyfile is NULL");
+ util_assert(key_type != NULL, "Internal error: key_type is NULL");
+
+ if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) != 0) {
+ warnx("Invalid key-type: %s", key_type);
+ return -EINVAL;
+ }
if (keybits == 0)
keybits = DEFAULT_KEYBITS;
@@ -374,6 +381,7 @@ out:
* determines the keybits.
* @param[in] xts if true an XTS key is generated
* @param[in] clearkeyfile the file name of the clear key to read
+ * @param[in] key_type the type of the key
* @param[in] card the card number to use (or AUTOSELECT)
* @param[in] domain the domain number to use (or AUTOSELECT)
* @param[in] verbose if true, verbose messages are printed
@@ -382,7 +390,7 @@ out:
*/
int generate_secure_key_clear(int pkey_fd, const char *keyfile,
size_t keybits, bool xts,
- const char *clearkeyfile,
+ const char *clearkeyfile, const char *key_type,
u16 card, u16 domain,
bool verbose)
{
@@ -397,6 +405,12 @@ int generate_secure_key_clear(int pkey_f
util_assert(keyfile != NULL, "Internal error: keyfile is NULL");
util_assert(clearkeyfile != NULL,
"Internal error: clearkeyfile is NULL");
+ util_assert(key_type != NULL, "Internal error: key_type is NULL");
+
+ if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) != 0) {
+ warnx("Invalid key-type: %s", key_type);
+ return -EINVAL;
+ }
secure_key_size = DOUBLE_KEYSIZE_FOR_XTS(SECURE_KEY_SIZE, xts);
secure_key = util_malloc(secure_key_size);
--- a/zkey/pkey.h
+++ b/zkey/pkey.h
@@ -103,12 +103,12 @@ struct pkey_verifykey {
int open_pkey_device(bool verbose);
int generate_secure_key_random(int pkey_fd, const char *keyfile,
- size_t keybits, bool xts, u16 card, u16 domain,
- bool verbose);
+ size_t keybits, bool xts, const char *key_type,
+ u16 card, u16 domain, bool verbose);
int generate_secure_key_clear(int pkey_fd, const char *keyfile,
size_t keybits, bool xts,
- const char *clearkeyfile,
+ const char *clearkeyfile, const char *key_type,
u16 card, u16 domain,
bool verbose);
--- a/zkey/zkey.1
+++ b/zkey/zkey.1
@@ -79,6 +79,8 @@ key repository.
.RB [ \-\-xts | \-x ]
.RB [ \-\-clearkey | \-c
.IR clear\-key\-file ]
+.RB [ \-\-key-type | \-K
+.IR type ]
.RB [ \-\-verbose | \-V ]
.
.PP
@@ -102,6 +104,8 @@ key repository.
.RB [ \-\-xts | \-x ]
.RB [ \-\-clearkey | \-c
.IR clear\-key\-file ]
+.RB [ \-\-key-type | \-K
+.IR type ]
.RB [ \-\-verbose | \-V ]
.PP
Use the
@@ -129,6 +133,11 @@ additional information can be associated
, or the
.B \-\-sector-size
options.
+.PP
+You can generate different types of secure keys: \fBCCA-AESDATA\fP keys.
+Specify the type of the secure key using the
+.B \-\-key\-type
+option. The default key type is CCA-AESDATA.
.
.SS "Validating secure AES keys"
.
@@ -730,6 +739,11 @@ This option is only available if
has been compiled with LUKS2 support enabled. If LUKS2 support is not enabled,
the default volume type is \fBplain\fP.
This option is only used for secure keys contained in the secure key repository.
+.TP
+.BR \-K ", " \-\-key-type\~\fItype\fP
+Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP.
+If this option is omitted, then a secure key of type
+CCA-AESDATA is generated.
.
.
.
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -217,6 +217,15 @@ static struct util_opt opt_vec[] = {
.command = COMMAND_GENERATE,
},
#endif
+ {
+ .option = { "key-type", required_argument, NULL, 'K'},
+ .argument = "type",
+ .desc = "The type of the key. Possible values are '"
+ KEY_TYPE_CCA_AESDATA"'. "
+ "When this option is omitted, the default is '"
+ KEY_TYPE_CCA_AESDATA"'",
+ .command = COMMAND_GENERATE,
+ },
/***********************************************************/
{
.flags = UTIL_OPT_FLAG_SECTION,
@@ -1019,7 +1028,7 @@ static int command_generate_clear(void)
rc = generate_secure_key_clear(g.pkey_fd, g.pos_arg,
g.keybits, g.xts,
- g.clearkeyfile,
+ g.clearkeyfile, g.key_type,
AUTOSELECT, AUTOSELECT,
g.verbose);
@@ -1036,7 +1045,7 @@ static int command_generate_random(void)
int rc;
rc = generate_secure_key_random(g.pkey_fd, g.pos_arg,
- g.keybits, g.xts,
+ g.keybits, g.xts, g.key_type,
AUTOSELECT, AUTOSELECT,
g.verbose);
@@ -1058,7 +1067,7 @@ static int command_generate_repository(v
rc = keystore_generate_key(g.keystore, g.name, g.description, g.volumes,
g.apqns, g.noapqncheck, g.sector_size,
g.keybits, g.xts, g.clearkeyfile,
- g.volume_type, g.pkey_fd);
+ g.volume_type, g.key_type, g.pkey_fd);
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
@@ -1085,6 +1094,8 @@ static int command_generate(void)
util_prg_print_parse_error();
return EXIT_FAILURE;
}
+ if (g.key_type == NULL)
+ g.key_type = KEY_TYPE_CCA_AESDATA;
if (g.name != NULL)
return command_generate_repository();
if (g.pos_arg != NULL) {

View File

@ -1,359 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: move IPL related definitions into separate header
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 9d39a4bd47008b15bbf4ebe672b91d6d63888536
Problem-ID: VS1804
Upstream-Description:
zipl: move IPL related definitions into separate header
Move the IPL related definitions into `include/boot/ipl.h`. This
allows the reuse of the definitions, e.g. in the boot loader for
protected guests.
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
include/boot/ipl.h | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++
zipl/boot/stage3.h | 140 ----------------------------------------------
2 files changed, 160 insertions(+), 139 deletions(-)
--- /dev/null
+++ b/include/boot/ipl.h
@@ -0,0 +1,159 @@
+/*
+ * IPL related definitions
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef IPL_H
+#define IPL_H
+
+#include "lib/zt_common.h"
+
+#define IPL_FLAG_SECURE 0x40
+
+#define IPL_RB_COMPONENT_FLAG_SIGNED 0x80
+#define IPL_RB_COMPONENT_FLAG_VERIFIED 0x40
+
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+/* IPL Parameter List header */
+struct ipl_pl_hdr {
+ uint32_t len;
+ uint8_t flags;
+ uint8_t reserved1[2];
+ uint8_t version;
+} __packed;
+
+/* IPL Parameter Block header */
+struct ipl_pb_hdr {
+ uint32_t len;
+ uint8_t pbt;
+} __packed;
+
+/* IPL Parameter Block 0 with common fields */
+struct ipl_pb0_common {
+ uint32_t len;
+ uint8_t pbt;
+ uint8_t flags;
+ uint8_t reserved1[2];
+ uint8_t loadparm[8];
+ uint8_t reserved2[84];
+} __packed;
+
+/* IPL Parameter Block 0 for FCP */
+struct ipl_pb0_fcp {
+ uint32_t len;
+ uint8_t pbt;
+ uint8_t reserved1[3];
+ uint8_t loadparm[8];
+ uint8_t reserved2[304];
+ uint8_t opt;
+ uint8_t reserved3[3];
+ uint8_t cssid;
+ uint8_t reserved4[1];
+ uint8_t devno;
+ uint8_t reserved5[4];
+ uint64_t wwpn;
+ uint64_t lun;
+ uint32_t bootprog;
+ uint8_t reserved6[12];
+ uint64_t br_lba;
+ uint32_t scp_data_len;
+ uint8_t reserved7[260];
+ uint8_t scp_data[];
+} __packed;
+
+/* IPL Parameter Block 0 for CCW */
+struct ipl_pb0_ccw {
+ uint32_t len;
+ uint8_t pbt;
+ uint8_t flags;
+ uint8_t reserved1[2];
+ uint8_t loadparm[8];
+ uint8_t reserved2[84];
+ uint16_t reserved3 : 13;
+ uint8_t ssid : 3;
+ uint16_t devno;
+ uint8_t vm_flags;
+ uint8_t reserved4[3];
+ uint32_t vm_parm_len;
+ uint8_t nss_name[8];
+ uint8_t vm_parm[64];
+ uint8_t reserved5[8];
+} __packed;
+
+struct ipl_parameter_block {
+ struct ipl_pl_hdr hdr;
+ union {
+ struct ipl_pb_hdr pb0_hdr;
+ struct ipl_pb0_common common;
+ struct ipl_pb0_fcp fcp;
+ struct ipl_pb0_ccw ccw;
+ char raw[PAGE_SIZE - sizeof(struct ipl_pl_hdr)];
+ };
+} __packed __aligned(PAGE_SIZE);
+
+/* IPL Report List header */
+struct ipl_rl_hdr {
+ uint32_t len;
+ uint8_t flags;
+ uint8_t reserved1[2];
+ uint8_t version;
+ uint8_t reserved2[8];
+} __packed;
+
+/* IPL Report Block header */
+/* Structure must not have any padding */
+struct ipl_rb_hdr {
+ uint32_t len;
+ uint8_t rbt;
+ uint8_t reserved1[11];
+};
+STATIC_ASSERT(sizeof(struct ipl_rb_hdr) == 4 + 1 + 11)
+
+/* IPL Report Block types */
+enum ipl_rbt {
+ IPL_RBT_CERTIFICATES = 1,
+ IPL_RBT_COMPONENTS = 2,
+};
+
+/* IPL Report Block for the certificate list */
+struct ipl_rb_certificate_entry {
+ uint64_t addr;
+ uint64_t len;
+} __packed;
+
+struct ipl_rb_certificates {
+ uint32_t len;
+ uint8_t rbt;
+ uint8_t reserved1[11];
+ struct ipl_rb_certificate_entry entries[];
+} __packed;
+
+/* IPL Report Block for the component list */
+struct ipl_rb_component_entry {
+ uint64_t addr;
+ uint64_t len;
+ uint8_t flags;
+ uint8_t reserved1[5];
+ uint16_t certificate_index;
+ uint8_t reserved2[8];
+};
+
+/* Structure must not have any padding */
+struct ipl_rb_components {
+ uint32_t len;
+ uint8_t rbt;
+ uint8_t reserved1[11];
+ struct ipl_rb_component_entry entries[];
+};
+STATIC_ASSERT(sizeof(struct ipl_rb_components) == 4 + 1 + 11)
+
+#endif /* __ASSEMBLER__ */
+#endif /* IPL_H */
--- a/zipl/boot/stage3.h
+++ b/zipl/boot/stage3.h
@@ -15,7 +15,7 @@
#include "libc.h"
#include "s390.h"
-#include "lib/zt_common.h"
+#include "boot/ipl.h"
#define IPL_DEVICE 0x10404UL
#define INITRD_START 0x10408UL
@@ -29,150 +29,12 @@
#define STAGE3_FLAG_SCSI 0x0001000000000000ULL
#define STAGE3_FLAG_KDUMP 0x0002000000000000ULL
-#define IPL_FLAG_SECURE 0x40
-
#define DEFAULT_PSW_LOAD 0x0008000080010000UL
#define PSW_ADDR_MASK 0x000000007FFFFFFFUL
#define UNSPECIFIED_ADDRESS -1UL
-/* IPL Parameter List header */
-struct ipl_pl_hdr {
- uint32_t len;
- uint8_t flags;
- uint8_t reserved1[2];
- uint8_t version;
-} __packed;
-
-/* IPL Parameter Block header */
-struct ipl_pb_hdr {
- uint32_t len;
- uint8_t pbt;
-} __packed;
-
-/* IPL Parameter Block 0 with common fields */
-struct ipl_pb0_common {
- uint32_t len;
- uint8_t pbt;
- uint8_t flags;
- uint8_t reserved1[2];
- uint8_t loadparm[8];
- uint8_t reserved2[84];
-} __packed;
-
-/* IPL Parameter Block 0 for FCP */
-struct ipl_pb0_fcp {
- uint32_t len;
- uint8_t pbt;
- uint8_t reserved1[3];
- uint8_t loadparm[8];
- uint8_t reserved2[304];
- uint8_t opt;
- uint8_t reserved3[3];
- uint8_t cssid;
- uint8_t reserved4[1];
- uint8_t devno;
- uint8_t reserved5[4];
- uint64_t wwpn;
- uint64_t lun;
- uint32_t bootprog;
- uint8_t reserved6[12];
- uint64_t br_lba;
- uint32_t scp_data_len;
- uint8_t reserved7[260];
- uint8_t scp_data[];
-} __packed;
-
-/* IPL Parameter Block 0 for CCW */
-struct ipl_pb0_ccw {
- uint32_t len;
- uint8_t pbt;
- uint8_t flags;
- uint8_t reserved1[2];
- uint8_t loadparm[8];
- uint8_t reserved2[84];
- uint16_t reserved3 : 13;
- uint8_t ssid : 3;
- uint16_t devno;
- uint8_t vm_flags;
- uint8_t reserved4[3];
- uint32_t vm_parm_len;
- uint8_t nss_name[8];
- uint8_t vm_parm[64];
- uint8_t reserved5[8];
-} __packed;
-
-struct ipl_parameter_block {
- struct ipl_pl_hdr hdr;
- union {
- struct ipl_pb_hdr pb0_hdr;
- struct ipl_pb0_common common;
- struct ipl_pb0_fcp fcp;
- struct ipl_pb0_ccw ccw;
- char raw[PAGE_SIZE - sizeof(struct ipl_pl_hdr)];
- };
-} __packed __aligned(PAGE_SIZE);
-
-/* IPL Report List header */
-struct ipl_rl_hdr {
- uint32_t len;
- uint8_t flags;
- uint8_t reserved1[2];
- uint8_t version;
- uint8_t reserved2[8];
-} __packed;
-
-/* IPL Report Block header */
-/* Structure must not have any padding */
-struct ipl_rb_hdr {
- uint32_t len;
- uint8_t rbt;
- uint8_t reserved1[11];
-};
-STATIC_ASSERT(sizeof(struct ipl_rb_hdr) == 4 + 1 + 11)
-
-/* IPL Report Block types */
-enum ipl_rbt {
- IPL_RBT_CERTIFICATES = 1,
- IPL_RBT_COMPONENTS = 2,
-};
-
-/* IPL Report Block for the certificate list */
-struct ipl_rb_certificate_entry {
- uint64_t addr;
- uint64_t len;
-} __packed;
-
-struct ipl_rb_certificates {
- uint32_t len;
- uint8_t rbt;
- uint8_t reserved1[11];
- struct ipl_rb_certificate_entry entries[];
-} __packed;
-
-/* IPL Report Block for the component list */
-struct ipl_rb_component_entry {
- uint64_t addr;
- uint64_t len;
- uint8_t flags;
- uint8_t reserved1[5];
- uint16_t certificate_index;
- uint8_t reserved2[8];
-};
-
-#define IPL_RB_COMPONENT_FLAG_SIGNED 0x80
-#define IPL_RB_COMPONENT_FLAG_VERIFIED 0x40
-
-/* Structure must not have any padding */
-struct ipl_rb_components {
- uint32_t len;
- uint8_t rbt;
- uint8_t reserved1[11];
- struct ipl_rb_component_entry entries[];
-};
-STATIC_ASSERT(sizeof(struct ipl_rb_components) == 4 + 1 + 11)
-
extern unsigned long long _parm_addr; /* address of parmline */
extern unsigned long long _initrd_addr; /* address of initrd */
extern unsigned long long _initrd_len; /* length of initrd */

View File

@ -1,665 +0,0 @@
Subject: zkey: Preparations for introducing a new key type
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: 298fab68fee86cb9b1862d60ca274971d4c39638
Problem-ID: SEC1717
Upstream-Description:
zkey: Preparations for introducing a new key type
Introduce helper functions and definitions to allow key type
independent code in the keystore implementation
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/cca.c | 4 -
zkey/keystore.c | 91 +++++++++++++++----------------------------
zkey/pkey.c | 103 ++++++++++++++++++++++++++++++++++++-------------
zkey/pkey.h | 17 +++++---
zkey/zkey-cryptsetup.c | 27 +++++++-----
zkey/zkey.c | 4 -
6 files changed, 139 insertions(+), 107 deletions(-)
--- a/zkey/cca.c
+++ b/zkey/cca.c
@@ -215,11 +215,11 @@ int key_token_change(struct cca_lib *cca
return -EIO;
}
- if (secure_key_size == 2 * SECURE_KEY_SIZE) {
+ if (secure_key_size == 2 * AESDATA_KEY_SIZE) {
cca->dll_CSNBKTC(&return_code, &reason_code,
&exit_data_len, exit_data,
&rule_array_count, rule_array,
- secure_key + SECURE_KEY_SIZE);
+ secure_key + AESDATA_KEY_SIZE);
pr_verbose(verbose, "CSNBKTC (Key Token Change) with '%s' "
"returned: return_code: %ld, reason_code: %ld",
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -70,8 +70,6 @@ struct key_filenames {
#define DEFAULT_VOLUME_TYPE VOLUME_TYPE_PLAIN
#endif
-#define IS_XTS(secure_key_size) (secure_key_size > SECURE_KEY_SIZE ? 1 : 0)
-
#define REC_KEY "Key"
#define REC_DESCRIPTION "Description"
#define REC_SEC_KEY_SIZE "Secure key size"
@@ -1440,7 +1438,7 @@ static int _keystore_generate_verificati
if (key == NULL)
return -EIO;
- rc = generate_key_verification_pattern((const char *)key, key_size,
+ rc = generate_key_verification_pattern(key, key_size,
vp, vp_len, keystore->verbose);
free(key);
@@ -1854,6 +1852,7 @@ int keystore_import_key(struct keystore
struct key_filenames file_names = { NULL, NULL, NULL };
struct properties *key_props = NULL;
size_t secure_key_size;
+ const char *key_type;
u8 *secure_key;
u64 mkvp;
int rc;
@@ -1877,6 +1876,14 @@ int keystore_import_key(struct keystore
goto out_free_key_filenames;
}
+ key_type = get_key_type(secure_key, secure_key_size);
+ if (key_type == NULL) {
+ warnx("Key '%s' is not a valid secure key", name);
+ free(secure_key);
+ rc = -EINVAL;
+ goto out_free_key_filenames;
+ }
+
rc = get_master_key_verification_pattern(secure_key, secure_key_size,
&mkvp, keystore->verbose);
if (rc != 0) {
@@ -1907,7 +1914,7 @@ int keystore_import_key(struct keystore
rc = _keystore_create_info_file(keystore, name, &file_names,
description, volumes, apqns,
noapqncheck, sector_size, volume_type,
- KEY_TYPE_CCA_AESDATA);
+ key_type);
if (rc != 0)
goto out_free_props;
@@ -2252,7 +2259,7 @@ static void _keystore_print_record(struc
const char *name,
struct properties *properties,
bool validation, const char *skey_filename,
- size_t secure_key_size,
+ size_t secure_key_size, bool is_xts,
size_t clear_key_bitsize, bool valid,
bool is_old_mk, bool reenc_pending, u64 mkvp)
{
@@ -2308,13 +2315,12 @@ static void _keystore_print_record(struc
util_rec_set(rec, REC_DESCRIPTION,
description != NULL ? description : "");
util_rec_set(rec, REC_SEC_KEY_SIZE, "%lu bytes", secure_key_size);
- if (!validation || valid)
+ if ((!validation || valid) && clear_key_bitsize != 0)
util_rec_set(rec, REC_CLR_KEY_SIZE, "%lu bits",
clear_key_bitsize);
else
util_rec_set(rec, REC_CLR_KEY_SIZE, "(unknown)");
- util_rec_set(rec, REC_XTS,
- IS_XTS(secure_key_size) ? "Yes" : "No");
+ util_rec_set(rec, REC_XTS, is_xts ? "Yes" : "No");
util_rec_set(rec, REC_KEY_TYPE, key_type);
if (validation) {
if (valid)
@@ -2525,6 +2531,7 @@ static int _keystore_process_validate(st
_keystore_print_record(info->rec, name, properties, 1,
file_names->skey_filename, secure_key_size,
+ is_xts_key(secure_key, secure_key_size),
clear_key_bitsize, valid, is_old_mk,
_keystore_reencipher_key_exists(file_names),
mkvp);
@@ -3297,29 +3304,29 @@ static int _keystore_display_key(struct
void *private)
{
struct util_rec *rec = (struct util_rec *)private;
- struct secaeskeytoken *secure_key;
- size_t secure_key_size;
+ u8 *secure_key;
+ size_t secure_key_size, clear_key_bitsize = 0;
int rc = 0;
- secure_key = (struct secaeskeytoken *)
- read_secure_key(file_names->skey_filename,
+ secure_key = read_secure_key(file_names->skey_filename,
&secure_key_size, keystore->verbose);
if (secure_key == NULL)
return -EIO;
- if (secure_key_size < SECURE_KEY_SIZE) {
+ if (secure_key_size < MIN_SECURE_KEY_SIZE) {
pr_verbose(keystore,
"Size of secure key is too small: %lu expected %lu",
- secure_key_size, SECURE_KEY_SIZE);
+ secure_key_size, MIN_SECURE_KEY_SIZE);
rc = -EIO;
goto out;
}
+ get_key_bit_size(secure_key, secure_key_size, &clear_key_bitsize);
+
_keystore_print_record(rec, name, properties, 0,
file_names->skey_filename, secure_key_size,
- IS_XTS(secure_key_size) ? secure_key->bitsize * 2
- : secure_key->bitsize,
- 0, 0,
+ is_xts_key(secure_key, secure_key_size),
+ clear_key_bitsize, 0, 0,
_keystore_reencipher_key_exists(file_names), 0);
out:
@@ -3682,37 +3689,6 @@ out:
}
/**
- * Returns the size of the secure key file
- *
- * @param[in] keystore the keystore
- * @param[in] skey_filename the file name of the secure key
- *
- * @returns the size of the secure key, or -1 in case of an error
- */
-static size_t _keystore_get_key_file_size(struct keystore *keystore,
- const char *skey_filename)
-{
- size_t secure_key_size;
- struct stat sb;
-
- if (stat(skey_filename, &sb)) {
- pr_verbose(keystore, "Key file '%s': %s",
- skey_filename, strerror(errno));
- return -1;
- }
-
- secure_key_size = sb.st_size;
- if (secure_key_size < SECURE_KEY_SIZE) {
- pr_verbose(keystore,
- "Size of secure key is too small: %lu expected %lu",
- secure_key_size, SECURE_KEY_SIZE);
- return -1;
- }
-
- return secure_key_size;
-}
-
-/**
* Processing function for the cryptsetup and crypttab functions.
* Extracts the required information and calls the secondary processing function
* contained in struct crypt_info.
@@ -3738,6 +3714,7 @@ static int _keystore_process_crypt(struc
size_t secure_key_size;
size_t sector_size = 0;
char *volumes = NULL;
+ u8 *secure_key = NULL;
char *dmname;
char *temp;
int rc = 0;
@@ -3745,18 +3722,14 @@ static int _keystore_process_crypt(struc
char *ch;
int i;
- secure_key_size = _keystore_get_key_file_size(keystore,
- file_names->skey_filename);
- if (secure_key_size < SECURE_KEY_SIZE) {
- pr_verbose(keystore,
- "Size of secure key is too small: %lu expected %lu",
- secure_key_size, SECURE_KEY_SIZE);
- rc = -EIO;
- goto out;
- }
+ secure_key = read_secure_key(file_names->skey_filename,
+ &secure_key_size, keystore->verbose);
+ if (secure_key == NULL)
+ return -EIO;
cipher_spec = _keystore_build_cipher_spec(properties,
- IS_XTS(secure_key_size));
+ is_xts_key(secure_key,
+ secure_key_size));
if (cipher_spec == NULL) {
rc = -EINVAL;
goto out;
@@ -3808,6 +3781,8 @@ out:
free(cipher_spec);
if (volume_type != NULL)
free(volume_type);
+ if (secure_key != NULL)
+ free(secure_key);
return rc;
}
--- a/zkey/pkey.c
+++ b/zkey/pkey.c
@@ -98,10 +98,8 @@ u8 *read_secure_key(const char *keyfile,
}
size = sb.st_size;
- if (size != SECURE_KEY_SIZE && size != 2*SECURE_KEY_SIZE) {
- warnx("File '%s' has an invalid size, %lu or %lu bytes "
- "expected", keyfile, SECURE_KEY_SIZE,
- 2 * SECURE_KEY_SIZE);
+ if (size < MIN_SECURE_KEY_SIZE || size > 2 * MAX_SECURE_KEY_SIZE) {
+ warnx("File '%s' has an invalid size: %lu", keyfile, size);
return NULL;
}
@@ -306,7 +304,7 @@ int generate_secure_key_random(int pkey_
if (keybits == 0)
keybits = DEFAULT_KEYBITS;
- secure_key_size = DOUBLE_KEYSIZE_FOR_XTS(SECURE_KEY_SIZE, xts);
+ secure_key_size = DOUBLE_KEYSIZE_FOR_XTS(AESDATA_KEY_SIZE, xts);
secure_key = util_malloc(secure_key_size);
pr_verbose(verbose, "Generate key on card %02x.%04x", card, domain);
@@ -344,7 +342,7 @@ int generate_secure_key_random(int pkey_
goto out;
}
- memcpy(secure_key, &gensec.seckey, SECURE_KEY_SIZE);
+ memcpy(secure_key, &gensec.seckey, AESDATA_KEY_SIZE);
if (xts) {
rc = ioctl(pkey_fd, PKEY_GENSECK, &gensec);
@@ -357,8 +355,8 @@ int generate_secure_key_random(int pkey_
goto out;
}
- memcpy(secure_key + SECURE_KEY_SIZE, &gensec.seckey,
- SECURE_KEY_SIZE);
+ memcpy(secure_key + AESDATA_KEY_SIZE, &gensec.seckey,
+ AESDATA_KEY_SIZE);
}
pr_verbose(verbose, "Successfully generated a secure key");
@@ -412,7 +410,7 @@ int generate_secure_key_clear(int pkey_f
return -EINVAL;
}
- secure_key_size = DOUBLE_KEYSIZE_FOR_XTS(SECURE_KEY_SIZE, xts);
+ secure_key_size = DOUBLE_KEYSIZE_FOR_XTS(AESDATA_KEY_SIZE, xts);
secure_key = util_malloc(secure_key_size);
clear_key = read_clear_key(clearkeyfile, keybits, xts, &clear_key_size,
@@ -453,7 +451,7 @@ int generate_secure_key_clear(int pkey_f
goto out;
}
- memcpy(secure_key, &clr2sec.seckey, SECURE_KEY_SIZE);
+ memcpy(secure_key, &clr2sec.seckey, AESDATA_KEY_SIZE);
if (xts) {
memcpy(&clr2sec.clrkey, clear_key + clear_key_size / 2,
@@ -469,8 +467,8 @@ int generate_secure_key_clear(int pkey_f
goto out;
}
- memcpy(secure_key+SECURE_KEY_SIZE, &clr2sec.seckey,
- SECURE_KEY_SIZE);
+ memcpy(secure_key + AESDATA_KEY_SIZE, &clr2sec.seckey,
+ AESDATA_KEY_SIZE);
}
pr_verbose(verbose,
@@ -505,21 +503,21 @@ static int validate_secure_xts_key(int p
u16 part1_keysize, u32 part1_attributes,
size_t *clear_key_bitsize, bool verbose)
{
- struct secaeskeytoken *token = (struct secaeskeytoken *)secure_key;
+ struct aesdatakeytoken *token = (struct aesdatakeytoken *)secure_key;
struct pkey_verifykey verifykey;
- struct secaeskeytoken *token2;
+ struct aesdatakeytoken *token2;
int rc;
util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
/* XTS uses 2 secure key tokens concatenated to each other */
- token2 = (struct secaeskeytoken *)(secure_key + SECURE_KEY_SIZE);
+ token2 = (struct aesdatakeytoken *)(secure_key + AESDATA_KEY_SIZE);
- if (secure_key_size != 2 * SECURE_KEY_SIZE) {
+ if (secure_key_size != 2 * AESDATA_KEY_SIZE) {
pr_verbose(verbose, "Size of secure key is too small: "
"%lu expected %lu", secure_key_size,
- 2 * SECURE_KEY_SIZE);
+ 2 * AESDATA_KEY_SIZE);
return -EINVAL;
}
@@ -591,17 +589,17 @@ int validate_secure_key(int pkey_fd,
size_t *clear_key_bitsize, int *is_old_mk,
bool verbose)
{
- struct secaeskeytoken *token = (struct secaeskeytoken *)secure_key;
+ struct aesdatakeytoken *token = (struct aesdatakeytoken *)secure_key;
struct pkey_verifykey verifykey;
int rc;
util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
- if (secure_key_size < SECURE_KEY_SIZE) {
+ if (secure_key_size < AESDATA_KEY_SIZE) {
pr_verbose(verbose, "Size of secure key is too small: "
"%lu expected %lu", secure_key_size,
- SECURE_KEY_SIZE);
+ AESDATA_KEY_SIZE);
return -EINVAL;
}
@@ -624,7 +622,7 @@ int validate_secure_key(int pkey_fd,
*clear_key_bitsize = verifykey.keysize;
/* XTS uses 2 secure key tokens concatenated to each other */
- if (secure_key_size > SECURE_KEY_SIZE) {
+ if (secure_key_size > AESDATA_KEY_SIZE) {
rc = validate_secure_xts_key(pkey_fd,
secure_key, secure_key_size,
verifykey.keysize,
@@ -656,7 +654,7 @@ int validate_secure_key(int pkey_fd,
*
* @returns 0 on success, a negative errno in case of an error
*/
-int generate_key_verification_pattern(const char *key, size_t key_size,
+int generate_key_verification_pattern(const u8 *key, size_t key_size,
char *vp, size_t vp_len, bool verbose)
{
int tfmfd = -1, opfd = -1, rc = 0;
@@ -691,7 +689,7 @@ int generate_key_verification_pattern(co
}
snprintf((char *)sa.salg_name, sizeof(sa.salg_name), "%s(paes)",
- key_size > SECURE_KEY_SIZE ? "xts" : "cbc");
+ is_xts_key(key, key_size) ? "xts" : "cbc");
tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (tfmfd < 0) {
@@ -788,15 +786,15 @@ int get_master_key_verification_pattern(
size_t secure_key_size, u64 *mkvp,
bool verbose)
{
- struct secaeskeytoken *token = (struct secaeskeytoken *)secure_key;
+ struct aesdatakeytoken *token = (struct aesdatakeytoken *)secure_key;
util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
util_assert(mkvp != NULL, "Internal error: mkvp is NULL");
- if (secure_key_size < SECURE_KEY_SIZE) {
+ if (secure_key_size < AESDATA_KEY_SIZE) {
pr_verbose(verbose, "Size of secure key is too small: "
"%lu expected %lu", secure_key_size,
- SECURE_KEY_SIZE);
+ AESDATA_KEY_SIZE);
return -EINVAL;
}
@@ -817,7 +815,7 @@ bool is_cca_aes_data_key(const u8 *key,
{
struct tokenheader *hdr = (struct tokenheader *)key;
- if (key == NULL || key_size < SECURE_KEY_SIZE)
+ if (key == NULL || key_size < AESDATA_KEY_SIZE)
return false;
if (hdr->type != TOKEN_TYPE_CCA_INTERNAL)
@@ -829,6 +827,57 @@ bool is_cca_aes_data_key(const u8 *key,
}
/**
+ * Check if the specified key is an XTS type key
+ *
+ * @param[in] key the secure key token
+ * @param[in] key_size the size of the secure key
+ *
+ * @returns true if the key is an XTS key type
+ */
+bool is_xts_key(const u8 *key, size_t key_size)
+{
+ if (is_cca_aes_data_key(key, key_size)) {
+ if (key_size == 2 * AESDATA_KEY_SIZE &&
+ is_cca_aes_data_key(key + AESDATA_KEY_SIZE,
+ key_size - AESDATA_KEY_SIZE))
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Gets the size in bits of the effective key of the specified secure key
+ *
+ * @param[in] key the secure key token
+ * @param[in] key_size the size of the secure key
+ * @param[out] bitsize On return, contains the size in bits of the key.
+ * If the key size can not be determined, then 0 is
+ * passed back as bitsize.
+ *
+ * @returns 0 on success, a negative errno in case of an error
+ */
+int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize)
+{
+ struct aesdatakeytoken *datakey = (struct aesdatakeytoken *)key;
+
+ util_assert(bitsize != NULL, "Internal error: bitsize is NULL");
+
+ if (is_cca_aes_data_key(key, key_size)) {
+ *bitsize = datakey->bitsize;
+ if (key_size == 2 * AESDATA_KEY_SIZE) {
+ datakey = (struct aesdatakeytoken *)key +
+ AESDATA_KEY_SIZE;
+ *bitsize += datakey->bitsize;
+ }
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
* Returns the type of the key
*
* @param[in] key the secure key token
--- a/zkey/pkey.h
+++ b/zkey/pkey.h
@@ -30,10 +30,10 @@ struct tokenheader {
#define TOKEN_VERSION_AESDATA 0x04
-struct secaeskeytoken {
- u8 type; /* 0x01 for internal key token */
+struct aesdatakeytoken {
+ u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */
u8 res0[3];
- u8 version; /* should be 0x04 */
+ u8 version; /* should be TOKEN_VERSION_AESDATA (0x04) */
u8 res1[1];
u8 flag; /* key flags */
u8 res2[1];
@@ -45,10 +45,13 @@ struct secaeskeytoken {
u8 tvv[4]; /* token validation value */
} __packed;
-#define SECURE_KEY_SIZE sizeof(struct secaeskeytoken)
+#define AESDATA_KEY_SIZE sizeof(struct aesdatakeytoken)
+
+#define MAX_SECURE_KEY_SIZE AESDATA_KEY_SIZE
+#define MIN_SECURE_KEY_SIZE AESDATA_KEY_SIZE
struct pkey_seckey {
- u8 seckey[SECURE_KEY_SIZE]; /* the secure key blob */
+ u8 seckey[AESDATA_KEY_SIZE]; /* the secure key blob */
};
struct pkey_clrkey {
@@ -123,7 +126,7 @@ int validate_secure_key(int pkey_fd,
size_t *clear_key_bitsize, int *is_old_mk,
bool verbose);
-int generate_key_verification_pattern(const char *key, size_t key_size,
+int generate_key_verification_pattern(const u8 *key, size_t key_size,
char *vp, size_t vp_len, bool verbose);
int get_master_key_verification_pattern(const u8 *secure_key,
@@ -131,6 +134,8 @@ int get_master_key_verification_pattern(
bool verbose);
bool is_cca_aes_data_key(const u8 *key, size_t key_size);
+bool is_xts_key(const u8 *key, size_t key_size);
+int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize);
const char *get_key_type(const u8 *key, size_t key_size);
#endif
--- a/zkey/zkey-cryptsetup.c
+++ b/zkey/zkey-cryptsetup.c
@@ -1329,22 +1329,25 @@ static int activate_unbound_keyslot(int
return rc;
}
-static int check_keysize_and_cipher_mode(size_t keysize)
+static int check_keysize_and_cipher_mode(const u8 *key, size_t keysize)
{
- if (keysize == 0) {
+ if (keysize < MIN_SECURE_KEY_SIZE ||
+ keysize > 2 * MAX_SECURE_KEY_SIZE) {
warnx("Invalid volume key size");
return -EINVAL;
}
if (strncmp(crypt_get_cipher_mode(g.cd), "xts", 3) == 0) {
- if (keysize != 2 * SECURE_KEY_SIZE) {
+ if (keysize < 2 * MIN_SECURE_KEY_SIZE ||
+ (key != NULL && !is_xts_key(key, keysize))) {
warnx("The volume key size %lu is not valid for the "
"cipher mode '%s'", keysize,
crypt_get_cipher_mode(g.cd));
return -EINVAL;
}
} else {
- if (keysize != SECURE_KEY_SIZE) {
+ if (keysize > MAX_SECURE_KEY_SIZE ||
+ (key != NULL && is_xts_key(key, keysize))) {
warnx("The volume key size %lu is not valid for the "
"cipher mode '%s'", keysize,
crypt_get_cipher_mode(g.cd));
@@ -1377,7 +1380,7 @@ static int open_keyslot(int keyslot, cha
vkeysize = crypt_get_volume_key_size(g.cd);
pr_verbose("Volume key size: %lu", vkeysize);
- rc = check_keysize_and_cipher_mode(vkeysize);
+ rc = check_keysize_and_cipher_mode(NULL, vkeysize);
if (rc != 0)
return rc;
@@ -1571,7 +1574,7 @@ static int reencipher_prepare(int token)
if (rc != 0)
goto out;
- rc = generate_key_verification_pattern(key, keysize,
+ rc = generate_key_verification_pattern((u8 *)key, keysize,
reenc_tok.verification_pattern,
sizeof(reenc_tok.verification_pattern),
g.verbose);
@@ -1851,8 +1854,8 @@ static int reencipher_complete(int token
}
- rc = generate_key_verification_pattern(key, keysize, vp, sizeof(vp),
- g.verbose);
+ rc = generate_key_verification_pattern((u8 *)key, keysize, vp,
+ sizeof(vp), g.verbose);
if (rc != 0) {
warnx("Failed to generate the verification pattern: %s",
strerror(-rc));
@@ -1998,7 +2001,7 @@ static int command_validate(void)
printf(" Status: %s\n", is_valid ? "Valid" : "Invalid");
printf(" Secure key size: %lu bytes\n", keysize);
printf(" XTS type key: %s\n",
- keysize > SECURE_KEY_SIZE ? "Yes" : "No");
+ is_xts_key((u8 *)key, keysize) ? "Yes" : "No");
printf(" Key type: %s\n",
get_key_type((u8 *)key, keysize));
if (is_valid) {
@@ -2076,7 +2079,7 @@ static int command_setvp(void)
token = find_token(g.cd, PAES_VP_TOKEN_NAME);
- rc = generate_key_verification_pattern(key, keysize,
+ rc = generate_key_verification_pattern((const u8 *)key, keysize,
vp_tok.verification_pattern,
sizeof(vp_tok.verification_pattern),
g.verbose);
@@ -2131,7 +2134,7 @@ static int command_setkey(void)
if (newkey == NULL)
return EXIT_FAILURE;
- rc = check_keysize_and_cipher_mode(newkey_size);
+ rc = check_keysize_and_cipher_mode(newkey, newkey_size);
if (rc != 0)
goto out;
@@ -2180,7 +2183,7 @@ static int command_setkey(void)
goto out;
}
- rc = generate_key_verification_pattern((char *)newkey, newkey_size, vp,
+ rc = generate_key_verification_pattern(newkey, newkey_size, vp,
sizeof(vp), g.verbose);
if (rc != 0) {
warnx("Failed to generate the verification pattern: %s",
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -1413,7 +1413,7 @@ static int command_validate_file(void)
goto out;
}
- rc = generate_key_verification_pattern((char *)secure_key,
+ rc = generate_key_verification_pattern(secure_key,
secure_key_size, vp, sizeof(vp),
g.verbose);
if (rc != 0) {
@@ -1441,7 +1441,7 @@ static int command_validate_file(void)
get_key_type(secure_key, secure_key_size));
printf(" Clear key size: %lu bits\n", clear_key_size);
printf(" XTS type key: %s\n",
- secure_key_size > SECURE_KEY_SIZE ? "Yes" : "No");
+ is_xts_key(secure_key, secure_key_size) ? "Yes" : "No");
printf(" Enciphered with: %s CCA master key (MKVP: %016llx)\n",
is_old_mk ? "OLD" : "CURRENT", mkvp);
printf(" Verification pattern: %.*s\n", VERIFICATION_PATTERN_LEN / 2,

View File

@ -1,148 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: move SIGP related functions and definitions into separate header
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 675c854fa3239882c59a9419c776eb13bc70cf76
Problem-ID: VS1804
Upstream-Description:
zipl: move SIGP related functions and definitions into separate header
Move SIGP related functions and definitions to
`include/boot/sigp.h`. This allows the reuse of the definitions in
assembler files.
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Acked-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
include/boot/sigp.h | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++
zipl/boot/s390.h | 38 -----------------------------------
2 files changed, 56 insertions(+), 37 deletions(-)
--- /dev/null
+++ b/include/boot/sigp.h
@@ -0,0 +1,55 @@
+/*
+ * SIGP related definitions and functions.
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef S390_SIGP_H
+#define S390_SIGP_H
+
+/* Signal Processor Order Codes */
+#define SIGP_STOP_AND_STORE_STATUS 9
+#define SIGP_SET_MULTI_THREADING 22
+#define SIGP_STORE_ASTATUS_AT_ADDRESS 23
+
+/* Signal Processor Condition Codes */
+#define SIGP_CC_ORDER_CODE_ACCEPTED 0
+#define SIGP_CC_BUSY 2
+
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+static inline int sigp(uint16_t addr, uint8_t order, uint32_t parm,
+ uint32_t *status)
+{
+ register unsigned int reg1 asm ("1") = parm;
+ int cc;
+
+ asm volatile(
+ " sigp %1,%2,0(%3)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ : "=d" (cc), "+d" (reg1) : "d" (addr), "a" (order) : "cc");
+ if (status && cc == 1)
+ *status = reg1;
+ return cc;
+}
+
+static inline int sigp_busy(uint16_t addr, uint8_t order, uint32_t parm,
+ uint32_t *status)
+{
+ int cc;
+
+ do {
+ cc = sigp(addr, order, parm, status);
+ } while (cc == SIGP_CC_BUSY);
+ return cc;
+}
+
+#endif /* __ASSEMBLER__ */
+#endif /* S390_SIGP_H */
--- a/zipl/boot/s390.h
+++ b/zipl/boot/s390.h
@@ -13,6 +13,7 @@
#include "lib/zt_common.h"
#include "libc.h"
+#include "boot/sigp.h"
#define __pa32(x) ((uint32_t)(unsigned long)(x))
#define __pa(x) ((unsigned long)(x))
@@ -295,43 +296,6 @@ static inline int diag308(unsigned long
}
/*
- * Signal Processor
- */
-#define SIGP_STOP_AND_STORE_STATUS 9
-#define SIGP_SET_MULTI_THREADING 22
-#define SIGP_STORE_ASTATUS_AT_ADDRESS 23
-
-#define SIGP_CC_ORDER_CODE_ACCEPTED 0
-#define SIGP_CC_BUSY 2
-
-static inline int sigp(uint16_t addr, uint8_t order, uint32_t parm,
- uint32_t *status)
-{
- register unsigned int reg1 asm ("1") = parm;
- int cc;
-
- asm volatile(
- " sigp %1,%2,0(%3)\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (cc), "+d" (reg1) : "d" (addr), "a" (order) : "cc");
- if (status && cc == 1)
- *status = reg1;
- return cc;
-}
-
-static inline int sigp_busy(uint16_t addr, uint8_t order, uint32_t parm,
- uint32_t *status)
-{
- int cc;
-
- do {
- cc = sigp(addr, order, parm, status);
- } while (cc == SIGP_CC_BUSY);
- return cc;
-}
-
-/*
* Store CPU address
*/
static inline unsigned short stap(void)

View File

@ -1,452 +0,0 @@
Subject: zkey: Introduce the CCA-AESCIPHER key type
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: ddde3f354f3506521877a4e2a6082c4d597629cb
Problem-ID: SEC1717
Upstream-Description:
zkey: Introduce the CCA-AESCIPHER key type
Add definitions and helper functions to support the new
CCA-AESCIPHER key type. Also enhance existing helper functions
to support CCA-AESCIPHER keys.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/keystore.c | 2
zkey/pkey.c | 91 +++++++++++++++++++++++++++++----
zkey/pkey.h | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
zkey/zkey.1 | 20 ++++---
zkey/zkey.c | 4 -
5 files changed, 235 insertions(+), 32 deletions(-)
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -341,6 +341,8 @@ static int _keystore_valid_key_type(cons
{
if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) == 0)
return 1;
+ if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
+ return 1;
return 0;
}
--- a/zkey/pkey.c
+++ b/zkey/pkey.c
@@ -782,23 +782,21 @@ out:
return rc;
}
-int get_master_key_verification_pattern(const u8 *secure_key,
- size_t secure_key_size, u64 *mkvp,
- bool verbose)
+int get_master_key_verification_pattern(const u8 *key, size_t key_size,
+ u64 *mkvp, bool UNUSED(verbose))
{
- struct aesdatakeytoken *token = (struct aesdatakeytoken *)secure_key;
+ struct aesdatakeytoken *datakey = (struct aesdatakeytoken *)key;
+ struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key;
- util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
+ util_assert(key != NULL, "Internal error: secure_key is NULL");
util_assert(mkvp != NULL, "Internal error: mkvp is NULL");
- if (secure_key_size < AESDATA_KEY_SIZE) {
- pr_verbose(verbose, "Size of secure key is too small: "
- "%lu expected %lu", secure_key_size,
- AESDATA_KEY_SIZE);
+ if (is_cca_aes_data_key(key, key_size))
+ *mkvp = datakey->mkvp;
+ else if (is_cca_aes_cipher_key(key, key_size))
+ memcpy(mkvp, cipherkey->kvp, sizeof(*mkvp));
+ else
return -EINVAL;
- }
-
- *mkvp = token->mkvp;
return 0;
}
@@ -827,6 +825,56 @@ bool is_cca_aes_data_key(const u8 *key,
}
/**
+ * Check if the specified key is a CCA AESCIPHER key token.
+ *
+ * @param[in] key the secure key token
+ * @param[in] key_size the size of the secure key
+ *
+ * @returns true if the key is an CCA AESCIPHER token type
+ */
+bool is_cca_aes_cipher_key(const u8 *key, size_t key_size)
+{
+ struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key;
+
+ if (key == NULL || key_size < AESCIPHER_KEY_SIZE)
+ return false;
+
+ if (cipherkey->type != TOKEN_TYPE_CCA_INTERNAL)
+ return false;
+ if (cipherkey->version != TOKEN_VERSION_AESCIPHER)
+ return false;
+ if (cipherkey->length > key_size)
+ return false;
+
+ if (cipherkey->kms != 0x03) /* key wrapped by master key */
+ return false;
+ if (cipherkey->kwm != 0x02) /* key wrapped using AESKW */
+ return false;
+ if (cipherkey->pfv != 0x00 && cipherkey->pfv != 0x01) /* V0 or V1 */
+ return false;
+ if (cipherkey->adv != 0x01) /* Should have ass. data sect. version 1 */
+ return false;
+ if (cipherkey->at != 0x02) /* Algorithm: AES */
+ return false;
+ if (cipherkey->kt != 0x0001) /* Key type: CIPHER */
+ return false;
+ if (cipherkey->adl != 26) /* Ass. data section length should be 26 */
+ return false;
+ if (cipherkey->kll != 0) /* Should have no key label */
+ return false;
+ if (cipherkey->eadl != 0) /* Should have no ext associated data */
+ return false;
+ if (cipherkey->uadl != 0) /* Should have no user associated data */
+ return false;
+ if (cipherkey->kufc != 2) /* Should have 2 KUFs */
+ return false;
+ if (cipherkey->kmfc != 3) /* Should have 3 KMFs */
+ return false;
+
+ return true;
+}
+
+/**
* Check if the specified key is an XTS type key
*
* @param[in] key the secure key token
@@ -841,6 +889,11 @@ bool is_xts_key(const u8 *key, size_t ke
is_cca_aes_data_key(key + AESDATA_KEY_SIZE,
key_size - AESDATA_KEY_SIZE))
return true;
+ } else if (is_cca_aes_cipher_key(key, key_size)) {
+ if (key_size == 2 * AESCIPHER_KEY_SIZE &&
+ is_cca_aes_cipher_key(key + AESCIPHER_KEY_SIZE,
+ key_size - AESCIPHER_KEY_SIZE))
+ return true;
}
return false;
@@ -860,6 +913,7 @@ bool is_xts_key(const u8 *key, size_t ke
int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize)
{
struct aesdatakeytoken *datakey = (struct aesdatakeytoken *)key;
+ struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key;
util_assert(bitsize != NULL, "Internal error: bitsize is NULL");
@@ -870,6 +924,17 @@ int get_key_bit_size(const u8 *key, size
AESDATA_KEY_SIZE;
*bitsize += datakey->bitsize;
}
+ } else if (is_cca_aes_cipher_key(key, key_size)) {
+ if (cipherkey->pfv == 0x00) /* V0 payload */
+ *bitsize = cipherkey->pl - 384;
+ else
+ *bitsize = 0; /* Unknown */
+ if (key_size > cipherkey->length) {
+ cipherkey = (struct aescipherkeytoken *)key +
+ cipherkey->length;
+ if (cipherkey->pfv == 0x00) /* V0 payload */
+ *bitsize += cipherkey->pl - 384;
+ }
} else {
return -EINVAL;
}
@@ -889,6 +954,8 @@ const char *get_key_type(const u8 *key,
{
if (is_cca_aes_data_key(key, key_size))
return KEY_TYPE_CCA_AESDATA;
+ if (is_cca_aes_cipher_key(key, key_size))
+ return KEY_TYPE_CCA_AESCIPHER;
return NULL;
}
--- a/zkey/pkey.h
+++ b/zkey/pkey.h
@@ -29,6 +29,7 @@ struct tokenheader {
#define TOKEN_TYPE_CCA_INTERNAL 0x01
#define TOKEN_VERSION_AESDATA 0x04
+#define TOKEN_VERSION_AESCIPHER 0x05
struct aesdatakeytoken {
u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */
@@ -45,10 +46,45 @@ struct aesdatakeytoken {
u8 tvv[4]; /* token validation value */
} __packed;
+struct aescipherkeytoken {
+ u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */
+ u8 res0;
+ u16 length; /* length of token */
+ u8 version; /* should be TOKEN_VERSION_CIPHER (0x05) */
+ u8 res1[3];
+ u8 kms; /* key material state, should be 0x03 */
+ u8 kvptype; /* key verification pattern type */
+ u8 kvp[16]; /* key verification pattern */
+ u8 kwm; /* key wrapping method, should be 0x02 */
+ u8 kwh; /* key wrapping hash algorithm */
+ u8 pfv; /* payload format version, should be 0x00*/
+ u8 res2;
+ u8 adv; /* associated data section version */
+ u8 res3;
+ u16 adl; /* associated data length */
+ u8 kll; /* length of optional key label */
+ u8 eadl; /* extended associated data length */
+ u8 uadl; /* user associated data length */
+ u8 res4;
+ u16 pl; /* payload bit length */
+ u8 res5;
+ u8 at; /* algorithm type, should be 0x02 (AES) */
+ u16 kt; /* key type, should be 0x001 (CIPHER) */
+ u8 kufc; /* key usage field count */
+ u16 kuf1; /* key usage field 1 */
+ u16 kuf2; /* key usage field 2 */
+ u8 kmfc; /* key management field count */
+ u16 kmf1; /* key management field 1 */
+ u16 kmf2; /* key management field 2 */
+ u16 kmf3; /* key management field 3 */
+ u8 varpart[80]; /* variable part */
+} __packed;
+
#define AESDATA_KEY_SIZE sizeof(struct aesdatakeytoken)
+#define AESCIPHER_KEY_SIZE sizeof(struct aescipherkeytoken)
-#define MAX_SECURE_KEY_SIZE AESDATA_KEY_SIZE
-#define MIN_SECURE_KEY_SIZE AESDATA_KEY_SIZE
+#define MAX_SECURE_KEY_SIZE MAX(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE)
+#define MIN_SECURE_KEY_SIZE MIN(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE)
struct pkey_seckey {
u8 seckey[AESDATA_KEY_SIZE]; /* the secure key blob */
@@ -58,12 +94,12 @@ struct pkey_clrkey {
u8 clrkey[32]; /* 16, 24, or 32 byte clear key value */
};
-#define PKEY_IOCTL_MAGIC 'p'
-#define AUTOSELECT 0xFFFF
-#define PKEYDEVICE "/dev/pkey"
-#define PKEY_KEYTYPE_AES_128 1
-#define PKEY_KEYTYPE_AES_192 2
-#define PKEY_KEYTYPE_AES_256 3
+#define PKEY_IOCTL_MAGIC 'p'
+#define AUTOSELECT 0xFFFF
+#define PKEYDEVICE "/dev/pkey"
+#define PKEY_KEYTYPE_AES_128 1
+#define PKEY_KEYTYPE_AES_192 2
+#define PKEY_KEYTYPE_AES_256 3
struct pkey_genseck {
u16 cardnr; /* in: card to use or FFFF for any */
@@ -97,7 +133,99 @@ struct pkey_verifykey {
#define PKEY_VERIFYKEY _IOWR(PKEY_IOCTL_MAGIC, 0x07, struct pkey_verifykey)
+enum pkey_key_type {
+ PKEY_TYPE_CCA_DATA = (u32) 1,
+ PKEY_TYPE_CCA_CIPHER = (u32) 2,
+};
+
+enum pkey_key_size {
+ PKEY_SIZE_AES_128 = (u32) 128,
+ PKEY_SIZE_AES_192 = (u32) 192,
+ PKEY_SIZE_AES_256 = (u32) 256,
+ PKEY_SIZE_UNKNOWN = (u32) 0xFFFFFFFF,
+};
+
+#define PKEY_FLAGS_MATCH_CUR_MKVP 0x00000002
+#define PKEY_FLAGS_MATCH_ALT_MKVP 0x00000004
+
+#define PKEY_KEYGEN_XPRT_SYM 0x00008000
+#define PKEY_KEYGEN_XPRT_UASY 0x00004000
+#define PKEY_KEYGEN_XPRT_AASY 0x00002000
+#define PKEY_KEYGEN_XPRT_RAW 0x00001000
+#define PKEY_KEYGEN_XPRT_CPAC 0x00000800
+#define PKEY_KEYGEN_XPRT_DES 0x00000080
+#define PKEY_KEYGEN_XPRT_AES 0x00000040
+#define PKEY_KEYGEN_XPRT_RSA 0x00000008
+
+struct pkey_apqn {
+ u16 card;
+ u16 domain;
+};
+
+struct pkey_genseck2 {
+ struct pkey_apqn *apqns; /* in: ptr to list of apqn targets */
+ u32 apqn_entries; /* in: # of apqn target list entries */
+ enum pkey_key_type type; /* in: key type to generate */
+ enum pkey_key_size size; /* in: key size to generate */
+ u32 keygenflags; /* in: key generation flags */
+ u8 *key; /* in: pointer to key blob buffer */
+ u32 keylen; /* in: available key blob buffer size */
+ /* out: actual key blob size */
+};
+
+#define PKEY_GENSECK2 _IOWR(PKEY_IOCTL_MAGIC, 0x11, struct pkey_genseck2)
+
+struct pkey_clr2seck2 {
+ struct pkey_apqn *apqns; /* in: ptr to list of apqn targets */
+ u32 apqn_entries; /* in: # of apqn target list entries */
+ enum pkey_key_type type; /* in: key type to generate */
+ enum pkey_key_size size; /* in: key size to generate */
+ u32 keygenflags; /* in: key generation flags */
+ struct pkey_clrkey clrkey; /* in: the clear key value */
+ u8 *key; /* in: pointer to key blob buffer */
+ u32 keylen; /* in: available key blob buffer size */
+ /* out: actual key blob size */
+};
+
+#define PKEY_CLR2SECK2 _IOWR(PKEY_IOCTL_MAGIC, 0x12, struct pkey_clr2seck2)
+
+struct pkey_verifykey2 {
+ u8 *key; /* in: pointer to key blob */
+ u32 keylen; /* in: key blob size */
+ u16 cardnr; /* in/out: card number */
+ u16 domain; /* in/out: domain number */
+ enum pkey_key_type type; /* out: the key type */
+ enum pkey_key_size size; /* out: the key size */
+ u32 flags; /* out: additional key info flags */
+};
+
+#define PKEY_VERIFYKEY2 _IOWR(PKEY_IOCTL_MAGIC, 0x17, struct pkey_verifykey2)
+
+struct pkey_apqns4key {
+ u8 *key; /* in: pointer to key blob */
+ u32 keylen; /* in: key blob size */
+ u32 flags; /* in: match controlling flags */
+ struct pkey_apqn *apqns; /* in/out: ptr to list of apqn targets*/
+ u32 apqn_entries; /* in: max # of apqn entries in list */
+ /* out: # apqns stored into the list */
+};
+
+#define PKEY_APQNS4K _IOWR(PKEY_IOCTL_MAGIC, 0x1B, struct pkey_apqns4key)
+
+struct pkey_apqns4keytype {
+ enum pkey_key_type type; /* in: key type */
+ u8 cur_mkvp[32]; /* in: current mkvp */
+ u8 alt_mkvp[32]; /* in: alternate mkvp */
+ u32 flags; /* in: match controlling flags */
+ struct pkey_apqn *apqns; /* in/out: ptr to list of apqn targets*/
+ u32 apqn_entries; /* in: max # of apqn entries in list */
+ /* out: # apqns stored into the list */
+};
+
+#define PKEY_APQNS4KT _IOWR(PKEY_IOCTL_MAGIC, 0x1C, struct pkey_apqns4keytype)
+
#define KEY_TYPE_CCA_AESDATA "CCA-AESDATA"
+#define KEY_TYPE_CCA_AESCIPHER "CCA-AESCIPHER"
#define PAES_BLOCK_SIZE 16
#define ENC_ZERO_LEN (2 * PAES_BLOCK_SIZE)
@@ -129,11 +257,11 @@ int validate_secure_key(int pkey_fd,
int generate_key_verification_pattern(const u8 *key, size_t key_size,
char *vp, size_t vp_len, bool verbose);
-int get_master_key_verification_pattern(const u8 *secure_key,
- size_t secure_key_size, u64 *mkvp,
- bool verbose);
+int get_master_key_verification_pattern(const u8 *key, size_t key_size,
+ u64 *mkvp, bool verbose);
bool is_cca_aes_data_key(const u8 *key, size_t key_size);
+bool is_cca_aes_cipher_key(const u8 *key, size_t key_size);
bool is_xts_key(const u8 *key, size_t key_size);
int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize);
const char *get_key_type(const u8 *key, size_t key_size);
--- a/zkey/zkey.1
+++ b/zkey/zkey.1
@@ -134,10 +134,14 @@ additional information can be associated
.B \-\-sector-size
options.
.PP
-You can generate different types of secure keys: \fBCCA-AESDATA\fP keys.
-Specify the type of the secure key using the
+You can generate different types of secure keys: \fBCCA-AESDATA\fP keys, and
+\fBCCA-AESCIPHER\fP keys. Specify the type of the secure key using the
.B \-\-key\-type
option. The default key type is CCA-AESDATA.
+.PP
+.B Note:
+Secure keys of type \fBCCA-AESCIPHER\fP require an IBM cryptographic
+adapter in CCA coprocessor mode of version 6 or later, e.g. a CEX6C.
.
.SS "Validating secure AES keys"
.
@@ -741,9 +745,11 @@ the default volume type is \fBplain\fP.
This option is only used for secure keys contained in the secure key repository.
.TP
.BR \-K ", " \-\-key-type\~\fItype\fP
-Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP.
-If this option is omitted, then a secure key of type
-CCA-AESDATA is generated.
+Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP
+and \fBCCA-AESCIPHER\fP. If this option is omitted, then a secure key of type
+CCA-AESDATA is generated. Secure keys of type \fBCCA-AESCIPHER\fP require an
+IBM cryptographic adapter in CCA coprocessor mode of version 6 or later, e.g.
+a CEX6C.
.
.
.
@@ -925,8 +931,8 @@ has been compiled with LUKS2 support ena
This option is only used for secure keys contained in the secure key repository.
.TP
.BR \-K ", " \-\-key-type\~\fItype\fP
-Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP.
-Only keys with the specified key type are listed.
+Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP
+and \fBCCA-AESCIPHER\fP. Only keys with the specified key type are listed.
This option is only used for secure keys contained in the secure key repository.
.
.
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -221,7 +221,7 @@ static struct util_opt opt_vec[] = {
.option = { "key-type", required_argument, NULL, 'K'},
.argument = "type",
.desc = "The type of the key. Possible values are '"
- KEY_TYPE_CCA_AESDATA"'. "
+ KEY_TYPE_CCA_AESDATA"' and '"KEY_TYPE_CCA_AESCIPHER"'. "
"When this option is omitted, the default is '"
KEY_TYPE_CCA_AESDATA"'",
.command = COMMAND_GENERATE,
@@ -446,7 +446,7 @@ static struct util_opt opt_vec[] = {
.option = { "key-type", required_argument, NULL, 'K'},
.argument = "type",
.desc = "The type of the key. Possible values are '"
- KEY_TYPE_CCA_AESDATA"'. "
+ KEY_TYPE_CCA_AESDATA"' and '"KEY_TYPE_CCA_AESCIPHER"'. "
"Use this option to list all keys with the specified "
"key type.",
.command = COMMAND_LIST,

View File

@ -1,117 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: add SIGP_SET_ARCHITECTURE to sigp.h and use it
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 0e385a81caf7c266c0784613e0264c03271eb99a
Problem-ID: VS1804
Upstream-Description:
zipl: add SIGP_SET_ARCHITECTURE to sigp.h and use it
This makes the code easier to read.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
include/boot/sigp.h | 1 +
zipl/boot/head.S | 6 ++++--
zipl/boot/stage3.c | 6 ++++--
zipl/boot/tape0.S | 6 ++++--
4 files changed, 13 insertions(+), 6 deletions(-)
--- a/include/boot/sigp.h
+++ b/include/boot/sigp.h
@@ -12,6 +12,7 @@
/* Signal Processor Order Codes */
#define SIGP_STOP_AND_STORE_STATUS 9
+#define SIGP_SET_ARCHITECTURE 18
#define SIGP_SET_MULTI_THREADING 22
#define SIGP_STORE_ASTATUS_AT_ADDRESS 23
--- a/zipl/boot/head.S
+++ b/zipl/boot/head.S
@@ -9,16 +9,18 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
+#include "boot/sigp.h"
+
.section .text.start
.globl _start
_start:
basr %r13,0
0: la %r7,2 /* First try code 2: */
la %r6,0 /* 64 bit psws are restored */
- sigp %r7,%r6,0x12 /* Switch to 64 bit */
+ sigp %r7,%r6,SIGP_SET_ARCHITECTURE /* Switch to 64 bit */
bc 8,.Lswitched_64-0b(%r13) /* Accepted ? */
la %r7,1 /* Failed - try code 1 */
- sigp %r7,%r6,0x12 /* Switch to 64 bit */
+ sigp %r7,%r6,SIGP_SET_ARCHITECTURE /* Switch to 64 bit */
.Lswitched_64:
sam64 /* Switch to 64 bit addr mode */
basr %r13,0
--- a/zipl/boot/stage3.c
+++ b/zipl/boot/stage3.c
@@ -10,6 +10,7 @@
*/
#include "libc.h"
+#include "boot/sigp.h"
#include "s390.h"
#include "stage3.h"
#include "error.h"
@@ -194,11 +195,12 @@ static inline void __noreturn start_kern
" sam31\n"
" sr %r1,%r1\n"
" sr %r2,%r2\n"
- " sigp %r1,%r2,0x12\n"
+ " sigp %r1,%r2,%[order]\n"
" lpsw 0\n"
: [addr] "=&d" (addr),
[code] "+&d" (code)
- : [psw] "a" (psw) );
+ : [psw] "a" (psw),
+ [order] "L" (SIGP_SET_ARCHITECTURE));
while (1);
}
--- a/zipl/boot/tape0.S
+++ b/zipl/boot/tape0.S
@@ -7,6 +7,8 @@
# it under the terms of the MIT license. See LICENSE for details.
#
+#include "boot/sigp.h"
+
IPL_BS = 1024 # block size for tape access
IPL_OFF = 0x4000 # temporary kernel load addr
COMMAND_LINE_SIZE = 896 # max command line length
@@ -184,10 +186,10 @@ iplstart:
0:
la %r7,2 #/* First try code 2: */
la %r6,0 #/* 64 bit psws are restored */
- sigp %r7,%r6,0x12 #/* Switch to 64 bit */
+ sigp %r7,%r6,SIGP_SET_ARCHITECTURE #/* Switch to 64 bit */
bc 8,.Lswitched_64-0b(%r13) #/* Accepted ? */
la %r7,1 #/* Failed - try code 1 */
- sigp %r7,%r6,0x12 #/* Switch to 64 bit */
+ sigp %r7,%r6,SIGP_SET_ARCHITECTURE #/* Switch to 64 bit */
.Lswitched_64:
sam64 #/* Switch to 64 bit addr mode */
basr %r13,0

View File

@ -1,278 +0,0 @@
Subject: zkey: Add wrappers for the new IOCTLs with fallback to the old once
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: d4027e6506963fbf995992e32490d56a6f7ea587
Problem-ID: SEC1717
Upstream-Description:
zkey: Add wrappers for the new IOCTLs with fallback to the old once
By default the new pkey IOCTL are used. In case the pkey device does not
support the new IOCTLs (i.e. errno ENOTTY is returned), then the wrapper
falls back to the old IOCTLs. The old IOCTLs only support secure keys of
type CCA-AESDATA.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/pkey.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 228 insertions(+)
--- a/zkey/pkey.c
+++ b/zkey/pkey.c
@@ -270,6 +270,234 @@ out:
}
/**
+ * Returns the PKEY_KEYTYPE_xxx value for the specified key size.
+ *
+ * @param[in] keysize the key size in bits
+ *
+ * @returns the PKEY_KEYTYPE_xxx value or 0 for an unknown key size
+ */
+static u32 keysize_to_keytype(enum pkey_key_size keysize)
+{
+ switch (keysize) {
+ case PKEY_SIZE_AES_128:
+ return PKEY_KEYTYPE_AES_128;
+ case PKEY_SIZE_AES_192:
+ return PKEY_KEYTYPE_AES_192;
+ case PKEY_SIZE_AES_256:
+ return PKEY_KEYTYPE_AES_256;
+ default:
+ return 0;
+ }
+}
+
+/**
+ * Returns the PKEY_SIZE_xxx value for the specified keybits.
+ *
+ * @param[in] keybits the key size in bits
+ *
+ * @returns thePKEY_SIZE_xxx value or 0 for an unknown key size
+ */
+static enum pkey_key_size keybits_to_keysize(u32 keybits)
+{
+ switch (keybits) {
+ case 128:
+ return PKEY_SIZE_AES_128;
+ case 192:
+ return PKEY_SIZE_AES_192;
+ case 256:
+ return PKEY_SIZE_AES_256;
+ default:
+ return PKEY_SIZE_UNKNOWN;
+ }
+}
+
+/*
+ * Wrapper for the PKEY_GENSECK/PKEY_GENSECK2 IOCTL to generate a secure
+ * key of any type by random. If the newer PKEY_GENSECK2 IOCTL is not supported
+ * by the pkey device, then it falls back to the older PKEY_GENSECK IOCTL
+ *
+ * @param[in] pkey_fd the pkey file descriptor
+ * @param[in/out] genseck info about key to generate
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error
+ */
+static int pkey_genseck2(int pkey_fd, struct pkey_genseck2 *genseck2,
+ bool verbose)
+{
+ struct pkey_genseck genseck;
+ int rc;
+ u32 i;
+
+ util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
+ util_assert(genseck2 != NULL, "Internal error: genseck2 is NULL");
+
+ rc = ioctl(pkey_fd, PKEY_GENSECK2, genseck2);
+ if (rc != 0 && errno != ENOTTY)
+ return -errno;
+ if (rc == 0)
+ return 0;
+
+ /* New IOCTL is not available, fall back to old one */
+ pr_verbose(verbose, "ioctl PKEY_GENSECK2 not supported, fall back to "
+ "PKEY_GENSECK");
+
+ if (genseck2->type != PKEY_TYPE_CCA_DATA) {
+ warnx("Key-type is not supported");
+ return -ENOTSUP;
+ }
+
+ if (genseck2->keylen < AESDATA_KEY_SIZE)
+ return -EINVAL;
+
+ memset(&genseck, 0, sizeof(genseck));
+
+ genseck.keytype = keysize_to_keytype(genseck2->size);
+ if (genseck.keytype == 0)
+ return -EINVAL;
+
+ for (i = 0; i < genseck2->apqn_entries; i++) {
+ genseck.cardnr = genseck2->apqns[i].card;
+ genseck.domain = genseck2->apqns[i].domain;
+
+ rc = ioctl(pkey_fd, PKEY_GENSECK, &genseck);
+ if (rc != 0)
+ continue;
+
+ memcpy(genseck2->key, &genseck.seckey.seckey, AESDATA_KEY_SIZE);
+ genseck2->keylen = AESDATA_KEY_SIZE;
+ return 0;
+ }
+
+ return -errno;
+}
+
+/*
+ * Wrapper for the PKEY_CLR2SECK/PKEY_CLR2SECK2 IOCTL to generate a secure
+ * key of any type from a clear key. If the newer PKEY_CLR2SECK2 IOCTL is not
+ * supported by the pkey device, then it falls back to the older PKEY_CLR2SECK
+ * IOCTL
+ *
+ * @param[in] pkey_fd the pkey file descriptor
+ * @param[in/out] clr2seck2 info about key to generate
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error
+ */
+static int pkey_clr2seck2(int pkey_fd, struct pkey_clr2seck2 *clr2seck2,
+ bool verbose)
+{
+ struct pkey_clr2seck clr2seck;
+ int rc;
+ u32 i;
+
+ util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
+ util_assert(clr2seck2 != NULL, "Internal error: clr2seck2 is NULL");
+
+ rc = ioctl(pkey_fd, PKEY_CLR2SECK2, clr2seck2);
+ if (rc != 0 && errno != ENOTTY)
+ return -errno;
+ if (rc == 0)
+ return 0;
+
+ /* New IOCTL is not available, fall back to old one */
+ pr_verbose(verbose, "ioctl PKEY_CLR2SECK2 not supported, fall back to "
+ "PKEY_CLR2SECK");
+
+ if (clr2seck2->type != PKEY_TYPE_CCA_DATA) {
+ warnx("Key-type is not supported");
+ return -ENOTSUP;
+ }
+
+ if (clr2seck2->keylen < AESDATA_KEY_SIZE)
+ return -EINVAL;
+
+ memset(&clr2seck, 0, sizeof(clr2seck));
+ clr2seck.clrkey = clr2seck2->clrkey;
+
+ clr2seck.keytype = keysize_to_keytype(clr2seck2->size);
+ if (clr2seck.keytype == 0)
+ return -EINVAL;
+
+ for (i = 0; i < clr2seck2->apqn_entries; i++) {
+ clr2seck.cardnr = clr2seck2->apqns[i].card;
+ clr2seck.domain = clr2seck2->apqns[i].domain;
+
+ rc = ioctl(pkey_fd, PKEY_CLR2SECK, &clr2seck);
+ if (rc != 0)
+ continue;
+
+ memcpy(clr2seck2->key, &clr2seck.seckey.seckey,
+ AESDATA_KEY_SIZE);
+ clr2seck2->keylen = AESDATA_KEY_SIZE;
+ return 0;
+ }
+
+ return -errno;
+}
+
+/*
+ * Wrapper for the PKEY_VERIFYKEY/PKEY_VERIFYKEY2 IOCTL to verify a secure
+ * key of any type. If the newer PKEY_VERIFYKEY2 IOCTL is not supported
+ * by the pkey device, then it falls back to the older PKEY_VERIFYKEY IOCTL
+ *
+ * @param[in] pkey_fd the pkey file descriptor
+ * @param[in/out] verifykey2 info about key to verify
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error
+ */
+static int pkey_verifyseck2(int pkey_fd, struct pkey_verifykey2 *verifykey2,
+ bool verbose)
+{
+ struct pkey_verifykey verifykey;
+ int rc;
+
+ util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
+ util_assert(verifykey2 != NULL, "Internal error: verifyseck2 is NULL");
+
+ rc = ioctl(pkey_fd, PKEY_VERIFYKEY2, verifykey2);
+ if (rc != 0 && errno != ENOTTY)
+ return -errno;
+ if (rc == 0)
+ return 0;
+
+ /* New IOCTL is not available, fall back to old one */
+ pr_verbose(verbose, "ioctl PKEY_VERIFYKEY2 not supported, fall back to "
+ "PKEY_VERIFYKEY");
+
+ if (!is_cca_aes_data_key(verifykey2->key, verifykey2->keylen))
+ return -ENODEV;
+
+ memset(&verifykey, 0, sizeof(verifykey));
+ memcpy(&verifykey.seckey, verifykey2->key, sizeof(verifykey.seckey));
+
+ /*
+ * Note: the old IOCTL does not support to check a specific card and
+ * domain. If falling back to the old IOCTL, this input is silently
+ * ignored, and all APQNs currently available in the system are used.
+ */
+ rc = ioctl(pkey_fd, PKEY_VERIFYKEY, &verifykey);
+ if (rc != 0)
+ return -errno;
+
+ if ((verifykey.attributes & PKEY_VERIFY_ATTR_AES) == 0)
+ return -ENODEV;
+
+ verifykey2->type = PKEY_TYPE_CCA_DATA;
+ verifykey2->cardnr = verifykey.cardnr;
+ verifykey2->domain = verifykey.domain;
+ verifykey2->size = keybits_to_keysize(verifykey.keysize);
+
+ if (verifykey.attributes & PKEY_VERIFY_ATTR_OLD_MKVP)
+ verifykey2->flags = PKEY_FLAGS_MATCH_ALT_MKVP;
+ else
+ verifykey2->flags = PKEY_FLAGS_MATCH_CUR_MKVP;
+
+ return 0;
+}
+
+/**
* Generate a secure key by random
*
* @param[in] pkey_fd the pkey file descriptor

View File

@ -1,56 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl/stage3: make IPL_DEVICE definition consistent with tape0.S
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: d884fb8db4c4f383780d6fc8087abd8f80e1c8b8
Problem-ID: VS1804
Upstream-Description:
zipl/stage3: make IPL_DEVICE definition consistent with tape0.S
Make `IPL_DEVICE` definition consistent with the kernel definition and
the definition in tape0.S. This allows us to refactor the code later.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/stage3.c | 2 +-
zipl/boot/stage3.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
--- a/zipl/boot/stage3.c
+++ b/zipl/boot/stage3.c
@@ -292,7 +292,7 @@ void start(void)
/* store subchannel ID into low core and into new kernel space */
subchannel_id = S390_lowcore.subchannel_id;
*(unsigned int *)__LC_IPLDEV = subchannel_id;
- *(unsigned int *)IPL_DEVICE = subchannel_id;
+ *(unsigned long long *)IPL_DEVICE = subchannel_id;
/* if valid command line is given, copy it into new kernel space */
if (_parm_addr != UNSPECIFIED_ADDRESS) {
--- a/zipl/boot/stage3.h
+++ b/zipl/boot/stage3.h
@@ -17,7 +17,7 @@
#include "boot/ipl.h"
-#define IPL_DEVICE 0x10404UL
+#define IPL_DEVICE 0x10400UL
#define INITRD_START 0x10408UL
#define INITRD_SIZE 0x10410UL
#define OLDMEM_BASE 0x10418UL

View File

@ -1,439 +0,0 @@
Subject: zkey: Add helper functions to build lists of APQNs
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: 663d362ff3b1036476bfce9e2563272bab087013
Problem-ID: SEC1717
Upstream-Description:
zkey: Add helper functions to build lists of APQNs
The new IOCTLs are based on list of APQNs that they try to send
the request to. Add some helper functions to build such lists
of APQNs based on the key type, and optionally a given mkvp.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/pkey.c | 383 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 383 insertions(+)
--- a/zkey/pkey.c
+++ b/zkey/pkey.c
@@ -46,6 +46,8 @@
#define DEFAULT_KEYBITS 256
+#define INITIAL_APQN_ENTRIES 16
+
/**
* Opens the pkey device and returns its file descriptor.
*
@@ -498,6 +500,387 @@ static int pkey_verifyseck2(int pkey_fd,
}
/**
+ * Print a list of APQNs if verbose is set
+ */
+static void pr_verbose_apqn_list(bool verbose, struct pkey_apqn *list, u32 num)
+{
+ u32 i;
+
+ if (!verbose)
+ return;
+
+ for (i = 0; i < num ; i++)
+ warnx(" APQN: %02x.%04x", list[i].card, list[i].domain);
+}
+
+/**
+ * Filter a n array list of APQNs (struct pkey_apqn) by a list of APQN strings.
+ *
+ * @param[in] apqn_list a zero terminated array of pointers to C-strings
+ * @param[in/out] apqns A list of APQNs as array of struct pkey_apqn to
+ * filter. The list is modified during filtering.
+ * @param[in/out] apqn_entries Number of entries in the list of APQNs. The
+ * number is modified during filtering.
+ *
+ * @returns 0 on success, a negative errno in case of an error
+ */
+static int filter_apqn_list(const char **apqn_list, struct pkey_apqn **apqns,
+ u32 *apqn_entries)
+{
+ unsigned int count, i, k, card, domain;
+ struct pkey_apqn *list = *apqns;
+ bool found;
+
+ if (apqn_list == NULL)
+ return 0;
+
+ for (count = 0; apqn_list[count] != NULL; count++)
+ ;
+ if (count == 0)
+ return 0;
+
+ for (i = 0; i < *apqn_entries; i++) {
+ found = false;
+ for (k = 0; apqn_list[k] != NULL; k++) {
+ if (sscanf(apqn_list[k], "%x.%x", &card, &domain) != 2)
+ return -EINVAL;
+
+ if (list[i].card == card && list[i].domain == domain) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ if (i < *apqn_entries - 1)
+ memmove(&list[i], &list[i+1],
+ (*apqn_entries - i - 1) *
+ sizeof(struct pkey_apqn));
+ (*apqn_entries)--;
+ i--;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Build a list of APQNs in the form accepted by the pkey IOCTLs from the
+ * List of APQNs as zero terminated array of pointers to C-strings that
+ * are usable for the CCA-AESDATA key type.
+ *
+ * @param[in] apqn_list a zero terminated array of pointers to C-strings
+ * @param[out] apqns A list of APQNs as array of struct pkey_apqn. The
+ * list must be freed by the caller using free().
+ * @param[out] apqn_entries Number of entries in the list of APQNs
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error
+ */
+static int build_apqn_list_for_aes_data(const char **apqn_list,
+ struct pkey_apqn **apqns,
+ u32 *apqn_entries, bool verbose)
+{
+ unsigned int card, domain, count = 0;
+ struct pkey_apqn *list = NULL;
+ u32 list_entries = 0;
+ int i;
+
+ pr_verbose(verbose, "Build a list of APQNs for CCA-AESDATA");
+
+ if (apqn_list != NULL)
+ for (count = 0; apqn_list[count] != NULL; count++)
+ ;
+
+ if (count > 0) {
+ list = util_malloc(count * sizeof(struct pkey_apqn));
+ list_entries = count;
+
+ for (i = 0; apqn_list[i] != NULL; i++) {
+ if (sscanf(apqn_list[i], "%x.%x", &card, &domain) != 2)
+ return -EINVAL;
+
+ list[i].card = card;
+ list[i].domain = domain;
+ }
+
+ } else {
+ /*
+ * Although the new pkey IOCTLs do not support APQN entries
+ * with ANY indication, build an ANY-list here. If we get here,
+ * then the new IOCTLs are not available, and it will fall back
+ * to the old IOCTL which do support ANY specifications.
+ */
+ list = util_malloc(sizeof(struct pkey_apqn));
+ list_entries = 1;
+
+ list[0].card = AUTOSELECT;
+ list[0].domain = AUTOSELECT;
+ }
+
+ *apqns = list;
+ *apqn_entries = list_entries;
+
+ pr_verbose(verbose, "%u APQNs found", list_entries);
+ pr_verbose_apqn_list(verbose, list, list_entries);
+ return 0;
+}
+
+/**
+ * Build a list of APQNs in the form accepted by the pkey IOCTLs from the
+ * List of APQNs as zero terminated array of pointers to C-strings that
+ * are usable for the specified key type.
+ *
+ * @param[in] pkey_fd the pkey file descriptor
+ * @param[in] type the key type
+ * @param[in] apqn_list a zero terminated array of pointers to C-strings
+ * @param[out] apqns A list of APQNs as array of struct pkey_apqn. The
+ * list must be freed by the caller using free().
+ * @param[out] apqn_entries Number of entries in the list of APQNs
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error
+ */
+static int build_apqn_list_for_key_type(int pkey_fd, enum pkey_key_type type,
+ const char **apqn_list,
+ struct pkey_apqn **apqns,
+ u32 *apqn_entries, bool verbose)
+{
+ struct pkey_apqns4keytype apqns4keytype;
+ int rc;
+
+ util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
+ util_assert(apqns != NULL, "Internal error: apqns is NULL");
+ util_assert(apqn_entries != NULL,
+ "Internal error: apqn_entries is NULL");
+
+ pr_verbose(verbose, "Build a list of APQNs for key type %d", type);
+
+ memset(&apqns4keytype, 0, sizeof(apqns4keytype));
+ apqns4keytype.type = type;
+ apqns4keytype.apqn_entries = INITIAL_APQN_ENTRIES;
+ apqns4keytype.apqns = (struct pkey_apqn *)util_malloc(
+ apqns4keytype.apqn_entries * sizeof(struct pkey_apqn));
+
+ do {
+ rc = ioctl(pkey_fd, PKEY_APQNS4KT, &apqns4keytype);
+ if (rc == 0)
+ break;
+ rc = -errno;
+ pr_verbose(verbose, "ioctl PKEY_APQNS4KT rc: %s",
+ strerror(-rc));
+
+ switch (rc) {
+ case -ENOSPC:
+ free(apqns4keytype.apqns);
+ apqns4keytype.apqns = (struct pkey_apqn *)
+ util_malloc(apqns4keytype.apqn_entries *
+ sizeof(struct pkey_apqn));
+ continue;
+ case -ENOTTY:
+ /*
+ * New IOCTL is not available: build the list
+ * manually (Key type CCA-AESDATA only)
+ */
+ free(apqns4keytype.apqns);
+
+ if (type != PKEY_TYPE_CCA_DATA)
+ return -ENOTSUP;
+
+ rc = build_apqn_list_for_aes_data(apqn_list, apqns,
+ apqn_entries,
+ verbose);
+ return rc;
+ default:
+ goto out;
+ }
+ } while (rc != 0);
+
+ if (apqns4keytype.apqn_entries == 0) {
+ pr_verbose(verbose, "No APQN available for key type %d", type);
+ rc = -ENODEV;
+ goto out;
+ }
+
+ rc = filter_apqn_list(apqn_list, &apqns4keytype.apqns,
+ &apqns4keytype.apqn_entries);
+ if (rc != 0)
+ goto out;
+
+ if (apqns4keytype.apqn_entries == 0) {
+ pr_verbose(verbose, "No APQN available for key type %d", type);
+ rc = -ENODEV;
+ goto out;
+ }
+
+ pr_verbose(verbose, "%u APQNs found", apqns4keytype.apqn_entries);
+ pr_verbose_apqn_list(verbose, apqns4keytype.apqns,
+ apqns4keytype.apqn_entries);
+
+out:
+ if (rc == 0) {
+ *apqns = apqns4keytype.apqns;
+ *apqn_entries = apqns4keytype.apqn_entries;
+ } else {
+ *apqns = NULL;
+ *apqn_entries = 0;
+ free(apqns4keytype.apqns);
+ }
+
+ return rc;
+}
+
+/**
+ * Build a list of APQNs in the form accepted by the pkey IOCTLs from the
+ * List of APQNs as zero terminated array of pointers to C-strings that are
+ * usable for the specufied key.
+ *
+ * @param[in] pkey_fd the pkey file descriptor
+ * @param[in] key the key
+ * @param[in] keylen the length of the key
+ * @param[in] flags PKEY_FLAGS_MATCH_xxx flags
+ * @param[in] apqn_list a zero terminated array of pointers to C-strings
+ * @param[out] apqns A list of APQNs as array of struct pkey_apqn. The
+ * list must be freed by the caller using free().
+ * @param[out] apqn_entries Number of entries in the list of APQNs
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error
+ */
+static int build_apqn_list_for_key(int pkey_fd, u8 *key, u32 keylen, u32 flags,
+ const char **apqn_list,
+ struct pkey_apqn **apqns,
+ u32 *apqn_entries, bool verbose)
+{
+ struct pkey_apqns4key apqns4key;
+ u64 mkvp;
+ int rc;
+
+ util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
+ util_assert(key != NULL, "Internal error: key is NULL");
+ util_assert(apqns != NULL, "Internal error: apqns is NULL");
+ util_assert(apqn_entries != NULL,
+ "Internal error: apqn_entries is NULL");
+
+ pr_verbose(verbose, "Build a list of APQNs for the key");
+
+ memset(&apqns4key, 0, sizeof(apqns4key));
+ apqns4key.key = key;
+ apqns4key.keylen = keylen;
+ apqns4key.flags = flags;
+ apqns4key.apqn_entries = INITIAL_APQN_ENTRIES;
+ apqns4key.apqns = (struct pkey_apqn *)util_malloc(
+ apqns4key.apqn_entries * sizeof(struct pkey_apqn));
+
+ do {
+ rc = ioctl(pkey_fd, PKEY_APQNS4K, &apqns4key);
+ if (rc == 0)
+ break;
+ rc = -errno;
+ pr_verbose(verbose, "ioctl PKEY_APQNS4K rc: %s", strerror(-rc));
+
+ switch (rc) {
+ case -ENOSPC:
+ free(apqns4key.apqns);
+ apqns4key.apqns = (struct pkey_apqn *)
+ util_malloc(apqns4key.apqn_entries *
+ sizeof(struct pkey_apqn));
+ continue;
+ case -ENOTTY:
+ /*
+ * New IOCTL is not available: build the list manually
+ * (Key type CCA-AESDATA only)
+ */
+ free(apqns4key.apqns);
+
+ if (!is_cca_aes_data_key(key, keylen))
+ return -ENOTSUP;
+
+ rc = get_master_key_verification_pattern(key, keylen,
+ &mkvp,
+ verbose);
+ if (rc != 0)
+ return rc;
+
+ rc = build_apqn_list_for_aes_data(apqn_list, apqns,
+ apqn_entries,
+ verbose);
+ return rc;
+ default:
+ goto out;
+ }
+ } while (rc != 0);
+
+ if (apqns4key.apqn_entries == 0) {
+ pr_verbose(verbose, "No APQN available for the key");
+ rc = -ENODEV;
+ goto out;
+ }
+
+ rc = filter_apqn_list(apqn_list, &apqns4key.apqns,
+ &apqns4key.apqn_entries);
+ if (rc != 0)
+ goto out;
+
+ if (apqns4key.apqn_entries == 0) {
+ pr_verbose(verbose, "No APQN available for the key");
+ rc = -ENODEV;
+ goto out;
+ }
+
+ pr_verbose(verbose, "%u APQNs found", apqns4key.apqn_entries);
+ pr_verbose_apqn_list(verbose, apqns4key.apqns, apqns4key.apqn_entries);
+
+out:
+ if (rc == 0) {
+ *apqns = apqns4key.apqns;
+ *apqn_entries = apqns4key.apqn_entries;
+ } else {
+ *apqns = NULL;
+ *apqn_entries = 0;
+ free(apqns4key.apqns);
+ }
+
+ return rc;
+}
+
+/**
+ * Convert the key type string into the pkey enumeration
+ *
+ * @param[in] key_type the type of the key
+ *
+ * @returns the pkey key type or 0 for an u known key type
+ */
+static enum pkey_key_type key_type_to_pkey_type(const char *key_type)
+{
+ if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) == 0)
+ return PKEY_TYPE_CCA_DATA;
+ if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
+ return PKEY_TYPE_CCA_CIPHER;
+
+ return 0;
+}
+
+/**
+ * Return the size of a key blob for a specific type
+ *
+ * @param[in] type the type of the key
+ *
+ * @returns the size of the key or 0 for an invalid key type
+ */
+static size_t key_size_for_type(enum pkey_key_type type)
+{
+ switch (type) {
+ case PKEY_TYPE_CCA_DATA:
+ return AESDATA_KEY_SIZE;
+ case PKEY_TYPE_CCA_CIPHER:
+ return AESCIPHER_KEY_SIZE;
+ default:
+ return 0;
+ }
+}
+
+/**
* Generate a secure key by random
*
* @param[in] pkey_fd the pkey file descriptor

View File

@ -1,109 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: move Linux layout definitions into separate header
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 7e37a1d4e0605ea120db18f82d039c055fd5d737
Problem-ID: VS1804
Upstream-Description:
zipl: move Linux layout definitions into separate header
Move the Linux layout values to `include/boot/linux_layout.h`. This
allows the reuse of the definitions, e.g. in assembler files, and
later for the creation of linker scripts.
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
include/boot/linux_layout.h | 33 +++++++++++++++++++++++++++++++++
zipl/boot/stage3.h | 9 ++-------
zipl/include/zipl.h | 3 +--
3 files changed, 36 insertions(+), 9 deletions(-)
--- /dev/null
+++ b/include/boot/linux_layout.h
@@ -0,0 +1,33 @@
+/*
+ * s390 Linux layout definitions
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef LINUX_LAYOUT_H
+#define LINUX_LAYOUT_H
+
+#include "lib/zt_common.h"
+
+/* Entry address offsets */
+#define IMAGE_ENTRY _AC(0x10000, UL)
+#define IMAGE_ENTRY_KDUMP _AC(0x10010, UL)
+
+/* Parameter address offsets */
+#define IPL_DEVICE _AC(0x10400, UL)
+#define INITRD_START _AC(0x10408, UL)
+#define INITRD_SIZE _AC(0x10410, UL)
+#define OLDMEM_BASE _AC(0x10418, UL)
+#define OLDMEM_SIZE _AC(0x10420, UL)
+#define COMMAND_LINE _AC(0x10480, UL)
+
+/* Parameter sizes */
+#define COMMAND_LINE_SIZE 896
+
+
+#ifndef __ASSEMBLER__
+#endif /* __ASSEMBLER__ */
+#endif /* LINUX_LAYOUT_H */
--- a/zipl/boot/stage3.h
+++ b/zipl/boot/stage3.h
@@ -16,14 +16,9 @@
#include "s390.h"
#include "boot/ipl.h"
+#include "boot/linux_layout.h"
+
-#define IPL_DEVICE 0x10400UL
-#define INITRD_START 0x10408UL
-#define INITRD_SIZE 0x10410UL
-#define OLDMEM_BASE 0x10418UL
-#define OLDMEM_SIZE 0x10420UL
-#define COMMAND_LINE 0x10480UL
-#define COMMAND_LINE_SIZE 896
#define COMMAND_LINE_EXTRA 0xE000
#define STAGE3_FLAG_SCSI 0x0001000000000000ULL
--- a/zipl/include/zipl.h
+++ b/zipl/include/zipl.h
@@ -14,14 +14,13 @@
#include <stdint.h>
#include "lib/zt_common.h"
+#include "boot/linux_layout.h"
#define ZIPL_MAGIC "zIPL"
#define ZIPL_MAGIC_SIZE 4
#define DISK_LAYOUT_ID 0x00000001
#define STAGE3_ENTRY 0xa000UL
-#define IMAGE_ENTRY 0x10000UL
-#define IMAGE_ENTRY_KDUMP 0x10010UL
#define STAGE2_LOAD_ADDRESS 0x2000UL
#define STAGE3_LOAD_ADDRESS 0xa000UL

View File

@ -1,542 +0,0 @@
Subject: zkey: Add support for generating AES CIPHER keys
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: b56c74fe7b6100b9a2ef17b8847cd850309cf487
Problem-ID: SEC1717
Upstream-Description:
zkey: Add support for generating AES CIPHER keys
Add support for generating secure keys using the new pkey
IOCTLs. This allows to generate secure keys of type CCA-AESDATA
as well as CCA-AESCIPHER, either by random inside the crypto
card, or from a given clear key.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/keystore.c | 60 +------------
zkey/pkey.c | 258 +++++++++++++++++++++++++++++++++-----------------------
zkey/pkey.h | 5 -
zkey/zkey.c | 6 -
4 files changed, 168 insertions(+), 161 deletions(-)
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -1667,52 +1667,6 @@ out:
}
/**
- * Extracts an online card/domain pair from the specified APQns. If none of the
- * specified APQNs are online, then -ENODEV is returned.
- * If no APQNs are specified at all, then it uses AUTOSELECT and returns zero.
- */
-static int _keystore_get_card_domain(const char *apqns, unsigned int *card,
- unsigned int *domain)
-{
- struct apqn_check apqn_check = { .noonlinecheck = 0, .nomsg = 1 };
- char **apqn_list;
- char *normalized = NULL;
- int rc = 0;
- int i;
-
- *card = AUTOSELECT;
- *domain = AUTOSELECT;
-
- if (apqns == NULL)
- return 0;
-
- apqn_list = str_list_split(apqns);
- if (apqn_list[0] == NULL)
- goto out;
-
- for (i = 0; apqn_list[i] != NULL; i++) {
- rc = _keystore_apqn_check(apqn_list[i], 0, 0, &normalized,
- &apqn_check);
- if (normalized != NULL)
- free(normalized);
- if (rc == -EINVAL)
- goto out;
- if (rc != 0)
- continue;
-
- if (sscanf(apqn_list[i], "%x.%x", card, domain) == 2)
- goto found;
- }
-
- warnx("None of the specified APQNs is online or of type CCA");
- rc = -ENODEV;
-found:
-out:
- str_list_free_string_array(apqn_list);
- return rc;
-}
-
-/**
* Generates a secure key by random and adds it to the key store
*
* @param[in] keystore the key store
@@ -1748,7 +1702,7 @@ int keystore_generate_key(struct keystor
{
struct key_filenames file_names = { NULL, NULL, NULL };
struct properties *key_props = NULL;
- unsigned int card, domain;
+ char **apqn_list = NULL;
int rc;
util_assert(keystore != NULL, "Internal error: keystore is NULL");
@@ -1776,21 +1730,21 @@ int keystore_generate_key(struct keystor
goto out_free_key_filenames;
}
- rc = _keystore_get_card_domain(apqns, &card, &domain);
- if (rc != 0)
- goto out_free_key_filenames;
+ if (apqns != NULL)
+ apqn_list = str_list_split(apqns);
if (clear_key_file == NULL)
rc = generate_secure_key_random(pkey_fd,
file_names.skey_filename,
keybits, xts, key_type,
- card, domain,
+ (const char **)apqn_list,
keystore->verbose);
else
rc = generate_secure_key_clear(pkey_fd,
file_names.skey_filename,
keybits, xts, clear_key_file,
- key_type, card, domain,
+ key_type,
+ (const char **)apqn_list,
keystore->verbose);
if (rc != 0)
goto out_free_props;
@@ -1812,6 +1766,8 @@ int keystore_generate_key(struct keystor
file_names.info_filename);
out_free_props:
+ if (apqn_list != NULL)
+ str_list_free_string_array(apqn_list);
if (key_props != NULL)
properties_free(key_props);
if (rc != 0)
--- a/zkey/pkey.c
+++ b/zkey/pkey.c
@@ -888,86 +888,109 @@ static size_t key_size_for_type(enum pke
* @param[in] keybits the cryptographic size of the key in bits
* @param[in] xts if true an XTS key is generated
* @param[in] key_type the type of the key
- * @param[in] card the card number to use (or AUTOSELECT)
- * @param[in] domain the domain number to use (or AUTOSELECT)
+ * @param[in] apqns a zero terminated array of pointers to APQN-strings,
+ * or NULL for AUTOSELECT
* @param[in] verbose if true, verbose messages are printed
*
* @returns 0 on success, a negative errno in case of an error
*/
int generate_secure_key_random(int pkey_fd, const char *keyfile,
size_t keybits, bool xts, const char *key_type,
- u16 card, u16 domain, bool verbose)
+ const char **apqns, bool verbose)
{
- struct pkey_genseck gensec;
- size_t secure_key_size;
- u8 *secure_key;
+ struct pkey_genseck2 genseck2;
+ size_t secure_key_size, size;
+ u8 *secure_key = NULL;
int rc;
util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
util_assert(keyfile != NULL, "Internal error: keyfile is NULL");
util_assert(key_type != NULL, "Internal error: key_type is NULL");
- if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) != 0) {
- warnx("Invalid key-type: %s", key_type);
- return -EINVAL;
- }
-
if (keybits == 0)
keybits = DEFAULT_KEYBITS;
- secure_key_size = DOUBLE_KEYSIZE_FOR_XTS(AESDATA_KEY_SIZE, xts);
- secure_key = util_malloc(secure_key_size);
+ pr_verbose(verbose, "Generate secure key by random");
- pr_verbose(verbose, "Generate key on card %02x.%04x", card, domain);
+ memset(&genseck2, 0, sizeof(genseck2));
- gensec.cardnr = card;
- gensec.domain = domain;
- switch (keybits) {
- case 128:
- gensec.keytype = PKEY_KEYTYPE_AES_128;
- break;
- case 192:
- if (xts) {
- warnx("Invalid value for '--keybits'|'-c' "
- "for XTS: '%lu'", keybits);
- rc = -EINVAL;
- goto out;
- }
- gensec.keytype = PKEY_KEYTYPE_AES_192;
- break;
- case 256:
- gensec.keytype = PKEY_KEYTYPE_AES_256;
- break;
- default:
+ genseck2.type = key_type_to_pkey_type(key_type);
+ if (genseck2.type == 0) {
+ warnx("Key-type not supported; %s", key_type);
+ return -ENOTSUP;
+ }
+
+ genseck2.size = keybits_to_keysize(keybits);
+ if (genseck2.size == 0) {
warnx("Invalid value for '--keybits'/'-c': '%lu'", keybits);
- rc = -EINVAL;
- goto out;
+ return -EINVAL;
+ }
+ if (keybits == 192 && xts) {
+ warnx("Invalid value for '--keybits'|'-c' "
+ "for XTS: '%lu'", keybits);
+ return -EINVAL;
}
- rc = ioctl(pkey_fd, PKEY_GENSECK, &gensec);
- if (rc < 0) {
- rc = -errno;
- warnx("Failed to generate a secure key: %s", strerror(errno));
- warnx("Make sure that all available CCA crypto adapters are "
- "setup with the same master key");
- goto out;
+ rc = build_apqn_list_for_key_type(pkey_fd, genseck2.type, apqns,
+ &genseck2.apqns,
+ &genseck2.apqn_entries, verbose);
+ if (rc != 0) {
+ if (rc == -ENODEV || rc == -ENOTSUP)
+ warnx("No APQN is available that can generate a secure "
+ "key of type %s", key_type);
+ else
+ warnx("Failed to build a list of APQNs that can "
+ "generate a secure key of type %s: %s", key_type,
+ strerror(-rc));
+ return rc;
}
- memcpy(secure_key, &gensec.seckey, AESDATA_KEY_SIZE);
+ size = key_size_for_type(genseck2.type);
+ secure_key_size = DOUBLE_KEYSIZE_FOR_XTS(size, xts);
+ secure_key = util_zalloc(secure_key_size);
+
+ genseck2.key = secure_key;
+ genseck2.keylen = size;
+
+ rc = pkey_genseck2(pkey_fd, &genseck2, verbose);
+ if (rc != 0) {
+ warnx("Failed to generate a secure key: %s", strerror(-rc));
+ goto out;
+ }
if (xts) {
- rc = ioctl(pkey_fd, PKEY_GENSECK, &gensec);
- if (rc < 0) {
- rc = -errno;
- warnx("Failed to generate a secure key: %s",
- strerror(errno));
- warnx("Make sure that all available CCA crypto "
- "adapters are setup with the same master key");
+ free(genseck2.apqns);
+ genseck2.apqns = NULL;
+ genseck2.apqn_entries = 0;
+
+ /*
+ * Ensure to generate 2nd key with an APQN that has the same
+ * master key that is used by the 1st key.
+ */
+ rc = build_apqn_list_for_key(pkey_fd, secure_key, size,
+ PKEY_FLAGS_MATCH_CUR_MKVP, apqns,
+ &genseck2.apqns,
+ &genseck2.apqn_entries, verbose);
+ if (rc != 0) {
+ if (rc == -ENODEV || rc == -ENOTSUP)
+ warnx("No APQN is available that can generate "
+ "a secure key of type %s", key_type);
+ else
+ warnx("Failed to build a list of APQNs that "
+ "can generate a secure key of type %s: "
+ "%s", key_type, strerror(-rc));
goto out;
}
- memcpy(secure_key + AESDATA_KEY_SIZE, &gensec.seckey,
- AESDATA_KEY_SIZE);
+ genseck2.key = secure_key + size;
+ genseck2.keylen = size;
+
+ rc = pkey_genseck2(pkey_fd, &genseck2, verbose);
+ if (rc != 0) {
+ warnx("Failed to generate a secure key: %s",
+ strerror(-rc));
+ goto out;
+ }
}
pr_verbose(verbose, "Successfully generated a secure key");
@@ -975,6 +998,7 @@ int generate_secure_key_random(int pkey_
rc = write_secure_key(keyfile, secure_key, secure_key_size, verbose);
out:
+ free(genseck2.apqns);
free(secure_key);
return rc;
}
@@ -991,8 +1015,8 @@ out:
* @param[in] xts if true an XTS key is generated
* @param[in] clearkeyfile the file name of the clear key to read
* @param[in] key_type the type of the key
- * @param[in] card the card number to use (or AUTOSELECT)
- * @param[in] domain the domain number to use (or AUTOSELECT)
+ * @param[in] apqns a zero terminated array of pointers to APQN-strings,
+ * or NULL for AUTOSELECT
* @param[in] verbose if true, verbose messages are printed
*
* @returns 0 on success, a negative errno in case of an error
@@ -1000,14 +1024,14 @@ out:
int generate_secure_key_clear(int pkey_fd, const char *keyfile,
size_t keybits, bool xts,
const char *clearkeyfile, const char *key_type,
- u16 card, u16 domain,
- bool verbose)
+ const char **apqns, bool verbose)
{
- struct pkey_clr2seck clr2sec;
+ struct pkey_clr2seck2 clr2seck2;
size_t secure_key_size;
size_t clear_key_size;
u8 *secure_key;
u8 *clear_key;
+ size_t size;
int rc;
util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
@@ -1016,70 +1040,99 @@ int generate_secure_key_clear(int pkey_f
"Internal error: clearkeyfile is NULL");
util_assert(key_type != NULL, "Internal error: key_type is NULL");
- if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) != 0) {
- warnx("Invalid key-type: %s", key_type);
- return -EINVAL;
- }
-
- secure_key_size = DOUBLE_KEYSIZE_FOR_XTS(AESDATA_KEY_SIZE, xts);
- secure_key = util_malloc(secure_key_size);
+ pr_verbose(verbose, "Generate secure key from a clear key");
clear_key = read_clear_key(clearkeyfile, keybits, xts, &clear_key_size,
verbose);
if (clear_key == NULL)
return -EINVAL;
- pr_verbose(verbose, "Generate key on card %02x.%04x", card, domain);
+ memset(&clr2seck2, 0, sizeof(clr2seck2));
+
+ memcpy(&clr2seck2.clrkey, clear_key,
+ HALF_KEYSIZE_FOR_XTS(clear_key_size, xts));
+
+ clr2seck2.type = key_type_to_pkey_type(key_type);
+ if (clr2seck2.type == 0) {
+ warnx("Key-type not supported; %s", key_type);
+ return -ENOTSUP;
+ }
- clr2sec.cardnr = card;
- clr2sec.domain = domain;
- switch (HALF_KEYSIZE_FOR_XTS(clear_key_size * 8, xts)) {
- case 128:
- clr2sec.keytype = PKEY_KEYTYPE_AES_128;
- break;
- case 192:
- clr2sec.keytype = PKEY_KEYTYPE_AES_192;
- break;
- case 256:
- clr2sec.keytype = PKEY_KEYTYPE_AES_256;
- break;
- default:
+ clr2seck2.size = keybits_to_keysize(HALF_KEYSIZE_FOR_XTS(
+ clear_key_size * 8, xts));
+ if (clr2seck2.size == 0) {
warnx("Invalid clear key size: '%lu' bytes", clear_key_size);
- rc = -EINVAL;
- goto out;
+ return -EINVAL;
+ }
+ if (keybits == 192 && xts) {
+ warnx("Invalid clear key size for XTS: '%lu' bytes",
+ clear_key_size);
+ return -EINVAL;
}
- memcpy(&clr2sec.clrkey, clear_key,
- HALF_KEYSIZE_FOR_XTS(clear_key_size, xts));
+ rc = build_apqn_list_for_key_type(pkey_fd, clr2seck2.type, apqns,
+ &clr2seck2.apqns,
+ &clr2seck2.apqn_entries, verbose);
+ if (rc != 0) {
+ if (rc == -ENODEV || rc == -ENOTSUP)
+ warnx("No APQN is available that can generate a secure "
+ "key of type %s", key_type);
+ else
+ warnx("Failed to build a list of APQNs that can "
+ "generate a secure key of type %s: %s", key_type,
+ strerror(-rc));
+ return rc;
+ }
- rc = ioctl(pkey_fd, PKEY_CLR2SECK, &clr2sec);
- if (rc < 0) {
- rc = -errno;
- warnx("Failed to generate a secure key from a "
- "clear key: %s", strerror(errno));
- warnx("Make sure that all available CCA crypto adapters are "
- "setup with the same master key");
+ size = key_size_for_type(clr2seck2.type);
+ secure_key_size = DOUBLE_KEYSIZE_FOR_XTS(size, xts);
+ secure_key = util_zalloc(secure_key_size);
+
+ clr2seck2.key = secure_key;
+ clr2seck2.keylen = size;
+
+ rc = pkey_clr2seck2(pkey_fd, &clr2seck2, verbose);
+ if (rc != 0) {
+ warnx("Failed to generate a secure key: %s", strerror(-rc));
goto out;
}
- memcpy(secure_key, &clr2sec.seckey, AESDATA_KEY_SIZE);
-
if (xts) {
- memcpy(&clr2sec.clrkey, clear_key + clear_key_size / 2,
+ free(clr2seck2.apqns);
+ clr2seck2.apqns = NULL;
+ clr2seck2.apqn_entries = 0;
+
+ memcpy(&clr2seck2.clrkey, clear_key + clear_key_size / 2,
clear_key_size / 2);
- rc = ioctl(pkey_fd, PKEY_CLR2SECK, &clr2sec);
- if (rc < 0) {
- rc = -errno;
- warnx("Failed to generate a secure key from "
- "a clear key: %s", strerror(errno));
- warnx("Make sure that all available CCA crypto "
- "adapters are setup with the same master key");
+ /*
+ * Ensure to generate 2nd key with an APQN that has the same
+ * master key that is used by the 1st key.
+ */
+ rc = build_apqn_list_for_key(pkey_fd, secure_key, size,
+ PKEY_FLAGS_MATCH_CUR_MKVP, apqns,
+ &clr2seck2.apqns,
+ &clr2seck2.apqn_entries, verbose);
+ if (rc != 0) {
+ if (rc == -ENODEV || rc == -ENOTSUP)
+ warnx("No APQN is available that can generate "
+ "a secure key of type %s", key_type);
+ else
+ warnx("Failed to build a list of APQNs that "
+ "can generate a secure key of type %s: "
+ "%s", key_type, strerror(-rc));
goto out;
}
- memcpy(secure_key + AESDATA_KEY_SIZE, &clr2sec.seckey,
- AESDATA_KEY_SIZE);
+ clr2seck2.key = secure_key + size;
+ clr2seck2.keylen = size;
+
+ rc = pkey_clr2seck2(pkey_fd, &clr2seck2, verbose);
+ if (rc != 0) {
+ warnx("Failed to generate a secure key: %s",
+ strerror(-rc));
+ goto out;
+ }
}
pr_verbose(verbose,
@@ -1088,10 +1141,11 @@ int generate_secure_key_clear(int pkey_f
rc = write_secure_key(keyfile, secure_key, secure_key_size, verbose);
out:
- memset(&clr2sec, 0, sizeof(clr2sec));
+ memset(&clr2seck2, 0, sizeof(clr2seck2));
memset(clear_key, 0, clear_key_size);
free(clear_key);
free(secure_key);
+ free(clr2seck2.apqns);
return rc;
}
--- a/zkey/pkey.h
+++ b/zkey/pkey.h
@@ -235,13 +235,12 @@ int open_pkey_device(bool verbose);
int generate_secure_key_random(int pkey_fd, const char *keyfile,
size_t keybits, bool xts, const char *key_type,
- u16 card, u16 domain, bool verbose);
+ const char **apqns, bool verbose);
int generate_secure_key_clear(int pkey_fd, const char *keyfile,
size_t keybits, bool xts,
const char *clearkeyfile, const char *key_type,
- u16 card, u16 domain,
- bool verbose);
+ const char **apqns, bool verbose);
u8 *read_secure_key(const char *keyfile, size_t *secure_key_size,
bool verbose);
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -1029,8 +1029,7 @@ static int command_generate_clear(void)
rc = generate_secure_key_clear(g.pkey_fd, g.pos_arg,
g.keybits, g.xts,
g.clearkeyfile, g.key_type,
- AUTOSELECT, AUTOSELECT,
- g.verbose);
+ NULL, g.verbose);
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
@@ -1046,8 +1045,7 @@ static int command_generate_random(void)
rc = generate_secure_key_random(g.pkey_fd, g.pos_arg,
g.keybits, g.xts, g.key_type,
- AUTOSELECT, AUTOSELECT,
- g.verbose);
+ NULL, g.verbose);
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

View File

@ -1,79 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: tape0: use constants defined in linux_layout.h
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: c871050097ecb2ec83cf3018ea36e01cd22cbe7d
Problem-ID: VS1804
Upstream-Description:
zipl: tape0: use constants defined in linux_layout.h
Use the constants defined in `linux_layout.h`. Therefore move the
`PARMAREA` address offset to `linux_layout.h` and include the header.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
include/boot/linux_layout.h | 1 +
zipl/boot/tape0.S | 14 +++-----------
2 files changed, 4 insertions(+), 11 deletions(-)
--- a/include/boot/linux_layout.h
+++ b/include/boot/linux_layout.h
@@ -17,6 +17,7 @@
#define IMAGE_ENTRY_KDUMP _AC(0x10010, UL)
/* Parameter address offsets */
+#define PARMAREA _AC(0x10400, UL)
#define IPL_DEVICE _AC(0x10400, UL)
#define INITRD_START _AC(0x10408, UL)
#define INITRD_SIZE _AC(0x10410, UL)
--- a/zipl/boot/tape0.S
+++ b/zipl/boot/tape0.S
@@ -8,29 +8,21 @@
#
#include "boot/sigp.h"
+#include "boot/linux_layout.h"
IPL_BS = 1024 # block size for tape access
IPL_OFF = 0x4000 # temporary kernel load addr
-COMMAND_LINE_SIZE = 896 # max command line length
-KERNEL_OFF = 0x10000 # kernel start code offset
+KERNEL_OFF = IMAGE_ENTRY # kernel start code offset
# relative to image start
__LC_IO_NEW_PSW = 0x1f0 # IO New PSW addr
-# Parameter address offsets
-
-PARMAREA = 0x10400 # Parameter area offset
-IPL_DEVICE = 0x10400 # IPL device offset
-INITRD_START = 0x10408 # ramdisk addr offset
-INITRD_SIZE = 0x10410 # ramdisk size offset
-COMMAND_LINE = 0x10480 # command line offset
-
# Default IPL parameter - will be overwritten by zIPL
RAMDISK_ORIGIN = 0x800000 # default ramdisk load addr
RAMDISK_SIZE = 0x800000 # default ramdisk size
PARMFILE_ADDR = 0x1000 # default parmfile load addr
-KERNEL_ADDR = 0x10000 # default kernel load addr
+KERNEL_ADDR = IMAGE_ENTRY # default kernel load addr
.org 0x0

View File

@ -1,425 +0,0 @@
Subject: zkey: Add support for validating AES CIPHER keys
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: 0fab6bdf2aa01e093f8a4f3d86c9183889a587fe
Problem-ID: SEC1717
Upstream-Description:
zkey: Add support for validating AES CIPHER keys
Add support for validating secure keys using the new pkey
IOCTLs. This allows to validate secure keys of type CCA-AESDATA
as well as CCA-AESCIPHER.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/keystore.c | 24 ++++++
zkey/pkey.c | 178 +++++++++++++++++++++++++------------------------
zkey/pkey.h | 2
zkey/zkey-cryptsetup.c | 6 -
zkey/zkey.c | 4 -
5 files changed, 120 insertions(+), 94 deletions(-)
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -2451,8 +2451,10 @@ static int _keystore_process_validate(st
void *private)
{
struct validate_info *info = (struct validate_info *)private;
+ char **apqn_list = NULL;
size_t clear_key_bitsize;
size_t secure_key_size;
+ char *apqns = NULL;
u8 *secure_key;
int is_old_mk;
int rc, valid;
@@ -2469,9 +2471,13 @@ static int _keystore_process_validate(st
goto out;
}
+ apqns = properties_get(properties, PROP_NAME_APQNS);
+ if (apqns != NULL)
+ apqn_list = str_list_split(apqns);
+
rc = validate_secure_key(info->pkey_fd, secure_key, secure_key_size,
&clear_key_bitsize, &is_old_mk,
- keystore->verbose);
+ (const char **)apqn_list, keystore->verbose);
if (rc != 0) {
valid = 0;
info->num_invalid++;
@@ -2510,6 +2516,10 @@ static int _keystore_process_validate(st
info->num_warnings++;
out:
+ if (apqns != NULL)
+ free(apqns);
+ if (apqn_list != NULL)
+ str_list_free_string_array(apqn_list);
if (rc != 0)
pr_verbose(keystore, "Failed to validate key '%s': %s",
name, strerror(-rc));
@@ -2726,7 +2736,9 @@ static int _keystore_process_reencipher(
struct reencipher_params params = info->params;
size_t clear_key_bitsize;
size_t secure_key_size;
+ char **apqn_list = NULL;
u8 *secure_key = NULL;
+ char *apqns = NULL;
char *out_file;
int is_old_mk;
char *temp;
@@ -2763,9 +2775,13 @@ static int _keystore_process_reencipher(
goto out;
}
+ apqns = properties_get(properties, PROP_NAME_APQNS);
+ if (apqns != NULL)
+ apqn_list = str_list_split(apqns);
+
rc = validate_secure_key(info->pkey_fd, secure_key, secure_key_size,
&clear_key_bitsize, &is_old_mk,
- keystore->verbose);
+ (const char **)apqn_list, keystore->verbose);
if (rc != 0) {
if (params.complete) {
warnx("Key '%s' is not valid, re-enciphering is not "
@@ -2864,6 +2880,10 @@ static int _keystore_process_reencipher(
info->num_reenciphered++;
out:
+ if (apqns != NULL)
+ free(apqns);
+ if (apqn_list != NULL)
+ str_list_free_string_array(apqn_list);
if (secure_key != NULL)
free(secure_key);
--- a/zkey/pkey.c
+++ b/zkey/pkey.c
@@ -1153,84 +1153,58 @@ out:
* Validates an XTS secure key (the second part)
*
* @param[in] pkey_fd the pkey file descriptor
+ * @param[in] apqn the APQN to verify the key with
* @param[in] secure_key a buffer containing the secure key
* @param[in] secure_key_size the secure key size
* @param[in] part1_keysize the key size of the first key part
- * @param[in] part1_attributes the attributes of the first key part
+ * @param[in] part1_flags the flags of the first key part
* @param[out] clear_key_bitsize on return , the cryptographic size of the
* clear key
* @param[in] verbose if true, verbose messages are printed
*
* @returns 0 on success, a negative errno in case of an error
*/
-static int validate_secure_xts_key(int pkey_fd,
+static int validate_secure_xts_key(int pkey_fd, struct pkey_apqn *apqn,
u8 *secure_key, size_t secure_key_size,
- u16 part1_keysize, u32 part1_attributes,
- size_t *clear_key_bitsize, bool verbose)
+ enum pkey_key_size part1_keysize,
+ u32 part1_flags, size_t *clear_key_bitsize,
+ bool verbose)
{
- struct aesdatakeytoken *token = (struct aesdatakeytoken *)secure_key;
- struct pkey_verifykey verifykey;
- struct aesdatakeytoken *token2;
+ struct pkey_verifykey2 verifykey2;
int rc;
util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
+ util_assert(apqn != NULL, "Internal error: apqn is NULL");
- /* XTS uses 2 secure key tokens concatenated to each other */
- token2 = (struct aesdatakeytoken *)(secure_key + AESDATA_KEY_SIZE);
+ memset(&verifykey2, 0, sizeof(verifykey2));
+ verifykey2.key = secure_key + (secure_key_size / 2);
+ verifykey2.keylen = secure_key_size / 2;
+ verifykey2.cardnr = apqn->card;
+ verifykey2.domain = apqn->domain;
- if (secure_key_size != 2 * AESDATA_KEY_SIZE) {
- pr_verbose(verbose, "Size of secure key is too small: "
- "%lu expected %lu", secure_key_size,
- 2 * AESDATA_KEY_SIZE);
- return -EINVAL;
- }
-
- if (token->bitsize != token2->bitsize) {
- pr_verbose(verbose, "XTS secure key contains 2 clear keys of "
- "different sizes");
- return -EINVAL;
- }
- if (token->keysize != token2->keysize) {
- pr_verbose(verbose, "XTS secure key contains 2 keys of "
- "different sizes");
- return -EINVAL;
- }
- if (memcmp(&token->mkvp, &token2->mkvp, sizeof(token->mkvp)) != 0) {
- pr_verbose(verbose, "XTS secure key contains 2 keys using "
- "different CCA master keys");
- return -EINVAL;
- }
-
- memcpy(&verifykey.seckey, token2, sizeof(verifykey.seckey));
-
- rc = ioctl(pkey_fd, PKEY_VERIFYKEY, &verifykey);
+ rc = pkey_verifyseck2(pkey_fd, &verifykey2, verbose);
if (rc < 0) {
- rc = -errno;
- pr_verbose(verbose, "Failed to validate a secure key: %s",
- strerror(-rc));
+ pr_verbose(verbose, "Failed to validate the 2nd part of the "
+ "XTS secure key on APQN %02x.%04x: %s", apqn->card,
+ apqn->domain, strerror(-rc));
return rc;
}
- if ((verifykey.attributes & PKEY_VERIFY_ATTR_AES) == 0) {
- pr_verbose(verbose, "Secure key is not an AES key");
- return -EINVAL;
- }
-
- if (verifykey.keysize != part1_keysize) {
+ if (verifykey2.size != part1_keysize) {
pr_verbose(verbose, "XTS secure key contains 2 keys using "
"different key sizes");
return -EINVAL;
}
- if (verifykey.attributes != part1_attributes) {
+ if (verifykey2.flags != part1_flags) {
pr_verbose(verbose, "XTS secure key contains 2 keys using "
- "different attributes");
+ "different master keys");
return -EINVAL;
}
- if (clear_key_bitsize)
- *clear_key_bitsize += verifykey.keysize;
+ if (clear_key_bitsize && verifykey2.size != PKEY_SIZE_UNKNOWN)
+ *clear_key_bitsize += verifykey2.size;
return 0;
}
@@ -1245,6 +1219,8 @@ static int validate_secure_xts_key(int p
* clear key
* @param[out] is_old_mk in return set to 1 to indicate if the secure key
* is currently enciphered by the OLD CCA master key
+ * @param[in] apqns a zero terminated array of pointers to APQN-strings,
+ * or NULL for AUTOSELECT
* @param[in] verbose if true, verbose messages are printed
*
* @returns 0 on success, a negative errno in case of an error
@@ -1252,59 +1228,89 @@ static int validate_secure_xts_key(int p
int validate_secure_key(int pkey_fd,
u8 *secure_key, size_t secure_key_size,
size_t *clear_key_bitsize, int *is_old_mk,
- bool verbose)
+ const char **apqns, bool verbose)
{
- struct aesdatakeytoken *token = (struct aesdatakeytoken *)secure_key;
- struct pkey_verifykey verifykey;
+ struct pkey_verifykey2 verifykey2;
+ struct pkey_apqn *list = NULL;
+ u32 i, list_entries = 0;
+ bool xts, valid;
int rc;
util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
- if (secure_key_size < AESDATA_KEY_SIZE) {
- pr_verbose(verbose, "Size of secure key is too small: "
- "%lu expected %lu", secure_key_size,
- AESDATA_KEY_SIZE);
- return -EINVAL;
- }
-
- memcpy(&verifykey.seckey, token, sizeof(verifykey.seckey));
+ xts = is_xts_key(secure_key, secure_key_size);
- rc = ioctl(pkey_fd, PKEY_VERIFYKEY, &verifykey);
- if (rc < 0) {
- rc = -errno;
- pr_verbose(verbose, "Failed to validate a secure key: %s",
- strerror(-rc));
+ rc = build_apqn_list_for_key(pkey_fd, secure_key,
+ HALF_KEYSIZE_FOR_XTS(secure_key_size, xts),
+ PKEY_FLAGS_MATCH_CUR_MKVP |
+ PKEY_FLAGS_MATCH_ALT_MKVP,
+ apqns, &list, &list_entries, verbose);
+ if (rc != 0) {
+ pr_verbose(verbose, "Failed to build a list of APQNs that can "
+ "validate this secure key: %s", strerror(-rc));
return rc;
}
- if ((verifykey.attributes & PKEY_VERIFY_ATTR_AES) == 0) {
- pr_verbose(verbose, "Secure key is not an AES key");
- return -EINVAL;
- }
-
- if (clear_key_bitsize)
- *clear_key_bitsize = verifykey.keysize;
-
- /* XTS uses 2 secure key tokens concatenated to each other */
- if (secure_key_size > AESDATA_KEY_SIZE) {
- rc = validate_secure_xts_key(pkey_fd,
- secure_key, secure_key_size,
- verifykey.keysize,
- verifykey.attributes,
- clear_key_bitsize,
- verbose);
- if (rc != 0)
- return rc;
+ if (is_old_mk != NULL)
+ *is_old_mk = true;
+ if (clear_key_bitsize != NULL)
+ *clear_key_bitsize = 0;
+
+ valid = false;
+ for (i = 0; i < list_entries; i++) {
+ memset(&verifykey2, 0, sizeof(verifykey2));
+ verifykey2.key = secure_key;
+ verifykey2.keylen = HALF_KEYSIZE_FOR_XTS(secure_key_size, xts);
+ verifykey2.cardnr = list[i].card;
+ verifykey2.domain = list[i].domain;
+
+ rc = pkey_verifyseck2(pkey_fd, &verifykey2, verbose);
+ if (rc < 0) {
+ pr_verbose(verbose, "Failed to validate the secure key "
+ "on APQN %02x.%04x: %s", list[i].card,
+ list[i].domain, strerror(-rc));
+ continue;
+ }
+
+ if (is_xts_key(secure_key, secure_key_size)) {
+ rc = validate_secure_xts_key(pkey_fd, &list[i],
+ secure_key,
+ secure_key_size,
+ verifykey2.size,
+ verifykey2.flags,
+ clear_key_bitsize,
+ verbose);
+ if (rc != 0)
+ continue;
+
+ }
+
+ valid = true;
+
+ if (clear_key_bitsize) {
+ if (verifykey2.size != PKEY_SIZE_UNKNOWN)
+ *clear_key_bitsize += verifykey2.size;
+ clear_key_bitsize = NULL; /* Set it only once */
+ }
+
+ /*
+ * If at least one of the APQNs have a matching current MK,
+ * then don't report OLD, even if some match the old MK.
+ */
+ if (is_old_mk &&
+ (verifykey2.flags & PKEY_FLAGS_MATCH_CUR_MKVP))
+ *is_old_mk = false;
}
- if (is_old_mk)
- *is_old_mk = (verifykey.attributes &
- PKEY_VERIFY_ATTR_OLD_MKVP) != 0;
+ if (!valid)
+ return -ENODEV;
pr_verbose(verbose, "Secure key validation completed successfully");
- return 0;
+ if (list != NULL)
+ free(list);
+ return rc;
}
/**
--- a/zkey/pkey.h
+++ b/zkey/pkey.h
@@ -251,7 +251,7 @@ int write_secure_key(const char *keyfile
int validate_secure_key(int pkey_fd,
u8 *secure_key, size_t secure_key_size,
size_t *clear_key_bitsize, int *is_old_mk,
- bool verbose);
+ const char **apqns, bool verbose);
int generate_key_verification_pattern(const u8 *key, size_t key_size,
char *vp, size_t vp_len, bool verbose);
--- a/zkey/zkey-cryptsetup.c
+++ b/zkey/zkey-cryptsetup.c
@@ -1492,7 +1492,7 @@ static int validate_keyslot(int keyslot,
keyslot = rc;
rc = validate_secure_key(g.pkey_fd, (u8 *)vkey, vkeysize, clear_keysize,
- &is_old, g.verbose);
+ &is_old, NULL, g.verbose);
if (rc != 0) {
if (invalid_msg != NULL)
warnx("%s", invalid_msg);
@@ -1972,7 +1972,7 @@ static int command_validate(void)
goto out;
rc = validate_secure_key(g.pkey_fd, (u8 *)key, keysize, &clear_keysize,
- &is_old_mk, g.verbose);
+ &is_old_mk, NULL, g.verbose);
is_valid = (rc == 0);
token = find_token(g.cd, PAES_REENC_TOKEN_NAME);
@@ -2139,7 +2139,7 @@ static int command_setkey(void)
goto out;
rc = validate_secure_key(g.pkey_fd, newkey, newkey_size, NULL,
- &is_old_mk, g.verbose);
+ &is_old_mk, NULL, g.verbose);
if (rc != 0) {
warnx("The secure key in file '%s' is not valid",
g.master_key_file);
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -1188,7 +1188,7 @@ static int command_reencipher_file(void)
return EXIT_FAILURE;
rc = validate_secure_key(g.pkey_fd, secure_key, secure_key_size, NULL,
- &is_old_mk, g.verbose);
+ &is_old_mk, NULL, g.verbose);
if (rc != 0) {
warnx("The secure key in file '%s' is not valid", g.pos_arg);
rc = EXIT_FAILURE;
@@ -1404,7 +1404,7 @@ static int command_validate_file(void)
return EXIT_FAILURE;
rc = validate_secure_key(g.pkey_fd, secure_key, secure_key_size,
- &clear_key_size, &is_old_mk, g.verbose);
+ &clear_key_size, &is_old_mk, NULL, g.verbose);
if (rc != 0) {
warnx("The secure key in file '%s' is not valid", g.pos_arg);
rc = EXIT_FAILURE;

View File

@ -1,45 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: use STAGE3_ENTRY for STAGE3_LOAD_ADDRESS
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: c07104dbc734ec6e55accf1bd2091b251f312ed8
Problem-ID: VS1804
Upstream-Description:
zipl: use STAGE3_ENTRY for STAGE3_LOAD_ADDRESS
Use STAGE3_ENTRY for STAGE3_LOAD_ADDRESS as they have the same value
and this makes it more clear that the load address of stage3 is also
its entry point.
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/include/zipl.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/zipl/include/zipl.h
+++ b/zipl/include/zipl.h
@@ -23,7 +23,7 @@
#define STAGE3_ENTRY 0xa000UL
#define STAGE2_LOAD_ADDRESS 0x2000UL
-#define STAGE3_LOAD_ADDRESS 0xa000UL
+#define STAGE3_LOAD_ADDRESS STAGE3_ENTRY
#define IMAGE_LOAD_ADDRESS IMAGE_ENTRY
#define ADDRESS_LIMIT 0x80000000UL

View File

@ -1,194 +0,0 @@
Subject: zkey: Add support for re-enciphering AES CIPHER keys
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: 560b672bfad3c7bb6631ed4e1676a8b2c836e030
Problem-ID: SEC1717
Upstream-Description:
zkey: Add support for re-enciphering AES CIPHER keys
For secure keys of type CCA-AESCIPHER the CCA verb CSNBKTC2
(Key Token Change2) is used. CCA-AESDATA keys will continue
to use CCA verb CSNBKTC (Key Token Change).
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/cca.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++------------
zkey/cca.h | 10 +++++++
2 files changed, 76 insertions(+), 15 deletions(-)
--- a/zkey/cca.c
+++ b/zkey/cca.c
@@ -142,6 +142,9 @@ int load_cca_library(struct cca_lib *cca
/* Get the Key Token Change function */
cca->dll_CSNBKTC = (t_CSNBKTC)dlsym(cca->lib_csulcca, "CSNBKTC");
+ /* Get the Key Token Change 2 function */
+ cca->dll_CSNBKTC2 = (t_CSNBKTC2)dlsym(cca->lib_csulcca, "CSNBKTC2");
+
/* Get the Cryptographic Facility Query function */
cca->dll_CSUACFQ = (t_CSUACFQ)dlsym(cca->lib_csulcca, "CSUACFQ");
@@ -153,6 +156,7 @@ int load_cca_library(struct cca_lib *cca
if (cca->dll_CSUACFV == NULL ||
cca->dll_CSNBKTC == NULL ||
+ cca->dll_CSNBKTC2 == NULL ||
cca->dll_CSUACFQ == NULL ||
cca->dll_CSUACRA == NULL ||
cca->dll_CSUACRD == NULL) {
@@ -187,10 +191,13 @@ int key_token_change(struct cca_lib *cca
u8 *secure_key, unsigned int secure_key_size,
char *method, bool verbose)
{
+ struct aescipherkeytoken *cipherkey =
+ (struct aescipherkeytoken *)secure_key;
long exit_data_len = 0, rule_array_count;
unsigned char rule_array[2 * 8] = { 0, };
unsigned char exit_data[4] = { 0, };
long return_code, reason_code;
+ long key_token_length;
util_assert(cca != NULL, "Internal error: cca is NULL");
util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
@@ -202,33 +209,77 @@ int key_token_change(struct cca_lib *cca
memcpy(rule_array + 8, "AES ", 8);
rule_array_count = 2;
- cca->dll_CSNBKTC(&return_code, &reason_code,
- &exit_data_len, exit_data,
- &rule_array_count, rule_array,
- secure_key);
-
- pr_verbose(verbose, "CSNBKTC (Key Token Change) with '%s' returned: "
- "return_code: %ld, reason_code: %ld", method, return_code,
- reason_code);
- if (return_code != 0) {
- print_CCA_error(return_code, reason_code);
- return -EIO;
- }
-
- if (secure_key_size == 2 * AESDATA_KEY_SIZE) {
+ if (is_cca_aes_data_key(secure_key, secure_key_size)) {
cca->dll_CSNBKTC(&return_code, &reason_code,
&exit_data_len, exit_data,
&rule_array_count, rule_array,
- secure_key + AESDATA_KEY_SIZE);
+ secure_key);
pr_verbose(verbose, "CSNBKTC (Key Token Change) with '%s' "
"returned: return_code: %ld, reason_code: %ld",
method, return_code, reason_code);
+ } else if (is_cca_aes_cipher_key(secure_key, secure_key_size)) {
+ key_token_length = cipherkey->length;
+ cca->dll_CSNBKTC2(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ &key_token_length,
+ (unsigned char *)cipherkey);
+
+ pr_verbose(verbose, "CSNBKTC2 (Key Token Change2) with '%s' "
+ "returned: return_code: %ld, reason_code: %ld",
+ method, return_code, reason_code);
+
+ pr_verbose(verbose, "key_token_length: %lu", key_token_length);
+ } else {
+ warnx("Invalid key type specified");
+ return -EINVAL;
+ }
+
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -EIO;
+ }
+
+ if (is_xts_key(secure_key, secure_key_size)) {
+ if (is_cca_aes_data_key(secure_key, secure_key_size)) {
+ cca->dll_CSNBKTC(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ secure_key + AESDATA_KEY_SIZE);
+
+ pr_verbose(verbose, "CSNBKTC (Key Token Change) with "
+ "'%s' returned: return_code: %ld, "
+ "reason_code: %ld", method, return_code,
+ reason_code);
+ } else if (is_cca_aes_cipher_key(secure_key, secure_key_size)) {
+ cipherkey = (struct aescipherkeytoken *)(secure_key +
+ AESCIPHER_KEY_SIZE);
+ key_token_length = cipherkey->length;
+ cca->dll_CSNBKTC2(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ &key_token_length,
+ (unsigned char *)cipherkey);
+
+ pr_verbose(verbose, "CSNBKTC2 (Key Token Change2) with "
+ "'%s' returned: return_code: %ld, "
+ "reason_code: %ld", method, return_code,
+ reason_code);
+
+ pr_verbose(verbose, "key_token_length: %lu",
+ key_token_length);
+ } else {
+ warnx("Invalid key type specified");
+ return -EINVAL;
+ }
+
if (return_code != 0) {
print_CCA_error(return_code, reason_code);
return -EIO;
}
}
+
return 0;
}
--- a/zkey/cca.h
+++ b/zkey/cca.h
@@ -25,6 +25,15 @@ typedef void (*t_CSNBKTC)(long *return_c
unsigned char *rule_array,
unsigned char *key_identifier);
+typedef void (*t_CSNBKTC2)(long *return_code,
+ long *reason_code,
+ long *exit_data_length,
+ unsigned char *exit_data,
+ long *rule_array_count,
+ unsigned char *rule_array,
+ long *key_identifier_length,
+ unsigned char *key_identifier);
+
typedef void (*t_CSUACFV)(long *return_code,
long *reason_code,
long *exit_data_length,
@@ -68,6 +77,7 @@ struct cca_version {
struct cca_lib {
void *lib_csulcca;
t_CSNBKTC dll_CSNBKTC;
+ t_CSNBKTC2 dll_CSNBKTC2;
t_CSUACFV dll_CSUACFV;
t_CSUACFQ dll_CSUACFQ;
t_CSUACRA dll_CSUACRA;

View File

@ -1,105 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: move loaders layout definitions into separate header
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 97ab8fb4e98c84a89d421c08b392db665125a3c0
Problem-ID: VS1804
Upstream-Description:
zipl: move loaders layout definitions into separate header
Move the loaders (stage2/stage3) layout values to
`include/boot/loaders_layout.h` and use the `_AC` macro for the
constants. This allows the reuse of the definitions, e.g. in assembler
files, and later for the creation of linker scripts.
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
include/boot/loaders_layout.h | 32 ++++++++++++++++++++++++++++++++
zipl/include/zipl.h | 14 +-------------
2 files changed, 33 insertions(+), 13 deletions(-)
--- /dev/null
+++ b/include/boot/loaders_layout.h
@@ -0,0 +1,32 @@
+/*
+ * zipl stage2/stage3 layout definitions
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ *
+ */
+
+#ifndef LOADERS_LAYOUT_H
+#define LOADERS_LAYOUT_H
+
+#include "lib/zt_common.h"
+#include "linux_layout.h"
+
+#define STAGE3_ENTRY _AC(0xa000, UL)
+
+#define STAGE2_LOAD_ADDRESS _AC(0x2000, UL)
+#define STAGE3_LOAD_ADDRESS STAGE3_ENTRY
+#define IMAGE_LOAD_ADDRESS IMAGE_ENTRY
+
+#define STAGE3_HEAP_SIZE _AC(0x4000, UL)
+#define STAGE3_HEAP_ADDRESS _AC(0x2000, UL)
+#define STAGE3_STACK_SIZE _AC(0x1000, UL)
+#define STAGE3_STACK_ADDRESS _AC(0xF000, UL)
+#define STAGE3_PARAMS_ADDRESS _AC(0x9000, UL)
+
+
+#ifndef __ASSEMBLER__
+#endif /* __ASSEMBLER__ */
+#endif /* LOADERS_LAYOUT_H */
--- a/zipl/include/zipl.h
+++ b/zipl/include/zipl.h
@@ -14,30 +14,18 @@
#include <stdint.h>
#include "lib/zt_common.h"
-#include "boot/linux_layout.h"
+#include "boot/loaders_layout.h"
#define ZIPL_MAGIC "zIPL"
#define ZIPL_MAGIC_SIZE 4
#define DISK_LAYOUT_ID 0x00000001
-#define STAGE3_ENTRY 0xa000UL
-
-#define STAGE2_LOAD_ADDRESS 0x2000UL
-#define STAGE3_LOAD_ADDRESS STAGE3_ENTRY
-#define IMAGE_LOAD_ADDRESS IMAGE_ENTRY
-
#define ADDRESS_LIMIT 0x80000000UL
#define ADDRESS_LIMIT_KDUMP 0x2000000UL /* HSA size: 32 MiB */
#define UNSPECIFIED_ADDRESS -1UL
#define MAXIMUM_PARMLINE_SIZE 0x380UL
#define MAXIMUM_PHYSICAL_BLOCKSIZE 0x1000UL
-#define STAGE3_HEAP_SIZE 0x4000UL
-#define STAGE3_HEAP_ADDRESS 0x2000UL
-#define STAGE3_STACK_SIZE 0x1000UL
-#define STAGE3_STACK_ADDRESS 0xF000UL
-#define STAGE3_PARAMS_ADDRESS 0x9000UL
-
#define PSW_ADDRESS_MASK 0x000000007fffffffUL
#define PSW_LOAD 0x0008000080000000UL
#define PSW_DISABLED_WAIT 0x000a000000000000UL

View File

@ -1,361 +0,0 @@
Subject: zkey: Check crypto card level during APQN cross checking
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: b7bb90c552f9b62c0b4ddc1295e76769149ee6bb
Problem-ID: SEC1717
Upstream-Description:
zkey: Check crypto card level during APQN cross checking
Secure keys of type CCA-AESCIPHER require a CEX6C or newer crypto
card. Also check for the minimum required card level during cross
checking of APQNs. Also display the card level in the APQN report.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/keystore.c | 25 +++++++++++++----
zkey/pkey.c | 20 ++++++++++++++
zkey/pkey.h | 1
zkey/utils.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
zkey/utils.h | 6 ++--
zkey/zkey.c | 9 ++++--
6 files changed, 126 insertions(+), 15 deletions(-)
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -1722,7 +1722,9 @@ int keystore_generate_key(struct keystor
if (rc != 0)
goto out_free_key_filenames;
- rc = cross_check_apqns(apqns, 0, true, keystore->verbose);
+ rc = cross_check_apqns(apqns, 0,
+ get_min_card_level_for_keytype(key_type), true,
+ keystore->verbose);
if (rc == -EINVAL)
goto out_free_key_filenames;
if (rc != 0 && rc != -ENOTSUP && noapqncheck == 0) {
@@ -1850,7 +1852,9 @@ int keystore_import_key(struct keystore
goto out_free_key;
}
- rc = cross_check_apqns(apqns, mkvp, true, keystore->verbose);
+ rc = cross_check_apqns(apqns, mkvp,
+ get_min_card_level_for_keytype(key_type), true,
+ keystore->verbose);
if (rc == -EINVAL)
goto out_free_key;
if (rc != 0 && rc != -ENOTSUP && noapqncheck == 0) {
@@ -1937,8 +1941,8 @@ int keystore_change_key(struct keystore
.nomsg = 0 };
struct key_filenames file_names = { NULL, NULL, NULL };
struct properties *key_props = NULL;
+ char *apqns_prop, *key_type;
size_t secure_key_size;
- char *apqns_prop;
u8 *secure_key;
char temp[30];
u64 mkvp;
@@ -2005,9 +2009,12 @@ int keystore_change_key(struct keystore
goto out;
apqns_prop = properties_get(key_props, PROP_NAME_APQNS);
- rc = cross_check_apqns(apqns_prop, mkvp, true,
- keystore->verbose);
+ key_type = properties_get(key_props, PROP_NAME_KEY_TYPE);
+ rc = cross_check_apqns(apqns_prop, mkvp,
+ get_min_card_level_for_keytype(key_type),
+ true, keystore->verbose);
free(apqns_prop);
+ free(key_type);
if (rc == -ENOTSUP)
rc = 0;
if (rc != 0 && noapqncheck == 0) {
@@ -2373,12 +2380,17 @@ static int _keystore_display_apqn_status
{
int rc, warning = 0;
char *apqns;
+ char *key_type;
apqns = properties_get(properties, PROP_NAME_APQNS);
if (apqns == NULL)
return 0;
- rc = cross_check_apqns(apqns, mkvp, true, keystore->verbose);
+ apqns = properties_get(properties, PROP_NAME_APQNS);
+ key_type = properties_get(properties, PROP_NAME_KEY_TYPE);
+ rc = cross_check_apqns(apqns, mkvp,
+ get_min_card_level_for_keytype(key_type), true,
+ keystore->verbose);
if (rc != 0 && rc != -ENOTSUP)
warning = 1;
@@ -2386,6 +2398,7 @@ static int _keystore_display_apqn_status
printf("\n");
free(apqns);
+ free(key_type);
return warning;
}
/**
--- a/zkey/pkey.c
+++ b/zkey/pkey.c
@@ -1630,3 +1630,23 @@ const char *get_key_type(const u8 *key,
return NULL;
}
+
+/**
+ * Returns the minimum card level for a specific key type
+ *
+ * @param[in] key_type the type of the key
+ *
+ * @returns the minimum card level, or -1 for unknown key types
+ */
+int get_min_card_level_for_keytype(const char *key_type)
+{
+ if (key_type == NULL)
+ return -1;
+
+ if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) == 0)
+ return 3;
+ if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
+ return 6;
+
+ return -1;
+}
--- a/zkey/pkey.h
+++ b/zkey/pkey.h
@@ -264,5 +264,6 @@ bool is_cca_aes_cipher_key(const u8 *key
bool is_xts_key(const u8 *key, size_t key_size);
int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize);
const char *get_key_type(const u8 *key, size_t key_size);
+int get_min_card_level_for_keytype(const char *key_type);
#endif
--- a/zkey/utils.c
+++ b/zkey/utils.c
@@ -119,6 +119,49 @@ out:
}
/**
+ * Returns the level of the card. For a CEX3C 3 is returned, for a CEX4C 4,
+ * and so on.
+ *
+ * @param[in] card card number
+ *
+ * @returns The card level, or -1 of the level can not be determined.
+ */
+int sysfs_get_card_level(int card)
+{
+ char *dev_path;
+ char type[20];
+ int rc;
+
+ dev_path = util_path_sysfs("bus/ap/devices/card%02x", card);
+ if (!util_path_is_dir(dev_path)) {
+ rc = -1;
+ goto out;
+ }
+ if (util_file_read_line(type, sizeof(type), "%s/type", dev_path) != 0) {
+ rc = -1;
+ goto out;
+ }
+ if (strncmp(type, "CEX", 3) != 0 || strlen(type) < 5) {
+ rc = -1;
+ goto out;
+ }
+ if (type[4] != 'C') {
+ rc = -1;
+ goto out;
+ }
+ if (type[3] < '1' || type[3] > '9') {
+ rc = -1;
+ goto out;
+ }
+
+ rc = type[3] - '0';
+
+out:
+ free(dev_path);
+ return rc;
+}
+
+/**
* Gets the 8 character ASCII serial number string of an card from the sysfs.
*
* @param[in] card card number
@@ -436,12 +479,14 @@ static int print_apqn_mk_info(int card,
{
struct print_apqn_info *info = (struct print_apqn_info *)handler_data;
struct mk_info mk_info;
- int rc;
+ int rc, level;
rc = sysfs_get_mkvps(card, domain, &mk_info, info->verbose);
if (rc == -ENOTSUP)
return rc;
+ level = sysfs_get_card_level(card);
+
util_rec_set(info->rec, "APQN", "%02x.%04x", card, domain);
if (rc == 0) {
@@ -470,6 +515,11 @@ static int print_apqn_mk_info(int card,
util_rec_set(info->rec, "OLD", "?");
}
+ if (level > 0)
+ util_rec_set(info->rec, "TYPE", "CEX%dC", level);
+ else
+ util_rec_set(info->rec, "TYPE", "?");
+
util_rec_print(info->rec);
return 0;
@@ -499,6 +549,7 @@ int print_mk_info(const char *apqns, boo
util_rec_def(info.rec, "NEW", UTIL_REC_ALIGN_LEFT, 16, "NEW MK");
util_rec_def(info.rec, "CUR", UTIL_REC_ALIGN_LEFT, 16, "CURRENT MK");
util_rec_def(info.rec, "OLD", UTIL_REC_ALIGN_LEFT, 16, "OLD MK");
+ util_rec_def(info.rec, "TYPE", UTIL_REC_ALIGN_LEFT, 6, "TYPE");
util_rec_print_hdr(info.rec);
rc = handle_apqns(apqns, print_apqn_mk_info, &info, verbose);
@@ -511,6 +562,7 @@ struct cross_check_info {
u64 mkvp;
u64 new_mkvp;
bool key_mkvp;
+ int min_level;
u32 num_cur_match;
u32 num_old_match;
u32 num_new_match;
@@ -525,7 +577,7 @@ static int cross_check_mk_info(int card,
struct cross_check_info *info = (struct cross_check_info *)handler_data;
struct mk_info mk_info;
char temp[200];
- int rc;
+ int rc, level;
rc = sysfs_get_mkvps(card, domain, &mk_info, info->verbose);
if (rc == -ENODEV) {
@@ -539,6 +591,19 @@ static int cross_check_mk_info(int card,
info->num_checked++;
+ if (info->min_level >= 0) {
+ level = sysfs_get_card_level(card);
+
+ if (level < info->min_level) {
+ info->print_mks = 1;
+ info->mismatch = 1;
+ sprintf(temp, "WARNING: APQN %02x.%04x: The card level "
+ "is less than CEX%dC.", card, domain,
+ info->min_level);
+ util_print_indented(temp, 0);
+ }
+ }
+
if (mk_info.new_mk.mk_state == MK_STATE_PARTIAL) {
info->print_mks = 1;
sprintf(temp, "INFO: APQN %02x.%04x: The NEW master key "
@@ -662,6 +727,8 @@ static int cross_check_mk_info(int card,
* @param[in] mkvp The master key verification pattern of a secure key.
* If this is all zero, then the master keys are not
* matched against it.
+ * @param[in] min_level The minimum card level required. If min_level is -1 then
+ * the card level is not checked.
* @param[in] print_mks if true, then a the full master key info of all
* specified APQns is printed, in case of a mismatch.
* @param[in] verbose if true, verbose messages are printed
@@ -671,7 +738,8 @@ static int cross_check_mk_info(int card,
* -ENOTSUP is returned when the mkvps sysfs attribute is not
* available, because the zcrypt kernel module is on an older level.
*/
-int cross_check_apqns(const char *apqns, u64 mkvp, bool print_mks, bool verbose)
+int cross_check_apqns(const char *apqns, u64 mkvp, int min_level,
+ bool print_mks, bool verbose)
{
struct cross_check_info info;
char temp[200];
@@ -680,10 +748,12 @@ int cross_check_apqns(const char *apqns,
memset(&info, 0, sizeof(info));
info.key_mkvp = mkvp != 0;
info.mkvp = mkvp;
+ info.min_level = min_level;
info.verbose = verbose;
- pr_verbose(verbose, "Cross checking APQNs with mkvp 0x%016llx: %s",
- mkvp, apqns != NULL ? apqns : "ANY");
+ pr_verbose(verbose, "Cross checking APQNs with mkvp 0x%016llx and "
+ "min-level %d: %s", mkvp, min_level,
+ apqns != NULL ? apqns : "ANY");
rc = handle_apqns(apqns, cross_check_mk_info, &info, verbose);
if (rc != 0)
--- a/zkey/utils.h
+++ b/zkey/utils.h
@@ -18,6 +18,8 @@ int sysfs_is_card_online(int card);
int sysfs_is_apqn_online(int card, int domain);
+int sysfs_get_card_level(int card);
+
int sysfs_get_serialnr(int card, char serialnr[9], bool verbose);
#define MK_STATE_EMPTY 0
@@ -48,7 +50,7 @@ int handle_apqns(const char *apqns, apqn
int print_mk_info(const char *apqns, bool verbose);
-int cross_check_apqns(const char *apqns, u64 mkvp, bool print_mks,
- bool verbose);
+int cross_check_apqns(const char *apqns, u64 mkvp, int min_level,
+ bool print_mks, bool verbose);
#endif
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -1122,7 +1122,9 @@ static int command_generate(void)
return EXIT_FAILURE;
}
- rc = cross_check_apqns(NULL, 0, true, g.verbose);
+ rc = cross_check_apqns(NULL, 0,
+ get_min_card_level_for_keytype(g.key_type),
+ true, g.verbose);
if (rc == -EINVAL)
return EXIT_FAILURE;
if (rc != 0 && rc != -ENOTSUP) {
@@ -1447,7 +1449,10 @@ static int command_validate_file(void)
printf(" %.*s\n", VERIFICATION_PATTERN_LEN / 2,
&vp[VERIFICATION_PATTERN_LEN / 2]);
- rc = cross_check_apqns(NULL, mkvp, true, g.verbose);
+ rc = cross_check_apqns(NULL, mkvp,
+ get_min_card_level_for_keytype(
+ get_key_type(secure_key, secure_key_size)),
+ true, g.verbose);
if (rc == -EINVAL)
return EXIT_FAILURE;
if (rc != 0 && rc != -ENOTSUP) {

View File

@ -1,192 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl/s390.h: rename `inline` macro into `__always_inline`
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 67e76b8ebd8acb4aef1d22309287776892b7267e
Problem-ID: VS1804
Upstream-Description:
zipl/s390.h: rename `inline` macro into `__always_inline`
Rename `inline` macro into `__always_inline` so one can differentiate
between the macro and the C keyword. While at it, undefine the
previous `__always_inline` macro so s390.h can be used in combination
with glibc.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/s390.h | 39 ++++++++++++++++++++++-----------------
1 file changed, 22 insertions(+), 17 deletions(-)
--- a/zipl/boot/s390.h
+++ b/zipl/boot/s390.h
@@ -19,7 +19,12 @@
#define __pa(x) ((unsigned long)(x))
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define barrier() __asm__ __volatile__("": : :"memory")
-#define inline inline __attribute__((always_inline))
+/* The Linux kernel (in stddef.h) and glibc (sys/cdefs.h) define
+ * __always_inline. Therefore undefine it first to allow the headers
+ * to be included first.
+ */
+#undef __always_inline
+#define __always_inline inline __attribute__((always_inline))
/*
* Helper macro for exception table entries
@@ -214,7 +219,7 @@ do { \
libc_stop(reason); \
} while (0)
-static inline int page_is_valid(unsigned long addr)
+static __always_inline int page_is_valid(unsigned long addr)
{
unsigned long tmp;
int rc;
@@ -234,7 +239,7 @@ static inline int page_is_valid(unsigned
return rc;
}
-static inline uint32_t csum_partial(const void *buf, int len, uint32_t sum)
+static __always_inline uint32_t csum_partial(const void *buf, int len, uint32_t sum)
{
register unsigned long reg2 asm("2") = (unsigned long) buf;
register unsigned long reg3 asm("3") = (unsigned long) len;
@@ -262,7 +267,7 @@ static inline uint32_t csum_partial(cons
"i" (low), "i" (high)); \
})
-static inline void __ctl_set_bit(unsigned int cr, unsigned int bit)
+static __always_inline void __ctl_set_bit(unsigned int cr, unsigned int bit)
{
unsigned long reg;
@@ -282,7 +287,7 @@ enum diag308_subcode {
DIAG308_STORE = 6,
};
-static inline int diag308(unsigned long subcode, void *addr)
+static __always_inline int diag308(unsigned long subcode, void *addr)
{
register unsigned long _addr asm("0") = (unsigned long) addr;
register unsigned long _rc asm("1") = 0;
@@ -298,7 +303,7 @@ static inline int diag308(unsigned long
/*
* Store CPU address
*/
-static inline unsigned short stap(void)
+static __always_inline unsigned short stap(void)
{
unsigned short cpu_address;
@@ -309,7 +314,7 @@ static inline unsigned short stap(void)
/*
* Program the clock comparator
*/
-static inline void set_clock_comparator(uint64_t time)
+static __always_inline void set_clock_comparator(uint64_t time)
{
asm volatile("sckc %0" : : "Q" (time));
}
@@ -317,7 +322,7 @@ static inline void set_clock_comparator(
/*
* Program the CPU timer
*/
-static inline void set_cpu_timer(uint64_t timer)
+static __always_inline void set_cpu_timer(uint64_t timer)
{
asm volatile("spt %0" : : "Q" (timer));
}
@@ -325,7 +330,7 @@ static inline void set_cpu_timer(uint64_
/*
* Get current time (store clock)
*/
-static inline unsigned long long get_tod_clock(void)
+static __always_inline unsigned long long get_tod_clock(void)
{
unsigned long long clk;
@@ -343,7 +348,7 @@ struct cpuid {
unsigned int unused:16;
} __packed __aligned(8);
-static inline void get_cpu_id(struct cpuid *ptr)
+static __always_inline void get_cpu_id(struct cpuid *ptr)
{
asm volatile("stidp %0" : "=Q" (*ptr));
}
@@ -351,7 +356,7 @@ static inline void get_cpu_id(struct cpu
/*
* Check if we run under z/VM
*/
-static inline int is_zvm(void)
+static __always_inline int is_zvm(void)
{
struct cpuid cpuid;
@@ -369,7 +374,7 @@ typedef struct {
/*
* Save vector registers
*/
-static inline void save_vx_regs(__vector128 *vxrs)
+static __always_inline void save_vx_regs(__vector128 *vxrs)
{
typedef struct { __vector128 _[32]; } addrtype;
@@ -383,7 +388,7 @@ static inline void save_vx_regs(__vector
/*
* Save vector registers safe
*/
-static inline void save_vx_regs_safe(__vector128 *vxrs)
+static __always_inline void save_vx_regs_safe(__vector128 *vxrs)
{
unsigned long cr0;
@@ -396,7 +401,7 @@ static inline void save_vx_regs_safe(__v
#define MAX_FACILITY_BIT (256*8) /* stfle_fac_list has 256 bytes */
-static inline int __test_facility(unsigned long nr, void *facilities)
+static __always_inline int __test_facility(unsigned long nr, void *facilities)
{
unsigned char *ptr;
@@ -411,12 +416,12 @@ static inline int __test_facility(unsign
* That makes it easier to query facility bits with the bit number as
* documented in the Principles of Operation.
*/
-static inline int test_facility(unsigned long nr)
+static __always_inline int test_facility(unsigned long nr)
{
return __test_facility(nr, &S390_lowcore.stfle_fac_list);
}
-static inline unsigned long __stfle_asm(uint64_t *stfle_fac_list, int size)
+static __always_inline unsigned long __stfle_asm(uint64_t *stfle_fac_list, int size)
{
register unsigned long reg0 asm("0") = size - 1;
@@ -433,7 +438,7 @@ static inline unsigned long __stfle_asm(
* @stfle_fac_list: array where facility list can be stored
* @size: size of passed in array in double words
*/
-static inline void stfle(uint64_t *stfle_fac_list, int size)
+static __always_inline void stfle(uint64_t *stfle_fac_list, int size)
{
unsigned long nr;

View File

@ -1,101 +0,0 @@
Subject: zkey: Add helper function to query the CCA firmware version
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: b0cc0e47378de9cd82b0cd14228b26be4d615ffc
Problem-ID: SEC1717
Upstream-Description:
zkey: Add helper function to query the CCA firmware version
Some future functions are dependent on the firmware version of the
CCA crypto adapter. This helper function allows to query the version
of the currently selected CCA adapter.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/cca.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
--- a/zkey/cca.c
+++ b/zkey/cca.c
@@ -474,6 +474,58 @@ static int get_cca_adapter_serialnr(stru
}
/**
+ * Queries the firmware version of the current CCA adapter
+ *
+ * @param[in] cca the CCA library structure
+ * @param[out] version the struct where the version is returned
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error.
+ */
+static int get_cca_adapter_version(struct cca_lib *cca,
+ struct cca_version *version,
+ bool verbose)
+{
+ long exit_data_len = 0, rule_array_count, verb_data_length = 0;
+ unsigned char rule_array[6 * 8] = { 0, };
+ unsigned char exit_data[4] = { 0, };
+ long return_code, reason_code;
+ char version_data[9];
+
+ util_assert(cca != NULL, "Internal error: cca is NULL");
+
+ memset(rule_array, 0, sizeof(rule_array));
+ memcpy(rule_array, "STATCCA ", 8);
+ rule_array_count = 1;
+
+ cca->dll_CSUACFQ(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ &verb_data_length, NULL);
+
+ pr_verbose(verbose, "CSUACFQ (Cryptographic Facility Query) returned: "
+ "return_code: %ld, reason_code: %ld", return_code,
+ reason_code);
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -EIO;
+ }
+
+ memcpy(version_data, rule_array+3*8, 8);
+ version_data[8] = '\0';
+
+ pr_verbose(verbose, "CCA firmware version string: %s", version_data);
+
+ if (sscanf((char *)version_data, "%u.%u.%uz", &version->ver,
+ &version->rel, &version->mod) != 3) {
+ warnx("CCA formware version is invalid: %s", version_data);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
* Selects the specified APQN to be used for the CCA host library.
*
* @param[in] cca the CCA library structure

View File

@ -1,74 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: move __always_inline/barrier/__pa32/pa to zt_common.h
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 24fe8c1d1b75185f341ec2d0efc6c34f0b9263f1
Problem-ID: VS1804
Upstream-Description:
zipl: move __always_inline/barrier/__pa32/pa to zt_common.h
Move `__always_inline/barrier/__pa32/pa` to `lib/zt_common.h` as this
is non-architecture dependent code.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
include/lib/zt_common.h | 12 ++++++++++++
zipl/boot/s390.h | 9 ---------
2 files changed, 12 insertions(+), 9 deletions(-)
--- a/include/lib/zt_common.h
+++ b/include/lib/zt_common.h
@@ -55,6 +55,18 @@
#define __may_alias __attribute__((may_alias))
#define __section(x) __attribute__((__section__(#x)))
#define __noinline __attribute__((__noinline__))
+/* The Linux kernel (in stddef.h) and glibc (sys/cdefs.h) define
+ * __always_inline. Therefore undefine it first to allow the headers
+ * to be included first.
+ */
+#undef __always_inline
+#define __always_inline inline __attribute__((always_inline))
+
+#define __pa32(x) ((uint32_t)(unsigned long)(x))
+#define __pa(x) ((unsigned long)(x))
+
+#define barrier() __asm__ __volatile__("": : :"memory")
+
typedef unsigned long long u64;
typedef signed long long s64;
--- a/zipl/boot/s390.h
+++ b/zipl/boot/s390.h
@@ -15,16 +15,7 @@
#include "libc.h"
#include "boot/sigp.h"
-#define __pa32(x) ((uint32_t)(unsigned long)(x))
-#define __pa(x) ((unsigned long)(x))
#define MIN(x, y) ((x) < (y) ? (x) : (y))
-#define barrier() __asm__ __volatile__("": : :"memory")
-/* The Linux kernel (in stddef.h) and glibc (sys/cdefs.h) define
- * __always_inline. Therefore undefine it first to allow the headers
- * to be included first.
- */
-#undef __always_inline
-#define __always_inline inline __attribute__((always_inline))
/*
* Helper macro for exception table entries

View File

@ -1,279 +0,0 @@
Subject: zkey: Add helper function to convert secure keys between key types
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: 7d4b1e18b6195f48414f42b4655f900872fed1e7
Problem-ID: SEC1717
Upstream-Description:
zkey: Add helper function to convert secure keys between key types
Add a helper function to convert a secure key from key type
CCA-AESDATA to CCA-AESCIPHER.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/cca.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
zkey/cca.h | 22 +++++++
2 files changed, 192 insertions(+), 1 deletion(-)
--- a/zkey/cca.c
+++ b/zkey/cca.c
@@ -55,6 +55,14 @@ static void print_CCA_error(int return_c
warnx("The secure key has a CCA master key "
"verification pattern that is not valid");
break;
+ case 90:
+ warnx("The operation has been rejected due to access "
+ "control checking");
+ break;
+ case 2143:
+ warnx("The operation has been rejected due to key "
+ "export restrictions of the secure key");
+ break;
}
break;
case 12:
@@ -154,12 +162,16 @@ int load_cca_library(struct cca_lib *cca
/* Cryptographic Resource Deallocate function */
cca->dll_CSUACRD = (t_CSUACRD)dlsym(cca->lib_csulcca, "CSUACRD");
+ /* Get the Key Translate 2 function */
+ cca->dll_CSNBKTR2 = (t_CSNBKTR2)dlsym(cca->lib_csulcca, "CSNBKTR2");
+
if (cca->dll_CSUACFV == NULL ||
cca->dll_CSNBKTC == NULL ||
cca->dll_CSNBKTC2 == NULL ||
cca->dll_CSUACFQ == NULL ||
cca->dll_CSUACRA == NULL ||
- cca->dll_CSUACRD == NULL) {
+ cca->dll_CSUACRD == NULL ||
+ cca->dll_CSNBKTR2 == NULL) {
pr_verbose(verbose, "%s", dlerror());
warnx("The command requires the IBM CCA Host Libraries and "
"Tools.\nFor the supported environments and downloads, "
@@ -729,3 +741,160 @@ void print_msg_for_cca_envvars(const cha
util_print_indented(msg, 0);
free(msg);
}
+
+/*
+ * Convert a secure key of type CCA-AESDATA into a secure key of type
+ * CCA-AESCIPHER.
+ *
+ * @param[in] cca the CCA library structure
+ * @param[in] input_key the secure key to convert
+ * @param[in] input_key_size the size of the secure key to convert
+ * @param[in] output_key buffer for the converted secure key
+ * @param[in/out] output_key_size on input: size of the output buffer.
+ * on exit: size of the converted secure key
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error.
+ */
+int convert_aes_data_to_cipher_key(struct cca_lib *cca,
+ u8 *input_key, unsigned int input_key_size,
+ u8 *output_key,
+ unsigned int *output_key_size,
+ bool verbose)
+{
+ long input_token_size, output_token_size, zero = 0;
+ long exit_data_len = 0, rule_array_count = 0;
+ unsigned char *input_token, *output_token;
+ unsigned char rule_array[8 * 2] = { 0, };
+ unsigned char null_token[64] = { 0, };
+ long null_token_len = sizeof(null_token);
+ unsigned char exit_data[4] = { 0, };
+ struct aescipherkeytoken *cipherkey;
+ long return_code, reason_code;
+ struct cca_version version;
+ unsigned char buffer[800];
+ int rc;
+
+ util_assert(cca != NULL, "Internal error: cca is NULL");
+ util_assert(input_key != NULL, "Internal error: input_key is NULL");
+ util_assert(output_key != NULL, "Internal error: output_key is NULL");
+ util_assert(output_key_size != NULL,
+ "Internal error: output_key_size is NULL");
+
+ if (is_cca_aes_cipher_key(input_key, input_key_size)) {
+ warnx("Invalid key-type specified");
+ return -EINVAL;
+ }
+
+ if (*output_key_size < (is_xts_key(input_key, input_key_size) ?
+ 2 * AESCIPHER_KEY_SIZE : AESCIPHER_KEY_SIZE))
+ return -EINVAL;
+
+ /*
+ * We need a CCA firmware version 6.3.27 or later to support
+ * conversion of secure keys that are exportable to CPACF protected keys
+ */
+ rc = get_cca_adapter_version(cca, &version, verbose);
+ if (rc != 0)
+ return rc;
+ if (version.ver < 6 ||
+ (version.ver == 6 && version.rel < 3) ||
+ (version.ver == 6 && version.rel < 3 && version.mod < 27)) {
+ util_print_indented("The used CCA firmware version does not "
+ "support converting a secure key that can "
+ "be used with the PAES cipher. The "
+ "required CCA firmware version is 6.3.27 "
+ "or later. For the supported environments "
+ "and updates, see: " CCA_WEB_PAGE, 0);
+ return -ENOTSUP;
+ }
+
+ input_token = input_key;
+ input_token_size = AESDATA_KEY_SIZE;
+ output_token = buffer;
+ output_token_size = sizeof(buffer);
+ memset(buffer, 0, sizeof(buffer));
+
+ memcpy(rule_array, "AES ", 8);
+ memcpy(rule_array + 8, "REFORMAT", 8);
+ rule_array_count = 2;
+
+ cca->dll_CSNBKTR2(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ &input_token_size, input_token,
+ &null_token_len, null_token,
+ &zero, NULL,
+ &output_token_size, output_token);
+
+ pr_verbose(verbose, "CSNBKTR2 (Key Translate2) "
+ "returned: return_code: %ld, reason_code: %ld", return_code,
+ reason_code);
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -EIO;
+ }
+
+ pr_verbose(verbose, "output_token_size: %lu", output_token_size);
+ if (output_token_size > (long)AESCIPHER_KEY_SIZE) {
+ pr_verbose(verbose, "Output key token too large");
+ return -EINVAL;
+ }
+
+ /*
+ * Check if the converted key allows export to CPACF protected key.
+ * If not, then the CCA host library or firmware code level is too low.
+ */
+ cipherkey = (struct aescipherkeytoken *)buffer;
+ if ((cipherkey->kmf1 & 0x0800) == 0) {
+ util_print_indented("The used CCA firmware version does not "
+ "support converting a secure key that can "
+ "be used with the PAES cipher. The "
+ "required CCA firmware version is 6.3.27 "
+ "or later. For the supported environments "
+ "and updates, see: " CCA_WEB_PAGE, 0);
+ return -ENOTSUP;
+ }
+
+ memset(output_key, 0, *output_key_size);
+ memcpy(output_key, buffer, output_token_size);
+ *output_key_size = AESCIPHER_KEY_SIZE;
+
+ if (is_xts_key(input_key, input_key_size)) {
+ input_token = input_key + AESDATA_KEY_SIZE;
+ input_token_size = AESDATA_KEY_SIZE;
+ output_token = buffer;
+ output_token_size = sizeof(buffer);
+ memset(buffer, 0, sizeof(buffer));
+
+ cca->dll_CSNBKTR2(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ &input_token_size, input_token,
+ &null_token_len, null_token,
+ &zero, NULL,
+ &output_token_size, output_token);
+
+ pr_verbose(verbose, "CSNBKTR2 (Key Translate2) "
+ "returned: return_code: %ld, reason_code: %ld",
+ return_code, reason_code);
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -EIO;
+ }
+
+ pr_verbose(verbose, "output_token_size: %lu",
+ output_token_size);
+ if (output_token_size > (long)AESCIPHER_KEY_SIZE) {
+ pr_verbose(verbose, "Output key token too large");
+ return -EINVAL;
+ }
+
+ memcpy(output_key + AESCIPHER_KEY_SIZE, buffer,
+ output_token_size);
+ *output_key_size += AESCIPHER_KEY_SIZE;
+ }
+
+ return 0;
+}
+
--- a/zkey/cca.h
+++ b/zkey/cca.h
@@ -68,6 +68,21 @@ typedef void (*t_CSUACRD)(long *return_c
long *ressource_name_length,
unsigned char *ressource_name);
+typedef void (*t_CSNBKTR2)(long *return_code,
+ long *reason_code,
+ long *exit_data_length,
+ unsigned char *exit_data,
+ long *rule_array_count,
+ unsigned char *rule_array,
+ long *input_key_token_length,
+ unsigned char *input_key_token,
+ long *input_KEK_key_identifier_length,
+ unsigned char *input_KEK_key_identifier,
+ long *output_KEK_key_identifier_length,
+ unsigned char *output_KEK_key_identifier,
+ long *output_key_token_length,
+ unsigned char *output_key_token);
+
struct cca_version {
unsigned int ver;
unsigned int rel;
@@ -82,6 +97,7 @@ struct cca_lib {
t_CSUACFQ dll_CSUACFQ;
t_CSUACRA dll_CSUACRA;
t_CSUACRD dll_CSUACRD;
+ t_CSNBKTR2 dll_CSNBKTR2;
struct cca_version version;
};
@@ -102,4 +118,10 @@ int select_cca_adapter_by_mkvp(struct cc
void print_msg_for_cca_envvars(const char *key_name);
+int convert_aes_data_to_cipher_key(struct cca_lib *cca,
+ u8 *input_key, unsigned int input_key_size,
+ u8 *output_key,
+ unsigned int *output_key_size,
+ bool verbose);
+
#endif

View File

@ -1,44 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: make BLK_PWRT unsigned int
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 2e28291c75d73b92921f7769eaa803fe3222f383
Problem-ID: VS1804
Upstream-Description:
zipl: make BLK_PWRT unsigned int
Otherwise there might be a compiler warning when using 'MIN(bl_count,
BLK_PWRT)'.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/fba2dump.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/zipl/boot/fba2dump.c
+++ b/zipl/boot/fba2dump.c
@@ -14,7 +14,7 @@
#include "fba.h"
#include "stage2dump.h"
-#define BLK_PWRT 64 /* Blocks per write */
+#define BLK_PWRT 64U /* Blocks per write */
#define BLK_SIZE 0x200 /* FBA block size */
#define BLK_PER_PAGE (PAGE_SIZE / BLK_SIZE) /* FBA blocks per page */

View File

@ -1,182 +0,0 @@
Subject: zkey: Add helper function to restrict export of secure keys
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: e7d79d5c5c0928c1bdbd6b669a6e70b8fd3352a5
Problem-ID: SEC1717
Upstream-Description:
zkey: Add helper function to restrict export of secure keys
Secure keys of type CCA-AESCIPHER can be export restricted, so that
these keys can not be exported by another key.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/cca.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
zkey/cca.h | 19 +++++++++++++
2 files changed, 101 insertions(+), 1 deletion(-)
--- a/zkey/cca.c
+++ b/zkey/cca.c
@@ -165,13 +165,17 @@ int load_cca_library(struct cca_lib *cca
/* Get the Key Translate 2 function */
cca->dll_CSNBKTR2 = (t_CSNBKTR2)dlsym(cca->lib_csulcca, "CSNBKTR2");
+ /* Get the Restrict Key Attribute function */
+ cca->dll_CSNBRKA = (t_CSNBRKA)dlsym(cca->lib_csulcca, "CSNBRKA");
+
if (cca->dll_CSUACFV == NULL ||
cca->dll_CSNBKTC == NULL ||
cca->dll_CSNBKTC2 == NULL ||
cca->dll_CSUACFQ == NULL ||
cca->dll_CSUACRA == NULL ||
cca->dll_CSUACRD == NULL ||
- cca->dll_CSNBKTR2 == NULL) {
+ cca->dll_CSNBKTR2 == NULL ||
+ cca->dll_CSNBRKA == NULL) {
pr_verbose(verbose, "%s", dlerror());
warnx("The command requires the IBM CCA Host Libraries and "
"Tools.\nFor the supported environments and downloads, "
@@ -898,3 +902,80 @@ int convert_aes_data_to_cipher_key(struc
return 0;
}
+/*
+ * Restrict the exportability of an AES CIPHER key. It restricts export by means
+ * of NOEX-AES, NOEX-DES, NOEX-RSA, NOEX-SYM, NOEXUASY, NOEXAASY, NOEX-RAW
+ * keywords.
+ * When this function is called with an AES DATA key, it does nothing and
+ * returns 0. AES DATA keys can not be export restricted.
+ *
+ * @param[in] cca the CCA library structure
+ * @param[in] secure_key the secure key to restrict
+ * @param[in] secure_key_size the size of the secure key to restrict
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error.
+ */
+int restrict_key_export(struct cca_lib *cca, u8 *secure_key,
+ unsigned int secure_key_size, bool verbose)
+{
+ struct aescipherkeytoken *cipherkey =
+ (struct aescipherkeytoken *)secure_key;
+ long exit_data_len = 0, rule_array_count = 0;
+ unsigned char rule_array[8 * 8] = { 0, };
+ unsigned char exit_data[4] = { 0, };
+ long return_code, reason_code;
+ long token_length, zero = 0;
+
+ util_assert(cca != NULL, "Internal error: cca is NULL");
+ util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
+
+ if (!is_cca_aes_cipher_key(secure_key, secure_key_size))
+ return 0;
+
+ memcpy(rule_array, "AES ", 8);
+ memcpy(rule_array + 8, "NOEX-AES", 8);
+ memcpy(rule_array + 16, "NOEX-DES", 8);
+ memcpy(rule_array + 24, "NOEX-RSA", 8);
+ memcpy(rule_array + 32, "NOEX-SYM", 8);
+ memcpy(rule_array + 40, "NOEXUASY", 8);
+ memcpy(rule_array + 48, "NOEXAASY", 8);
+ memcpy(rule_array + 56, "NOEX-RAW", 8);
+ rule_array_count = 8;
+
+ token_length = cipherkey->length;
+ cca->dll_CSNBRKA(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ &token_length, (unsigned char *)secure_key,
+ &zero, NULL, &zero, NULL, &zero, NULL);
+
+ pr_verbose(verbose, "CSNBRKA (Restrict Key Attribute) "
+ "returned: return_code: %ld, reason_code: %ld", return_code,
+ reason_code);
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -EIO;
+ }
+
+ if (is_xts_key(secure_key, secure_key_size)) {
+ cipherkey = (struct aescipherkeytoken *)(secure_key +
+ AESCIPHER_KEY_SIZE);
+ token_length = cipherkey->length;
+ cca->dll_CSNBRKA(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ &token_length, (unsigned char *)cipherkey,
+ &zero, NULL, &zero, NULL, &zero, NULL);
+
+ pr_verbose(verbose, "CSNBRKA (Restrict Key Attribute) "
+ "returned: return_code: %ld, reason_code: %ld",
+ return_code, reason_code);
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
--- a/zkey/cca.h
+++ b/zkey/cca.h
@@ -83,6 +83,21 @@ typedef void (*t_CSNBKTR2)(long *return_
long *output_key_token_length,
unsigned char *output_key_token);
+typedef void (*t_CSNBRKA)(long *return_code,
+ long *reason_code,
+ long *exit_data_length,
+ unsigned char *exit_data,
+ long *rule_array_count,
+ unsigned char *rule_array,
+ long *key_identifier_length,
+ unsigned char *key_identifier,
+ long *ey_encrypting_key_identifier_length,
+ unsigned char *ey_encrypting_key_identifier,
+ long *opt_parameter1_length,
+ unsigned char *opt_parameter1,
+ long *opt_parameter2_length,
+ unsigned char *opt_parameter2);
+
struct cca_version {
unsigned int ver;
unsigned int rel;
@@ -98,6 +113,7 @@ struct cca_lib {
t_CSUACRA dll_CSUACRA;
t_CSUACRD dll_CSUACRD;
t_CSNBKTR2 dll_CSNBKTR2;
+ t_CSNBRKA dll_CSNBRKA;
struct cca_version version;
};
@@ -124,4 +140,7 @@ int convert_aes_data_to_cipher_key(struc
unsigned int *output_key_size,
bool verbose);
+int restrict_key_export(struct cca_lib *cca, u8 *secure_key,
+ unsigned int secure_key_size, bool verbose);
+
#endif

View File

@ -1,105 +0,0 @@
Subject: [PATCH] [FEAT VS1804] Consolidate MIN and MAX macros
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: c55ceabc6726a7806922d288149003661f673a2f
Problem-ID: VS1804
Upstream-Description:
Consolidate MIN and MAX macros
Consolidate MIN and MAX macros and make sure it can be used in
combination with glib.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
include/lib/util_base.h | 17 +----------------
include/lib/zt_common.h | 17 +++++++++++++++++
zipl/boot/s390.h | 1 -
3 files changed, 18 insertions(+), 17 deletions(-)
--- a/include/lib/util_base.h
+++ b/include/lib/util_base.h
@@ -14,6 +14,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "zt_common.h"
void util_hexdump(FILE *fh, const char *tag, const void *data, int cnt);
void util_hexdump_grp(FILE *fh, const char *tag, const void *data, int group,
@@ -22,22 +23,6 @@ void util_print_indented(const char *str
#define UTIL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
-#define MIN(x, y) \
-({ \
- __typeof__(x) _x = (x); \
- __typeof__(y) _y = (y); \
- \
- _x < _y ? _x : _y; \
-})
-
-#define MAX(x, y) \
-({ \
- __typeof__(x) _x = (x); \
- __typeof__(y) _y = (y); \
- \
- _x > _y ? _x : _y; \
-})
-
static inline void util_ptr_vec_free(void **ptr_vec, int count)
{
int i;
--- a/include/lib/zt_common.h
+++ b/include/lib/zt_common.h
@@ -67,6 +67,23 @@
#define barrier() __asm__ __volatile__("": : :"memory")
+#undef MIN
+#define MIN(x, y) \
+ ({ \
+ __typeof__(x) _x = (x); \
+ __typeof__(y) _y = (y); \
+ \
+ _x < _y ? _x : _y; \
+ })
+
+#undef MAX
+#define MAX(x, y) \
+ ({ \
+ __typeof__(x) _x = (x); \
+ __typeof__(y) _y = (y); \
+ \
+ _x > _y ? _x : _y; \
+ })
typedef unsigned long long u64;
typedef signed long long s64;
--- a/zipl/boot/s390.h
+++ b/zipl/boot/s390.h
@@ -15,7 +15,6 @@
#include "libc.h"
#include "boot/sigp.h"
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
/*
* Helper macro for exception table entries

View File

@ -1,192 +0,0 @@
Subject: zkey: Add helper function to check an AES CIPHER key
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: 7fede7021ece58b9960532e17d963f844fe0de02
Problem-ID: SEC1717
Upstream-Description:
zkey: Add helper function to check an AES CIPHER key
The helper function performs a deep check of the AES CIPHER key
token and checks for any potentially insecure attributes.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/pkey.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
zkey/pkey.h | 1
2 files changed, 138 insertions(+)
--- a/zkey/pkey.c
+++ b/zkey/pkey.c
@@ -1650,3 +1650,140 @@ int get_min_card_level_for_keytype(const
return -1;
}
+
+/**
+ * Performs extended checks on an AES CIPHER key. It checks the key usage
+ * fields (KUFs) and key management fields (KMFs) of the key. The function
+ * returns -EINVAL and issues warning messages if a mismatch is detected.
+ *
+ * @param[in] key the secure key token
+ * @param[in] key_size the size of the secure key
+ *
+ * @returns 0 on success, a negative errno in case of an error
+ */
+int check_aes_cipher_key(const u8 *key, size_t key_size)
+{
+ struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key;
+ bool mismatch = false;
+
+ if (!is_cca_aes_cipher_key(key, key_size)) {
+ warnx("The key is not of type '"KEY_TYPE_CCA_AESCIPHER"'");
+ return -EINVAL;
+ }
+
+ if ((cipherkey->kuf1 & 0x8000) == 0) {
+ printf("WARNING: The secure key can not be used for "
+ "encryption\n");
+ mismatch = true;
+ }
+ if ((cipherkey->kuf1 & 0x4000) == 0) {
+ printf("WARNING: The secure key can not be used for "
+ "decryption\n");
+ mismatch = true;
+ }
+ if (cipherkey->kuf1 & 0x2000) {
+ printf("INFO: The secure key can be used for data translate\n");
+ mismatch = true;
+ }
+ if (cipherkey->kuf1 & 0x1000) {
+ printf("WARNING: The secure key can only be used in UDXs\n");
+ mismatch = true;
+ }
+
+ if (cipherkey->kmf1 & 0x8000) {
+ printf("WARNING: The secure key can be exported using a "
+ "symmetric key\n");
+ mismatch = true;
+ }
+ if (cipherkey->kmf1 & 0x4000) {
+ printf("WARNING: The secure key can be exported using an "
+ "unauthenticated asymmetric key\n");
+ mismatch = true;
+ }
+ if (cipherkey->kmf1 & 0x2000) {
+ printf("WARNING: The secure key can be exported using an "
+ "authenticated asymmetric key\n");
+ mismatch = true;
+ }
+ if (cipherkey->kmf1 & 0x1000) {
+ printf("WARNING: The secure key can be exported using a RAW "
+ "key\n");
+ mismatch = true;
+ }
+ if ((cipherkey->kmf1 & 0x0800) == 0) {
+ printf("WARNING: The secure key can not be transformed into a "
+ "CPACF protected key\n");
+ mismatch = true;
+ }
+ if ((cipherkey->kmf1 & 0x0080) == 0) {
+ printf("WARNING: The secure key can be exported using a DES "
+ "key\n");
+ mismatch = true;
+ }
+ if ((cipherkey->kmf1 & 0x0040) == 0) {
+ printf("WARNING: The secure key can be exported using an AES "
+ "key\n");
+ mismatch = true;
+ }
+ if ((cipherkey->kmf1 & 0x0008) == 0) {
+ printf("WARNING: The secure key can be exported using an RSA "
+ "key\n");
+ mismatch = true;
+ }
+
+ if (cipherkey->kmf2 & 0xC000) {
+ printf("WARNING: The secure key is incomplete\n");
+ mismatch = true;
+ }
+ if (cipherkey->kmf2 & 0x0010) {
+ printf("WARNING: The secure key was previously encrypted with "
+ "an untrusted KEK\n");
+ mismatch = true;
+ }
+ if (cipherkey->kmf2 & 0x0008) {
+ printf("WARNING: The secure key was previously in a format "
+ "without type or usage attributes\n");
+ mismatch = true;
+ }
+ if (cipherkey->kmf2 & 0x0004) {
+ printf("WARNING: The secure key was previously encrypted with "
+ "a key weaker than itself\n");
+ mismatch = true;
+ }
+ if (cipherkey->kmf2 & 0x0002) {
+ printf("WARNING: The secure key was previously in a non-CCA "
+ "format\n");
+ mismatch = true;
+ }
+ if (cipherkey->kmf2 & 0x0001) {
+ printf("WARNING: The secure key was previously encrypted in "
+ "ECB mode\n");
+ mismatch = true;
+ }
+
+ if ((cipherkey->kmf3 & 0xFF00) == 0x0000 ||
+ (cipherkey->kmf3 & 0x00FF) == 0x0000) {
+ printf("WARNING: The secure key was created by an unknown "
+ "method\n");
+ mismatch = true;
+ }
+ if ((cipherkey->kmf3 & 0xFF00) == 0x0400 ||
+ (cipherkey->kmf3 & 0x00FF) == 0x0004) {
+ printf("WARNING: The secure key was created from cleartext key "
+ "components\n");
+ mismatch = true;
+ }
+ if ((cipherkey->kmf3 & 0xFF00) == 0x0500 ||
+ (cipherkey->kmf3 & 0x00FF) == 0x0005) {
+ printf("WARNING: The secure key was entered as a cleartext key "
+ "value\n");
+ mismatch = true;
+ }
+ if ((cipherkey->kmf3 & 0x00FF) == 0x0012) {
+ printf("WARNING: The secure key was converted from a CCA "
+ "key-token that had no export control attributes\n");
+ mismatch = true;
+ }
+
+ return mismatch ? -EINVAL : 0;
+}
--- a/zkey/pkey.h
+++ b/zkey/pkey.h
@@ -265,5 +265,6 @@ bool is_xts_key(const u8 *key, size_t ke
int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize);
const char *get_key_type(const u8 *key, size_t key_size);
int get_min_card_level_for_keytype(const char *key_type);
+int check_aes_cipher_key(const u8 *key, size_t key_size);
#endif

View File

@ -1,76 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: remove libc.h include in s390.h
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: f454c6825f5087cf671d0dfbe96f7f3d148569d6
Problem-ID: VS1804
Upstream-Description:
zipl: remove libc.h include in s390.h
This allows the use of s390.h in combination with other libc
implementations than our minimal libc, e.g. with glibc.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/s390.h | 1 -
zipl/boot/sclp.c | 1 +
zipl/boot/sclp_stage3.c | 1 +
zipl/boot/stage2dump.c | 1 +
4 files changed, 3 insertions(+), 1 deletion(-)
--- a/zipl/boot/s390.h
+++ b/zipl/boot/s390.h
@@ -12,7 +12,6 @@
#define S390_H
#include "lib/zt_common.h"
-#include "libc.h"
#include "boot/sigp.h"
--- a/zipl/boot/sclp.c
+++ b/zipl/boot/sclp.c
@@ -9,6 +9,7 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
+#include "libc.h"
#include "error.h"
#include "s390.h"
#include "sclp.h"
--- a/zipl/boot/sclp_stage3.c
+++ b/zipl/boot/sclp_stage3.c
@@ -9,6 +9,7 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
+#include "libc.h"
#include "sclp.h"
#include "sclp_stage3.h"
--- a/zipl/boot/stage2dump.c
+++ b/zipl/boot/stage2dump.c
@@ -13,6 +13,7 @@
#include "lib/zt_common.h"
+#include "libc.h"
#include "error.h"
#include "sclp.h"
#include "stage2dump.h"

View File

@ -1,225 +0,0 @@
Subject: zkey: Add key checks when importing a CCA-AESCIPHER key
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: 0d9e42264db9935e28f663802c5b95795af79160
Problem-ID: SEC1717
Upstream-Description:
zkey: Add key checks when importing a CCA-AESCIPHER key
Perform extended checks on a secure key that is imported into
the key repository. Warn the user if the imported key is by
any means insecure, e.g. has been originally created in an
insecure way. Prompt the user to continue the import if a
potential insecurity is detected.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/keystore.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++----------
zkey/keystore.h | 3 +-
zkey/utils.c | 24 ++++++++++++++++++++++
zkey/utils.h | 2 +
zkey/zkey.1 | 6 +++++
zkey/zkey.c | 2 -
6 files changed, 85 insertions(+), 12 deletions(-)
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -1801,18 +1801,21 @@ out_free_key_filenames:
* default is used.
* @param[in] import_file The name of a secure key containing the key to import
* @param[in] volume_type the type of volume
+ * @param[in] cca the CCA library struct
*
* @returns 0 for success or a negative errno in case of an error
*/
int keystore_import_key(struct keystore *keystore, const char *name,
const char *description, const char *volumes,
const char *apqns, bool noapqncheck, size_t sector_size,
- const char *import_file, const char *volume_type)
+ const char *import_file, const char *volume_type,
+ struct cca_lib *cca)
{
struct key_filenames file_names = { NULL, NULL, NULL };
struct properties *key_props = NULL;
size_t secure_key_size;
const char *key_type;
+ int selected = 1;
u8 *secure_key;
u64 mkvp;
int rc;
@@ -1862,6 +1865,51 @@ int keystore_import_key(struct keystore
goto out_free_key;
}
+ if (is_cca_aes_cipher_key(secure_key, secure_key_size)) {
+ if (cca->lib_csulcca == NULL) {
+ rc = load_cca_library(cca, keystore->verbose);
+ if (rc != 0)
+ goto out_free_key;
+ }
+
+ rc = select_cca_adapter_by_mkvp(cca, mkvp, apqns,
+ FLAG_SEL_CCA_MATCH_CUR_MKVP |
+ FLAG_SEL_CCA_MATCH_OLD_MKVP,
+ keystore->verbose);
+ if (rc == -ENOTSUP) {
+ rc = 0;
+ selected = 0;
+ }
+ if (rc != 0) {
+ warnx("No APQN found that is suitable for "
+ "working with the secure AES key '%s'", name);
+ rc = 0;
+ goto out_free_key;
+ }
+
+ rc = restrict_key_export(cca, secure_key, secure_key_size,
+ keystore->verbose);
+ if (rc != 0) {
+ warnx("Failed to export-restrict the imported secure "
+ "key: %s", strerror(-rc));
+ if (!selected)
+ print_msg_for_cca_envvars("secure AES key");
+ goto out_free_key;
+ }
+
+ rc = check_aes_cipher_key(secure_key, secure_key_size);
+ if (rc != 0) {
+ warnx("The secure key to import might not be secure");
+ printf("%s: Do you want to import it anyway [y/N]? ",
+ program_invocation_short_name);
+ if (!prompt_for_yes(keystore->verbose)) {
+ warnx("Operation aborted");
+ rc = -ECANCELED;
+ goto out_free_key;
+ }
+ }
+ }
+
rc = write_secure_key(file_names.skey_filename, secure_key,
secure_key_size, keystore->verbose);
free(secure_key);
@@ -3180,7 +3228,6 @@ static int _keystore_prompt_for_remove(s
struct key_filenames *file_names)
{
struct properties *key_prop;
- char str[20];
char *msg;
int rc;
@@ -3198,14 +3245,7 @@ static int _keystore_prompt_for_remove(s
printf("%s: Remove key '%s' [y/N]? ", program_invocation_short_name,
name);
- if (fgets(str, sizeof(str), stdin) == NULL) {
- rc = -EIO;
- goto out;
- }
- if (str[strlen(str) - 1] == '\n')
- str[strlen(str) - 1] = '\0';
- pr_verbose(keystore, "Prompt reply: '%s'", str);
- if (strcasecmp(str, "y") != 0 && strcasecmp(str, "yes") != 0) {
+ if (!prompt_for_yes(keystore->verbose)) {
warnx("Operation aborted");
rc = -ECANCELED;
goto out;
--- a/zkey/keystore.h
+++ b/zkey/keystore.h
@@ -37,7 +37,8 @@ int keystore_generate_key(struct keystor
int keystore_import_key(struct keystore *keystore, const char *name,
const char *description, const char *volumes,
const char *apqns, bool noapqncheck, size_t sector_size,
- const char *import_file, const char *volume_type);
+ const char *import_file, const char *volume_type,
+ struct cca_lib *cca);
int keystore_change_key(struct keystore *keystore, const char *name,
const char *description, const char *volumes,
--- a/zkey/utils.c
+++ b/zkey/utils.c
@@ -793,3 +793,27 @@ int cross_check_apqns(const char *apqns,
return rc;
}
+
+/*
+ * Prompts for yes or no. Returns true if 'y' or 'yes' was entered.
+ *
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns true if 'y' or 'yes' was entered (case insensitive). Returns false
+ * otherwise.
+ */
+bool prompt_for_yes(bool verbose)
+{
+ char str[20];
+
+ if (fgets(str, sizeof(str), stdin) == NULL)
+ return false;
+
+ if (str[strlen(str) - 1] == '\n')
+ str[strlen(str) - 1] = '\0';
+ pr_verbose(verbose, "Prompt reply: '%s'", str);
+ if (strcasecmp(str, "y") == 0 || strcasecmp(str, "yes") == 0)
+ return true;
+
+ return false;
+}
--- a/zkey/utils.h
+++ b/zkey/utils.h
@@ -53,4 +53,6 @@ int print_mk_info(const char *apqns, boo
int cross_check_apqns(const char *apqns, u64 mkvp, int min_level,
bool print_mks, bool verbose);
+bool prompt_for_yes(bool verbose);
+
#endif
--- a/zkey/zkey.1
+++ b/zkey/zkey.1
@@ -349,6 +349,12 @@ additional information can be associated
, or the
.B \-\-sector-size
options.
+.PP
+.B Note:
+The \fBimport\fP command requires the CCA host library (libcsulcca.so)
+to be installed when secure keys of type \fBCCA-AESCIPHER\fP are imported.
+For the supported environments and downloads, see:
+\fIhttp://www.ibm.com/security/cryptocards\fP
.
.SS "Export AES secure keys from the secure key repository"
.
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -1522,7 +1522,7 @@ static int command_import(void)
rc = keystore_import_key(g.keystore, g.name, g.description, g.volumes,
g.apqns, g.noapqncheck, g.sector_size,
- g.pos_arg, g.volume_type);
+ g.pos_arg, g.volume_type, &g.cca);
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

View File

@ -1,679 +0,0 @@
Subject: zkey: Add 'convert' command to convert keys from one type to another
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: a86e41a51827b524c5f88db5e24282166df9b3c8
Problem-ID: SEC1717
Upstream-Description:
zkey: Add 'convert' command to convert keys from one type to another
Add a new 'convert' command. It allows to convert a secure key from
one key type to another. Currently only keys of type CCA-AESDATA can be
converted to CCA-AESCIPHER.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/keystore.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++
zkey/keystore.h | 4
zkey/zkey.1 | 93 ++++++++++++++++++++
zkey/zkey.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 557 insertions(+), 1 deletion(-)
--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -3947,6 +3947,218 @@ int keystore_crypttab(struct keystore *k
}
/**
+ * Converts a secure keys in the keystore
+ *
+ * @param[in] keystore the key store
+ * @param[in] name the name of the key to convert
+ * @param[in] key_type the type of the key to convert it to
+ * @param[in] noapqncheck if true, the specified APQN(s) are not checked for
+ * existence and type.
+ * @param[in] pkey_fd the file descriptor of /dev/pkey
+ * @param[in] cca the CCA library struct
+ *
+ * @returns 0 for success or a negative errno in case of an error
+ */
+int keystore_convert_key(struct keystore *keystore, const char *name,
+ const char *key_type, bool noapqncheck, bool quiet,
+ int pkey_fd, struct cca_lib *cca)
+{
+ struct key_filenames file_names = { NULL, NULL, NULL };
+ u8 output_key[2 * MAX_SECURE_KEY_SIZE];
+ struct properties *properties = NULL;
+ int rc, min_level, selected = 1;
+ unsigned int output_key_size;
+ char *cur_key_type = NULL;
+ char **apqn_list = NULL;
+ size_t secure_key_size;
+ u8 *secure_key = NULL;
+ char *apqns = NULL;
+ char *temp;
+ u64 mkvp;
+
+ util_assert(keystore != NULL, "Internal error: keystore is NULL");
+ util_assert(name != NULL, "Internal error: name is NULL");
+
+ rc = _keystore_get_key_filenames(keystore, name, &file_names);
+ if (rc != 0)
+ goto out;
+
+ rc = _keystore_ensure_keyfiles_exist(&file_names, name);
+ if (rc != 0)
+ goto out;
+
+ properties = properties_new();
+ rc = properties_load(properties, file_names.info_filename, 1);
+ if (rc != 0) {
+ warnx("Key '%s' does not exist or is invalid", name);
+ goto out;
+ }
+
+ cur_key_type = _keystore_get_key_type(properties);
+ if (strcasecmp(cur_key_type, key_type) == 0) {
+ warnx("The secure key '%s' is already of type %s", name,
+ cur_key_type);
+ rc = 0;
+ goto out;
+ }
+ if (strcasecmp(cur_key_type, KEY_TYPE_CCA_AESDATA) != 0) {
+ warnx("Only secure keys of type %s can "
+ "be converted. The secure key '%s' is of type %s",
+ KEY_TYPE_CCA_AESDATA, name, cur_key_type);
+ rc = 0;
+ goto out;
+ }
+
+ secure_key = read_secure_key(file_names.skey_filename,
+ &secure_key_size, keystore->verbose);
+ if (secure_key == NULL) {
+ rc = -ENOENT;
+ goto out;
+ }
+
+ min_level = get_min_card_level_for_keytype(key_type);
+ if (min_level < 0) {
+ warnx("Invalid key-type specified: %s", key_type);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ apqns = properties_get(properties, PROP_NAME_APQNS);
+ if (apqns != NULL)
+ apqn_list = str_list_split(apqns);
+
+ rc = cross_check_apqns(apqns, 0, min_level, true, keystore->verbose);
+ if (rc == -EINVAL)
+ goto out;
+ if (rc != 0 && rc != -ENOTSUP && !noapqncheck) {
+ warnx("Your master key setup is improper for converting key "
+ "'%s'", name);
+ goto out;
+ }
+
+ rc = validate_secure_key(pkey_fd, secure_key, secure_key_size,
+ NULL, NULL, (const char **)apqn_list,
+ keystore->verbose);
+ if (rc != 0)
+ goto out;
+
+ rc = get_master_key_verification_pattern(secure_key, secure_key_size,
+ &mkvp, keystore->verbose);
+ if (rc)
+ goto out;
+
+ rc = select_cca_adapter_by_mkvp(cca, mkvp, NULL,
+ FLAG_SEL_CCA_MATCH_CUR_MKVP,
+ keystore->verbose);
+ if (rc == -ENOTSUP) {
+ rc = 0;
+ selected = 0;
+ }
+ if (rc != 0) {
+ warnx("No APQN found that is suitable for "
+ "converting the secure AES key '%s'", name);
+ goto out;
+ }
+
+ if (!quiet) {
+ util_print_indented("ATTENTION: Converting a secure key is "
+ "irreversible, and might have an effect "
+ "on the volumes encrypted with it!", 0);
+ _keystore_msg_for_volumes("The following volumes are encrypted "
+ "with this key:", properties, NULL);
+ printf("%s: Convert key '%s [y/N]'? ",
+ program_invocation_short_name, name);
+ if (!prompt_for_yes(keystore->verbose)) {
+ warnx("Operation aborted");
+ rc = -ECANCELED;
+ goto out;
+ }
+ }
+
+ memset(output_key, 0, sizeof(output_key));
+ output_key_size = sizeof(output_key);
+ rc = convert_aes_data_to_cipher_key(cca, secure_key,
+ secure_key_size, output_key,
+ &output_key_size,
+ keystore->verbose);
+ if (rc != 0) {
+ warnx("Converting the secure key '%s' from %s to %s has failed",
+ name, KEY_TYPE_CCA_AESDATA, key_type);
+ if (!selected)
+ print_msg_for_cca_envvars("secure AES key");
+ goto out;
+ }
+
+ rc = restrict_key_export(cca, output_key, output_key_size,
+ keystore->verbose);
+ if (rc != 0) {
+ warnx("Export restricting the converted secure key '%s' has "
+ "failed", name);
+ if (!selected)
+ print_msg_for_cca_envvars("secure AES key");
+ goto out;
+ }
+
+ rc = properties_set2(properties, PROP_NAME_KEY_TYPE, key_type, true);
+ if (rc != 0) {
+ warnx("Invalid characters in key-type");
+ goto out;
+ }
+
+ rc = properties_save(properties, file_names.info_filename, 1);
+ if (rc != 0) {
+ pr_verbose(keystore,
+ "Failed to write key info file '%s': %s",
+ file_names.info_filename, strerror(-rc));
+ goto out;
+ }
+
+ rc = write_secure_key(file_names.skey_filename, output_key,
+ output_key_size, keystore->verbose);
+ if (rc != 0)
+ goto out;
+
+ pr_verbose(keystore, "Secure key '%s' was converted successfully",
+ name);
+
+ util_asprintf(&temp, "The following LUKS2 volumes are "
+ "encrypted with key '%s'. These volumes still contain "
+ "the secure AES volume key of type CCA-AESDATA. To "
+ "change the secure AES volume key in the LUKS2 header, "
+ "run command 'zkey-cryptsetup setkey <device> "
+ "--master-key-file %s':", name,
+ file_names.skey_filename);
+ _keystore_msg_for_volumes(temp, properties, VOLUME_TYPE_LUKS2);
+ free(temp);
+ util_asprintf(&temp, "The following plain mode volumes are "
+ "encrypted with key '%s'. You must adapt the crypttab "
+ "entries for this volumes and change the key size "
+ "parameter to 'size=%u' or run command 'zkey crypttab "
+ "--volumes <device>' for each volume to re-generate the "
+ "crypttab entries:", name, output_key_size * 8, name);
+ _keystore_msg_for_volumes(temp, properties, VOLUME_TYPE_PLAIN);
+ free(temp);
+
+out:
+ _keystore_free_key_filenames(&file_names);
+ if (properties != NULL)
+ properties_free(properties);
+ if (secure_key != NULL)
+ free(secure_key);
+ if (apqns != NULL)
+ free(apqns);
+ if (apqn_list != NULL)
+ str_list_free_string_array(apqn_list);
+ if (cur_key_type != NULL)
+ free(cur_key_type);
+
+ if (rc != 0)
+ pr_verbose(keystore, "Failed to convert key '%s': %s",
+ name, strerror(-rc));
+ return rc;
+}
+
+/**
* Frees a keystore object
*
* @param[in] keystore the key store
--- a/zkey/keystore.h
+++ b/zkey/keystore.h
@@ -81,6 +81,10 @@ int keystore_crypttab(struct keystore *k
const char *volume_type, const char *keyfile,
size_t keyfile_offset, size_t keyfile_size, size_t tries);
+int keystore_convert_key(struct keystore *keystore, const char *name,
+ const char *key_type, bool noapqncheck, bool quiet,
+ int pkey_fd, struct cca_lib *cca);
+
void keystore_free(struct keystore *keystore);
--- a/zkey/zkey.1
+++ b/zkey/zkey.1
@@ -62,7 +62,8 @@ in size.
The \fBzkey\fP tool can operate in two modes. When argument
.I secure\-key\-file
is specified then it operates on the secure key contained in the specified file.
-This applies to commands \fBgenerate\fP, \fBvalidate\fP, and \fBreencipher\fP.
+This applies to commands \fBgenerate\fP, \fBvalidate\fP, \fBreencipher\fP, and
+\fBconvert\fP.
When the
.B \-\-name
option is specified then it operates on a secure key contained in the secure
@@ -680,6 +681,72 @@ questions, you can specify the
option. These options are passed to the generated command(s) and behave in the
same way as with \fBcryptsetup\fP.
.
+.SS "Convert existing AES secure keys from one key type to another type"
+.
+.B zkey
+.BR convert | con
+.I secure\-key\-file
+.RB \-\-key-type | \-K
+.IR type
+.RB [ \-\-no\-apqn\-check ]
+.RB [ \-\-force | \-F ]
+.RB [ \-\-verbose | \-V ]
+.
+.PP
+.B zkey
+.BR convert | con
+.B \-\-name | \-N
+.IR key-name
+.RB \-\-key-type | \-K
+.IR type
+.RB [ \-\-no\-apqn\-check ]
+.RB [ \-\-force | \-F ]
+.RB [ \-\-verbose | \-V ]
+.
+.PP
+Use the
+.B convert
+command to convert an existing secure key from one key type to another type.
+You can convert secure keys of type CCA-AESDATA to type CCA-AESCIPHER only.
+
+.B Note:
+Secure keys converted to type \fBCCA-AESCIPHER\fP require an IBM cryptographic
+adapter in CCA coprocessor mode of version 6 or later, e.g. a CEX6C.
+
+The secure key can either be contained in a file in the file system, or in a
+secure key repository. To convert a secure key contained in a file, specify
+the file name with option \fIsecure\-key\-file\fP. To convert a secure key
+contained in the secure key repository, specify the name of the key
+that is to be converted using the
+.B \-\-name
+option. You cannot use wildcards. The convert command prompts for
+a confirmation, unless you specify the
+.B \-\-force
+option.
+.PP
+.B Note:
+Converting a secure key is irreversible!
+When converting a secure key that is associated with one or multiple volumes,
+a message informs you about the associated volumes. When the secure key is
+converted, this might have an effect on these volumes.
+.P
+For volumes with volume type \fBplain\fP, you must adapt the crypttab entries
+and change the key size parameter to \fBsize=<new-key-size-in-bits>\fP or run
+command \fBzkey crypttab --volumes <device>\fP for each associated volume to
+re-generate the crypttab entries.
+.P
+Associated volumes of type \fLUKS2\fP still contain the secure AES volume key of
+the original type. To change the secure AES volume key in the LUKS2 header,
+run command \fBzkey-cryptsetup setkey <device> --master-key-file
+<converted-key>\fP for each associated volume.
+.
+.P
+.B Note:
+The \fBconvert\fP command requires the CCA host library (libcsulcca.so)
+to be installed. The required CCA IBM cryptographic adapter firmware version
+is 6.3.27 or later. For the supported environments and downloads, see:
+\fIhttp://www.ibm.com/security/cryptocards\fP
+.
.
.
.
@@ -1203,6 +1270,30 @@ cryptsetup command(s).
.
.
.
+.SS "Options for the convert command"
+.TP
+.BR \-N ", " \-\-name\~\fIkey-name\fP
+Specifies the name of the secure key in the secure key repository. You cannot
+use wildcards.
+This option is only used for secure keys contained in the secure key repository.
+.TP
+.BR \-K ", " \-\-key-type\~\fItype\fP
+Specifies the key type to which the secure key shall be converted to.
+Possible values are \fBCCA-AESCIPHER\fP. Secure keys of type \fBCCA-AESCIPHER\fP
+require an IBM cryptographic adapter in CCA coprocessor mode of version 6 or
+later, e.g. a CEX6C.
+.TP
+.BR \-\-no\-apqn\-check
+Do not check if the associated APQNs are available and capable of converting
+the secure key to type CCA-AESCIPHER.
+This option is only used for secure keys contained in the secure key repository.
+.TP
+.BR \-F ", " \-\-force\fP
+The user is prompted to confirm the convertion of a secure key. Use this option
+to convert a secure key without prompting for a confirmation.
+.
+.
+.
.SS "General options"
.TP
.BR \-V ", " \-\-verbose
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -106,6 +106,7 @@ static struct zkey_globals {
#define COMMAND_COPY "copy "
#define COMMAND_CRYPTTAB "crypttab"
#define COMMAND_CRYPTSETUP "cryptsetup"
+#define COMMAND_CONVERT "convert"
#define ZKEY_COMMAND_MAX_LEN 10
@@ -767,6 +768,38 @@ static struct util_opt opt_vec[] = {
/***********************************************************/
{
.flags = UTIL_OPT_FLAG_SECTION,
+ .desc = "OPTIONS",
+ .command = COMMAND_CONVERT,
+ },
+ {
+ .option = { "name", required_argument, NULL, 'N'},
+ .argument = "NAME",
+ .desc = "Name of the secure AES key in the repository that is "
+ "to be converted",
+ .command = COMMAND_CONVERT,
+ },
+ {
+ .option = { "key-type", required_argument, NULL, 'K'},
+ .argument = "type",
+ .desc = "The type of the key to convert the secure key to. "
+ "Possible values are '"KEY_TYPE_CCA_AESCIPHER"'. ",
+ .command = COMMAND_CONVERT,
+ },
+ {
+ .option = {"no-apqn-check", 0, NULL, OPT_NO_APQN_CHECK},
+ .desc = "Do not check if the associated APQN(s) are available",
+ .command = COMMAND_CONVERT,
+ .flags = UTIL_OPT_FLAG_NOSHORT,
+ },
+ {
+ .option = {"force", 0, NULL, 'F'},
+ .desc = "Do not prompt for a confirmation when converting a "
+ "key",
+ .command = COMMAND_CONVERT,
+ },
+ /***********************************************************/
+ {
+ .flags = UTIL_OPT_FLAG_SECTION,
.desc = "COMMON OPTIONS"
},
{
@@ -812,6 +845,7 @@ static int command_rename(void);
static int command_copy(void);
static int command_crypttab(void);
static int command_cryptsetup(void);
+static int command_convert(void);
static struct zkey_command zkey_commands[] = {
{
@@ -946,6 +980,21 @@ static struct zkey_command zkey_commands
.has_options = 1,
.need_keystore = 1,
},
+ {
+ .command = COMMAND_CONVERT,
+ .abbrev_len = 3,
+ .function = command_convert,
+ .need_cca_library = 1,
+ .need_pkey_device = 1,
+ .short_desc = "Convert a secure AES key",
+ .long_desc = "Convert an existing secure AES key that is "
+ "either contained in SECURE-KEY-FILE or is stored "
+ "in the repository from one key type to another "
+ "type.",
+ .has_options = 1,
+ .pos_arg = "[SECURE-KEY-FILE]",
+ .pos_arg_optional = 1,
+ },
{ .command = NULL }
};
@@ -1691,6 +1740,206 @@ static int command_cryptsetup(void)
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
+/*
+ * Command handler for 'convert'.
+ *
+ * Converts secure keys from one key type to another
+ */
+static int command_convert_file(void)
+{
+ u8 output_key[2 * MAX_SECURE_KEY_SIZE];
+ unsigned int output_key_size;
+ size_t secure_key_size;
+ int rc, is_old_mk;
+ int selected = 1;
+ u8 *secure_key;
+ int min_level;
+ u64 mkvp;
+
+ if (g.name != NULL) {
+ warnx("Option '--name|-N' is not valid for "
+ "re-enciphering a key outside of the repository");
+ util_prg_print_parse_error();
+ return EXIT_FAILURE;
+ }
+ if (g.noapqncheck) {
+ warnx("Option '--no-apqn-check' is not valid for "
+ "converting a key outside of the repository");
+ util_prg_print_parse_error();
+ return EXIT_FAILURE;
+ }
+
+ min_level = get_min_card_level_for_keytype(g.key_type);
+ if (min_level < 0) {
+ warnx("Invalid key-type specified: %s", g.key_type);
+ return EXIT_FAILURE;
+ }
+
+ rc = cross_check_apqns(NULL, 0, min_level, true, g.verbose);
+ if (rc == -EINVAL)
+ return EXIT_FAILURE;
+ if (rc != 0 && rc != -ENOTSUP) {
+ warnx("Your master key setup is improper");
+ return EXIT_FAILURE;
+ }
+
+ /* Read the secure key to be re-enciphered */
+ secure_key = read_secure_key(g.pos_arg, &secure_key_size, g.verbose);
+ if (secure_key == NULL)
+ return EXIT_FAILURE;
+
+ rc = validate_secure_key(g.pkey_fd, secure_key, secure_key_size, NULL,
+ &is_old_mk, NULL, g.verbose);
+ if (rc != 0) {
+ warnx("The secure key in file '%s' is not valid", g.pos_arg);
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+
+ rc = get_master_key_verification_pattern(secure_key, secure_key_size,
+ &mkvp, g.verbose);
+ if (rc != 0) {
+ warnx("Failed to get the master key verification pattern: %s",
+ strerror(-rc));
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+
+ if (strcasecmp(get_key_type(secure_key, secure_key_size),
+ g.key_type) == 0) {
+ warnx("The secure key in file '%s' is already of type %s",
+ g.pos_arg, get_key_type(secure_key, secure_key_size));
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+
+ if (is_cca_aes_data_key(secure_key, secure_key_size)) {
+ if (strcasecmp(g.key_type, KEY_TYPE_CCA_AESCIPHER) != 0) {
+ warnx("The secure key in file '%s' can not be "
+ "converted into type %s", g.pos_arg, g.key_type);
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+ } else if (is_cca_aes_cipher_key(secure_key, secure_key_size)) {
+ warnx("The secure key in file '%s' is already of type %s",
+ g.pos_arg, KEY_TYPE_CCA_AESCIPHER);
+ rc = EXIT_FAILURE;
+ goto out;
+ } else {
+ warnx("The secure key in file '%s' has an unsupported key type",
+ g.pos_arg);
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+
+ rc = select_cca_adapter_by_mkvp(&g.cca, mkvp, NULL,
+ FLAG_SEL_CCA_MATCH_CUR_MKVP,
+ g.verbose);
+ if (rc == -ENOTSUP) {
+ rc = 0;
+ selected = 0;
+ }
+ if (rc != 0) {
+ warnx("No APQN found that is suitable for "
+ "converting the secure AES key in file '%s'", g.pos_arg);
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+
+ if (!g.force) {
+ util_print_indented("ATTENTION: Converting a secure key is "
+ "irreversible, and might have an effect "
+ "on the volumes encrypted with it!", 0);
+ printf("%s: Convert key in file '%s' [y/N]? ",
+ program_invocation_short_name, g.pos_arg);
+ if (!prompt_for_yes(g.verbose)) {
+ warnx("Operation aborted");
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+ }
+
+ memset(output_key, 0, sizeof(output_key));
+ output_key_size = sizeof(output_key);
+ rc = convert_aes_data_to_cipher_key(&g.cca, secure_key, secure_key_size,
+ output_key, &output_key_size,
+ g.verbose);
+ if (rc != 0) {
+ warnx("Converting the secure key from %s to %s has failed",
+ get_key_type(secure_key, secure_key_size), g.key_type);
+ if (!selected)
+ print_msg_for_cca_envvars("secure AES key");
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+
+ rc = restrict_key_export(&g.cca, output_key, output_key_size,
+ g.verbose);
+ if (rc != 0) {
+ warnx("Export restricting the converted secure key has failed");
+ if (!selected)
+ print_msg_for_cca_envvars("secure AES key");
+ rc = EXIT_FAILURE;
+ goto out;
+ }
+
+ pr_verbose("Secure key was converted successfully");
+
+ /* Write the converted secure key */
+ rc = write_secure_key(g.outputfile ? g.outputfile : g.pos_arg,
+ output_key, output_key_size, g.verbose);
+ if (rc != 0)
+ rc = EXIT_FAILURE;
+out:
+ free(secure_key);
+ return rc;
+}
+
+/*
+ * Command handler for 'convert in repository'.
+ *
+ * Converts secure keys from one key type to another
+ */
+static int command_convert_repository(void)
+{
+ int rc;
+
+ if (g.name == NULL) {
+ misc_print_required_parm("--name/-N");
+ return EXIT_FAILURE;
+ }
+
+ rc = keystore_convert_key(g.keystore, g.name, g.key_type, g.noapqncheck,
+ g.force, g.pkey_fd, &g.cca);
+
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+/*
+ * Command handler for 'convert'.
+ *
+ * Converts secure keys from one key type to another
+ */
+static int command_convert(void)
+{
+ if (g.key_type == NULL) {
+ misc_print_required_parm("--key-type/-K");
+ return EXIT_FAILURE;
+ }
+ if (strcasecmp(g.key_type, KEY_TYPE_CCA_AESCIPHER) != 0) {
+ warnx("Secure keys can only be converted into key type %s",
+ KEY_TYPE_CCA_AESCIPHER);
+ return EXIT_FAILURE;
+ }
+
+ if (g.pos_arg != NULL)
+ return command_convert_file();
+ else
+ return command_convert_repository();
+
+ return EXIT_SUCCESS;
+}
+
/**
* Opens the keystore. The keystore directory is either the
* default directory or as specified in an environment variable

View File

@ -1,51 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl/libc: include 's390.h'
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: b0f82d22f9f60a0a8db1976751aa5a875e7c5f80
Problem-ID: VS1804
Upstream-Description:
zipl/libc: include 's390.h'
Include 'boot/s390.h' in 'libc.c' as `PAGE_SIZE` is used there and
move the 'libc.h' include directive to the top.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/libc.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/zipl/boot/libc.c
+++ b/zipl/boot/libc.c
@@ -9,12 +9,14 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
+#include "libc.h"
+
#include <stdarg.h>
#include "lib/zt_common.h"
+#include "boot/s390.h"
#include "error.h"
-#include "libc.h"
#include "sclp.h"
extern char __heap_start[];

View File

@ -1,63 +0,0 @@
Subject: zkey: Allow 'zkey-cryptsetup setkey' to set different key types
From: Ingo Franzki <ifranzki@linux.ibm.com>
Summary: zkey: Add support for CCA AES CIPHER keys
Description: With CCA 5 there is a new secure key type, the so called
variable length symmetric cipher key token. This token format
can hold AES keys with size 128, 192 and 256 bits together
with additional attributes cryptographic bound to the key
token. The attributes may limit the usage of the key, for
example restrict export or usability scope. So this key type
is considered to be even more secure than the traditional
secure key token. This key token type is also called "CCA
AES CIPHER key", where the formerly used key token is called
"CCA AES DATA key".
The zkey as well as the zkey-cryptsetup tools are enhanced
to support AES CIPHER keys. That is, zkey can manage AES DATA
keys, as well as AES CIPHER keys. The key type must be specified
at key generation time, the default is to generate AED DATA
keys.
Upstream-ID: bc987c8d18ddeb6fec46113a7fe7588555b592e7
Problem-ID: SEC1717
Upstream-Description:
zkey: Allow 'zkey-cryptsetup setkey' to set different key types
When a secure key has been converted from type CCA-AESDATA to type
CCA-AESCIPHER, the secure key stored in the LUKS2 header of a volume
encrypted with that key should also changed.
Command 'zkey-cryptsetup setkey' allows to set (replace) the volume
key in the LUKS2 header. It now accepts keys to be set that have
a different size of the original volume keys. CCA-AESCIPHER keys
are larger than CCA-AESDATA keys.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
zkey/zkey-cryptsetup.c | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
--- a/zkey/zkey-cryptsetup.c
+++ b/zkey/zkey-cryptsetup.c
@@ -2169,14 +2169,7 @@ static int command_setkey(void)
if (rc < 0)
goto out;
- if (keysize != newkey_size) {
- warnx("The secure key in file '%s' has an invalid size",
- g.master_key_file);
- rc = -EINVAL;
- goto out;
- }
-
- if (memcmp(newkey, key, keysize) == 0) {
+ if (keysize == newkey_size && memcmp(newkey, key, keysize) == 0) {
warnx("The secure key in file '%s' is equal to the current "
"volume key, setkey is ignored", g.master_key_file);
rc = 0;

View File

@ -1,69 +0,0 @@
Subject: [PATCH] [FEAT VS1804] include/boot/s390.h: move panic and panic_notify to libc.h
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 2568863f581cff9bf3b1e27c2d2917b5ae3b5177
Problem-ID: VS1804
Upstream-Description:
include/boot/s390.h: move panic and panic_notify to libc.h
... as this code is not s390 specific and not every user of s390.h
wants to implement `panic_notify`.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
include/boot/s390.h | 9 ---------
zipl/boot/libc.h | 8 ++++++++
2 files changed, 8 insertions(+), 9 deletions(-)
--- a/include/boot/s390.h
+++ b/include/boot/s390.h
@@ -201,15 +201,6 @@ struct _lowcore {
#define S390_lowcore (*((struct _lowcore *) 0))
-void panic_notify(unsigned long reason);
-
-#define panic(reason, x...) \
-do { \
- printf(x); \
- panic_notify(reason); \
- libc_stop(reason); \
-} while (0)
-
static __always_inline int page_is_valid(unsigned long addr)
{
unsigned long tmp;
--- a/zipl/boot/libc.h
+++ b/zipl/boot/libc.h
@@ -61,6 +61,14 @@ void libc_stop(unsigned long);
void start(void);
void pgm_check_handler(void);
void pgm_check_handler_fn(void);
+void panic_notify(unsigned long reason);
+
+#define panic(reason, ...) \
+ do { \
+ printf(__VA_ARGS__); \
+ panic_notify(reason); \
+ libc_stop(reason); \
+ } while (0)
static inline int isdigit(int c)
{

View File

@ -1,73 +0,0 @@
Subject: [PATCH] [FEAT VS1804] include/boot/s390.h: fixes for -Werror=sign-conversion
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 305235a7bce814f71ec113a612b6117c96894e23
Problem-ID: VS1804
Upstream-Description:
include/boot/s390.h: fixes for -Werror=sign-conversion
Errors fixed:
../../include/boot/s390.h: In function '__stfle_asm':
../../include/boot/s390.h:424:41: error: conversion to 'long unsigned int' from 'int' may change the sign of the result [-Werror=sign-conversion]
register unsigned long reg0 asm("0") = size - 1;
../../include/boot/s390.h: In function 'stfle':
../../include/boot/s390.h:453:31: error: conversion to 'long unsigned int' from 'int' may change the sign of the result [-Werror=sign-conversion]
nr = MIN((nr + 1) * 8, size * 8UL);
../../include/boot/s390.h: In function 'diag308':
../../include/boot/s390.h:296:9: error: conversion from 'long unsigned int' to 'int' may change value [-Werror=conversion]
return _rc;
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
include/boot/s390.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/include/boot/s390.h
+++ b/include/boot/s390.h
@@ -269,7 +269,7 @@ enum diag308_subcode {
DIAG308_STORE = 6,
};
-static __always_inline int diag308(unsigned long subcode, void *addr)
+static __always_inline unsigned long diag308(unsigned long subcode, void *addr)
{
register unsigned long _addr asm("0") = (unsigned long) addr;
register unsigned long _rc asm("1") = 0;
@@ -403,7 +403,7 @@ static __always_inline int test_facility
return __test_facility(nr, &S390_lowcore.stfle_fac_list);
}
-static __always_inline unsigned long __stfle_asm(uint64_t *stfle_fac_list, int size)
+static __always_inline unsigned long __stfle_asm(uint64_t *stfle_fac_list, unsigned int size)
{
register unsigned long reg0 asm("0") = size - 1;
@@ -420,7 +420,7 @@ static __always_inline unsigned long __s
* @stfle_fac_list: array where facility list can be stored
* @size: size of passed in array in double words
*/
-static __always_inline void stfle(uint64_t *stfle_fac_list, int size)
+static __always_inline void stfle(uint64_t *stfle_fac_list, unsigned int size)
{
unsigned long nr;

View File

@ -1,640 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl: refactor all EBCDIC code into separate files
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: a37170b8bec07a0ffc3270a4c78124e1117f0337
Problem-ID: VS1804
Upstream-Description:
zipl: refactor all EBCDIC code into separate files
This allows the reuse of the code later in sclp.c. While at it, also
declare @source parameter of `ebcdic_to_ascii` function as `const` and
rename all `ebc_` function name prefixes into `ebcdic_`. Move
conversion tables to separate file so it only gets linked into loaders
that need it.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/Makefile | 16 ++--
zipl/boot/ebcdic.c | 30 ++++++++
zipl/boot/ebcdic.h | 45 ++++++++++++
zipl/boot/ebcdic_conv.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++
zipl/boot/ebcdic_conv.h | 21 ++++++
zipl/boot/libc.c | 19 -----
zipl/boot/libc.h | 25 -------
zipl/boot/menu.c | 9 +-
zipl/boot/stage3.c | 156 --------------------------------------------
9 files changed, 280 insertions(+), 208 deletions(-)
--- a/zipl/boot/Makefile
+++ b/zipl/boot/Makefile
@@ -28,22 +28,22 @@ all: data.o data.h tape0.bin stage3.bin
eckd2dump_sv.exec: \
head.o stage2dump.o cio.o eckd2dump.o eckd2dump_sv.o \
- libc.o sclp.o entry.o
+ libc.o ebcdic.o sclp.o entry.o
eckd2dump_mv.exec: \
head.o stage2dump.o cio.o eckd2dump.o eckd2dump_mv.o \
- libc.o sclp.o entry.o
+ libc.o ebcdic.o sclp.o entry.o
fba2dump.exec: \
head.o stage2dump.o cio.o fba2dump.o \
- libc.o sclp.o entry.o
+ libc.o ebcdic.o sclp.o entry.o
tape2dump.exec: \
head.o stage2dump.o cio.o tape2dump.o \
- libc.o sclp.o entry.o
-eckd2.exec: head.o stage2.o cio.o eckd2.o libc.o menu.o sclp.o \
+ libc.o ebcdic.o sclp.o entry.o
+eckd2.exec: head.o stage2.o cio.o eckd2.o libc.o ebcdic.o menu.o sclp.o \
kdump2.o kdump.o entry.o
-fba2.exec: head.o stage2.o cio.o fba2.o libc.o menu.o sclp.o \
+fba2.exec: head.o stage2.o cio.o fba2.o libc.o ebcdic.o menu.o sclp.o \
kdump2.o kdump.o entry.o
-stage3.exec: head.o stage3.o kdump3.o libc.o sclp.o sclp_stage3.o \
- kdump.o entry.o stage3.lds
+stage3.exec: head.o stage3.o kdump3.o libc.o ebcdic.o ebcdic_conv.o sclp.o \
+ sclp_stage3.o kdump.o entry.o stage3.lds
%.exec: %.o
STAGE=$$( \
--- /dev/null
+++ b/zipl/boot/ebcdic.c
@@ -0,0 +1,30 @@
+/*
+ * EBCDIC specific functions
+ *
+ * Copyright IBM Corp. 2013, 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ *
+ */
+
+#include "ebcdic.h"
+
+
+/*
+ * Convert ebcdic string to number with given base
+ */
+unsigned long ebcdic_strtoul(char *nptr, char **endptr, int base)
+{
+ unsigned long val = 0;
+
+ while (ebcdic_isdigit(*nptr)) {
+ if (val != 0)
+ val *= base;
+ val += *nptr - 0xf0;
+ nptr++;
+ }
+ if (endptr)
+ *endptr = (char *)nptr;
+ return val;
+}
--- /dev/null
+++ b/zipl/boot/ebcdic.h
@@ -0,0 +1,45 @@
+/*
+ * EBCDIC specific functions
+ *
+ * Copyright IBM Corp. 2013, 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ *
+ */
+
+#ifndef EBCDIC_H
+#define EBCDIC_H
+
+#include "lib/zt_common.h"
+
+
+#ifndef __ASSEMBLER__
+
+unsigned long ebcdic_strtoul(char *, char **, int);
+
+static __always_inline int ecbdic_isspace(char c)
+{
+ return (c == 0x40) || (c == 0x05) || (c == 0x15) || (c == 0x25) ||
+ (c == 0x0b) || (c == 0x0c) || (c == 0x0d);
+}
+
+static __always_inline int ebcdic_isdigit(char c)
+{
+ return (c >= 0xf0) && (c <= 0xf9);
+}
+
+static __always_inline int ebcdic_isupper(char c)
+{
+ return (c >= 0xC1 && c <= 0xC9) || (c >= 0xD1 && c <= 0xD9) ||
+ (c >= 0xE2 && c <= 0xE9);
+}
+
+static __always_inline char ebcdic_tolower(char c)
+{
+ if (ebcdic_isupper(c))
+ c -= 0x40;
+ return c;
+}
+#endif /* __ASSEMBLER__ */
+#endif /* EBCDIC_H */
--- /dev/null
+++ b/zipl/boot/ebcdic_conv.c
@@ -0,0 +1,167 @@
+/*
+ * EBCDIC conversion functions
+ *
+ * Copyright IBM Corp. 2013, 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ *
+ */
+
+#include "ebcdic_conv.h"
+#include "libc.h"
+#include "boot/s390.h"
+
+
+static unsigned char ebcdic_037[256] = {
+/* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */
+ 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
+/* 0x08 -GE -SPS -RPT VT FF CR SO SI */
+ 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+/* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC
+ -ENP ->LF */
+ 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
+/* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB
+ -IUS */
+ 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+/* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC
+ -INP */
+ 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
+/* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL
+ -SW */
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
+/* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */
+ 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
+/* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */
+ 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
+/* 0x40 SP RSP ä ---- */
+ 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
+/* 0x48 . < ( + | */
+ 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
+/* 0x50 & ---- */
+ 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
+/* 0x58 ß ! $ * ) ; */
+ 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
+/* 0x60 - / ---- Ä ---- ---- ---- */
+ 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
+/* 0x68 ---- , % _ > ? */
+ 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+/* 0x70 --- ---- ---- ---- ---- ---- ---- */
+ 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+/* 0x78 * ` : # @ ' = " */
+ 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+/* 0x80 * a b c d e f g */
+ 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+/* 0x88 h i ---- ---- ---- */
+ 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
+/* 0x90 ° j k l m n o p */
+ 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+/* 0x98 q r ---- ---- */
+ 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
+/* 0xA0 ~ s t u v w x */
+ 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+/* 0xA8 y z ---- ---- ---- ---- */
+ 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
+/* 0xB0 ^ ---- § ---- */
+ 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
+/* 0xB8 ---- [ ] ---- ---- ---- ---- */
+ 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
+/* 0xC0 { A B C D E F G */
+ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+/* 0xC8 H I ---- ö ---- */
+ 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
+/* 0xD0 } J K L M N O P */
+ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+/* 0xD8 Q R ---- ü */
+ 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
+/* 0xE0 \ S T U V W X */
+ 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+/* 0xE8 Y Z ---- Ö ---- ---- ---- */
+ 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
+/* 0xF0 0 1 2 3 4 5 6 7 */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+/* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */
+ 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
+};
+
+static unsigned char ebcdic_500[256] = {
+/* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */
+ 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
+/* 0x08 -GE -SPS -RPT VT FF CR SO SI */
+ 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+/* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC
+ -ENP ->LF */
+ 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
+/* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB
+ -IUS */
+ 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+/* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC
+ -INP */
+ 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
+/* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL
+ -SW */
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
+/* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */
+ 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
+/* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */
+ 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
+/* 0x40 SP RSP ä ---- */
+ 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
+/* 0x48 . < ( + | */
+ 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
+/* 0x50 & ---- */
+ 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
+/* 0x58 ß ! $ * ) ; */
+ 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
+/* 0x60 - / ---- Ä ---- ---- ---- */
+ 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
+/* 0x68 ---- , % _ > ? */
+ 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+/* 0x70 --- ---- ---- ---- ---- ---- ---- */
+ 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+/* 0x78 * ` : # @ ' = " */
+ 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+/* 0x80 * a b c d e f g */
+ 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+/* 0x88 h i ---- ---- ---- */
+ 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
+/* 0x90 ° j k l m n o p */
+ 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+/* 0x98 q r ---- ---- */
+ 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
+/* 0xA0 ~ s t u v w x */
+ 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+/* 0xA8 y z ---- ---- ---- ---- */
+ 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
+/* 0xB0 ^ ---- § ---- */
+ 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
+/* 0xB8 ---- [ ] ---- ---- ---- ---- */
+ 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
+/* 0xC0 { A B C D E F G */
+ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+/* 0xC8 H I ---- ö ---- */
+ 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
+/* 0xD0 } J K L M N O P */
+ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+/* 0xD8 Q R ---- ü */
+ 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
+/* 0xE0 \ S T U V W X */
+ 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+/* 0xE8 Y Z ---- Ö ---- ---- ---- */
+ 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
+/* 0xF0 0 1 2 3 4 5 6 7 */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+/* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */
+ 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
+};
+
+void ebcdic_to_ascii(unsigned char *target, const unsigned char *source,
+ unsigned int l)
+{
+ unsigned char *ebc;
+ unsigned int i;
+
+ ebc = is_zvm() ? ebcdic_037 : ebcdic_500;
+ for (i = 0; i < l; i++)
+ target[i] = ebc[source[i]];
+}
--- /dev/null
+++ b/zipl/boot/ebcdic_conv.h
@@ -0,0 +1,21 @@
+/*
+ * EBCDIC conversion functions
+ *
+ * Copyright IBM Corp. 2013, 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ *
+ */
+
+#ifndef EBCDIC_CONV_H
+#define EBCDIC_CONV_H
+
+
+#ifndef __ASSEMBLER__
+
+void ebcdic_to_ascii(unsigned char *target, const unsigned char *source,
+ unsigned int l);
+
+#endif /* __ASSEMBLER__ */
+#endif /* EBCDIC_CONV_H */
--- a/zipl/boot/libc.c
+++ b/zipl/boot/libc.c
@@ -18,6 +18,7 @@
#include "error.h"
#include "sclp.h"
+#include "ebcdic.h"
extern char __heap_start[];
extern char __heap_stop[];
@@ -129,24 +130,6 @@ int strncmp(const char *s1, const char *
return 0;
}
-/*
- * Convert ebcdic string to number with given base
- */
-unsigned long ebcstrtoul(char *nptr, char **endptr, int base)
-{
- unsigned long val = 0;
-
- while (ebc_isdigit(*nptr)) {
- if (val != 0)
- val *= base;
- val += *nptr - 0xf0;
- nptr++;
- }
- if (endptr)
- *endptr = (char *) nptr;
- return val;
-}
-
static int skip_atoi(const char **c)
{
int i = 0;
--- a/zipl/boot/libc.h
+++ b/zipl/boot/libc.h
@@ -51,7 +51,6 @@ void *memmove(void *, const void *, unsi
void *memset(void *, int c, unsigned long);
char *strcat(char *, const char *);
int strncmp(const char *, const char *, unsigned long);
-unsigned long ebcstrtoul(char *, char **, int);
int strlen(const char *);
char *strcpy(char *, const char *);
unsigned long get_zeroed_page(void);
@@ -80,28 +79,4 @@ static inline int isspace(char c)
return (c == 32) || (c >= 9 && c <= 13);
}
-static inline int ebc_isspace(char c)
-{
- return (c == 0x40) || (c == 0x05) || (c == 0x15) || (c == 0x25) ||
- (c == 0x0b) || (c == 0x0c) || (c == 0x0d);
-}
-
-static inline int ebc_isdigit(char c)
-{
- return (c >= 0xf0) && (c <= 0xf9);
-}
-
-static inline int ebc_isupper(char c)
-{
- return (c >= 0xC1 && c <= 0xC9) || (c >= 0xD1 && c <= 0xD9) ||
- (c >= 0xE2 && c <= 0xE9);
-}
-
-static inline char ebc_tolower(char c)
-{
- if (ebc_isupper(c))
- c -= 0x40;
- return c;
-}
-
#endif /* LIBC_H */
--- a/zipl/boot/menu.c
+++ b/zipl/boot/menu.c
@@ -12,6 +12,7 @@
#include "libc.h"
#include "menu.h"
#include "sclp.h"
+#include "ebcdic.h"
static const char *msg_econfig = "Error: undefined configuration\n";
@@ -55,8 +56,8 @@ static int menu_read(void)
/* input under zVM needs to be converted to lower case */
if (is_zvm())
for (i = 0; i < count; i++)
- temp_area[i] = ebc_tolower(temp_area[i]);
- value = ebcstrtoul((char *)temp_area, &endptr, 10);
+ temp_area[i] = ebcdic_tolower(temp_area[i]);
+ value = ebcdic_strtoul((char *)temp_area, &endptr, 10);
if ((endptr != temp_area) && (value < BOOT_MENU_ENTRIES - 1) &&
(__stage2_params.config[value] != 0)) {
@@ -112,7 +113,7 @@ static int menu_param(unsigned long *val
int i;
if (!sclp_param(loadparm))
- *value = ebcstrtoul(loadparm, &endptr, 10);
+ *value = ebcdic_strtoul(loadparm, &endptr, 10);
/* got number, done */
if (endptr != loadparm)
@@ -121,7 +122,7 @@ static int menu_param(unsigned long *val
/* no number, check for keyword */
i = 0;
/* skip leading whitespaces */
- while ((i < PARAM_SIZE) && ebc_isspace(loadparm[i]))
+ while ((i < PARAM_SIZE) && ecbdic_isspace(loadparm[i]))
i++;
if (!strncmp(&loadparm[i], "PROMPT", 6)) {
--- a/zipl/boot/stage3.c
+++ b/zipl/boot/stage3.c
@@ -12,9 +12,12 @@
#include "libc.h"
#include "boot/sigp.h"
#include "boot/s390.h"
+#include "boot/sigp.h"
#include "stage3.h"
#include "error.h"
#include "zipl.h"
+#include "ebcdic.h"
+#include "ebcdic_conv.h"
#define for_each_rb_entry(entry, rb) \
for (entry = rb->entries; \
@@ -24,159 +27,6 @@
static const char *msg_sipl_inval = "Secure boot failure: invalid load address";
static const char *msg_sipl_unverified = "Secure boot failure: unverified load address";
-static unsigned char ebc_037[256] = {
-/* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */
- 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
-/* 0x08 -GE -SPS -RPT VT FF CR SO SI */
- 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-/* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC
- -ENP ->LF */
- 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
-/* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB
- -IUS */
- 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-/* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC
- -INP */
- 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
-/* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL
- -SW */
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
-/* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */
- 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
-/* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */
- 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
-/* 0x40 SP RSP ä ---- */
- 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
-/* 0x48 . < ( + | */
- 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
-/* 0x50 & ---- */
- 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
-/* 0x58 ß ! $ * ) ; */
- 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
-/* 0x60 - / ---- Ä ---- ---- ---- */
- 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
-/* 0x68 ---- , % _ > ? */
- 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
-/* 0x70 --- ---- ---- ---- ---- ---- ---- */
- 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-/* 0x78 * ` : # @ ' = " */
- 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
-/* 0x80 * a b c d e f g */
- 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-/* 0x88 h i ---- ---- ---- */
- 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
-/* 0x90 ° j k l m n o p */
- 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
-/* 0x98 q r ---- ---- */
- 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
-/* 0xA0 ~ s t u v w x */
- 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-/* 0xA8 y z ---- ---- ---- ---- */
- 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
-/* 0xB0 ^ ---- § ---- */
- 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
-/* 0xB8 ---- [ ] ---- ---- ---- ---- */
- 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
-/* 0xC0 { A B C D E F G */
- 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
-/* 0xC8 H I ---- ö ---- */
- 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
-/* 0xD0 } J K L M N O P */
- 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
-/* 0xD8 Q R ---- ü */
- 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
-/* 0xE0 \ S T U V W X */
- 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
-/* 0xE8 Y Z ---- Ö ---- ---- ---- */
- 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
-/* 0xF0 0 1 2 3 4 5 6 7 */
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-/* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */
- 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
-};
-
-static unsigned char ebc_500[256] = {
-/* 0x00 NUL SOH STX ETX *SEL HT *RNL DEL */
- 0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
-/* 0x08 -GE -SPS -RPT VT FF CR SO SI */
- 0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-/* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC
- -ENP ->LF */
- 0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
-/* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB
- -IUS */
- 0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-/* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC
- -INP */
- 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
-/* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL
- -SW */
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
-/* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */
- 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
-/* 0x38 -SBS -IT -RFF -CU3 DC4 NAK ---- SUB */
- 0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
-/* 0x40 SP RSP ä ---- */
- 0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
-/* 0x48 . < ( + | */
- 0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
-/* 0x50 & ---- */
- 0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
-/* 0x58 ß ! $ * ) ; */
- 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
-/* 0x60 - / ---- Ä ---- ---- ---- */
- 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
-/* 0x68 ---- , % _ > ? */
- 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
-/* 0x70 --- ---- ---- ---- ---- ---- ---- */
- 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-/* 0x78 * ` : # @ ' = " */
- 0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
-/* 0x80 * a b c d e f g */
- 0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-/* 0x88 h i ---- ---- ---- */
- 0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
-/* 0x90 ° j k l m n o p */
- 0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
-/* 0x98 q r ---- ---- */
- 0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
-/* 0xA0 ~ s t u v w x */
- 0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-/* 0xA8 y z ---- ---- ---- ---- */
- 0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
-/* 0xB0 ^ ---- § ---- */
- 0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
-/* 0xB8 ---- [ ] ---- ---- ---- ---- */
- 0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
-/* 0xC0 { A B C D E F G */
- 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
-/* 0xC8 H I ---- ö ---- */
- 0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
-/* 0xD0 } J K L M N O P */
- 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
-/* 0xD8 Q R ---- ü */
- 0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
-/* 0xE0 \ S T U V W X */
- 0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
-/* 0xE8 Y Z ---- Ö ---- ---- ---- */
- 0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
-/* 0xF0 0 1 2 3 4 5 6 7 */
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-/* 0xF8 8 9 ---- ---- Ü ---- ---- ---- */
- 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
-};
-
-static void ebcdic_to_ascii(unsigned char *target, unsigned char *source,
- unsigned int l)
-{
- unsigned char *ebc;
- unsigned int i;
-
- ebc = is_zvm() ? ebc_037 : ebc_500;
- for (i = 0; i < l; i++)
- target[i] = ebc[source[i]];
-}
-
static inline void __noreturn start_kernel(void)
{
struct psw_t *psw = &S390_lowcore.program_new_psw;

View File

@ -1,79 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl/sclp: add macros for the control-program masks
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 303a3707e2e59e0ad581876db426a52fffa606b0
Problem-ID: VS1804
Upstream-Description:
zipl/sclp: add macros for the control-program masks
Add macros for the control-program masks and use them.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/sclp.c | 16 ++++++++--------
zipl/boot/sclp.h | 6 ++++++
2 files changed, 14 insertions(+), 8 deletions(-)
--- a/zipl/boot/sclp.c
+++ b/zipl/boot/sclp.c
@@ -126,20 +126,20 @@ int sclp_setup(int initialise)
switch (initialise) {
case SCLP_INIT:
- sccb->receive_mask = 0x80000000;
- sccb->send_mask = 0x40000000;
+ sccb->receive_mask = SCLP_EVENT_MASK_OPCMD;
+ sccb->send_mask = SCLP_EVENT_MASK_MSG;
break;
case SCLP_DISABLE:
- sccb->receive_mask = 0x0;
- sccb->send_mask = 0x0;
+ sccb->receive_mask = SCLP_EVENT_MASK_DISABLE;
+ sccb->send_mask = SCLP_EVENT_MASK_DISABLE;
break;
case SCLP_HSA_INIT:
- sccb->receive_mask = 0x0;
- sccb->send_mask = 0x40000010;
+ sccb->receive_mask = SCLP_EVENT_MASK_DISABLE;
+ sccb->send_mask = SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_SDIAS;
break;
case SCLP_HSA_INIT_ASYNC:
- sccb->receive_mask = 0x00000010;
- sccb->send_mask = 0x40000010;
+ sccb->receive_mask = SCLP_EVENT_MASK_SDIAS;
+ sccb->send_mask = SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_SDIAS;
break;
}
--- a/zipl/boot/sclp.h
+++ b/zipl/boot/sclp.h
@@ -28,6 +28,12 @@
#define SCLP_CMD_READ_INFO2 0x00020001
#define SCLP_CMD_READ_DATA 0x00770005
+/* SCLP event masks */
+#define SCLP_EVENT_MASK_DISABLE 0x00000000
+#define SCLP_EVENT_MASK_SDIAS 0x00000010
+#define SCLP_EVENT_MASK_MSG 0x40000000
+#define SCLP_EVENT_MASK_OPCMD 0x80000000
+
#define PSW_EXT_MASK 0x00080000ULL
#define PSW_EXT_ADDR 0x80000000ULL
#define PSW_WAIT_MASK 0x010a0000ULL

View File

@ -1,163 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl/sclp: add `sclp_print_ascii`
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: f99560f734e8101a0e8195d73e3350d9211335b8
Problem-ID: VS1804
Upstream-Description:
zipl/sclp: add `sclp_print_ascii`
Add `sclp_print_ascii` function that can be used to print output on
the SCLP ASCII console. This would increase the size of the
loaders (e.g. eckd2.bin and fba2.bin) and therefore might break the
compilation. In order to avoid that add a macro 'ENABLE_SCLP_ASCII'
which must be defined by the users of the `sclp_print_ascii` function.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/sclp.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
zipl/boot/sclp.h | 20 +++++++++++++++++++-
2 files changed, 69 insertions(+), 1 deletion(-)
--- a/zipl/boot/sclp.c
+++ b/zipl/boot/sclp.c
@@ -13,6 +13,10 @@
#include "error.h"
#include "boot/s390.h"
#include "sclp.h"
+#include "ebcdic.h"
+#ifdef ENABLE_SCLP_ASCII
+# include "ebcdic_conv.h"
+#endif /* ENABLE_SCLP_ASCII */
/* Perform service call. Return 0 on success, non-zero otherwise. */
static int sclp_service_call(unsigned int command, void *sccb)
@@ -133,6 +137,10 @@ int sclp_setup(int initialise)
sccb->receive_mask = SCLP_EVENT_MASK_DISABLE;
sccb->send_mask = SCLP_EVENT_MASK_DISABLE;
break;
+ case SCLP_LINE_ASCII_INIT:
+ sccb->receive_mask = SCLP_EVENT_MASK_DISABLE;
+ sccb->send_mask = SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_ASCII;
+ break;
case SCLP_HSA_INIT:
sccb->receive_mask = SCLP_EVENT_MASK_DISABLE;
sccb->send_mask = SCLP_EVENT_MASK_MSG | SCLP_EVENT_MASK_SDIAS;
@@ -161,6 +169,48 @@ out_free_page:
return rc;
}
+#ifdef ENABLE_SCLP_ASCII
+/* Content of @buffer must be EBCDIC encoded. The function used for
+ * the conversion `ebcdic_to_ascii` differentiates whether the code
+ * runs on z/VM or not and then selects the appropriate EBCDIC
+ * coding.
+ */
+int sclp_print_ascii(const char *buffer)
+{
+ struct write_sccb *sccb = NULL;
+ int rc, str_len = strlen(buffer);
+ unsigned long data_len = str_len + 1;
+
+ /* don't overflow the sccb buffer */
+ if (data_len > SCCB_MAX_DATA_LEN)
+ data_len = SCCB_MAX_DATA_LEN;
+
+ sccb = (void *)get_zeroed_page();
+ sccb->header.length = sizeof(struct write_sccb) - sizeof(struct mdb)
+ + data_len;
+ sccb->header.function_code = SCLP_FC_NORMAL_WRITE;
+ sccb->msg_buf.header.length = sizeof(struct msg_buf) - sizeof(struct mdb)
+ + data_len;
+ sccb->msg_buf.header.type = SCLP_EVENT_DATA_ASCII;
+ sccb->msg_buf.header.flags = 0;
+ ebcdic_to_ascii(sccb->msg_buf.data,
+ (const unsigned char *)buffer,
+ data_len - 1);
+ sccb->msg_buf.data[data_len - 1] = '\0';
+
+ /* SCLP command for write data */
+ rc = start_sclp(SCLP_CMD_WRITE_DATA, sccb);
+ if (rc || sccb->header.response_code != 0x20) {
+ rc = 1;
+ goto out_free_page;
+ }
+ rc = 0;
+out_free_page:
+ free_page((unsigned long) sccb);
+ return rc;
+}
+#endif /* ENABLE_SCLP_ASCII */
+
int sclp_print(char *buffer)
{
struct write_sccb *sccb;
--- a/zipl/boot/sclp.h
+++ b/zipl/boot/sclp.h
@@ -28,9 +28,16 @@
#define SCLP_CMD_READ_INFO2 0x00020001
#define SCLP_CMD_READ_DATA 0x00770005
+/* SCLP function codes */
+#define SCLP_FC_NORMAL_WRITE 0
+
+/* SCLP event data types */
+#define SCLP_EVENT_DATA_ASCII 0x1a
+
/* SCLP event masks */
#define SCLP_EVENT_MASK_DISABLE 0x00000000
#define SCLP_EVENT_MASK_SDIAS 0x00000010
+#define SCLP_EVENT_MASK_ASCII 0x00000040
#define SCLP_EVENT_MASK_MSG 0x40000000
#define SCLP_EVENT_MASK_OPCMD 0x80000000
@@ -46,6 +53,11 @@
#define SCLP_DISABLE 0x1
#define SCLP_HSA_INIT 0x2
#define SCLP_HSA_INIT_ASYNC 0x3
+#define SCLP_LINE_ASCII_INIT 0x4
+
+#define SCCB_SIZE PAGE_SIZE
+#define SCCB_MAX_DATA_LEN (SCCB_SIZE - sizeof(struct sccb_header) \
+ - sizeof(struct evbuf_header))
typedef uint32_t sccb_mask_t;
@@ -114,7 +126,10 @@ struct mdb {
struct msg_buf {
struct evbuf_header header;
- struct mdb mdb;
+ union {
+ struct mdb mdb;
+ uint8_t data[0];
+ };
} __packed;
struct write_sccb {
@@ -164,6 +179,9 @@ struct read_sccb {
int start_sclp(unsigned int, void *);
int sclp_setup(int);
int sclp_print(char *);
+# ifdef ENABLE_SCLP_ASCII
+int sclp_print_ascii(const char *);
+# endif /* ENABLE_SCLP_ASCII */
int sclp_param(char *);
int sclp_read(unsigned long, void *, int *);
int sclp_read_info(struct read_info_sccb *sccb);

View File

@ -1,47 +0,0 @@
Subject: [PATCH] [FEAT VS1804] zipl/libc: printf: print on linemode and ASCII console
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: e51663bbca8770c1f7986dac47a59193dbf96010
Problem-ID: VS1804
Upstream-Description:
zipl/libc: printf: print on linemode and ASCII console
... if the `ENABLE_SCLP_ASCII` macro is defined.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
zipl/boot/libc.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/zipl/boot/libc.c
+++ b/zipl/boot/libc.c
@@ -406,8 +406,11 @@ void printf(const char *fmt, ...)
buf[LINE_LENGTH - 2] = '.';
buf[LINE_LENGTH - 3] = '.';
}
- sclp_print(buf);
va_end(va);
+ sclp_print(buf);
+#ifdef ENABLE_SCLP_ASCII
+ sclp_print_ascii(buf);
+#endif /* ENABLE_SCLP_ASCII */
}
/*

View File

@ -1,134 +0,0 @@
Subject: [PATCH] [FEAT VS1804] Consolidate `ALIGN, __ALIGN_MASK, ARRAY_SIZE` macros
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 67aef9bbf3b5d18c70e8c4a45734bcb6d6744a8c
Problem-ID: VS1804
Upstream-Description:
Consolidate `ALIGN, __ALIGN_MASK, ARRAY_SIZE` macros
Consolidate `ALIGN, __ALIGN_MASK, ARRAY_SIZE` macros and add them to
lib/zt_common.h. While at it, adapt coding style.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
cmsfs-fuse/dasd.c | 1 +
cmsfs-fuse/helper.h | 2 --
include/lib/zt_common.h | 4 ++++
zconf/qeth/misc.h | 2 --
zdev/include/misc.h | 2 +-
zdump/zg.c | 2 +-
zdump/zg.h | 3 ---
zipl/include/zipl.h | 4 ----
8 files changed, 7 insertions(+), 13 deletions(-)
--- a/cmsfs-fuse/dasd.c
+++ b/cmsfs-fuse/dasd.c
@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <unistd.h>
+#include "lib/zt_common.h"
#include "cmsfs-fuse.h"
#include "edf.h"
#include "helper.h"
--- a/cmsfs-fuse/helper.h
+++ b/cmsfs-fuse/helper.h
@@ -49,6 +49,4 @@ extern FILE *logfile;
fprintf(stderr, COMP "Warning, " __VA_ARGS__); \
} while (0)
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-
#endif
--- a/include/lib/zt_common.h
+++ b/include/lib/zt_common.h
@@ -44,6 +44,10 @@
# define STATIC_ASSERT(test)
#endif
+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1)
+#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
#define RELEASE_STRING STRINGIFY (S390_TOOLS_RELEASE)
#define TOOLS_LIBDIR STRINGIFY (S390_TOOLS_LIBDIR)
#define TOOLS_SYSCONFDIR STRINGIFY (S390_TOOLS_SYSCONFDIR)
--- a/zconf/qeth/misc.h
+++ b/zconf/qeth/misc.h
@@ -12,8 +12,6 @@
#include <stdbool.h>
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
-
char *misc_link_target(const char *fmt, ...);
bool misc_str_in_list(const char *str, const char *strings[], int array_size);
int misc_argz_add_from_file(char **argz, size_t *argz_len,
--- a/zdev/include/misc.h
+++ b/zdev/include/misc.h
@@ -15,10 +15,10 @@
#include <stdio.h>
#include <stdlib.h>
+#include "lib/zt_common.h"
#include "lib/util_list.h"
#include "exit_code.h"
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define SCOPE_ACTIVE(x) ((x) & config_active ? 1 : 0)
#define SCOPE_PERSISTENT(x) ((x) & config_persistent ? 1 : 0)
#define SCOPE_AUTOCONF(x) ((x) & config_autoconf ? 1 : 0)
--- a/zdump/zg.c
+++ b/zdump/zg.c
@@ -432,7 +432,7 @@ char *zg_devnode_create(dev_t dev)
char *file_path;
unsigned int i;
- for (i = 0; i < ARRAY_ELEMENT_CNT(dir_vec); i++) {
+ for (i = 0; i < ARRAY_SIZE(dir_vec); i++) {
if (dir_vec[i] == NULL)
continue;
file_path = devnode_create_dir(dir_vec[i], dev);
--- a/zdump/zg.h
+++ b/zdump/zg.h
@@ -122,10 +122,7 @@ do { \
* Misc
*/
#define PAGE_SIZE 4096UL
-#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
-#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE)
-#define ARRAY_ELEMENT_CNT(x) (sizeof(x) / sizeof(x[0]))
#define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
static inline u32 zg_csum_partial(const void *buf, int len, u32 sum)
--- a/zipl/include/zipl.h
+++ b/zipl/include/zipl.h
@@ -62,10 +62,6 @@ typedef uint64_t address_t;
* resulting return code or 0. */
#define DRY_RUN_FUNC(x) (dry_run ? 0 : (x))
-#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
-#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
-
extern int verbose;
extern int interactive;
extern int dry_run;

View File

@ -1,803 +0,0 @@
Subject: [PATCH] [FEAT VS1804] genprotimg: boot: initial bootloader support
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 3356d6f4facd748f8f5cf24ffc5056db3e915f2c
Problem-ID: VS1804
Upstream-Description:
genprotimg: boot: initial bootloader support
Add a boot loader for protected virtualization (PV) that can be
combined with a kernel/initrd/parmfile to form a single bootable file.
This file must be constructed in a way that it can be used (1) for a
QEMU direct kernel boot and (2) it can be zipl'ed by the normal,
unmodified zipl program.
This new boot loader consists of two parts:
1. stage3a boot loader (cleartext), this loader is responsible for
the transition into the protected mode by doing diag308 subcode 8
and 10 calls.
2. stage3b boot loader (encrypted), this loader is very similar to the
normal zipl stage3 boot loader. It will be loaded by the Ultravisor
after the successful transition into protected mode. Like the zipl
stage3 boot loader it moves the kernel and patches in the values
for initrd and parmline.
The requirements for (1) and (2) result in the following constraints:
1. It must be possible to place stage3a and stage3b at a location >=
0x10000 because the zipl stage3 loader zeroes out everything at
addresses lower than 0x10000 of the image.
2. As the stage3 loader of zipl assumes that the passed kernel image
looks like a normal kernel image, the zipl stage3 loader modifies the
content at the memory area 0x10400 - 0x10800, therefore we leave this
area unused in our stage3a loader.
3. The default entry address used by the zipl stage3 loader is 0x10000
so we add a simple branch to 0x11000 at 0x10000 so the zipl stage3
loader can modify the area 0x10400 - 0x10800 without affecting the
stage3a loader.
The stage3b loader is linked at address 0x9000, therefore it will not
work at another address. The relocation support for the stage3b
loader, so that it can be placed at addresses != 0x9000, is added in
the next patch. This loader with relocation support has the name
'stage3b_reloc'.
The memory layout of the single bootable file looks like:
+-----------------------+-----------+------------------------+
|Start |End |Use |
+=======================+===========+========================+
|0 |0x7 |Short PSW, starting |
| | |instruction at 0x11000 |
+-----------------------+-----------+------------------------+
|0x10000 |0x10012 |Branch to 0x11000 |
+-----------------------+-----------+------------------------+
|0x10013 |0x10fff |Left intentionally |
| | |unused |
+-----------------------+-----------+------------------------+
|0x11000 |0x12fff |Stage3a |
+-----------------------+-----------+------------------------+
|0x13000 |0x13fff |IPIB used as argument |
| | |for the diag308 call |
+-----------------------+-----------+------------------------+
|0x14000 |0x1[45]fff |UV header used for the |
| | |diag308 call (size can |
| | |be either 1 or 2 pages) |
+-----------------------+-----------+------------------------+
|NEXT_PAGE_ALIGNED_ADDR | |Encrypted Kernel |
+-----------------------+-----------+------------------------+
|NEXT_PAGE_ALIGNED_ADDR | |Encrypted Cmdline |
+-----------------------+-----------+------------------------+
|NEXT_PAGE_ALIGNED_ADDR | |Encrypted Initrd |
+-----------------------+-----------+------------------------+
|NEXT_PAGE_ALIGNED_ADDR | |Encrypted Stage3b_reloc |
+-----------------------+-----------+------------------------+
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
genprotimg/boot/.gitignore | 3
genprotimg/boot/Makefile | 83 +++++++++++++++++++++++++++
genprotimg/boot/common_memory_layout.h | 25 ++++++++
genprotimg/boot/head.S | 29 +++++++++
genprotimg/boot/stage3a.c | 62 ++++++++++++++++++++
genprotimg/boot/stage3a.h | 34 +++++++++++
genprotimg/boot/stage3a.lds | 101 +++++++++++++++++++++++++++++++++
genprotimg/boot/stage3a_init.S | 26 ++++++++
genprotimg/boot/stage3b.c | 77 +++++++++++++++++++++++++
genprotimg/boot/stage3b.h | 38 ++++++++++++
genprotimg/boot/stage3b.lds | 87 ++++++++++++++++++++++++++++
include/boot/ipl.h | 25 ++++++++
include/boot/s390.h | 22 +++++--
zipl/boot/error.h | 6 +
14 files changed, 613 insertions(+), 5 deletions(-)
--- /dev/null
+++ b/genprotimg/boot/.gitignore
@@ -0,0 +1,3 @@
+*.elf
+*.bin
+*.d
--- /dev/null
+++ b/genprotimg/boot/Makefile
@@ -0,0 +1,83 @@
+# Common definitions
+include ../../common.mak
+
+ZIPL_DIR := $(rootdir)/zipl
+ZIPL_BOOT_DIR := $(ZIPL_DIR)/boot
+
+INCLUDE_PATHS := $(ZIPL_BOOT_DIR) $(ZIPL_DIR)/include $(rootdir)/include
+INCLUDE_PARMS := $(addprefix -I,$(INCLUDE_PATHS))
+
+ALL_CFLAGS := $(NO_PIE_CFLAGS) -Os -g \
+ $(INCLUDE_PARMS) \
+ -DENABLE_SCLP_ASCII=1 \
+ -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
+ -fno-builtin -ffreestanding -fno-asynchronous-unwind-tables \
+ -fno-delete-null-pointer-checks \
+ -fexec-charset=IBM1047 -m64 -mpacked-stack \
+ -mstack-size=4096 -mstack-guard=128 -msoft-float \
+ -Wall -Wformat-security -Wextra -Werror
+
+FILES := stage3a.bin stage3b.bin
+
+ZIPL_SRCS_C := libc.c ebcdic.c ebcdic_conv.c sclp.c
+ZIPL_SRCS_ASM := entry.S
+
+ZIPL_OBJS_C := $(ZIPL_SRCS_C:%.c=%.o)
+ZIPL_OBJS_ASM := $(ZIPL_SRCS_ASM:%.S=%.o)
+ZIPL_OBJS := $(ZIPL_OBJS_C) $(ZIPL_OBJS_ASM)
+
+
+all: $(FILES)
+
+# Prevent make from using some default rules...
+%: %.S
+
+%.o: %.S Makefile
+ $(CC) $(ALL_CFLAGS) -c -o $@ $<
+
+%.o: %.c Makefile
+ $(CC) $(ALL_CFLAGS) -c -o $@ $<
+
+
+# Special rules for zipl object files
+$(ZIPL_OBJS_C): %.o : $(ZIPL_BOOT_DIR)/%.c
+ $(CC) $(ALL_CFLAGS) -c -o $@ $<
+
+$(ZIPL_OBJS_ASM): %.o : $(ZIPL_BOOT_DIR)/%.S
+ $(CC) $(ALL_CFLAGS) -c -o $@ $<
+
+dependencies_zipl_c := $(ZIPL_SRCS_C:%.c=.%.o.d)
+
+$(dependencies_zipl_c): .%.o.d : $(ZIPL_BOOT_DIR)/%.c
+ $(CC_SILENT) -MM $(ALL_CPPFLAGS) $(ALL_CFLAGS) $< > $@
+
+ifneq ($(MAKECMDGOALS),clean)
+-include $(dependencies_zipl_c)
+endif
+
+
+stage3a.elf: head.o stage3a_init.o stage3a.o stage3a.lds $(ZIPL_OBJS)
+stage3b.elf: head.o stage3b.o stage3b.lds $(ZIPL_OBJS)
+
+%.elf: %.o
+ case $* in \
+ stage3a) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage3a.lds";; \
+ stage3b) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage3b.lds";; \
+ esac; \
+ $(LINK) $$SFLAGS -m64 $(filter %.o, $^) -o $@
+ @chmod a-x $@
+
+%.bin: %.elf
+ $(OBJCOPY) -O binary \
+ --only-section=.text* \
+ --only-section=.ex_table* \
+ --only-section=.fixup* \
+ --only-section=.data* \
+ --only-section=.rodata* \
+ $< $@
+ @chmod a-x $@
+
+clean:
+ rm -f *.o *.elf *.bin *.map .*.d
+
+.PHONY: all clean
--- /dev/null
+++ b/genprotimg/boot/common_memory_layout.h
@@ -0,0 +1,25 @@
+/*
+ * Common memory layout for stage3a and stage3b bootloader.
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef COMMON_MEMORY_LAYOUT_H
+#define COMMON_MEMORY_LAYOUT_H
+
+#include "boot/loaders_layout.h"
+
+#define STACK_ADDRESS STAGE3_STACK_ADDRESS
+#define STACK_SIZE STAGE3_STACK_SIZE
+
+#define HEAP_ADDRESS STAGE3_HEAP_ADDRESS
+#define HEAP_SIZE STAGE3_HEAP_SIZE
+
+
+#ifndef __ASSEMBLER__
+
+#endif /* __ASSEMBLER__ */
+#endif /* COMMON_MEMORY_LAYOUT_H */
--- /dev/null
+++ b/genprotimg/boot/head.S
@@ -0,0 +1,29 @@
+/*
+ * Entry code for stage 3a boot loader
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+
+#include "common_memory_layout.h"
+
+#include "boot/s390.h"
+#include "boot/sigp.h"
+
+.section .text.start
+.globl _start
+_start:
+ /* Might be called after a diag308 so better set
+ * architecture and addressing mode
+ */
+ lhi %r1, 1
+ sigp %r1, %r0, SIGP_SET_ARCHITECTURE
+ sam64
+
+ /* Initialize stack */
+ lgfi %r15, STACK_ADDRESS + STACK_SIZE - STACK_FRAME_OVERHEAD
+ brasl %r14, initialize
+.previous
--- /dev/null
+++ b/genprotimg/boot/stage3a.c
@@ -0,0 +1,62 @@
+/*
+ * Main program for stage3a bootloader
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "libc.h"
+#include "stage3a.h"
+
+#include "lib/zt_common.h"
+#include "boot/s390.h"
+#include "boot/ipl.h"
+#include "sclp.h"
+#include "error.h"
+
+
+static volatile struct stage3a_args __section(".loader_parms") loader_parms;
+
+void __noreturn start(void)
+{
+ int rc;
+ volatile struct stage3a_args *args = &loader_parms;
+ /* calculate the IPIB memory address */
+ struct ipl_parameter_block *ipib = (void *)((uint64_t)args + args->ipib_offs);
+
+ /* Calculate the PV header memory address and set it and its
+ * size in the IPIB. This allows the PV header to be position
+ * independent.
+ */
+ ipib->pv.pv_hdr_addr = (uint64_t)args + args->hdr_offs;
+ ipib->pv.pv_hdr_size = args->hdr_size;
+
+ /* set up ASCII and line-mode */
+ sclp_setup(SCLP_LINE_ASCII_INIT);
+
+ /* test if Secure Execution Unpack facility is available */
+ stfle(S390_lowcore.stfle_fac_list,
+ ARRAY_SIZE(S390_lowcore.stfle_fac_list));
+ rc = test_facility(UNPACK_FACILITY);
+ if (rc == 0)
+ panic(ENOPV, "Secure unpack facility is not available\n");
+
+ rc = diag308(DIAG308_SET_PV, ipib);
+ if (rc != DIAG308_RC_OK)
+ panic(EPV, "Protected boot setup has failed: 0x%x\n", rc);
+
+ rc = diag308(DIAG308_UNPACK_PV, 0x0);
+ if (rc != DIAG308_RC_OK) {
+ sclp_setup(SCLP_LINE_ASCII_INIT);
+ panic(EPV, "Protected boot has failed: 0x%x\n", rc);
+ }
+
+ while (1)
+ ;
+}
+
+void panic_notify(unsigned long UNUSED(rc))
+{
+}
--- /dev/null
+++ b/genprotimg/boot/stage3a.h
@@ -0,0 +1,34 @@
+/*
+ * Main program for stage3a bootloader.
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef STAGE3A_H
+#define STAGE3A_H
+
+#include "lib/zt_common.h"
+#include "boot/loaders_layout.h"
+
+#define STAGE3A_INIT_ENTRY IMAGE_ENTRY
+#define STAGE3A_ENTRY (STAGE3A_INIT_ENTRY + _AC(0x1000, UL))
+#define STAGE3A_LOAD_ADDRESS IMAGE_LOAD_ADDRESS
+
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+/* Must not have any padding */
+struct stage3a_args {
+ uint64_t hdr_offs;
+ uint64_t hdr_size;
+ uint64_t ipib_offs;
+};
+STATIC_ASSERT(sizeof(struct stage3a_args) == 3 * 8)
+
+#endif /* __ASSEMBLER__ */
+#endif /* STAGE3A_H */
--- /dev/null
+++ b/genprotimg/boot/stage3a.lds
@@ -0,0 +1,101 @@
+/*
+ * Memory layout for stage 3a
+ * ==========================
+ *
+ * General memory layout
+ * ---------------------
+ *
+ * 0x00000 - 0x01fff Lowcore
+ * 0x02000 - 0x05fff Memory allocation (heap)
+ * 0x0f000 - 0x0ffff Stack
+ * 0x10000 - 0x10012 Jump to the "actual" stage3a code
+ * 0x11000 - 0x12fff Stage3a code + arguments (offsets and lengths to the
+ * actual data: IPIB and UV header)
+ */
+
+OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
+OUTPUT_ARCH(s390:64-bit)
+
+ENTRY(_init)
+
+__heap_size__ = 0x4000;
+__stack_size__ = 0x1000;
+
+SECTIONS
+{
+ . = 0x0;
+
+ . = 0x2000;
+ __heap_start = .;
+ .heap : {
+ . = . + __heap_size__;
+ ASSERT(__heap_stop - __heap_start == __heap_size__,
+ "Heap section doesn't conform to the described memory layout");
+ }
+ __heap_stop = .;
+
+ . = 0xf000;
+ __stack_start = .;
+ .stack : {
+ . = . + __stack_size__;
+ ASSERT(__stack_end - __stack_start == __stack_size__,
+ "Stack section doesn't conform to the described memory layout");
+ }
+ __stack_end = .;
+
+ . = 0x10000;
+ __text_init_start = .;
+ .text : {
+ stage3a_init.o(.text.init)
+ __text_init_stop = ABSOLUTE(.);
+ /* Text size of text_init must be smaller than 'PARMAREA - IMAGE_ENTRY',
+ * otherwise the text data could be overwritten by the original zipl stage3
+ * boot loader */
+ ASSERT(__text_init_stop - __text_init_start < 0x400,
+ "Text size must be smaller than 'PARMAREA - IMAGE_ENTRY'");
+ . = 0x1000;
+ head.o(.text.start)
+ *(.text)
+ }
+
+ .ex_table ALIGN(16) : {
+ __ex_table_start = .;
+ *(.ex_table)
+ __ex_table_stop = .;
+ }
+
+ .bss ALIGN(16) : {
+ __bss_start = .;
+ *(.bss)
+ __bss_stop = .;
+ }
+
+ .rodata ALIGN(16) : {
+ *(.rodata)
+ *(.rodata.*)
+ }
+
+ .data ALIGN(16) : {
+ *(.data)
+ . = ALIGN(16);
+ /* The IPIB offset and the UV header offset and size will be
+ * saved in 'loader_parms' */
+ __loader_parms_start = .;
+ KEEP(*(.loader_parms));
+ __loader_parms_stop = .;
+ ASSERT(__loader_parms_stop - __loader_parms_start == 3 * 8,
+ "Data size must be equal to 'sizeof(struct stage3a_args)'");
+ ASSERT(ABSOLUTE(.) < 0x13000, "Data section doesn't conform to the described memory layout");
+ }
+
+ /* List this explicitly as otherwise .note.gnu.build-id will be
+ * put at 0x0 */
+ .notes : {
+ *(.note.*)
+ }
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.eh_frame)
+ }
+}
--- /dev/null
+++ b/genprotimg/boot/stage3a_init.S
@@ -0,0 +1,26 @@
+/*
+ * Entry code for stage 3a boot loader
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "stage3a.h"
+#include "boot/sigp.h"
+
+.section .text.init
+.globl _init
+_init:
+ /* set architecture and switch to 64bit */
+ lhi %r1, 1
+ sigp %r1, %r0, SIGP_SET_ARCHITECTURE
+ sam64
+ /* The original stage3 boot loader will try to store the
+ * kernel command line and the address and size of the
+ * ramdisk. Simply ignore this by starting at 0x11000.
+ */
+ lgfi %r1, STAGE3A_ENTRY
+ br %r1
+.previous
--- /dev/null
+++ b/genprotimg/boot/stage3b.c
@@ -0,0 +1,77 @@
+/*
+ * Main program for stage3b bootloader
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "libc.h"
+#include "stage3b.h"
+
+#include "lib/zt_common.h"
+#include "boot/s390.h"
+#include "boot/linux_layout.h"
+#include "boot/loaders_layout.h"
+#include "sclp.h"
+#include "error.h"
+
+
+static volatile struct stage3b_args __section(".loader_parms") loader_parms;
+
+static inline void __noreturn load_psw(struct psw_t psw)
+{
+ asm volatile("lpswe %0" : : "Q"(psw) : "cc");
+
+ while (1)
+ ;
+}
+
+void __noreturn start(void)
+{
+ volatile struct stage3b_args *args = &loader_parms;
+ volatile struct memblob *kernel = &args->kernel;
+ volatile struct memblob *cmdline = &args->cmdline;
+ volatile struct memblob *initrd = &args->initrd;
+ volatile struct psw_t psw = args->psw;
+
+ /* set up ASCII and line-mode */
+ sclp_setup(SCLP_LINE_ASCII_INIT);
+
+ if (kernel->size < IMAGE_LOAD_ADDRESS)
+ panic(EINTERNAL, "Invalid kernel\n");
+
+ if (cmdline->size > COMMAND_LINE_SIZE)
+ panic(EINTERNAL, "Command line is too large\n");
+
+ /* move the kernel and cut the kernel header */
+ memmove((void *)IMAGE_LOAD_ADDRESS,
+ (void *)(kernel->src + IMAGE_LOAD_ADDRESS),
+ kernel->size - IMAGE_LOAD_ADDRESS);
+
+ /* move the kernel cmdline */
+ memmove((void *)COMMAND_LINE,
+ (void *)cmdline->src,
+ cmdline->size);
+ /* the initrd does not need to be moved */
+
+ if (initrd->size != 0) {
+ /* copy initrd start address and size into new kernel space */
+ *(unsigned long long *)INITRD_START = initrd->src;
+ *(unsigned long long *)INITRD_SIZE = initrd->size;
+ }
+
+ /* disable ASCII and line-mode */
+ sclp_setup(SCLP_DISABLE);
+
+ /* use lpswe instead of diag308 as a I/O subsystem reset is not
+ * needed as this was already done by the diag308 subcode 10 call
+ * in stage3a
+ */
+ load_psw(psw);
+}
+
+void panic_notify(unsigned long UNUSED(rc))
+{
+}
--- /dev/null
+++ b/genprotimg/boot/stage3b.h
@@ -0,0 +1,38 @@
+/*
+ * Main program for stage3b bootloader
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#ifndef STAGE3B_H
+#define STAGE3B_H
+
+#include "lib/zt_common.h"
+
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+#include "boot/s390.h"
+
+/* Must not have any padding included */
+struct memblob {
+ uint64_t src;
+ uint64_t size;
+};
+STATIC_ASSERT(sizeof(struct memblob) == 2 * 8)
+
+/* Must not have any padding included */
+struct stage3b_args {
+ struct memblob kernel;
+ struct memblob cmdline;
+ struct memblob initrd;
+ struct psw_t psw;
+};
+STATIC_ASSERT(sizeof(struct stage3b_args) == 3 * sizeof(struct memblob) + 16)
+#endif /* __ASSEMBLER__ */
+#endif /* STAGE3B_H */
--- /dev/null
+++ b/genprotimg/boot/stage3b.lds
@@ -0,0 +1,87 @@
+/*
+ * Memory layout for stage 3b
+ * ==========================
+ *
+ * General memory layout
+ * ---------------------
+ *
+ * 0x00000 - 0x01fff Lowcore
+ * 0x02000 - 0x05fff Memory allocation (heap)
+ * 0x0a000 - 0x0efff Stage3b code
+ * 0x0f000 - 0x0ffff Stack
+ */
+
+OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
+OUTPUT_ARCH(s390:64-bit)
+
+ENTRY(_start)
+
+__heap_size__ = 0x4000;
+__stack_size__ = 0x1000;
+
+SECTIONS
+{
+ . = 0x0;
+
+ . = 0x2000;
+ __heap_start = .;
+ .heap : {
+ . = . + __heap_size__;
+ ASSERT(__heap_stop - __heap_start == __heap_size__,
+ "Heap section doesn't conform to the described memory layout");
+ }
+ __heap_stop = .;
+
+ . = 0xa000;
+ .text : {
+ head.o(.text.start)
+ *(.text)
+ }
+
+ .ex_table ALIGN(16) : {
+ __ex_table_start = .;
+ *(.ex_table)
+ __ex_table_stop = .;
+ }
+
+ .bss ALIGN(16) : {
+ __bss_start = .;
+ *(.bss)
+ __bss_stop = .;
+ }
+
+ .rodata ALIGN(16) : {
+ *(.rodata)
+ *(.rodata.*)
+ }
+
+ .data ALIGN(16) : {
+ *(.data)
+ . = ALIGN(16);
+ __loader_parms_start = .;
+ KEEP(*(.loader_parms));
+ __loader_parms_end = .;
+ ASSERT(__loader_parms_end - __loader_parms_start == 3 * 16 + 16,
+ "Data size must be equal to 'sizeof(struct stage3b_args)'");
+ }
+
+ . = 0xf000;
+ __stack_start = .;
+ .stack : {
+ . = . + __stack_size__;
+ ASSERT(__stack_end - __stack_start == __stack_size__,
+ "Stack section doesn't conform to the described memory layout");
+ }
+ __stack_end = .;
+
+ /* List this explicitly as otherwise .note.gnu.build-id will be
+ * put at 0x0 */
+ .notes : {
+ *(.note.*)
+ }
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.eh_frame)
+ }
+}
--- a/include/boot/ipl.h
+++ b/include/boot/ipl.h
@@ -89,6 +89,30 @@ struct ipl_pb0_ccw {
uint8_t reserved5[8];
} __packed;
+/* Structure must not have any padding */
+struct ipl_pb0_pv_comp {
+ uint64_t tweak_pref;
+ uint64_t addr;
+ uint64_t len;
+};
+STATIC_ASSERT(sizeof(struct ipl_pb0_pv_comp) == 3 * 8)
+
+/* IPL Parameter Block 0 for PV */
+struct ipl_pb0_pv {
+ uint32_t len;
+ uint8_t pbt;
+ uint8_t reserved1[3];
+ uint8_t loadparm[8];
+ uint8_t reserved2[84];
+ uint8_t reserved3[3];
+ uint8_t version;
+ uint8_t reserved4[4];
+ uint32_t num_comp;
+ uint64_t pv_hdr_addr;
+ uint64_t pv_hdr_size;
+ struct ipl_pb0_pv_comp components[];
+} __packed;
+
struct ipl_parameter_block {
struct ipl_pl_hdr hdr;
union {
@@ -96,6 +120,7 @@ struct ipl_parameter_block {
struct ipl_pb0_common common;
struct ipl_pb0_fcp fcp;
struct ipl_pb0_ccw ccw;
+ struct ipl_pb0_pv pv;
char raw[PAGE_SIZE - sizeof(struct ipl_pl_hdr)];
};
} __packed __aligned(PAGE_SIZE);
--- a/include/boot/s390.h
+++ b/include/boot/s390.h
@@ -18,6 +18,12 @@
#define PAGE_SIZE _AC(4096, UL)
+/* Minimum size of a stack frame in bytes */
+#define STACK_FRAME_OVERHEAD _AC(160, U)
+
+/* Facilities */
+#define UNPACK_FACILITY _AC(161, U)
+
#ifndef __ASSEMBLER__
@@ -262,11 +268,17 @@ static __always_inline void __ctl_set_bi
* DIAG 308 support
*/
enum diag308_subcode {
- DIAG308_REL_HSA = 2,
- DIAG308_IPL = 3,
- DIAG308_DUMP = 4,
- DIAG308_SET = 5,
- DIAG308_STORE = 6,
+ DIAG308_REL_HSA = 2,
+ DIAG308_IPL = 3,
+ DIAG308_DUMP = 4,
+ DIAG308_SET = 5,
+ DIAG308_STORE = 6,
+ DIAG308_SET_PV = 8,
+ DIAG308_UNPACK_PV = 10,
+};
+
+enum diag308_rc {
+ DIAG308_RC_OK = 0x0001,
};
static __always_inline unsigned long diag308(unsigned long subcode, void *addr)
--- a/zipl/boot/error.h
+++ b/zipl/boot/error.h
@@ -71,4 +71,10 @@
#define ENOTIME 0x00004605 /* The zipl time stamps do not match */
#define ENOMSS 0x00004606 /* Could not enable MSS */
+/*
+ * PV error codes
+ */
+#define ENOPV 0x00004607 /* No support for PV */
+#define EPV 0x00004608 /* PV error */
+
#endif /* ERROR_H */

View File

@ -1,479 +0,0 @@
Subject: [PATCH] [FEAT VS1804] genprotimg: boot: use C pre-processor for linker script generation
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: 2d600570df98a1d26a6f3947ae8c39bcde00b464
Problem-ID: VS1804
Upstream-Description:
genprotimg: boot: use C pre-processor for linker script generation
Use C pre-processor for linker script generation. This allows the
usage of constants in our "linker scripts" `*.lds.S` (actually, these
are assembler files, so we can make us of the C pre-processor and its
capabilities).
Suggested-by: Philipp Rudo <prudo@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
genprotimg/boot/.gitignore | 1
genprotimg/boot/Makefile | 13 ++++-
genprotimg/boot/stage3a.lds | 101 -----------------------------------------
genprotimg/boot/stage3a.lds.S | 103 ++++++++++++++++++++++++++++++++++++++++++
genprotimg/boot/stage3b.h | 4 +
genprotimg/boot/stage3b.lds | 87 -----------------------------------
genprotimg/boot/stage3b.lds.S | 87 +++++++++++++++++++++++++++++++++++
7 files changed, 207 insertions(+), 189 deletions(-)
--- a/genprotimg/boot/.gitignore
+++ b/genprotimg/boot/.gitignore
@@ -1,3 +1,4 @@
*.elf
+*.lds
*.bin
*.d
--- a/genprotimg/boot/Makefile
+++ b/genprotimg/boot/Makefile
@@ -39,6 +39,17 @@ all: $(FILES)
$(CC) $(ALL_CFLAGS) -c -o $@ $<
+# Dependencies for the .lds generation
+sources_lds_S = $(wildcard *.lds.S)
+dependencies_lds_S = $(sources_lds_s:%.lds.S=.%.lds.d)
+# Include all ".lds.d" dependency files for all make targets except for "clean"
+ifneq ($(MAKECMDGOALS),clean)
+-include $(dependencies_lds_S)
+endif
+
+%.lds: %.lds.S Makefile
+ $(CPP) -Wp,-MD,.$@.d,-MT,$@ $(INCLUDE_PARMS) -P -C -o $@ $<
+
# Special rules for zipl object files
$(ZIPL_OBJS_C): %.o : $(ZIPL_BOOT_DIR)/%.c
$(CC) $(ALL_CFLAGS) -c -o $@ $<
@@ -78,6 +89,6 @@ stage3b.elf: head.o stage3b.o stage3b.ld
@chmod a-x $@
clean:
- rm -f *.o *.elf *.bin *.map .*.d
+ rm -f *.o *.elf *.bin *.map .*.d *.lds
.PHONY: all clean
--- a/genprotimg/boot/stage3a.lds
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Memory layout for stage 3a
- * ==========================
- *
- * General memory layout
- * ---------------------
- *
- * 0x00000 - 0x01fff Lowcore
- * 0x02000 - 0x05fff Memory allocation (heap)
- * 0x0f000 - 0x0ffff Stack
- * 0x10000 - 0x10012 Jump to the "actual" stage3a code
- * 0x11000 - 0x12fff Stage3a code + arguments (offsets and lengths to the
- * actual data: IPIB and UV header)
- */
-
-OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
-OUTPUT_ARCH(s390:64-bit)
-
-ENTRY(_init)
-
-__heap_size__ = 0x4000;
-__stack_size__ = 0x1000;
-
-SECTIONS
-{
- . = 0x0;
-
- . = 0x2000;
- __heap_start = .;
- .heap : {
- . = . + __heap_size__;
- ASSERT(__heap_stop - __heap_start == __heap_size__,
- "Heap section doesn't conform to the described memory layout");
- }
- __heap_stop = .;
-
- . = 0xf000;
- __stack_start = .;
- .stack : {
- . = . + __stack_size__;
- ASSERT(__stack_end - __stack_start == __stack_size__,
- "Stack section doesn't conform to the described memory layout");
- }
- __stack_end = .;
-
- . = 0x10000;
- __text_init_start = .;
- .text : {
- stage3a_init.o(.text.init)
- __text_init_stop = ABSOLUTE(.);
- /* Text size of text_init must be smaller than 'PARMAREA - IMAGE_ENTRY',
- * otherwise the text data could be overwritten by the original zipl stage3
- * boot loader */
- ASSERT(__text_init_stop - __text_init_start < 0x400,
- "Text size must be smaller than 'PARMAREA - IMAGE_ENTRY'");
- . = 0x1000;
- head.o(.text.start)
- *(.text)
- }
-
- .ex_table ALIGN(16) : {
- __ex_table_start = .;
- *(.ex_table)
- __ex_table_stop = .;
- }
-
- .bss ALIGN(16) : {
- __bss_start = .;
- *(.bss)
- __bss_stop = .;
- }
-
- .rodata ALIGN(16) : {
- *(.rodata)
- *(.rodata.*)
- }
-
- .data ALIGN(16) : {
- *(.data)
- . = ALIGN(16);
- /* The IPIB offset and the UV header offset and size will be
- * saved in 'loader_parms' */
- __loader_parms_start = .;
- KEEP(*(.loader_parms));
- __loader_parms_stop = .;
- ASSERT(__loader_parms_stop - __loader_parms_start == 3 * 8,
- "Data size must be equal to 'sizeof(struct stage3a_args)'");
- ASSERT(ABSOLUTE(.) < 0x13000, "Data section doesn't conform to the described memory layout");
- }
-
- /* List this explicitly as otherwise .note.gnu.build-id will be
- * put at 0x0 */
- .notes : {
- *(.note.*)
- }
-
- /* Sections to be discarded */
- /DISCARD/ : {
- *(.eh_frame)
- }
-}
--- /dev/null
+++ b/genprotimg/boot/stage3a.lds.S
@@ -0,0 +1,103 @@
+/*
+ * Memory layout for stage 3a
+ * ==========================
+ *
+ * General memory layout
+ * ---------------------
+ *
+ * 0x00000 - 0x01fff Lowcore
+ * 0x02000 - 0x05fff Memory allocation (heap)
+ * 0x0f000 - 0x0ffff Stack
+ * 0x10000 - 0x10012 Jump to the "actual" stage3a code
+ * 0x11000 - 0x12fff Stage3a code + arguments (offsets and lengths to the
+ * actual data: IPIB and UV header)
+ */
+
+#include "stage3a.h"
+#include "common_memory_layout.h"
+
+OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
+OUTPUT_ARCH(s390:64-bit)
+
+ENTRY(_init)
+
+SECTIONS
+{
+ . = 0x0;
+
+ . = HEAP_ADDRESS;
+ __heap_start = .;
+ .heap : {
+ . = . + HEAP_SIZE;
+ ASSERT(__heap_stop - __heap_start == HEAP_SIZE,
+ "Heap section doesn't conform to the described memory layout");
+ }
+ __heap_stop = .;
+
+ . = STACK_ADDRESS;
+ __stack_start = .;
+ .stack : {
+ . = . + STACK_SIZE;
+ ASSERT(__stack_end - __stack_start == STACK_SIZE,
+ "Stack section doesn't conform to the described memory layout");
+ }
+ __stack_end = .;
+
+ . = STAGE3A_INIT_ENTRY;
+ __text_init_start = .;
+ .text : {
+ stage3a_init.o(.text.init)
+ __text_init_stop = ABSOLUTE(.);
+ /* Text size of text_init must be smaller than 'PARMAREA - IMAGE_ENTRY',
+ * otherwise the text data could be overwritten by the original zipl stage3
+ * boot loader */
+ ASSERT(__text_init_stop - __text_init_start < PARMAREA - IMAGE_ENTRY,
+ "Text size must be smaller than 'PARMAREA - IMAGE_ENTRY'");
+ . = 0x1000;
+ ASSERT(ABSOLUTE(.) == STAGE3A_ENTRY,
+ "Text section doesn't conform to the described memory layout");
+ head.o(.text.start)
+ *(.text)
+ }
+
+ .ex_table ALIGN(16) : {
+ __ex_table_start = .;
+ *(.ex_table)
+ __ex_table_stop = .;
+ }
+
+ .bss ALIGN(16) : {
+ __bss_start = .;
+ *(.bss)
+ __bss_stop = .;
+ }
+
+ .rodata ALIGN(16) : {
+ *(.rodata)
+ *(.rodata.*)
+ }
+
+ .data ALIGN(16) : {
+ *(.data)
+ . = ALIGN(16);
+ /* The IPIB offset and the UV header offset and size will be
+ * saved in 'loader_parms' */
+ __loader_parms_start = .;
+ KEEP(*(.loader_parms));
+ __loader_parms_stop = .;
+ ASSERT(__loader_parms_stop - __loader_parms_start == 3 * 8,
+ "Data size must be equal to 'sizeof(struct stage3a_args)'");
+ ASSERT(ABSOLUTE(.) < 0x13000, "Data section doesn't conform to the described memory layout");
+ }
+
+ /* List this explicitly as otherwise .note.gnu.build-id will be
+ * put at 0x0 */
+ .notes : {
+ *(.note.*)
+ }
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.eh_frame)
+ }
+}
--- a/genprotimg/boot/stage3b.h
+++ b/genprotimg/boot/stage3b.h
@@ -11,6 +11,10 @@
#define STAGE3B_H
#include "lib/zt_common.h"
+#include "boot/loaders_layout.h"
+
+#define STAGE3B_ENTRY STAGE3_ENTRY
+#define STAGE3B_LOAD_ADDRESS STAGE3B_ENTRY
#ifndef __ASSEMBLER__
--- a/genprotimg/boot/stage3b.lds
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Memory layout for stage 3b
- * ==========================
- *
- * General memory layout
- * ---------------------
- *
- * 0x00000 - 0x01fff Lowcore
- * 0x02000 - 0x05fff Memory allocation (heap)
- * 0x0a000 - 0x0efff Stage3b code
- * 0x0f000 - 0x0ffff Stack
- */
-
-OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
-OUTPUT_ARCH(s390:64-bit)
-
-ENTRY(_start)
-
-__heap_size__ = 0x4000;
-__stack_size__ = 0x1000;
-
-SECTIONS
-{
- . = 0x0;
-
- . = 0x2000;
- __heap_start = .;
- .heap : {
- . = . + __heap_size__;
- ASSERT(__heap_stop - __heap_start == __heap_size__,
- "Heap section doesn't conform to the described memory layout");
- }
- __heap_stop = .;
-
- . = 0xa000;
- .text : {
- head.o(.text.start)
- *(.text)
- }
-
- .ex_table ALIGN(16) : {
- __ex_table_start = .;
- *(.ex_table)
- __ex_table_stop = .;
- }
-
- .bss ALIGN(16) : {
- __bss_start = .;
- *(.bss)
- __bss_stop = .;
- }
-
- .rodata ALIGN(16) : {
- *(.rodata)
- *(.rodata.*)
- }
-
- .data ALIGN(16) : {
- *(.data)
- . = ALIGN(16);
- __loader_parms_start = .;
- KEEP(*(.loader_parms));
- __loader_parms_end = .;
- ASSERT(__loader_parms_end - __loader_parms_start == 3 * 16 + 16,
- "Data size must be equal to 'sizeof(struct stage3b_args)'");
- }
-
- . = 0xf000;
- __stack_start = .;
- .stack : {
- . = . + __stack_size__;
- ASSERT(__stack_end - __stack_start == __stack_size__,
- "Stack section doesn't conform to the described memory layout");
- }
- __stack_end = .;
-
- /* List this explicitly as otherwise .note.gnu.build-id will be
- * put at 0x0 */
- .notes : {
- *(.note.*)
- }
-
- /* Sections to be discarded */
- /DISCARD/ : {
- *(.eh_frame)
- }
-}
--- /dev/null
+++ b/genprotimg/boot/stage3b.lds.S
@@ -0,0 +1,87 @@
+/*
+ * Memory layout for stage 3b
+ * ==========================
+ *
+ * General memory layout
+ * ---------------------
+ *
+ * 0x00000 - 0x01fff Lowcore
+ * 0x02000 - 0x05fff Memory allocation (heap)
+ * 0x0a000 - 0x0efff Stage3b code
+ * 0x0f000 - 0x0ffff Stack
+ */
+
+#include "stage3b.h"
+#include "common_memory_layout.h"
+
+OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
+OUTPUT_ARCH(s390:64-bit)
+
+ENTRY(_start)
+
+SECTIONS
+{
+ . = 0x0;
+
+ . = HEAP_ADDRESS;
+ __heap_start = .;
+ .heap : {
+ . = . + HEAP_SIZE;
+ ASSERT(__heap_stop - __heap_start == HEAP_SIZE,
+ "Heap section doesn't conform to the described memory layout");
+ }
+ __heap_stop = .;
+
+ . = STAGE3B_ENTRY;
+ .text : {
+ head.o(.text.start)
+ *(.text)
+ }
+
+ .ex_table ALIGN(16) : {
+ __ex_table_start = .;
+ *(.ex_table)
+ __ex_table_stop = .;
+ }
+
+ .bss ALIGN(16) : {
+ __bss_start = .;
+ *(.bss)
+ __bss_stop = .;
+ }
+
+ .rodata ALIGN(16) : {
+ *(.rodata)
+ *(.rodata.*)
+ }
+
+ .data ALIGN(16) : {
+ *(.data)
+ . = ALIGN(16);
+ __loader_parms_start = .;
+ KEEP(*(.loader_parms));
+ __loader_parms_end = .;
+ ASSERT(__loader_parms_end - __loader_parms_start == 3 * 16 + 16,
+ "Data size must be equal to 'sizeof(struct stage3b_args)'");
+ }
+
+ . = STACK_ADDRESS;
+ __stack_start = .;
+ .stack : {
+ . = . + STACK_SIZE;
+ ASSERT(__stack_end - __stack_start == STACK_SIZE,
+ "Stack section doesn't conform to the described memory layout");
+ }
+ __stack_end = .;
+
+ /* List this explicitly as otherwise .note.gnu.build-id will be
+ * put at 0x0 */
+ .notes : {
+ *(.note.*)
+ }
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.eh_frame)
+ }
+}

View File

@ -1,120 +0,0 @@
Subject: [PATCH] [FEAT VS1804] genprotimg: add relocator for stage3b
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: d2f8f972cff7aacbef8e72577af70dbf59ba3ead
Problem-ID: VS1804
Upstream-Description:
genprotimg: add relocator for stage3b
Add support for the placement of the stage3b loader at other addresses
than 0xa000. For this add a position independent relocator that first
copies the original stage3b code to the memory location 0xa000 and
then starts it.
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
genprotimg/boot/Makefile | 5 +++
genprotimg/boot/stage3b_reloc.S | 53 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+), 1 deletion(-)
--- a/genprotimg/boot/Makefile
+++ b/genprotimg/boot/Makefile
@@ -17,7 +17,7 @@ ALL_CFLAGS := $(NO_PIE_CFLAGS) -Os -g \
-mstack-size=4096 -mstack-guard=128 -msoft-float \
-Wall -Wformat-security -Wextra -Werror
-FILES := stage3a.bin stage3b.bin
+FILES := stage3a.bin stage3b.bin stage3b_reloc.bin
ZIPL_SRCS_C := libc.c ebcdic.c ebcdic_conv.c sclp.c
ZIPL_SRCS_ASM := entry.S
@@ -66,14 +66,17 @@ ifneq ($(MAKECMDGOALS),clean)
-include $(dependencies_zipl_c)
endif
+stage3b_reloc.o: stage3b.bin
stage3a.elf: head.o stage3a_init.o stage3a.o stage3a.lds $(ZIPL_OBJS)
stage3b.elf: head.o stage3b.o stage3b.lds $(ZIPL_OBJS)
+stage3b_reloc.elf:
%.elf: %.o
case $* in \
stage3a) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage3a.lds";; \
stage3b) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-T,stage3b.lds";; \
+ stage3b_reloc) SFLAGS="$(NO_PIE_LINKFLAGS) -nostdlib -Wl,-estage3b_reloc_start,-Ttext,0";; \
esac; \
$(LINK) $$SFLAGS -m64 $(filter %.o, $^) -o $@
@chmod a-x $@
--- /dev/null
+++ b/genprotimg/boot/stage3b_reloc.S
@@ -0,0 +1,53 @@
+/*
+ * Relocator code for stage 3b boot loader
+ *
+ * Copyright IBM Corp. 2020
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "stage3b.h"
+#include "boot/sigp.h"
+
+.macro MEMCPY dst,src,len
+ lgr %r0, \dst
+ lgr %r1, \len
+ lgr %r2, \src
+ lgr %r3, \len
+
+20: mvcle %r0, %r2, 0
+ jo 20b
+.endm
+
+.org 0x0
+.section .text.start
+.globl stage3b_reloc_start
+stage3b_reloc_start:
+ /* Might be called after a diag308 so better set
+ * architecture and addressing mode
+ */
+ lhi %r1, 1
+ sigp %r1, %r0, SIGP_SET_ARCHITECTURE
+ sam64
+
+.copy_stage3b:
+ /* Location of stage3b in memory */
+ larl %r8, stage3b_start
+
+ /* Destination for stage3b */
+ lgfi %r9, STAGE3B_LOAD_ADDRESS
+
+ /* Size of stage3b */
+ lghi %r11, stage3b_end - stage3b_start
+
+ /* Copy the stage3b loader to address STAGE3B_LOAD_ADDRESS */
+ MEMCPY %r9, %r8, %r11
+
+ /* Branch to STAGE3B_ENTRY */
+ lgfi %r9, STAGE3B_ENTRY
+ br %r9
+stage3b_start:
+ .incbin "stage3b.bin"
+stage3b_end:
+.previous

View File

@ -1,38 +0,0 @@
Subject: [PATCH] [FEAT VS1804] README.md: remove useless empty line
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Summary: genprotimg: Introduce new tool for the creation of PV images
Description: genprotimg takes a kernel, host-key documents, optionally an
initrd, optionally a file with the kernel command line, and it
generates a single, loadable image file. The image consists of a
concatenation of a plain text boot loader, the encrypted
components for kernel, initrd, and cmdline, and the
integrity-protected PV header, containing metadata necessary for
running the guest in PV mode. It's possible to use this image file
as a kernel for zIPL or for a direct kernel boot using QEMU.
Upstream-ID: b06af6026f08d67339a109ba7457373ab82d3248
Problem-ID: VS1804
Upstream-Description:
README.md: remove useless empty line
Remove useless empty line.
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
---
README.md | 1 -
1 file changed, 1 deletion(-)
--- a/README.md
+++ b/README.md
@@ -1,4 +1,3 @@
-
s390-tools
==========

Some files were not shown because too many files have changed in this diff Show More