mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Compare commits
98 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 094905af87 | |||
| dcce14923c | |||
| 1fd78d9f5e | |||
| 9d1baaa594 | |||
| efcfbce386 | |||
| 3d74c534bf | |||
| ca2ffe9e18 | |||
| 52192908eb | |||
| d4cee7e65a | |||
| bfbf456b83 | |||
| 235e997a77 | |||
| c079e48d7d | |||
| 4762e65acb | |||
| cb614ed1ee | |||
| 8face3e63e | |||
| ea14f5471c | |||
| b2ae5a91ac | |||
| edfb6a03d8 | |||
| 5eace91ee7 | |||
| 86856f98db | |||
| 154734efc7 | |||
| c7fcb457b0 | |||
| 244bf4e550 | |||
| 0f7ed7d4fc | |||
| 121d5d8013 | |||
| abe0ba7412 | |||
| 2227bb8330 | |||
| aa09b29248 | |||
| 2790d4faaa | |||
| bbc46edaf5 | |||
| e5c0fb249b | |||
| b6d8e5833c | |||
| d71628326d | |||
| 8bfe18e674 | |||
| 275105fe3d | |||
| 19259aeb65 | |||
| 125df52887 | |||
| 852fb9dfb8 | |||
| b0fe75b92f | |||
| bc987c8d18 | |||
| a86e41a518 | |||
| 0d9e42264d | |||
| 7fede7021e | |||
| e7d79d5c5c | |||
| 7d4b1e18b6 | |||
| b0cc0e4737 | |||
| b7bb90c552 | |||
| 560b672bfa | |||
| 0fab6bdf2a | |||
| b56c74fe7b | |||
| 663d362ff3 | |||
| d4027e6506 | |||
| ddde3f354f | |||
| 298fab68fe | |||
| b47007b8ac | |||
| 91c35543ca | |||
| 9de85f4295 | |||
| e15e8a1bfa | |||
| 4fc0c3cfef | |||
| a0ed6709cf | |||
| 552a915465 | |||
| 1091b0bf65 | |||
| 016a0a56fc | |||
| 0b4cbf0041 | |||
| d854aed4b8 | |||
| 7f8e31e861 | |||
| a5b58038a0 | |||
| c2244a5795 | |||
| ea7cc9ea60 | |||
| b32c031474 | |||
| bfc3dd018c | |||
| 625b81130a | |||
| bf8872e94a | |||
| a84d1c5d58 | |||
| 696e8458f0 | |||
| 95c7258ea7 | |||
| 21de913a5e | |||
| 7a2a96e8a3 | |||
| 7a569c7e33 | |||
| dc2ac0c916 | |||
| 367598b187 | |||
| c01bcfa73a | |||
| fe457e2082 | |||
| 1d25112589 | |||
| 27a8c4434c | |||
| e6a3b18104 | |||
| 36292cb166 | |||
| 49da03e2e7 | |||
| 139dff3525 | |||
| 94227b44d5 | |||
| a9f4ae2db3 | |||
| 15b7f9d83f | |||
| 214580a704 | |||
| 96f13ead2b | |||
| 8023a72b11 | |||
| abc1875300 | |||
| 7d4c8c2781 | |||
| f0afc6c89a |
@@ -56,6 +56,7 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Kittipon Meesompop
|
- Kittipon Meesompop
|
||||||
- Klaus-Dieter Wacker
|
- Klaus-Dieter Wacker
|
||||||
- Lakhvich Dmitriy
|
- Lakhvich Dmitriy
|
||||||
|
- Marc Hartmayer
|
||||||
- Mark Dettinger
|
- Mark Dettinger
|
||||||
- Martin Kammerer
|
- Martin Kammerer
|
||||||
- Martin Peschke
|
- Martin Peschke
|
||||||
@@ -97,6 +98,7 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Thomas Richter
|
- Thomas Richter
|
||||||
- Thomas Spatzier
|
- Thomas Spatzier
|
||||||
- Thomas Weber
|
- Thomas Weber
|
||||||
|
- Tuan Hoang
|
||||||
- Ursula Braun
|
- Ursula Braun
|
||||||
- Utz Bacher
|
- Utz Bacher
|
||||||
- Vasily Gorbik
|
- Vasily Gorbik
|
||||||
|
|||||||
@@ -1,5 +1,49 @@
|
|||||||
Release history for s390-tools (MIT version)
|
Release history for s390-tools (MIT version)
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
* __v2.12.0 (2019-12-17)__
|
||||||
|
|
||||||
|
For Linux kernel version: 5.4
|
||||||
|
|
||||||
|
Changes of existing tools:
|
||||||
|
- dbginfo: Gather qdisc related data (using 'tc')
|
||||||
|
- dbginfo: Gather extended network statistics (using 'ip link')
|
||||||
|
- dbginfo: Collect all files under /usr/lib/systemd/system/
|
||||||
|
- cpumf/cpumf_helper: Add IBM z15 machine name
|
||||||
|
- zkey: Display MKVP when validating a secure key
|
||||||
|
- zkey: Cross check APQNs when generating, validating, or importing secure keys,
|
||||||
|
and when changing APQN associations
|
||||||
|
- zkey: Check crypto card level during APQN cross checking
|
||||||
|
- zkey: Add support for generating, validating, and re-enciphering AES CIPHER keys
|
||||||
|
- zkey-cryptsetup: Add --to-new and --from-old options
|
||||||
|
- zkey-cryptsetup: Allow setkey to set different key types
|
||||||
|
- lszcrypt/chzcrypt: CEX7S exploitation support
|
||||||
|
- zcryptstats: Add support for CEX7 crypto card
|
||||||
|
- zipl: Ship a minimal zipl.conf
|
||||||
|
- zipl: Add value of target= as search path for BLS case
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- dasdview: Fix exit status in error cases
|
||||||
|
- zipl: Fix various compile warnings
|
||||||
|
- zipl: Fix dependency generation in zipl/boot
|
||||||
|
- zipl: Fix entry point for stand-alone kdump
|
||||||
|
- zipl: Add missing options to help output
|
||||||
|
|
||||||
|
* __v2.11.0 (2019-09-06)__
|
||||||
|
|
||||||
|
For Linux kernel version: 5.3
|
||||||
|
|
||||||
|
Changes of existing tools:
|
||||||
|
- dasdfmt: Add support for thin-provisioned volumes
|
||||||
|
- lsdasd: Add support for thin-provisioned volumes
|
||||||
|
- libdasd: Provide function to utilise release space ioctl
|
||||||
|
- libdasd: Provide function to read ese sysfs attribute
|
||||||
|
- dbginfo: Add lspci (PCI devices) and smc_dbg (SMC sockets)
|
||||||
|
- dbginfo: Gather ethtool related data
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- zipl: Fix freeing of uninitialized pointer
|
||||||
|
- zipl: Set correct secure IPL default value
|
||||||
|
|
||||||
* __v2.10.0 (2019-07-31)__
|
* __v2.10.0 (2019-07-31)__
|
||||||
|
|
||||||
For Linux kernel version: 5.2
|
For Linux kernel version: 5.2
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ COMMON_INCLUDED = true
|
|||||||
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
|
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
|
||||||
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
|
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
|
||||||
VERSION = 2
|
VERSION = 2
|
||||||
RELEASE = 10
|
RELEASE = 12
|
||||||
PATCHLEVEL = 0
|
PATCHLEVEL = 0
|
||||||
DISTRELEASE = build-$(shell date +%Y%m%d)
|
DISTRELEASE = build-$(shell date +%Y%m%d)
|
||||||
S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
|
S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
|
||||||
|
|||||||
@@ -213,6 +213,7 @@ my $system_z_hwtype_map = {
|
|||||||
2965 => 'IBM z13s',
|
2965 => 'IBM z13s',
|
||||||
3906 => 'IBM z14',
|
3906 => 'IBM z14',
|
||||||
3907 => 'IBM z14 ZR1',
|
3907 => 'IBM z14 ZR1',
|
||||||
|
8561 => 'IBM z15',
|
||||||
};
|
};
|
||||||
|
|
||||||
sub get_hardware_type()
|
sub get_hardware_type()
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ Format the first two tracks and write label and partition information. Only use
|
|||||||
this option if you are sure that the target DASD already contains a regular
|
this option if you are sure that the target DASD already contains a regular
|
||||||
format with the specified blocksize. A blocksize can optionally be specified
|
format with the specified blocksize. A blocksize can optionally be specified
|
||||||
using \fB-b\fR (\fB--blocksize\fR).
|
using \fB-b\fR (\fB--blocksize\fR).
|
||||||
|
.br
|
||||||
|
For thin-provisioned DASD ESE volumes this is the default mode.
|
||||||
.IP expand
|
.IP expand
|
||||||
Format all unformatted tracks at the end of the target DASD. This mode assumes
|
Format all unformatted tracks at the end of the target DASD. This mode assumes
|
||||||
that tracks at the beginning of the DASD volume have already been correctly
|
that tracks at the beginning of the DASD volume have already been correctly
|
||||||
@@ -136,6 +138,10 @@ using \fB-b\fR (\fB--blocksize\fR).
|
|||||||
Perform a complete format check on a DASD volume. A blocksize can be specified
|
Perform a complete format check on a DASD volume. A blocksize can be specified
|
||||||
with \fB-b\fR (\fB--blocksize\fR).
|
with \fB-b\fR (\fB--blocksize\fR).
|
||||||
|
|
||||||
|
.TP
|
||||||
|
\fB--no-discard\fR
|
||||||
|
Omit a full space release when formatting a thin-provisioned DASD ESE volume.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-r\fR \fIcylindercount\fR or \fB--requestsize\fR=\fIcylindercount\fR
|
\fB-r\fR \fIcylindercount\fR or \fB--requestsize\fR=\fIcylindercount\fR
|
||||||
Number of cylinders to be processed in one formatting step.
|
Number of cylinders to be processed in one formatting step.
|
||||||
|
|||||||
+55
-3
@@ -53,6 +53,7 @@ static const struct util_prg prg = {
|
|||||||
/* Defines for options with no short command */
|
/* Defines for options with no short command */
|
||||||
#define OPT_CHECK 128
|
#define OPT_CHECK 128
|
||||||
#define OPT_NOZERO 129
|
#define OPT_NOZERO 129
|
||||||
|
#define OPT_NODISCARD 130
|
||||||
|
|
||||||
static struct util_opt opt_vec[] = {
|
static struct util_opt opt_vec[] = {
|
||||||
UTIL_OPT_SECTION("FORMAT ACTIONS"),
|
UTIL_OPT_SECTION("FORMAT ACTIONS"),
|
||||||
@@ -105,6 +106,11 @@ static struct util_opt opt_vec[] = {
|
|||||||
.desc = "Prevent storage server from modifying record 0",
|
.desc = "Prevent storage server from modifying record 0",
|
||||||
.flags = UTIL_OPT_FLAG_NOSHORT,
|
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.option = { "no-discard", no_argument, NULL, OPT_NODISCARD },
|
||||||
|
.desc = "Do not discard space before formatting",
|
||||||
|
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.option = { NULL, no_argument, NULL, 'y' },
|
.option = { NULL, no_argument, NULL, 'y' },
|
||||||
.desc = "Start formatting without further user-confirmation",
|
.desc = "Start formatting without further user-confirmation",
|
||||||
@@ -921,6 +927,8 @@ static void dasdfmt_print_info(dasdfmt_info_t *info, char *devname,
|
|||||||
printf("Drive Geometry: %d Cylinders * %d Heads = %d Tracks\n",
|
printf("Drive Geometry: %d Cylinders * %d Heads = %d Tracks\n",
|
||||||
cylinders, heads, (cylinders * heads));
|
cylinders, heads, (cylinders * heads));
|
||||||
|
|
||||||
|
printf("Device Type: %s Provisioned\n",
|
||||||
|
info->ese ? "Thinly" : "Fully");
|
||||||
printf("\nI am going to format the device ");
|
printf("\nI am going to format the device ");
|
||||||
printf("%s in the following way:\n", devname);
|
printf("%s in the following way:\n", devname);
|
||||||
printf(" Device number of device : 0x%x\n", info->dasd_info.devno);
|
printf(" Device number of device : 0x%x\n", info->dasd_info.devno);
|
||||||
@@ -939,7 +947,10 @@ static void dasdfmt_print_info(dasdfmt_info_t *info, char *devname,
|
|||||||
(p->intensity & DASD_FMT_INT_COMPAT) ? "yes" : "no");
|
(p->intensity & DASD_FMT_INT_COMPAT) ? "yes" : "no");
|
||||||
printf(" Blocksize : %d\n", p->blksize);
|
printf(" Blocksize : %d\n", p->blksize);
|
||||||
printf(" Mode : %s\n", mode_str[mode]);
|
printf(" Mode : %s\n", mode_str[mode]);
|
||||||
|
if (info->ese) {
|
||||||
|
printf(" Full Space Release : %s\n",
|
||||||
|
(info->no_discard || mode == FULL) ? "no" : "yes");
|
||||||
|
}
|
||||||
if (info->testmode)
|
if (info->testmode)
|
||||||
printf("Test mode active, omitting ioctl.\n");
|
printf("Test mode active, omitting ioctl.\n");
|
||||||
}
|
}
|
||||||
@@ -1234,6 +1245,26 @@ static void dasdfmt_format(dasdfmt_info_t *info, unsigned int cylinders,
|
|||||||
process_tracks(info, cylinders, heads, format_params);
|
process_tracks(info, cylinders, heads, format_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dasdfmt_release_space(dasdfmt_info_t *info)
|
||||||
|
{
|
||||||
|
format_data_t r = {
|
||||||
|
.start_unit = 0,
|
||||||
|
.stop_unit = 0,
|
||||||
|
.intensity = DASD_FMT_INT_ESE_FULL,
|
||||||
|
};
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (!info->ese || info->no_discard)
|
||||||
|
return;
|
||||||
|
|
||||||
|
printf("Releasing space for the entire device...\n");
|
||||||
|
err = dasd_release_space(dev_filename, &r);
|
||||||
|
if (err) {
|
||||||
|
ERRMSG_EXIT(EXIT_FAILURE, "%s: Could not release space (%s)\n",
|
||||||
|
prog_name, strerror(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void dasdfmt_prepare_and_format(dasdfmt_info_t *info,
|
static void dasdfmt_prepare_and_format(dasdfmt_info_t *info,
|
||||||
unsigned int cylinders,
|
unsigned int cylinders,
|
||||||
unsigned int heads, format_data_t *p)
|
unsigned int heads, format_data_t *p)
|
||||||
@@ -1329,6 +1360,8 @@ static void dasdfmt_quick_format(dasdfmt_info_t *info, unsigned int cylinders,
|
|||||||
|
|
||||||
if (info->force) {
|
if (info->force) {
|
||||||
printf("Skipping format check due to --force.\n");
|
printf("Skipping format check due to --force.\n");
|
||||||
|
} else if (info->ese) {
|
||||||
|
printf("Skipping format check due to thin-provisioned device.\n");
|
||||||
} else {
|
} else {
|
||||||
check_blocksize(info, p->blksize);
|
check_blocksize(info, p->blksize);
|
||||||
|
|
||||||
@@ -1438,6 +1471,7 @@ static void do_format_dasd(dasdfmt_info_t *info, char *devname,
|
|||||||
dasdfmt_prepare_and_format(info, cylinders, heads, p);
|
dasdfmt_prepare_and_format(info, cylinders, heads, p);
|
||||||
break;
|
break;
|
||||||
case QUICK:
|
case QUICK:
|
||||||
|
dasdfmt_release_space(info);
|
||||||
dasdfmt_quick_format(info, cylinders, heads, p);
|
dasdfmt_quick_format(info, cylinders, heads, p);
|
||||||
break;
|
break;
|
||||||
case EXPAND:
|
case EXPAND:
|
||||||
@@ -1461,6 +1495,19 @@ static void do_format_dasd(dasdfmt_info_t *info, char *devname,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void eval_format_mode(dasdfmt_info_t *info)
|
||||||
|
{
|
||||||
|
if (!info->force && info->mode_specified && info->ese && mode == EXPAND) {
|
||||||
|
ERRMSG_EXIT(EXIT_FAILURE,
|
||||||
|
"WARNING: The specified device is thin-provisioned\n"
|
||||||
|
"Format mode 'expand' is not feasible.\n"
|
||||||
|
"Use --mode=full or --mode=quick to perform a clean format\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info->mode_specified)
|
||||||
|
mode = info->ese ? QUICK : FULL;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
dasdfmt_info_t info = {
|
dasdfmt_info_t info = {
|
||||||
@@ -1496,8 +1543,6 @@ int main(int argc, char *argv[])
|
|||||||
format_params.blksize = DEFAULT_BLOCKSIZE;
|
format_params.blksize = DEFAULT_BLOCKSIZE;
|
||||||
format_params.intensity = DASD_FMT_INT_COMPAT;
|
format_params.intensity = DASD_FMT_INT_COMPAT;
|
||||||
|
|
||||||
mode = FULL;
|
|
||||||
|
|
||||||
/*************** parse parameters **********************/
|
/*************** parse parameters **********************/
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -1601,6 +1646,10 @@ int main(int argc, char *argv[])
|
|||||||
"invalid. Consult the man page for "
|
"invalid. Consult the man page for "
|
||||||
"more information.\n",
|
"more information.\n",
|
||||||
prog_name, optarg);
|
prog_name, optarg);
|
||||||
|
info.mode_specified = 1;
|
||||||
|
break;
|
||||||
|
case OPT_NODISCARD:
|
||||||
|
info.no_discard = 1;
|
||||||
break;
|
break;
|
||||||
case OPT_CHECK:
|
case OPT_CHECK:
|
||||||
info.check = 1;
|
info.check = 1;
|
||||||
@@ -1645,6 +1694,9 @@ int main(int argc, char *argv[])
|
|||||||
"device information failed (%s).\n",
|
"device information failed (%s).\n",
|
||||||
prog_name, strerror(rc));
|
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 */
|
/* Either let the user specify the blksize or get it from the kernel */
|
||||||
if (!info.blksize_specified) {
|
if (!info.blksize_specified) {
|
||||||
if (!(mode == FULL ||
|
if (!(mode == FULL ||
|
||||||
|
|||||||
+3
-45
@@ -27,10 +27,6 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* SECTION: Definition needed for DASD-API (see dasd.h) *
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Represents possible format modes that can be specified when formatting
|
* Represents possible format modes that can be specified when formatting
|
||||||
* a DASD.
|
* a DASD.
|
||||||
@@ -45,57 +41,16 @@ static const char mode_str[3][10] = {
|
|||||||
"Full", "Quick", "Expand"
|
"Full", "Quick", "Expand"
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* values to be used for format_data_t.intensity
|
|
||||||
* 0/8: normal format
|
|
||||||
* 1/9: also write record zero
|
|
||||||
* 3/11: also write home address
|
|
||||||
* 4/12: invalidate track
|
|
||||||
*/
|
|
||||||
#define DASD_FMT_INT_FMT_R0 1 /* write record zero */
|
|
||||||
#define DASD_FMT_INT_FMT_HA 2 /* write home address, also set FMT_R0 ! */
|
|
||||||
#define DASD_FMT_INT_INVAL 4 /* invalidate tracks */
|
|
||||||
#define DASD_FMT_INT_COMPAT 8 /* use OS/390 compatible disk layout */
|
|
||||||
#define DASD_FMT_INT_FMT_NOR0 16 /* remove permission to write record zero */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* values to be used in format_check_t for indicating
|
|
||||||
* possible format errors
|
|
||||||
*/
|
|
||||||
#define DASD_FMT_ERR_TOO_FEW_RECORDS 1
|
|
||||||
#define DASD_FMT_ERR_TOO_MANY_RECORDS 2
|
|
||||||
#define DASD_FMT_ERR_BLKSIZE 3
|
|
||||||
#define DASD_FMT_ERR_RECORD_ID 4
|
|
||||||
#define DASD_FMT_ERR_KEY_LENGTH 5
|
|
||||||
|
|
||||||
/*
|
|
||||||
* values to be used for dasd_information2_t.format
|
|
||||||
* 0x00: NOT formatted
|
|
||||||
* 0x01: Linux disc layout
|
|
||||||
* 0x02: Common disc layout
|
|
||||||
*/
|
|
||||||
#define DASD_FORMAT_NONE 0
|
|
||||||
#define DASD_FORMAT_LDL 1
|
|
||||||
#define DASD_FORMAT_CDL 2
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* SECTION: DASDFMT internal types *
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#define DASD_PARTN_BITS 2
|
#define DASD_PARTN_BITS 2
|
||||||
#define PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
|
#define PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
|
||||||
|
|
||||||
#define EXIT_MISUSE 1
|
#define EXIT_MISUSE 1
|
||||||
#define EXIT_BUSY 2
|
#define EXIT_BUSY 2
|
||||||
#define LABEL_LENGTH 14
|
|
||||||
#define VLABEL_CHARS 84
|
|
||||||
#define LINE_LENGTH 80
|
|
||||||
#define ERR_LENGTH 90
|
#define ERR_LENGTH 90
|
||||||
|
|
||||||
#define DEFAULT_BLOCKSIZE 4096
|
#define DEFAULT_BLOCKSIZE 4096
|
||||||
/* requestsize - number of cylinders in one format step */
|
/* requestsize - number of cylinders in one format step */
|
||||||
#define DEFAULT_REQUESTSIZE 10
|
#define DEFAULT_REQUESTSIZE 10
|
||||||
#define USABLE_PARTITIONS ((1 << DASD_PARTN_BITS) - 1)
|
|
||||||
|
|
||||||
#define ERRMSG(x...) {fflush(stdout);fprintf(stderr,x);}
|
#define ERRMSG(x...) {fflush(stdout);fprintf(stderr,x);}
|
||||||
#define ERRMSG_EXIT(ec,x...) {fflush(stdout);fprintf(stderr,x);exit(ec);}
|
#define ERRMSG_EXIT(ec,x...) {fflush(stdout);fprintf(stderr,x);exit(ec);}
|
||||||
@@ -137,6 +92,9 @@ typedef struct dasdfmt_info {
|
|||||||
int force_host;
|
int force_host;
|
||||||
int layout_specified;
|
int layout_specified;
|
||||||
int check;
|
int check;
|
||||||
|
int mode_specified;
|
||||||
|
int ese;
|
||||||
|
int no_discard;
|
||||||
} dasdfmt_info_t;
|
} dasdfmt_info_t;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+38
-38
@@ -160,19 +160,19 @@ dasdview_get_info(dasdview_info_t *info)
|
|||||||
if (err != EBADF)
|
if (err != EBADF)
|
||||||
zt_error_print("dasdview: "
|
zt_error_print("dasdview: "
|
||||||
"Could not retrieve geo information!\n");
|
"Could not retrieve geo information!\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dasd_get_blocksize(info->device, &info->blksize) != 0) {
|
if (dasd_get_blocksize(info->device, &info->blksize) != 0) {
|
||||||
zt_error_print("dasdview: "
|
zt_error_print("dasdview: "
|
||||||
"Could not retrieve blocksize information!\n");
|
"Could not retrieve blocksize information!\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dasd_get_info(info->device, &info->dasd_info) != 0) {
|
if (dasd_get_info(info->device, &info->dasd_info) != 0) {
|
||||||
zt_error_print("dasdview: "
|
zt_error_print("dasdview: "
|
||||||
"Could not retrieve disk information!\n");
|
"Could not retrieve disk information!\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
characteristics = (struct dasd_eckd_characteristics *)
|
characteristics = (struct dasd_eckd_characteristics *)
|
||||||
@@ -261,7 +261,7 @@ dasdview_parse_input(unsigned long long *p, dasdview_info_t *info, char *s)
|
|||||||
error:
|
error:
|
||||||
zt_error_print("dasdview: usage error\n"
|
zt_error_print("dasdview: usage error\n"
|
||||||
"%s is not a valid begin/size value!", s);
|
"%s is not a valid begin/size value!", s);
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -454,7 +454,7 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
|||||||
if (rc) {
|
if (rc) {
|
||||||
zt_error_print("error when reading label from device:"
|
zt_error_print("error when reading label from device:"
|
||||||
" rc=%d\n", rc);
|
" rc=%d\n", rc);
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
lzds_dasd_get_vlabel(info->dasd, &tmpvlabel);
|
lzds_dasd_get_vlabel(info->dasd, &tmpvlabel);
|
||||||
memcpy(&vlabel, tmpvlabel, sizeof(vlabel));
|
memcpy(&vlabel, tmpvlabel, sizeof(vlabel));
|
||||||
@@ -600,7 +600,7 @@ dasdview_print_volser(dasdview_info_t *info)
|
|||||||
if (rc) {
|
if (rc) {
|
||||||
zt_error_print("error when reading label from device:"
|
zt_error_print("error when reading label from device:"
|
||||||
" rc=%d\n", rc);
|
" rc=%d\n", rc);
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
lzds_dasd_get_vlabel(info->dasd, &tmpvlabel);
|
lzds_dasd_get_vlabel(info->dasd, &tmpvlabel);
|
||||||
memcpy(&vlabel, tmpvlabel, sizeof(vlabel));
|
memcpy(&vlabel, tmpvlabel, sizeof(vlabel));
|
||||||
@@ -644,7 +644,7 @@ dasdview_read_vtoc(dasdview_info_t *info)
|
|||||||
zt_error_print("dasdview: disk layout error\n"
|
zt_error_print("dasdview: disk layout error\n"
|
||||||
"%s is not formatted with the z/OS "
|
"%s is not formatted with the z/OS "
|
||||||
"compatible disk layout!\n", info->device);
|
"compatible disk layout!\n", info->device);
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
vtocblk = (u_int64_t)vtoc_get_cyl_from_cchhb(&vlabel.vtoc) *
|
vtocblk = (u_int64_t)vtoc_get_cyl_from_cchhb(&vlabel.vtoc) *
|
||||||
@@ -664,7 +664,7 @@ dasdview_read_vtoc(dasdview_info_t *info)
|
|||||||
if ((vtocblk <= 0) || (vtocblk > maxblk)) {
|
if ((vtocblk <= 0) || (vtocblk > maxblk)) {
|
||||||
zt_error_print("dasdview: VTOC error\n"
|
zt_error_print("dasdview: VTOC error\n"
|
||||||
"Volume label VTOC pointer is not valid!\n");
|
"Volume label VTOC pointer is not valid!\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
vtoc_read_label(info->device, (vtocblk - 1) * info->blksize,
|
vtoc_read_label(info->device, (vtocblk - 1) * info->blksize,
|
||||||
@@ -676,7 +676,7 @@ dasdview_read_vtoc(dasdview_info_t *info)
|
|||||||
/* format4 DSCB is invalid */
|
/* format4 DSCB is invalid */
|
||||||
zt_error_print("dasdview: VTOC error\n"
|
zt_error_print("dasdview: VTOC error\n"
|
||||||
"Format 4 DSCB is invalid!\n");
|
"Format 4 DSCB is invalid!\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
info->f4c++;
|
info->f4c++;
|
||||||
@@ -724,19 +724,19 @@ dasdview_read_vtoc(dasdview_info_t *info)
|
|||||||
if (info->f4c > 1) {
|
if (info->f4c > 1) {
|
||||||
zt_error_print("dasdview: VTOC error\n"
|
zt_error_print("dasdview: VTOC error\n"
|
||||||
"More than one FMT4 DSCB!\n");
|
"More than one FMT4 DSCB!\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->f5c > 1) {
|
if (info->f5c > 1) {
|
||||||
zt_error_print("dasdview: VTOC error\n"
|
zt_error_print("dasdview: VTOC error\n"
|
||||||
"More than one FMT5 DSCB!\n");
|
"More than one FMT5 DSCB!\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->f7c > 1) {
|
if (info->f7c > 1) {
|
||||||
zt_error_print("dasdview: VTOC error\n"
|
zt_error_print("dasdview: VTOC error\n"
|
||||||
"More than one FMT7 DSCB!\n");
|
"More than one FMT7 DSCB!\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -975,7 +975,7 @@ static void dasdview_print_format1_8_short_info_raw(format1_label_t *f1,
|
|||||||
}
|
}
|
||||||
if (rc) {
|
if (rc) {
|
||||||
zt_error_print("dasdview: Broken format 3 DSCB chain \n");
|
zt_error_print("dasdview: Broken format 3 DSCB chain \n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
f3 = (dscb && dscb->fmtid == 0xf3) ? (format3_label_t *)dscb : NULL;
|
f3 = (dscb && dscb->fmtid == 0xf3) ? (format3_label_t *)dscb : NULL;
|
||||||
|
|
||||||
@@ -990,7 +990,7 @@ static void dasdview_print_format1_8_short_info_raw(format1_label_t *f1,
|
|||||||
if (f3->DS3FMTID != 0xf3) {
|
if (f3->DS3FMTID != 0xf3) {
|
||||||
zt_error_print("dasdview: Broken format 3 DSCB"
|
zt_error_print("dasdview: Broken format 3 DSCB"
|
||||||
" chain \n");
|
" chain \n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
for (j = 0; j < 4; ++j)
|
for (j = 0; j < 4; ++j)
|
||||||
dasdview_print_short_info_extent_raw(&f3->DS3EXTNT[j]);
|
dasdview_print_short_info_extent_raw(&f3->DS3EXTNT[j]);
|
||||||
@@ -1002,7 +1002,7 @@ static void dasdview_print_format1_8_short_info_raw(format1_label_t *f1,
|
|||||||
if (rc) {
|
if (rc) {
|
||||||
zt_error_print("dasdview: Broken format 3 DSCB"
|
zt_error_print("dasdview: Broken format 3 DSCB"
|
||||||
" chain \n");
|
" chain \n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -1025,7 +1025,7 @@ static void dasdview_print_vtoc_info_raw(dasdview_info_t *info)
|
|||||||
rc = lzds_raw_vtoc_alloc_dscbiterator(info->rawvtoc, &it);
|
rc = lzds_raw_vtoc_alloc_dscbiterator(info->rawvtoc, &it);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
zt_error_print("dasdview: could not allocate DSCB iterator \n");
|
zt_error_print("dasdview: could not allocate DSCB iterator \n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
while (!lzds_dscbiterator_get_next_dscb(it, &dscb)) {
|
while (!lzds_dscbiterator_get_next_dscb(it, &dscb)) {
|
||||||
if (dscb->fmtid == 0xf1)
|
if (dscb->fmtid == 0xf1)
|
||||||
@@ -1058,7 +1058,7 @@ static void dasdview_print_vtoc_info_raw(dasdview_info_t *info)
|
|||||||
rc = lzds_raw_vtoc_alloc_dscbiterator(info->rawvtoc, &it);
|
rc = lzds_raw_vtoc_alloc_dscbiterator(info->rawvtoc, &it);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
zt_error_print("dasdview: could not allocate DSCB iterator \n");
|
zt_error_print("dasdview: could not allocate DSCB iterator \n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
while (!lzds_dscbiterator_get_next_dscb(it, &dscb)) {
|
while (!lzds_dscbiterator_get_next_dscb(it, &dscb)) {
|
||||||
if (dscb->fmtid == 0xf1 || dscb->fmtid == 0xf8)
|
if (dscb->fmtid == 0xf1 || dscb->fmtid == 0xf8)
|
||||||
@@ -1739,23 +1739,23 @@ static void dasdview_print_vtoc_raw(dasdview_info_t *info)
|
|||||||
if (rc) {
|
if (rc) {
|
||||||
zt_error_print("error when reading label from device:"
|
zt_error_print("error when reading label from device:"
|
||||||
" rc=%d\n", rc);
|
" rc=%d\n", rc);
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
rc = lzds_dasd_alloc_rawvtoc(info->dasd);
|
rc = lzds_dasd_alloc_rawvtoc(info->dasd);
|
||||||
if (rc == EINVAL) {
|
if (rc == EINVAL) {
|
||||||
zt_error_print("dasdview: Cannot read VTOC because disk does"
|
zt_error_print("dasdview: Cannot read VTOC because disk does"
|
||||||
" not contain valid VOL1 label.\n",
|
" not contain valid VOL1 label.\n",
|
||||||
info->device);
|
info->device);
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
} else if (rc) {
|
} else if (rc) {
|
||||||
zt_error_print("error when reading vtoc from device:"
|
zt_error_print("error when reading vtoc from device:"
|
||||||
" rc=%d\n", rc);
|
" rc=%d\n", rc);
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
rc = lzds_dasd_get_rawvtoc(info->dasd, &info->rawvtoc);
|
rc = lzds_dasd_get_rawvtoc(info->dasd, &info->rawvtoc);
|
||||||
if (rc || !info->rawvtoc) {
|
if (rc || !info->rawvtoc) {
|
||||||
zt_error_print("dasdview: libvtoc could not read vtoc\n");
|
zt_error_print("dasdview: libvtoc could not read vtoc\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->vtoc_info || info->vtoc_all)
|
if (info->vtoc_info || info->vtoc_all)
|
||||||
@@ -1764,7 +1764,7 @@ static void dasdview_print_vtoc_raw(dasdview_info_t *info)
|
|||||||
rc = lzds_raw_vtoc_alloc_dscbiterator(info->rawvtoc, &it);
|
rc = lzds_raw_vtoc_alloc_dscbiterator(info->rawvtoc, &it);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
zt_error_print("dasdview: could not allocate DSCB iterator\n");
|
zt_error_print("dasdview: could not allocate DSCB iterator\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
while (!lzds_dscbiterator_get_next_dscb(it, &record))
|
while (!lzds_dscbiterator_get_next_dscb(it, &record))
|
||||||
dasdview_print_vtoc_dscb(info, record);
|
dasdview_print_vtoc_dscb(info, record);
|
||||||
@@ -1858,7 +1858,7 @@ static void dasdview_view_standard(dasdview_info_t *info)
|
|||||||
zt_error_print("dasdview: open error\n"
|
zt_error_print("dasdview: open error\n"
|
||||||
"Unable to open device %s in read-only mode!\n",
|
"Unable to open device %s in read-only mode!\n",
|
||||||
info->device);
|
info->device);
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
j = (info->begin / SEEK_STEP);
|
j = (info->begin / SEEK_STEP);
|
||||||
@@ -1877,7 +1877,7 @@ static void dasdview_view_standard(dasdview_info_t *info)
|
|||||||
zt_error_print("dasdview: seek error\n"
|
zt_error_print("dasdview: seek error\n"
|
||||||
"Unable to seek in device %s!\n",
|
"Unable to seek in device %s!\n",
|
||||||
info->device);
|
info->device);
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
b++;
|
b++;
|
||||||
a += SEEK_STEP;
|
a += SEEK_STEP;
|
||||||
@@ -1890,7 +1890,7 @@ static void dasdview_view_standard(dasdview_info_t *info)
|
|||||||
zt_error_print("dasdview: seek error\n"
|
zt_error_print("dasdview: seek error\n"
|
||||||
"Unable to seek in device %s!\n",
|
"Unable to seek in device %s!\n",
|
||||||
info->device);
|
info->device);
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1926,7 +1926,7 @@ static void dasdview_view_standard(dasdview_info_t *info)
|
|||||||
zt_error_print("dasdview: read error\n"
|
zt_error_print("dasdview: read error\n"
|
||||||
"Unable to read from device %s!\n",
|
"Unable to read from device %s!\n",
|
||||||
info->device);
|
info->device);
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->format1)
|
if (info->format1)
|
||||||
@@ -1945,7 +1945,7 @@ static void dasdview_view_standard(dasdview_info_t *info)
|
|||||||
zt_error_print("dasdview: read error\n"
|
zt_error_print("dasdview: read error\n"
|
||||||
"Unable to read from device %s!\n",
|
"Unable to read from device %s!\n",
|
||||||
info->device);
|
info->device);
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->format1)
|
if (info->format1)
|
||||||
@@ -2112,18 +2112,18 @@ static void dasdview_view_raw(dasdview_info_t *info)
|
|||||||
trackdata = memalign(4096, trckbuffsize * RAWTRACKSIZE);
|
trackdata = memalign(4096, trckbuffsize * RAWTRACKSIZE);
|
||||||
if (!trackdata) {
|
if (!trackdata) {
|
||||||
zt_error_print("failed to allocate memory\n");
|
zt_error_print("failed to allocate memory\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
rc = lzds_dasd_alloc_dasdhandle(info->dasd, &dasdh);
|
rc = lzds_dasd_alloc_dasdhandle(info->dasd, &dasdh);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
zt_error_print("failed to allocate memory\n");
|
zt_error_print("failed to allocate memory\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
rc = lzds_dasdhandle_open(dasdh);
|
rc = lzds_dasdhandle_open(dasdh);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
lzds_dasdhandle_free(dasdh);
|
lzds_dasdhandle_free(dasdh);
|
||||||
zt_error_print("failed to open device\n");
|
zt_error_print("failed to open device\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
/* residual is the number of tracks we still have to read */
|
/* residual is the number of tracks we still have to read */
|
||||||
residual = tracks_to_read;
|
residual = tracks_to_read;
|
||||||
@@ -2135,7 +2135,7 @@ static void dasdview_view_raw(dasdview_info_t *info)
|
|||||||
trckend, trackdata);
|
trckend, trackdata);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
perror("Error on read");
|
perror("Error on read");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
data = trackdata;
|
data = trackdata;
|
||||||
for (i = 0; i < trckcount; ++i) {
|
for (i = 0; i < trckcount; ++i) {
|
||||||
@@ -2153,7 +2153,7 @@ static void dasdview_view_raw(dasdview_info_t *info)
|
|||||||
lzds_dasdhandle_free(dasdh);
|
lzds_dasdhandle_free(dasdh);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
perror("Error on closing file");
|
perror("Error on closing file");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2253,7 +2253,7 @@ int main(int argc, char *argv[])
|
|||||||
zt_error_print("dasdview: usage error\n"
|
zt_error_print("dasdview: usage error\n"
|
||||||
"%s is no valid argument for"
|
"%s is no valid argument for"
|
||||||
" option -t/--vtoc\n", optarg);
|
" option -t/--vtoc\n", optarg);
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
info.vtoc = 1;
|
info.vtoc = 1;
|
||||||
info.action_specified = 1;
|
info.action_specified = 1;
|
||||||
@@ -2301,13 +2301,13 @@ int main(int argc, char *argv[])
|
|||||||
rc = lzds_zdsroot_alloc(&info.zdsroot);
|
rc = lzds_zdsroot_alloc(&info.zdsroot);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
zt_error_print("Could not allocate index\n");
|
zt_error_print("Could not allocate index\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
rc = lzds_zdsroot_add_device(info.zdsroot, info.device,
|
rc = lzds_zdsroot_add_device(info.zdsroot, info.device,
|
||||||
&info.dasd);
|
&info.dasd);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
zt_error_print("Could not add device to index\n");
|
zt_error_print("Could not add device to index\n");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2328,7 +2328,7 @@ int main(int argc, char *argv[])
|
|||||||
if (info.begin > max) {
|
if (info.begin > max) {
|
||||||
zt_error_print("dasdview: usage error\n"
|
zt_error_print("dasdview: usage error\n"
|
||||||
"'begin' value is not within disk range!");
|
"'begin' value is not within disk range!");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.size_specified)
|
if (info.size_specified)
|
||||||
@@ -2343,7 +2343,7 @@ int main(int argc, char *argv[])
|
|||||||
zt_error_print("dasdview: usage error\n"
|
zt_error_print("dasdview: usage error\n"
|
||||||
"'begin' + 'size' is not within "
|
"'begin' + 'size' is not within "
|
||||||
"disk range!");
|
"disk range!");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((info.begin_specified || info.size_specified) &&
|
if ((info.begin_specified || info.size_specified) &&
|
||||||
@@ -2355,7 +2355,7 @@ int main(int argc, char *argv[])
|
|||||||
zt_error_print("dasdview: usage error\n"
|
zt_error_print("dasdview: usage error\n"
|
||||||
"Options -1 or -2 make only sense with "
|
"Options -1 or -2 make only sense with "
|
||||||
"options -b or -s!");
|
"options -b or -s!");
|
||||||
exit(-1);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do the output */
|
/* do the output */
|
||||||
|
|||||||
@@ -54,6 +54,16 @@ typedef struct dasd_information2_t {
|
|||||||
unsigned int reserved7; /* reserved for further use ,... */
|
unsigned int reserved7; /* reserved for further use ,... */
|
||||||
} dasd_information2_t;
|
} dasd_information2_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* values to be used for dasd_information2_t.format
|
||||||
|
* 0x00: NOT formatted
|
||||||
|
* 0x01: Linux disc layout
|
||||||
|
* 0x02: Common disc layout
|
||||||
|
*/
|
||||||
|
#define DASD_FORMAT_NONE 0
|
||||||
|
#define DASD_FORMAT_LDL 1
|
||||||
|
#define DASD_FORMAT_CDL 2
|
||||||
|
|
||||||
struct dasd_eckd_characteristics {
|
struct dasd_eckd_characteristics {
|
||||||
unsigned short cu_type;
|
unsigned short cu_type;
|
||||||
struct {
|
struct {
|
||||||
@@ -139,6 +149,16 @@ typedef struct format_data_t {
|
|||||||
unsigned int intensity;
|
unsigned int intensity;
|
||||||
} format_data_t;
|
} format_data_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* values to be used for format_data_t.intensity
|
||||||
|
*/
|
||||||
|
#define DASD_FMT_INT_FMT_R0 1 /* write record zero */
|
||||||
|
#define DASD_FMT_INT_FMT_HA 2 /* write home address, also set FMT_R0 ! */
|
||||||
|
#define DASD_FMT_INT_INVAL 4 /* invalidate tracks */
|
||||||
|
#define DASD_FMT_INT_COMPAT 8 /* use OS/390 compatible disk layout */
|
||||||
|
#define DASD_FMT_INT_FMT_NOR0 16 /* remove permission to write record zero */
|
||||||
|
#define DASD_FMT_INT_ESE_FULL 32 /* release space for entire volume */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* struct format_check_t
|
* struct format_check_t
|
||||||
* represents all data necessary to evaluate the format of
|
* represents all data necessary to evaluate the format of
|
||||||
@@ -157,6 +177,16 @@ typedef struct format_check_t {
|
|||||||
unsigned int key_length; /* Key length of first record in error */
|
unsigned int key_length; /* Key length of first record in error */
|
||||||
} format_check_t;
|
} format_check_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* values to be used in format_check_t for indicating
|
||||||
|
* possible format errors
|
||||||
|
*/
|
||||||
|
#define DASD_FMT_ERR_TOO_FEW_RECORDS 1
|
||||||
|
#define DASD_FMT_ERR_TOO_MANY_RECORDS 2
|
||||||
|
#define DASD_FMT_ERR_BLKSIZE 3
|
||||||
|
#define DASD_FMT_ERR_RECORD_ID 4
|
||||||
|
#define DASD_FMT_ERR_KEY_LENGTH 5
|
||||||
|
|
||||||
#ifndef __linux__
|
#ifndef __linux__
|
||||||
/* definition from hdreg.h */
|
/* definition from hdreg.h */
|
||||||
struct hd_geometry {
|
struct hd_geometry {
|
||||||
@@ -181,6 +211,8 @@ struct hd_geometry {
|
|||||||
#define BIODASDINFO2 _IOR(DASD_IOCTL_LETTER, 3, dasd_information2_t)
|
#define BIODASDINFO2 _IOR(DASD_IOCTL_LETTER, 3, dasd_information2_t)
|
||||||
/* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */
|
/* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */
|
||||||
#define BIODASDFMT _IOW(DASD_IOCTL_LETTER, 1, format_data_t)
|
#define BIODASDFMT _IOW(DASD_IOCTL_LETTER, 1, format_data_t)
|
||||||
|
/* Release Allocated Space */
|
||||||
|
#define BIODASDRAS _IOW(DASD_IOCTL_LETTER, 3, format_data_t)
|
||||||
/* Check device format according to format_data_t */
|
/* Check device format according to format_data_t */
|
||||||
#define BIODASDCHECKFMT _IOWR(DASD_IOCTL_LETTER, 2, format_check_t)
|
#define BIODASDCHECKFMT _IOWR(DASD_IOCTL_LETTER, 2, format_check_t)
|
||||||
|
|
||||||
@@ -204,6 +236,7 @@ int dasd_check_format(const char *device, format_check_t *p);
|
|||||||
int dasd_format_disk(int fd, format_data_t *p);
|
int dasd_format_disk(int fd, format_data_t *p);
|
||||||
int dasd_disk_disable(const char *device, int *fd);
|
int dasd_disk_disable(const char *device, int *fd);
|
||||||
int dasd_disk_enable(int fd);
|
int dasd_disk_enable(int fd);
|
||||||
|
int dasd_release_space(const char *device, format_data_t *r);
|
||||||
int dasd_get_blocksize(const char *device, unsigned int *blksize);
|
int dasd_get_blocksize(const char *device, unsigned int *blksize);
|
||||||
int dasd_get_blocksize_in_bytes(const char *device, unsigned long long *blksize);
|
int dasd_get_blocksize_in_bytes(const char *device, unsigned long long *blksize);
|
||||||
int dasd_get_geo(const char *device, struct hd_geometry *geo);
|
int dasd_get_geo(const char *device, struct hd_geometry *geo);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int dasd_sys_raw_track_access(char *);
|
int dasd_sys_raw_track_access(char *);
|
||||||
|
int dasd_sys_ese(char *);
|
||||||
int dasd_reset_chpid(char *, char *);
|
int dasd_reset_chpid(char *, char *);
|
||||||
int dasd_get_host_access_count(char *device);
|
int dasd_get_host_access_count(char *device);
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
#define __packed __attribute__((packed))
|
#define __packed __attribute__((packed))
|
||||||
#define __aligned(x) __attribute__((aligned(x)))
|
#define __aligned(x) __attribute__((aligned(x)))
|
||||||
#define __may_alias __attribute__((may_alias))
|
#define __may_alias __attribute__((may_alias))
|
||||||
|
#define __section(x) __attribute__((__section__(#x)))
|
||||||
|
#define __noinline __attribute__((__noinline__))
|
||||||
|
|
||||||
typedef unsigned long long u64;
|
typedef unsigned long long u64;
|
||||||
typedef signed long long s64;
|
typedef signed long long s64;
|
||||||
|
|||||||
+22
-1
@@ -146,9 +146,10 @@ int dasd_is_ro(const char *device, bool *ro)
|
|||||||
{
|
{
|
||||||
int fd, val;
|
int fd, val;
|
||||||
|
|
||||||
fd = dasd_open_device(device, O_RDWR);
|
fd = dasd_open_device(device, O_RDONLY);
|
||||||
RUN_IOCTL(fd, BLKROGET, &val);
|
RUN_IOCTL(fd, BLKROGET, &val);
|
||||||
*ro = (val != 0) ? true : false;
|
*ro = (val != 0) ? true : false;
|
||||||
|
dasd_close_device(fd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -228,6 +229,26 @@ int dasd_check_format(const char *device, format_check_t *p)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Release Allocated Space
|
||||||
|
*
|
||||||
|
* @param[in] fd device node's file descriptor
|
||||||
|
* @param[in] r format options
|
||||||
|
*
|
||||||
|
* @retval 0 in case of success
|
||||||
|
* @retval errno in case of failure
|
||||||
|
*/
|
||||||
|
int dasd_release_space(const char *device, format_data_t *r)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = dasd_open_device(device, O_RDONLY);
|
||||||
|
RUN_IOCTL(fd, BIODASDRAS, r);
|
||||||
|
dasd_close_device(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reread partition table
|
* Reread partition table
|
||||||
*
|
*
|
||||||
|
|||||||
+38
-1
@@ -57,6 +57,43 @@ int dasd_sys_raw_track_access(char *devnode)
|
|||||||
return (rc == 1) ? 1 : 0;
|
return (rc == 1) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is volume extent space efficient a.k.a. thin-provisioned
|
||||||
|
*
|
||||||
|
* The "devnode" parameter can be any valid relative or absolute path to
|
||||||
|
* a DASD device node, for example:
|
||||||
|
*
|
||||||
|
* - /dev/dasda
|
||||||
|
* - /dev/disk/by-path/ccw-0.0.bf20
|
||||||
|
*
|
||||||
|
* @param[in] devnode Device node of interest
|
||||||
|
*
|
||||||
|
* @retval 1 Volume is extent space efficient
|
||||||
|
* @retval 0 Volume is not extent space efficient or
|
||||||
|
* cannot be determined
|
||||||
|
*/
|
||||||
|
int dasd_sys_ese(char *devnode)
|
||||||
|
{
|
||||||
|
char busid[DASD_BUS_ID_SIZE];
|
||||||
|
char *path;
|
||||||
|
FILE *fp;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (util_sys_get_dev_addr(devnode, busid) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
path = util_path_sysfs("bus/ccw/devices/%s/ese", busid);
|
||||||
|
fp = fopen(path, "r");
|
||||||
|
if (!fp) {
|
||||||
|
free(path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = fgetc(fp) - '0';
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return (rc == 1) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
int dasd_get_pm_from_chpid(char *busid, unsigned int chpid, int *mask)
|
int dasd_get_pm_from_chpid(char *busid, unsigned int chpid, int *mask)
|
||||||
{
|
{
|
||||||
@@ -173,7 +210,7 @@ int dasd_reset_chpid(char *devnode, char *chpid_char)
|
|||||||
*/
|
*/
|
||||||
int dasd_get_host_access_count(char *device)
|
int dasd_get_host_access_count(char *device)
|
||||||
{
|
{
|
||||||
char busid[9];
|
char busid[DASD_BUS_ID_SIZE];
|
||||||
char *path;
|
char *path;
|
||||||
long value;
|
long value;
|
||||||
|
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
#include "lib/util_panic.h"
|
#include "lib/util_panic.h"
|
||||||
|
|
||||||
/* Make functions noinline to have a nice backtrace */
|
/* Make functions noinline to have a nice backtrace */
|
||||||
#define __noinline __attribute__((noinline))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test util_panic()
|
* Test util_panic()
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ pxelinux.initramfs: $(BBINSTALL)
|
|||||||
$(BUSYBOX)/_install:
|
$(BUSYBOX)/_install:
|
||||||
wget https://busybox.net/downloads/$(BUSYBOX).tar.bz2
|
wget https://busybox.net/downloads/$(BUSYBOX).tar.bz2
|
||||||
tar xjf $(BUSYBOX).tar.bz2
|
tar xjf $(BUSYBOX).tar.bz2
|
||||||
make -C $(BUSYBOX) defconfig
|
$(MAKE) -C $(BUSYBOX) defconfig
|
||||||
make -C $(BUSYBOX) install
|
$(MAKE) -C $(BUSYBOX) install
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
|
||||||
|
|||||||
+83
-12
@@ -173,6 +173,12 @@ readonly OUTPUT_FILE_LSOF="${WORKPATH}open_files.out"
|
|||||||
# File that includes content of OSA OAT
|
# File that includes content of OSA OAT
|
||||||
readonly OUTPUT_FILE_OSAOAT="${WORKPATH}osa_oat"
|
readonly OUTPUT_FILE_OSAOAT="${WORKPATH}osa_oat"
|
||||||
|
|
||||||
|
# File that includes content of Ethtool commands
|
||||||
|
readonly OUTPUT_FILE_ETHTOOL="${WORKPATH}ethtool.out"
|
||||||
|
|
||||||
|
# File that includes content of tc commands
|
||||||
|
readonly OUTPUT_FILE_TC="${WORKPATH}tc.out"
|
||||||
|
|
||||||
# File that includes the output of journalctl
|
# File that includes the output of journalctl
|
||||||
readonly OUTPUT_FILE_JOURNALCTL="${WORKPATH}journalctl.out"
|
readonly OUTPUT_FILE_JOURNALCTL="${WORKPATH}journalctl.out"
|
||||||
|
|
||||||
@@ -192,7 +198,7 @@ readonly OUTPUT_FILE_NVME="${WORKPATH}nvme.out"
|
|||||||
readonly MOUNT_POINT_DEBUGFS="/sys/kernel/debug"
|
readonly MOUNT_POINT_DEBUGFS="/sys/kernel/debug"
|
||||||
|
|
||||||
# The amount of steps running the whole collections
|
# The amount of steps running the whole collections
|
||||||
readonly COLLECTION_COUNT=12
|
readonly COLLECTION_COUNT=14
|
||||||
|
|
||||||
# The kernel version (e.g. '2' from 2.6.32 or '3' from 3.2.1)
|
# The kernel version (e.g. '2' from 2.6.32 or '3' from 3.2.1)
|
||||||
readonly KERNEL_VERSION=$(uname -r 2>/dev/null | cut -d'.' -f1)
|
readonly KERNEL_VERSION=$(uname -r 2>/dev/null | cut -d'.' -f1)
|
||||||
@@ -371,7 +377,7 @@ CONFIGFILES="\
|
|||||||
$(find /lib/modules -name modules.dep 2>/dev/null)\
|
$(find /lib/modules -name modules.dep 2>/dev/null)\
|
||||||
/etc/docker\
|
/etc/docker\
|
||||||
/lib/systemd/system/docker.service\
|
/lib/systemd/system/docker.service\
|
||||||
/usr/lib/systemd/system/docker.service\
|
/usr/lib/systemd/system\
|
||||||
/etc/apparmor.d\
|
/etc/apparmor.d\
|
||||||
"
|
"
|
||||||
|
|
||||||
@@ -398,6 +404,7 @@ CMDS="uname -a\
|
|||||||
:ip link show\
|
:ip link show\
|
||||||
:ip ntable\
|
:ip ntable\
|
||||||
:ip a sh\
|
:ip a sh\
|
||||||
|
:ip -s -s link\
|
||||||
:firewall-cmd --list-all\
|
:firewall-cmd --list-all\
|
||||||
:ipcs -a\
|
:ipcs -a\
|
||||||
:netstat -pantu\
|
:netstat -pantu\
|
||||||
@@ -456,7 +463,7 @@ CMDS="uname -a\
|
|||||||
:java -version\
|
:java -version\
|
||||||
:cat /root/.bash_history\
|
:cat /root/.bash_history\
|
||||||
:env\
|
:env\
|
||||||
:journalctl --all --no-pager --since=$(date -d '5 day ago' +%Y-%m-%d) --until=now --lines=50000 \
|
:journalctl --all --no-pager --lines=100000 --output=short-precise\
|
||||||
> '${OUTPUT_FILE_JOURNALCTL}'\
|
> '${OUTPUT_FILE_JOURNALCTL}'\
|
||||||
:openssl engine\
|
:openssl engine\
|
||||||
:systemd-delta\
|
:systemd-delta\
|
||||||
@@ -472,6 +479,8 @@ CMDS="uname -a\
|
|||||||
:systemctl status docker.service\
|
:systemctl status docker.service\
|
||||||
:blockdev --report\
|
:blockdev --report\
|
||||||
:lvdisplay\
|
:lvdisplay\
|
||||||
|
:lspci -vv\
|
||||||
|
:smc_dbg\
|
||||||
"
|
"
|
||||||
|
|
||||||
########################################
|
########################################
|
||||||
@@ -556,6 +565,11 @@ collect_cmdsout() {
|
|||||||
done
|
done
|
||||||
IFS="${ifs_orig}"
|
IFS="${ifs_orig}"
|
||||||
|
|
||||||
|
if echo "${RUNTIME_ENVIRONMENT}" | grep -qi "z/VM" >/dev/null 2>&1; then
|
||||||
|
call_run_command "hyptop -b -d 1 -n 5 -f \#,c,m,C:s,M:s,o -S c" "${OUTPUT_FILE_CMD}"
|
||||||
|
else call_run_command "hyptop -b -d 1 -n 5 -f \#,T,c,e,m,C:s,E:s,M:s,o -S c" "${OUTPUT_FILE_CMD}"
|
||||||
|
fi
|
||||||
|
|
||||||
pr_log_stdout " "
|
pr_log_stdout " "
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -750,6 +764,59 @@ collect_osaoat() {
|
|||||||
pr_log_stdout " "
|
pr_log_stdout " "
|
||||||
}
|
}
|
||||||
|
|
||||||
|
########################################
|
||||||
|
collect_ethtool() {
|
||||||
|
local network_devices
|
||||||
|
local network_device
|
||||||
|
|
||||||
|
network_devices=$(ls /sys/class/net 2>/dev/null)
|
||||||
|
if which ethtool >/dev/null 2>&1; then
|
||||||
|
if test -n "${network_devices}"; then
|
||||||
|
pr_syslog_stdout "8 of ${COLLECTION_COUNT}: Collecting ethtool output"
|
||||||
|
for network_device in ${network_devices}; do
|
||||||
|
call_run_command "ethtool ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
|
||||||
|
call_run_command "ethtool -k ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
|
||||||
|
call_run_command "ethtool -a ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
|
||||||
|
call_run_command "ethtool -c ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
|
||||||
|
call_run_command "ethtool -g ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
|
||||||
|
call_run_command "ethtool -i ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
|
||||||
|
call_run_command "ethtool -l ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
|
||||||
|
call_run_command "ethtool -P ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
|
||||||
|
call_run_command "ethtool -S ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
|
||||||
|
call_run_command "ethtool -T ${network_device}" "${OUTPUT_FILE_ETHTOOL}"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
pr_syslog_stdout "8 of ${COLLECTION_COUNT}: Collecting ethtool output skipped - no devices"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pr_syslog_stdout "8 of ${COLLECTION_COUNT}: Collecting ethtool output skipped - not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
pr_log_stdout " "
|
||||||
|
}
|
||||||
|
|
||||||
|
########################################
|
||||||
|
collect_tc() {
|
||||||
|
local network_devices
|
||||||
|
local network_device
|
||||||
|
|
||||||
|
network_devices=$(ls /sys/class/net 2>/dev/null)
|
||||||
|
if which tc >/dev/null 2>&1; then
|
||||||
|
if test -n "${network_devices}"; then
|
||||||
|
pr_syslog_stdout "9 of ${COLLECTION_COUNT}: Collecting tc output"
|
||||||
|
for network_device in ${network_devices}; do
|
||||||
|
call_run_command "tc -s qdisc show dev ${network_device}" "${OUTPUT_FILE_TC}"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
pr_syslog_stdout "9 of ${COLLECTION_COUNT}: Collecting tc output skipped - no devices"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pr_syslog_stdout "9 of ${COLLECTION_COUNT}: Collecting tc output skipped - not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
pr_log_stdout " "
|
||||||
|
}
|
||||||
|
|
||||||
########################################
|
########################################
|
||||||
# OpenVSwitch
|
# OpenVSwitch
|
||||||
collect_ovs() {
|
collect_ovs() {
|
||||||
@@ -766,7 +833,7 @@ collect_ovs() {
|
|||||||
:ovsdb-client dump\
|
:ovsdb-client dump\
|
||||||
"
|
"
|
||||||
if test -n "${br_list}"; then
|
if test -n "${br_list}"; then
|
||||||
pr_syslog_stdout "8 of ${COLLECTION_COUNT}: Collecting OpenVSwitch output"
|
pr_syslog_stdout "10 of ${COLLECTION_COUNT}: Collecting OpenVSwitch output"
|
||||||
IFS=:
|
IFS=:
|
||||||
for ovscmd in ${ovscmds}; do
|
for ovscmd in ${ovscmds}; do
|
||||||
IFS=${ifs_orig} call_run_command "${ovscmd}" "${OUTPUT_FILE_OVS}.out"
|
IFS=${ifs_orig} call_run_command "${ovscmd}" "${OUTPUT_FILE_OVS}.out"
|
||||||
@@ -785,7 +852,7 @@ collect_ovs() {
|
|||||||
IFS="${ifs_orig}"
|
IFS="${ifs_orig}"
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
pr_syslog_stdout "8 of ${COLLECTION_COUNT}: Collecting OpenVSwitch output skipped"
|
pr_syslog_stdout "10 of ${COLLECTION_COUNT}: Collecting OpenVSwitch output skipped"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pr_log_stdout " "
|
pr_log_stdout " "
|
||||||
@@ -798,12 +865,12 @@ collect_domain_xml() {
|
|||||||
|
|
||||||
domain_list=$(virsh list --all --name)
|
domain_list=$(virsh list --all --name)
|
||||||
if test -n "${domain_list}"; then
|
if test -n "${domain_list}"; then
|
||||||
pr_syslog_stdout "9 of ${COLLECTION_COUNT}: Collecting domain xml files"
|
pr_syslog_stdout "11 of ${COLLECTION_COUNT}: Collecting domain xml files"
|
||||||
for domain in ${domain_list}; do
|
for domain in ${domain_list}; do
|
||||||
call_run_command "virsh dumpxml ${domain}" "${OUTPUT_FILE_XML}_${domain}.xml"
|
call_run_command "virsh dumpxml ${domain}" "${OUTPUT_FILE_XML}_${domain}.xml"
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
pr_syslog_stdout "9 of ${COLLECTION_COUNT}: Collecting domain xml files skipped"
|
pr_syslog_stdout "11 of ${COLLECTION_COUNT}: Collecting domain xml files skipped"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pr_log_stdout " "
|
pr_log_stdout " "
|
||||||
@@ -817,23 +884,23 @@ collect_docker() {
|
|||||||
# call docker inspect for all containers
|
# call docker inspect for all containers
|
||||||
item_list=$(docker ps -qa)
|
item_list=$(docker ps -qa)
|
||||||
if test -n "${item_list}"; then
|
if test -n "${item_list}"; then
|
||||||
pr_syslog_stdout "10a of ${COLLECTION_COUNT}: Collecting docker container output"
|
pr_syslog_stdout "12a of ${COLLECTION_COUNT}: Collecting docker container output"
|
||||||
for item in ${item_list}; do
|
for item in ${item_list}; do
|
||||||
call_run_command "docker inspect ${item}" "${OUTPUT_FILE_DOCKER}"
|
call_run_command "docker inspect ${item}" "${OUTPUT_FILE_DOCKER}"
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
pr_syslog_stdout "10a of ${COLLECTION_COUNT}: Collecting docker container output skipped"
|
pr_syslog_stdout "12a of ${COLLECTION_COUNT}: Collecting docker container output skipped"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# call docker inspect for all networks
|
# call docker inspect for all networks
|
||||||
item_list=$(docker network ls -q)
|
item_list=$(docker network ls -q)
|
||||||
if test -n "${item_list}"; then
|
if test -n "${item_list}"; then
|
||||||
pr_syslog_stdout "10b of ${COLLECTION_COUNT}: Collecting docker network output"
|
pr_syslog_stdout "12b of ${COLLECTION_COUNT}: Collecting docker network output"
|
||||||
for item in ${item_list}; do
|
for item in ${item_list}; do
|
||||||
call_run_command "docker network inspect ${item}" "${OUTPUT_FILE_DOCKER}"
|
call_run_command "docker network inspect ${item}" "${OUTPUT_FILE_DOCKER}"
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
pr_syslog_stdout "10b of ${COLLECTION_COUNT}: Collecting docker network output skipped"
|
pr_syslog_stdout "12b of ${COLLECTION_COUNT}: Collecting docker network output skipped"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pr_log_stdout " "
|
pr_log_stdout " "
|
||||||
@@ -843,7 +910,7 @@ collect_docker() {
|
|||||||
collect_nvme() {
|
collect_nvme() {
|
||||||
local NVME
|
local NVME
|
||||||
|
|
||||||
pr_syslog_stdout "11 of ${COLLECTION_COUNT}: Collecting nvme output"
|
pr_syslog_stdout "13 of ${COLLECTION_COUNT}: Collecting nvme output"
|
||||||
call_run_command "nvme list" "${OUTPUT_FILE_NVME}"
|
call_run_command "nvme list" "${OUTPUT_FILE_NVME}"
|
||||||
|
|
||||||
for NVME in /dev/nvme[0-9]*; do
|
for NVME in /dev/nvme[0-9]*; do
|
||||||
@@ -1150,6 +1217,10 @@ collect_configfiles
|
|||||||
|
|
||||||
collect_osaoat
|
collect_osaoat
|
||||||
|
|
||||||
|
collect_ethtool
|
||||||
|
|
||||||
|
collect_tc
|
||||||
|
|
||||||
collect_ovs
|
collect_ovs
|
||||||
|
|
||||||
collect_domain_xml
|
collect_domain_xml
|
||||||
|
|||||||
+22
-14
@@ -52,7 +52,7 @@ Sample invocation:
|
|||||||
.br
|
.br
|
||||||
dbginfo.sh: Debug information script version %S390_TOOLS_VERSION%
|
dbginfo.sh: Debug information script version %S390_TOOLS_VERSION%
|
||||||
.br
|
.br
|
||||||
Copyright IBM Corp. 2002, 2017
|
Copyright IBM Corp. 2002, 2019
|
||||||
.PP
|
.PP
|
||||||
Hardware platform = s390x
|
Hardware platform = s390x
|
||||||
.br
|
.br
|
||||||
@@ -60,34 +60,42 @@ Kernel version = <kernel\-version>
|
|||||||
.br
|
.br
|
||||||
Runtime environment = z/VM
|
Runtime environment = z/VM
|
||||||
.PP
|
.PP
|
||||||
1 of 11: Collecting command output
|
1 of 14: Collecting command output
|
||||||
.PP
|
.PP
|
||||||
2 of 11: Collecting z/VM command output
|
2 of 14: Collecting z/VM command output
|
||||||
.PP
|
.PP
|
||||||
3 of 11: Collecting procfs
|
3 of 14: Collecting procfs
|
||||||
.PP
|
.PP
|
||||||
4 of 11: Collecting sysfs
|
4 of 14: Collecting sysfs
|
||||||
.PP
|
.PP
|
||||||
5 of 11: Collecting log files
|
5 of 14: Collecting log files
|
||||||
.PP
|
.PP
|
||||||
6 of 11: Collecting config files
|
6 of 14: Collecting config files
|
||||||
.PP
|
.PP
|
||||||
7 of 11: Collecting osa oat output skipped \- not available
|
7 of 14: Collecting osa oat output skipped \- not available
|
||||||
.PP
|
.PP
|
||||||
8 of 11: Collecting OpenVSwitch output
|
8 of 14: Collecting ethtool output
|
||||||
.PP
|
.PP
|
||||||
9 of 11: Collecting domain xml files
|
9 of 14: Collecting tc output
|
||||||
|
.pp
|
||||||
|
10 of 14: Collecting OpenVSwitch output
|
||||||
.PP
|
.PP
|
||||||
10a of 11: Collecting docker container output
|
11 of 14: Collecting domain xml files
|
||||||
10b of 11: Collecting docker network output
|
|
||||||
.PP
|
.PP
|
||||||
11 of 11: Postprocessing
|
12a of 14: Collecting docker container output
|
||||||
|
12b of 14: Collecting docker network output
|
||||||
|
.PP
|
||||||
|
13 of 14: Collecting nvme output
|
||||||
|
.PP
|
||||||
|
14 of 14: Postprocessing
|
||||||
.PP
|
.PP
|
||||||
Finalizing: Creating archive with collected data
|
Finalizing: Creating archive with collected data
|
||||||
.PP
|
.PP
|
||||||
Collected data was saved to:
|
Collected data was saved to:
|
||||||
.br
|
.br
|
||||||
>> /data\-collection/DBGINFO\-2015\-02\-26\-21\-39\-16\-host\-012345.tgz <<
|
>> /data\-collection/DBGINFO\-2019\-08\-19\-21\-39\-16\-host\-012345.tgz <<
|
||||||
|
.br
|
||||||
|
Review the collected data before sending to your service organization.
|
||||||
.SH HINTS
|
.SH HINTS
|
||||||
Run the script with root authority.
|
Run the script with root authority.
|
||||||
.br
|
.br
|
||||||
|
|||||||
+23
-7
@@ -164,6 +164,7 @@ function gatherDeviceData() {
|
|||||||
read DEV_UID 2> /dev/null < $DEVPATH/uid || continue
|
read DEV_UID 2> /dev/null < $DEVPATH/uid || continue
|
||||||
read READONLY 2> /dev/null < $DEVPATH/readonly || continue
|
read READONLY 2> /dev/null < $DEVPATH/readonly || continue
|
||||||
read DISCIPLINE 2> /dev/null < $DEVPATH/discipline || continue
|
read DISCIPLINE 2> /dev/null < $DEVPATH/discipline || continue
|
||||||
|
read ESE 2> /dev/null < $DEVPATH/ese
|
||||||
|
|
||||||
# Block device specific information is only available for
|
# Block device specific information is only available for
|
||||||
# devices that are online and not a PAV alias
|
# devices that are online and not a PAV alias
|
||||||
@@ -244,7 +245,7 @@ function newoutput()
|
|||||||
#-------------------------------------------#
|
#-------------------------------------------#
|
||||||
|
|
||||||
if [[ "$ONLINE" == 0 ]]; then
|
if [[ "$ONLINE" == 0 ]]; then
|
||||||
printf "%s:%s:%-8s offline\n" \
|
printf "%s:%s:%-8s offline\n" \
|
||||||
"$SORTKEYLEN" "$SORTKEY" \
|
"$SORTKEYLEN" "$SORTKEY" \
|
||||||
"$BUSID" ;
|
"$BUSID" ;
|
||||||
return
|
return
|
||||||
@@ -252,7 +253,7 @@ function newoutput()
|
|||||||
|
|
||||||
if [[ "$ALIAS" == 1 ]]; then
|
if [[ "$ALIAS" == 1 ]]; then
|
||||||
if [[ "$BASEONLY" == "false" ]]; then
|
if [[ "$BASEONLY" == "false" ]]; then
|
||||||
printf "%s:%s:%-8s alias %28s\n" \
|
printf "%s:%s:%-8s alias %26s\n" \
|
||||||
"$SORTKEYLEN" "$SORTKEY" \
|
"$SORTKEYLEN" "$SORTKEY" \
|
||||||
"$BUSID" \
|
"$BUSID" \
|
||||||
"$DISCIPLINE"
|
"$DISCIPLINE"
|
||||||
@@ -286,7 +287,11 @@ function newoutput()
|
|||||||
ACTIVE="active"
|
ACTIVE="active"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf "%s:%s:%-8s %-6s%-4s %-8s %-2s:%-2s %-4s %-4s %-8s %s\n" \
|
if [[ "$ESE" == 1 ]]; then
|
||||||
|
DISCIPLINE="${DISCIPLINE} (ESE)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "%s:%s:%-8s %-6s%-2s %-8s %-2s:%-2s %-11s %-4s %-8s %s\n" \
|
||||||
"$SORTKEYLEN" "$SORTKEY" \
|
"$SORTKEYLEN" "$SORTKEY" \
|
||||||
"$BUSID" \
|
"$BUSID" \
|
||||||
"$ACTIVE" \
|
"$ACTIVE" \
|
||||||
@@ -378,6 +383,10 @@ function extended()
|
|||||||
read OPM NPPM CABLEPM CUIRPM HPFPM IFCCPM 2> /dev/null < $DEVPATH/path_masks
|
read OPM NPPM CABLEPM CUIRPM HPFPM IFCCPM 2> /dev/null < $DEVPATH/path_masks
|
||||||
read -a C 2> /dev/null < $DEVPATH/../chpids
|
read -a C 2> /dev/null < $DEVPATH/../chpids
|
||||||
read PIM PAM POM 2> /dev/null < $DEVPATH/../pimpampom
|
read PIM PAM POM 2> /dev/null < $DEVPATH/../pimpampom
|
||||||
|
read ESE 2> /dev/null < $DEVPATH/ese
|
||||||
|
read EXTSZ 2> /dev/null < $DEVPATH/extent_pool/extent_size
|
||||||
|
read CAPACITY 2> /dev/null < $DEVPATH/capacity/logical_capacity
|
||||||
|
read ALLOCATED 2> /dev/null < $DEVPATH/capacity/space_allocated
|
||||||
|
|
||||||
# convert to hexadecimal values
|
# convert to hexadecimal values
|
||||||
PIM=0x$PIM
|
PIM=0x$PIM
|
||||||
@@ -550,7 +559,11 @@ function extended()
|
|||||||
COLON=":"
|
COLON=":"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \
|
if [[ "$ESE" == 1 ]]; then
|
||||||
|
DISCIPLINE="${DISCIPLINE} (ESE)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# extent_size:\t\t\t\t%s# logical_capacity:\t\t\t%s# space_allocated:\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \
|
||||||
"$SORTKEYLEN" "$SORTKEY" \
|
"$SORTKEYLEN" "$SORTKEY" \
|
||||||
"$BUSID" \
|
"$BUSID" \
|
||||||
"$BLOCKNAME" \
|
"$BLOCKNAME" \
|
||||||
@@ -562,6 +575,9 @@ function extended()
|
|||||||
"$SSIZE" \
|
"$SSIZE" \
|
||||||
"$MBSIZE" \
|
"$MBSIZE" \
|
||||||
"$BLOCKCOUNT" \
|
"$BLOCKCOUNT" \
|
||||||
|
"$EXTSZ" \
|
||||||
|
"$CAPACITY" \
|
||||||
|
"$ALLOCATED" \
|
||||||
"$DIAG" \
|
"$DIAG" \
|
||||||
"$READONLY" \
|
"$READONLY" \
|
||||||
"$EER" \
|
"$EER" \
|
||||||
@@ -787,10 +803,10 @@ fi
|
|||||||
|
|
||||||
if [[ "$PRINTUID" == "true" ]] && [[ "$OUTPUT" != "old" ]]; then
|
if [[ "$PRINTUID" == "true" ]] && [[ "$OUTPUT" != "old" ]]; then
|
||||||
printf "Bus-ID Name UID\n"
|
printf "Bus-ID Name UID\n"
|
||||||
printf "==============================================================================\n"
|
printf "================================================================================\n"
|
||||||
elif [[ "$OUTPUT" == "new" ]]; then
|
elif [[ "$OUTPUT" == "new" ]]; then
|
||||||
printf "Bus-ID Status Name Device Type BlkSz Size Blocks\n"
|
printf "Bus-ID Status Name Device Type BlkSz Size Blocks\n"
|
||||||
printf "==============================================================================\n"
|
printf "================================================================================\n"
|
||||||
elif [[ "$OUTPUT" == "extended" ]]; then
|
elif [[ "$OUTPUT" == "extended" ]]; then
|
||||||
PROCESSING=" $PROCESSING | sed 's/#/\n/g' "
|
PROCESSING=" $PROCESSING | sed 's/#/\n/g' "
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
.\" Copyright 2017 IBM Corp.
|
.\" Copyright 2019 IBM Corp.
|
||||||
.\" s390-tools is free software; you can redistribute it and/or modify
|
.\" s390-tools is free software; you can redistribute it and/or modify
|
||||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||||
.\"
|
.\"
|
||||||
.TH CHZCRYPT 8 "OCT 2017" "s390-tools"
|
.TH CHZCRYPT 8 "AUG 2019" "s390-tools"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
chzcrypt \- modify zcrypt configuration
|
chzcrypt \- modify zcrypt configuration
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* chzcrypt - Tool to modify zcrypt configuration
|
* chzcrypt - Tool to modify zcrypt configuration
|
||||||
*
|
*
|
||||||
* Copyright IBM Corp. 2008, 2017
|
* Copyright IBM Corp. 2008, 2019
|
||||||
*
|
*
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
@@ -47,7 +47,7 @@ const struct util_prg prg = {
|
|||||||
{
|
{
|
||||||
.owner = "IBM Corp.",
|
.owner = "IBM Corp.",
|
||||||
.pub_first = 2008,
|
.pub_first = 2008,
|
||||||
.pub_last = 2017,
|
.pub_last = 2019,
|
||||||
},
|
},
|
||||||
UTIL_PRG_COPYRIGHT_END
|
UTIL_PRG_COPYRIGHT_END
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" lszcrypt.8
|
.\" lszcrypt.8
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright 2017 IBM Corp.
|
.\" Copyright 2019 IBM Corp.
|
||||||
.\" s390-tools is free software; you can redistribute it and/or modify
|
.\" s390-tools is free software; you can redistribute it and/or modify
|
||||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||||
.\"
|
.\"
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
.\" nroff -man lszcrypt.8
|
.\" nroff -man lszcrypt.8
|
||||||
.\" to process this source
|
.\" to process this source
|
||||||
.\"
|
.\"
|
||||||
.TH LSZCRYPT 8 "JAN 2019" "s390-tools"
|
.TH LSZCRYPT 8 "AUG 2019" "s390-tools"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
lszcrypt \- display zcrypt device and configuration information
|
lszcrypt \- display zcrypt device and configuration information
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -118,7 +118,7 @@ explanation:
|
|||||||
.B TYPE and HWTYPE
|
.B TYPE and HWTYPE
|
||||||
The HWTYPE is a numeric value showing which type of hardware the zcrypt
|
The HWTYPE is a numeric value showing which type of hardware the zcrypt
|
||||||
device driver presumes that this crypto card is. The currently known values
|
device driver presumes that this crypto card is. The currently known values
|
||||||
are 7=CEX3C, 8=CEX3A, 10=CEX4, 11=CEX5 and 12=CEX6.
|
are 7=CEX3C, 8=CEX3A, 10=CEX4, 11=CEX5, 12=CEX6 and 13=CEX7.
|
||||||
.br
|
.br
|
||||||
The TYPE is a human readable value showing the hardware type and the basic
|
The TYPE is a human readable value showing the hardware type and the basic
|
||||||
function type (A=Accelerator, C=CCA Coprocessor, P=EP11 Coprocessor). So
|
function type (A=Accelerator, C=CCA Coprocessor, P=EP11 Coprocessor). So
|
||||||
@@ -167,7 +167,7 @@ operations within the guests.
|
|||||||
.B DRIVER
|
.B DRIVER
|
||||||
.br
|
.br
|
||||||
Shows which card or queue device driver currently handles this crypto
|
Shows which card or queue device driver currently handles this crypto
|
||||||
resource. Currently known drivers are cex4card/cex4queue (CEX4-CEX6
|
resource. Currently known drivers are cex4card/cex4queue (CEX4-CEX7
|
||||||
hardware), cex2card/cex2cqueue (CEX2C and CEX3C hardware),
|
hardware), cex2card/cex2cqueue (CEX2C and CEX3C hardware),
|
||||||
cex2acard/cex2aqueue (CEX2A and CEX3A hardware) and vfio_ap (queue reserved
|
cex2acard/cex2aqueue (CEX2A and CEX3A hardware) and vfio_ap (queue reserved
|
||||||
for use by kvm hypervisor for kvm guests and not accessible to host
|
for use by kvm hypervisor for kvm guests and not accessible to host
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* lszcrypt - Display zcrypt devices and configuration settings
|
* lszcrypt - Display zcrypt devices and configuration settings
|
||||||
*
|
*
|
||||||
* Copyright IBM Corp. 2008, 2018
|
* Copyright IBM Corp. 2008, 2019
|
||||||
*
|
*
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
@@ -86,7 +86,7 @@ const struct util_prg prg = {
|
|||||||
{
|
{
|
||||||
.owner = "IBM Corp.",
|
.owner = "IBM Corp.",
|
||||||
.pub_first = 2008,
|
.pub_first = 2008,
|
||||||
.pub_last = 2018,
|
.pub_last = 2019,
|
||||||
},
|
},
|
||||||
UTIL_PRG_COPYRIGHT_END
|
UTIL_PRG_COPYRIGHT_END
|
||||||
}
|
}
|
||||||
@@ -302,9 +302,10 @@ static void show_capability(const char *id_str)
|
|||||||
printf("%s\n", CAP_CCA);
|
printf("%s\n", CAP_CCA);
|
||||||
printf("%s", CAP_RNG);
|
printf("%s", CAP_RNG);
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10: /* CEX4S */
|
||||||
case 11:
|
case 11: /* CEX5S */
|
||||||
case 12:
|
case 12: /* CEX6S */
|
||||||
|
case 13: /* CEX7S */
|
||||||
if (func_val & MASK_ACCEL) {
|
if (func_val & MASK_ACCEL) {
|
||||||
if (func_val & MASK_RSA4K)
|
if (func_val & MASK_RSA4K)
|
||||||
printf("%s", CAP_RSA4K);
|
printf("%s", CAP_RSA4K);
|
||||||
|
|||||||
+13
-10
@@ -147,8 +147,9 @@ struct chsc_cmb_area {
|
|||||||
#define CRYPTO_TYPE_CEX4S 10
|
#define CRYPTO_TYPE_CEX4S 10
|
||||||
#define CRYPTO_TYPE_CEX5S 11
|
#define CRYPTO_TYPE_CEX5S 11
|
||||||
#define CRYPTO_TYPE_CEX6S 12
|
#define CRYPTO_TYPE_CEX6S 12
|
||||||
|
#define CRYPTO_TYPE_CEX7S 13
|
||||||
|
|
||||||
#define CRYPTO_TYPE_TOLERATION CRYPTO_TYPE_CEX6S
|
#define CRYPTO_TYPE_TOLERATION CRYPTO_TYPE_CEX7S
|
||||||
|
|
||||||
struct crypto_counter {
|
struct crypto_counter {
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -235,8 +236,8 @@ const struct crypto_mode mode_pcica[1] = {
|
|||||||
.counters = counter_pcica },
|
.counters = counter_pcica },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_CEX456_MODES 11
|
#define NUM_CEX4567_MODES 11
|
||||||
const struct crypto_mode mode_cex456[NUM_CEX456_MODES] = {
|
const struct crypto_mode mode_cex4567[NUM_CEX4567_MODES] = {
|
||||||
{ 0 },
|
{ 0 },
|
||||||
{ 0 },
|
{ 0 },
|
||||||
{ 0 },
|
{ 0 },
|
||||||
@@ -256,7 +257,7 @@ const struct crypto_mode mode_cex456[NUM_CEX456_MODES] = {
|
|||||||
.counters = counter_ep11 },
|
.counters = counter_ep11 },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_CRYPTO_TYPES 13
|
#define NUM_CRYPTO_TYPES 14
|
||||||
const struct crypto_type crypto_types[NUM_CRYPTO_TYPES] = {
|
const struct crypto_type crypto_types[NUM_CRYPTO_TYPES] = {
|
||||||
{ 0 },
|
{ 0 },
|
||||||
{ 0 },
|
{ 0 },
|
||||||
@@ -275,12 +276,14 @@ const struct crypto_type crypto_types[NUM_CRYPTO_TYPES] = {
|
|||||||
.modes = mode_accel },
|
.modes = mode_accel },
|
||||||
{ .name = "CEX3C", .num_modes = NUM_COPROC_MODES,
|
{ .name = "CEX3C", .num_modes = NUM_COPROC_MODES,
|
||||||
.modes = mode_coproc },
|
.modes = mode_coproc },
|
||||||
{ .name = "CEX4", .num_modes = NUM_CEX456_MODES,
|
{ .name = "CEX4", .num_modes = NUM_CEX4567_MODES,
|
||||||
.modes = mode_cex456 },
|
.modes = mode_cex4567 },
|
||||||
{ .name = "CEX5", .num_modes = NUM_CEX456_MODES,
|
{ .name = "CEX5", .num_modes = NUM_CEX4567_MODES,
|
||||||
.modes = mode_cex456 },
|
.modes = mode_cex4567 },
|
||||||
{ .name = "CEX6", .num_modes = NUM_CEX456_MODES,
|
{ .name = "CEX6", .num_modes = NUM_CEX4567_MODES,
|
||||||
.modes = mode_cex456 },
|
.modes = mode_cex4567 },
|
||||||
|
{ .name = "CEX7", .num_modes = NUM_CEX4567_MODES,
|
||||||
|
.modes = mode_cex4567 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -345,6 +345,7 @@ static exit_code_t udev_read_zfcp_lun_rule(const char *filename,
|
|||||||
in_fc,
|
in_fc,
|
||||||
in_scsi,
|
in_scsi,
|
||||||
} state = none;
|
} state = none;
|
||||||
|
bool empty_rule = true;
|
||||||
|
|
||||||
rc = udev_read_file(filename, &file);
|
rc = udev_read_file(filename, &file);
|
||||||
if (rc)
|
if (rc)
|
||||||
@@ -374,16 +375,22 @@ static exit_code_t udev_read_zfcp_lun_rule(const char *filename,
|
|||||||
state = in_scsi;
|
state = in_scsi;
|
||||||
node = zfcp_lun_node_from_entry(entry, node,
|
node = zfcp_lun_node_from_entry(entry, node,
|
||||||
list);
|
list);
|
||||||
|
if (node)
|
||||||
|
empty_rule = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case in_fc:
|
case in_fc:
|
||||||
node = zfcp_lun_node_from_entry(entry, node, list);
|
node = zfcp_lun_node_from_entry(entry, node, list);
|
||||||
if (node)
|
if (node) {
|
||||||
add_fc_setting_from_entry(entry, node);
|
add_fc_setting_from_entry(entry, node);
|
||||||
|
empty_rule = false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case in_scsi:
|
case in_scsi:
|
||||||
if (node)
|
if (node) {
|
||||||
add_scsi_setting_from_entry(entry, node);
|
add_scsi_setting_from_entry(entry, node);
|
||||||
|
empty_rule = false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -393,7 +400,7 @@ static exit_code_t udev_read_zfcp_lun_rule(const char *filename,
|
|||||||
out:
|
out:
|
||||||
udev_free_file(file);
|
udev_free_file(file);
|
||||||
|
|
||||||
if (!node)
|
if (empty_rule)
|
||||||
warn_once("Warning: Invalid udev rule: %s\n", filename);
|
warn_once("Warning: Invalid udev rule: %s\n", filename);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|||||||
+4
-2
@@ -15,6 +15,8 @@
|
|||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#include "dfo.h"
|
#include "dfo.h"
|
||||||
#include "zg.h"
|
#include "zg.h"
|
||||||
|
|
||||||
@@ -80,7 +82,7 @@ struct nt_prstatus_64 {
|
|||||||
u64 orig_gpr2;
|
u64 orig_gpr2;
|
||||||
u32 pr_fpvalid;
|
u32 pr_fpvalid;
|
||||||
u8 pad3[4];
|
u8 pad3[4];
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fpregset ELF Note
|
* fpregset ELF Note
|
||||||
@@ -89,7 +91,7 @@ struct nt_fpregset_64 {
|
|||||||
u32 fpc;
|
u32 fpc;
|
||||||
u32 pad;
|
u32 pad;
|
||||||
u64 fprs[16];
|
u64 fprs[16];
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* prpsinfo ELF Note
|
* prpsinfo ELF Note
|
||||||
|
|||||||
+5
-3
@@ -12,6 +12,8 @@
|
|||||||
#ifndef DF_LKCD_H
|
#ifndef DF_LKCD_H
|
||||||
#define DF_LKCD_H
|
#define DF_LKCD_H
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#define DF_LKCD_MAGIC 0xa8190173618f23edULL
|
#define DF_LKCD_MAGIC 0xa8190173618f23edULL
|
||||||
#define DF_LKCD_MAGIC_ASM 0x733339302d64756dULL
|
#define DF_LKCD_MAGIC_ASM 0x733339302d64756dULL
|
||||||
#define DF_LKCD_VERSION 0x8 /* dump version number */
|
#define DF_LKCD_VERSION 0x8 /* dump version number */
|
||||||
@@ -53,7 +55,7 @@ struct df_lkcd_hdr {
|
|||||||
u32 dump_compress;
|
u32 dump_compress;
|
||||||
u32 dump_flags;
|
u32 dump_flags;
|
||||||
u32 dump_device;
|
u32 dump_device;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* s390 LKCD asm header
|
* s390 LKCD asm header
|
||||||
@@ -65,7 +67,7 @@ struct df_lkcd_hdr_asm {
|
|||||||
u16 cpu_cnt;
|
u16 cpu_cnt;
|
||||||
u16 real_cpu_cnt;
|
u16 real_cpu_cnt;
|
||||||
u32 lc_vec[512];
|
u32 lc_vec[512];
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Page header
|
* Page header
|
||||||
@@ -74,6 +76,6 @@ struct df_lkcd_pg_hdr {
|
|||||||
u64 addr; /* Address of dump page */
|
u64 addr; /* Address of dump page */
|
||||||
u32 size; /* Size of dump page */
|
u32 size; /* Size of dump page */
|
||||||
u32 flags; /* flags (DF_LKCD_COMPRESSED, DF_LKCD_RAW,...) */
|
u32 flags; /* flags (DF_LKCD_COMPRESSED, DF_LKCD_RAW,...) */
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
#endif /* DF_LKCD_H */
|
#endif /* DF_LKCD_H */
|
||||||
|
|||||||
+6
-4
@@ -12,6 +12,8 @@
|
|||||||
#ifndef DF_S390_H
|
#ifndef DF_S390_H
|
||||||
#define DF_S390_H
|
#define DF_S390_H
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#include "dt.h"
|
#include "dt.h"
|
||||||
#include "zg.h"
|
#include "zg.h"
|
||||||
|
|
||||||
@@ -59,7 +61,7 @@ struct df_s390_hdr {
|
|||||||
u64 mvdump_zipl_time; /* 0x208 */
|
u64 mvdump_zipl_time; /* 0x208 */
|
||||||
u8 end_pad2[0x800-0x210]; /* 0x210 */
|
u8 end_pad2[0x800-0x210]; /* 0x210 */
|
||||||
u32 lc_vec[DF_S390_CPU_MAX]; /* 0x800 */
|
u32 lc_vec[DF_S390_CPU_MAX]; /* 0x800 */
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* End marker: Should be at the end of every valid s390 crash dump.
|
* End marker: Should be at the end of every valid s390 crash dump.
|
||||||
@@ -67,7 +69,7 @@ struct df_s390_hdr {
|
|||||||
struct df_s390_em {
|
struct df_s390_em {
|
||||||
char str[8];
|
char str[8];
|
||||||
u64 tod;
|
u64 tod;
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Segment header for s390 extended dump format
|
* Segment header for s390 extended dump format
|
||||||
@@ -77,7 +79,7 @@ struct df_s390_dump_segm_hdr {
|
|||||||
u64 len;
|
u64 len;
|
||||||
u64 stop_marker;
|
u64 stop_marker;
|
||||||
u8 reserved[0x1000 - 24];
|
u8 reserved[0x1000 - 24];
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert DFI arch to s390 arch
|
* Convert DFI arch to s390 arch
|
||||||
@@ -118,7 +120,7 @@ struct df_s390_dumper {
|
|||||||
u32 size;
|
u32 size;
|
||||||
u8 force;
|
u8 force;
|
||||||
u64 mem;
|
u64 mem;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* s390 dump helpers
|
* s390 dump helpers
|
||||||
|
|||||||
+4
-1
@@ -13,7 +13,10 @@
|
|||||||
#define DFI_H
|
#define DFI_H
|
||||||
|
|
||||||
#include <linux/utsname.h>
|
#include <linux/utsname.h>
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
#include "lib/util_list.h"
|
#include "lib/util_list.h"
|
||||||
|
|
||||||
#include "zg.h"
|
#include "zg.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -68,7 +71,7 @@ struct dfi_lowcore_64 {
|
|||||||
u32 access_regs_save_area[16]; /* 0x1340 */
|
u32 access_regs_save_area[16]; /* 0x1340 */
|
||||||
u64 cregs_save_area[16]; /* 0x1380 */
|
u64 cregs_save_area[16]; /* 0x1380 */
|
||||||
u8 pad_0x1400[0x2000-0x1400]; /* 0x1400 */
|
u8 pad_0x1400[0x2000-0x1400]; /* 0x1400 */
|
||||||
} __attribute__((packed));
|
} __packed;
|
||||||
|
|
||||||
static inline u64 dfi_lc_size(enum dfi_arch arch)
|
static inline u64 dfi_lc_size(enum dfi_arch arch)
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-2
@@ -26,14 +26,14 @@ struct vol_parm {
|
|||||||
u8 blk_size;
|
u8 blk_size;
|
||||||
u8 end_sec;
|
u8 end_sec;
|
||||||
u8 num_heads;
|
u8 num_heads;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct vol_parm_table {
|
struct vol_parm_table {
|
||||||
u64 timestamp;
|
u64 timestamp;
|
||||||
u16 vol_cnt;
|
u16 vol_cnt;
|
||||||
struct vol_parm vol_parm[MAX_VOLUMES];
|
struct vol_parm vol_parm[MAX_VOLUMES];
|
||||||
u8 ssid[MAX_VOLUMES];
|
u8 ssid[MAX_VOLUMES];
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Device signature
|
* Device signature
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#include "zgetdump.h"
|
#include "zgetdump.h"
|
||||||
|
|
||||||
#ifdef __s390x__
|
#ifdef __s390x__
|
||||||
@@ -38,7 +41,7 @@ struct os_info {
|
|||||||
u64 init_fn_size;
|
u64 init_fn_size;
|
||||||
u32 init_fn_csum;
|
u32 init_fn_csum;
|
||||||
u8 reserved[4004];
|
u8 reserved[4004];
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* File local static data
|
* File local static data
|
||||||
|
|||||||
+8
-6
@@ -12,7 +12,9 @@
|
|||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
#include "lib/util_part.h"
|
#include "lib/util_part.h"
|
||||||
|
|
||||||
#include "zgetdump.h"
|
#include "zgetdump.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -28,7 +30,7 @@ struct scsi_dump_sb {
|
|||||||
uint64_t csum_off;
|
uint64_t csum_off;
|
||||||
uint64_t csum_size;
|
uint64_t csum_size;
|
||||||
uint64_t csum;
|
uint64_t csum;
|
||||||
} __attribute((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* File local static data
|
* File local static data
|
||||||
@@ -46,7 +48,7 @@ struct scsi_blockptr {
|
|||||||
uint16_t size;
|
uint16_t size;
|
||||||
uint16_t blockct;
|
uint16_t blockct;
|
||||||
uint8_t reserved[4];
|
uint8_t reserved[4];
|
||||||
} __attribute__((__packed__));
|
} __packed;
|
||||||
|
|
||||||
enum component_entry_type {
|
enum component_entry_type {
|
||||||
component_execute = 0x01,
|
component_execute = 0x01,
|
||||||
@@ -61,7 +63,7 @@ struct component_entry {
|
|||||||
uint64_t load_address;
|
uint64_t load_address;
|
||||||
uint64_t load_psw;
|
uint64_t load_psw;
|
||||||
} address;
|
} address;
|
||||||
} __attribute__((__packed__));
|
} __packed;
|
||||||
|
|
||||||
enum component_header_type {
|
enum component_header_type {
|
||||||
component_header_ipl = 0x00,
|
component_header_ipl = 0x00,
|
||||||
@@ -72,7 +74,7 @@ struct component_header {
|
|||||||
uint8_t magic[4];
|
uint8_t magic[4];
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t reserved[27];
|
uint8_t reserved[27];
|
||||||
} __attribute__((__packed__));
|
} __packed;
|
||||||
|
|
||||||
struct boot_info {
|
struct boot_info {
|
||||||
char magic[4];
|
char magic[4];
|
||||||
@@ -81,7 +83,7 @@ struct boot_info {
|
|||||||
uint8_t dev_type;
|
uint8_t dev_type;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint64_t sb_off;
|
uint64_t sb_off;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct scsi_mbr {
|
struct scsi_mbr {
|
||||||
char magic[4];
|
char magic[4];
|
||||||
@@ -90,7 +92,7 @@ struct scsi_mbr {
|
|||||||
struct scsi_blockptr blockptr;
|
struct scsi_blockptr blockptr;
|
||||||
uint8_t reserved2[0x50];
|
uint8_t reserved2[0x50];
|
||||||
struct boot_info boot_info;
|
struct boot_info boot_info;
|
||||||
} __attribute__((__packed__));
|
} __packed;
|
||||||
|
|
||||||
#define BOOT_INFO_VERSION 1
|
#define BOOT_INFO_VERSION 1
|
||||||
#define BOOT_INFO_MAGIC "zIPL"
|
#define BOOT_INFO_MAGIC "zIPL"
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ struct scsi_dump_sb {
|
|||||||
uint64_t csum_off;
|
uint64_t csum_off;
|
||||||
uint64_t csum_size;
|
uint64_t csum_size;
|
||||||
uint64_t csum;
|
uint64_t csum;
|
||||||
} __attribute((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Layout of SCSI disk block pointer
|
* Layout of SCSI disk block pointer
|
||||||
@@ -72,7 +72,7 @@ struct linear_blockptr {
|
|||||||
uint16_t size;
|
uint16_t size;
|
||||||
uint16_t blockct;
|
uint16_t blockct;
|
||||||
uint8_t reserved[4];
|
uint8_t reserved[4];
|
||||||
} __attribute((packed));
|
} __packed;
|
||||||
|
|
||||||
/* From boot.h in zipl */
|
/* From boot.h in zipl */
|
||||||
struct boot_info {
|
struct boot_info {
|
||||||
@@ -82,7 +82,7 @@ struct boot_info {
|
|||||||
uint8_t dev_type;
|
uint8_t dev_type;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint64_t sb_off;
|
uint64_t sb_off;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
/* From install.c in zipl */
|
/* From install.c in zipl */
|
||||||
struct scsi_mbr {
|
struct scsi_mbr {
|
||||||
@@ -92,7 +92,7 @@ struct scsi_mbr {
|
|||||||
struct linear_blockptr lin;
|
struct linear_blockptr lin;
|
||||||
uint8_t reserverd[0x50];
|
uint8_t reserverd[0x50];
|
||||||
struct boot_info boot_info;
|
struct boot_info boot_info;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
/* From boot.h in zipl */
|
/* From boot.h in zipl */
|
||||||
#define BOOT_INFO_VERSION 1
|
#define BOOT_INFO_VERSION 1
|
||||||
|
|||||||
+2
-1
@@ -745,10 +745,11 @@ function check_size_requirements() {
|
|||||||
|
|
||||||
trap emergency_shutdown SIGHUP SIGTERM SIGINT SIGQUIT;
|
trap emergency_shutdown SIGHUP SIGTERM SIGINT SIGQUIT;
|
||||||
|
|
||||||
check_blktrace;
|
|
||||||
|
|
||||||
parse_params $@;
|
parse_params $@;
|
||||||
|
|
||||||
|
check_blktrace;
|
||||||
|
|
||||||
determine_host_adapters;
|
determine_host_adapters;
|
||||||
|
|
||||||
check_cpuplugd;
|
check_cpuplugd;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ all:
|
|||||||
install: all
|
install: all
|
||||||
$(MAKE) -C src install
|
$(MAKE) -C src install
|
||||||
$(MAKE) -C man install
|
$(MAKE) -C man install
|
||||||
|
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 doc/zipl.conf.minimal $(DESTDIR)$(TOOLS_LIBDIR)/zipl.conf
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(MAKE) -C src clean
|
$(MAKE) -C src clean
|
||||||
|
|||||||
+4
-4
@@ -1,8 +1,8 @@
|
|||||||
# Common definitions
|
# Common definitions
|
||||||
include ../../common.mak
|
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) \
|
-I $(rootdir)/include -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
|
||||||
-fno-builtin -ffreestanding -fno-asynchronous-unwind-tables \
|
-fno-builtin -ffreestanding -fno-asynchronous-unwind-tables \
|
||||||
-fno-delete-null-pointer-checks \
|
-fno-delete-null-pointer-checks \
|
||||||
-fexec-charset=IBM1047 -m64 -mpacked-stack \
|
-fexec-charset=IBM1047 -m64 -mpacked-stack \
|
||||||
@@ -21,10 +21,10 @@ all: data.o data.h tape0.bin stage3.bin
|
|||||||
%: %.S
|
%: %.S
|
||||||
|
|
||||||
%.o: %.S
|
%.o: %.S
|
||||||
$(CC) $(CFLAGS_BOOT) -c -o $@ $<
|
$(CC) $(ALL_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(CFLAGS_BOOT) -c -o $@ $<
|
$(CC) $(ALL_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
eckd2dump_sv.exec: \
|
eckd2dump_sv.exec: \
|
||||||
head.o stage2dump.o cio.o eckd2dump.o eckd2dump_sv.o \
|
head.o stage2dump.o cio.o eckd2dump.o eckd2dump_sv.o \
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#include "eckd2dump.h"
|
#include "eckd2dump.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "stage2dump.h"
|
#include "stage2dump.h"
|
||||||
@@ -19,8 +21,7 @@
|
|||||||
/*
|
/*
|
||||||
* Magic number at start of dump record
|
* Magic number at start of dump record
|
||||||
*/
|
*/
|
||||||
uint64_t magic __attribute__((section(".stage2.head")))
|
uint64_t __section(.stage2.head) magic = 0x584d554c54363401ULL; /* XMULT64, version 1 */
|
||||||
= 0x584d554c54363401ULL; /* XMULT64, version 1 */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parameter format for ECKD MV dumper (13 bytes):
|
* Parameter format for ECKD MV dumper (13 bytes):
|
||||||
@@ -59,8 +60,7 @@ struct mvdump_parm_table {
|
|||||||
(MAX_DUMP_VOLUMES * (sizeof(struct mvdump_param) + 1))];
|
(MAX_DUMP_VOLUMES * (sizeof(struct mvdump_param) + 1))];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
static struct mvdump_parm_table mvdump_table
|
static struct mvdump_parm_table __section(.eckd2dump_mv.tail) mvdump_table;
|
||||||
__attribute__((section(".eckd2dump_mv.tail")));
|
|
||||||
|
|
||||||
static int volnr_current;
|
static int volnr_current;
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#include "eckd2dump.h"
|
#include "eckd2dump.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "stage2dump.h"
|
#include "stage2dump.h"
|
||||||
@@ -16,8 +18,7 @@
|
|||||||
/*
|
/*
|
||||||
* Magic number at start of dump record
|
* Magic number at start of dump record
|
||||||
*/
|
*/
|
||||||
uint64_t magic __attribute__((section(".stage2.head"))) =
|
uint64_t __section(.stage2.head) magic = 0x5845434b44363401ULL; /* "XECKD64", version 1 */
|
||||||
0x5845434b44363401ULL; /* "XECKD64", version 1 */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ECKD parameter block passed by zipl
|
* ECKD parameter block passed by zipl
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "fba.h"
|
#include "fba.h"
|
||||||
#include "stage2dump.h"
|
#include "stage2dump.h"
|
||||||
@@ -20,8 +21,7 @@
|
|||||||
/*
|
/*
|
||||||
* Magic number at start of dump record
|
* Magic number at start of dump record
|
||||||
*/
|
*/
|
||||||
uint64_t magic __attribute__((section(".stage2.head")))
|
uint64_t __section(.stage2.head) magic = 0x5844464241363401ULL; /* XDFBA64, version 1 */
|
||||||
= 0x5844464241363401ULL; /* XDFBA64, version 1 */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FBA dump device partition specification
|
* FBA dump device partition specification
|
||||||
|
|||||||
+4
-2
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "libc.h"
|
#include "libc.h"
|
||||||
#include "sclp.h"
|
#include "sclp.h"
|
||||||
@@ -343,7 +345,7 @@ void pgm_check_handler_fn(void)
|
|||||||
libc_stop(psw_old->addr);
|
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 wait_psw = { .mask = psw_mask, .addr = 0 };
|
||||||
struct psw_t old_psw, *wait_psw_ptr = &wait_psw;
|
struct psw_t old_psw, *wait_psw_ptr = &wait_psw;
|
||||||
@@ -383,7 +385,7 @@ void initialize(void)
|
|||||||
/*
|
/*
|
||||||
* Load disabled wait PSW with reason code in address field
|
* 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;
|
struct psw_t psw;
|
||||||
|
|
||||||
|
|||||||
+3
-6
@@ -11,6 +11,8 @@
|
|||||||
#ifndef LIBC_H
|
#ifndef LIBC_H
|
||||||
#define LIBC_H
|
#define LIBC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define NULL ((void *) 0)
|
#define NULL ((void *) 0)
|
||||||
|
|
||||||
#define EPERM 1 /* Operation not permitted */
|
#define EPERM 1 /* Operation not permitted */
|
||||||
@@ -41,11 +43,6 @@
|
|||||||
|
|
||||||
#define MIB (1024ULL * 1024)
|
#define MIB (1024ULL * 1024)
|
||||||
|
|
||||||
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 printf(const char *, ...);
|
||||||
void sprintf(char *, const char *, ...);
|
void sprintf(char *, const char *, ...);
|
||||||
void *memcpy(void *, const void *, unsigned long);
|
void *memcpy(void *, const void *, unsigned long);
|
||||||
@@ -60,7 +57,7 @@ char *strcpy(char *, const char *);
|
|||||||
unsigned long get_zeroed_page(void);
|
unsigned long get_zeroed_page(void);
|
||||||
void free_page(unsigned long);
|
void free_page(unsigned long);
|
||||||
void initialize(void);
|
void initialize(void);
|
||||||
void libc_stop(unsigned long) __attribute__((noreturn));
|
void libc_stop(unsigned long);
|
||||||
void start(void);
|
void start(void);
|
||||||
void pgm_check_handler(void);
|
void pgm_check_handler(void);
|
||||||
void pgm_check_handler_fn(void);
|
void pgm_check_handler_fn(void);
|
||||||
|
|||||||
+5
-8
@@ -27,7 +27,6 @@ static void menu_prompt(int timeout)
|
|||||||
static int menu_read(void)
|
static int menu_read(void)
|
||||||
{
|
{
|
||||||
char *temp_area = (char *)get_zeroed_page();
|
char *temp_area = (char *)get_zeroed_page();
|
||||||
uint16_t *configs = __stage2_params.config;
|
|
||||||
int timeout, rc, i, count = 0;
|
int timeout, rc, i, count = 0;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
int value;
|
int value;
|
||||||
@@ -60,7 +59,7 @@ static int menu_read(void)
|
|||||||
value = ebcstrtoul((char *)temp_area, &endptr, 10);
|
value = ebcstrtoul((char *)temp_area, &endptr, 10);
|
||||||
|
|
||||||
if ((endptr != temp_area) && (value < BOOT_MENU_ENTRIES - 1) &&
|
if ((endptr != temp_area) && (value < BOOT_MENU_ENTRIES - 1) &&
|
||||||
(configs[value] != 0)) {
|
(__stage2_params.config[value] != 0)) {
|
||||||
/* valid config found - finish */
|
/* valid config found - finish */
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@@ -80,14 +79,13 @@ out_free_page:
|
|||||||
|
|
||||||
static int menu_list(void)
|
static int menu_list(void)
|
||||||
{
|
{
|
||||||
uint16_t *configs = __stage2_params.config;
|
|
||||||
char *name;
|
char *name;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < BOOT_MENU_ENTRIES; i++) {
|
for (i = 0; i < BOOT_MENU_ENTRIES; i++) {
|
||||||
if (configs[i] == 0)
|
if (__stage2_params.config[i] == 0)
|
||||||
continue;
|
continue;
|
||||||
name = configs[i] + ((void *)&__stage2_params);
|
name = __stage2_params.config[i] + ((void *)&__stage2_params);
|
||||||
printf("%s\n", name);
|
printf("%s\n", name);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -136,7 +134,6 @@ static int menu_param(unsigned long *value)
|
|||||||
|
|
||||||
int menu(void)
|
int menu(void)
|
||||||
{
|
{
|
||||||
uint16_t *configs = __stage2_params.config;
|
|
||||||
unsigned long value = 0;
|
unsigned long value = 0;
|
||||||
char *cmd_line_extra;
|
char *cmd_line_extra;
|
||||||
char endstring[15];
|
char endstring[15];
|
||||||
@@ -178,11 +175,11 @@ int menu(void)
|
|||||||
|
|
||||||
boot:
|
boot:
|
||||||
/* sanity - config entry not valid */
|
/* sanity - config entry not valid */
|
||||||
if (configs[value] == 0)
|
if (__stage2_params.config[value] == 0)
|
||||||
panic(EINTERNAL, "%s", msg_econfig);
|
panic(EINTERNAL, "%s", msg_econfig);
|
||||||
|
|
||||||
printf("Booting %s\n",
|
printf("Booting %s\n",
|
||||||
(char *)(configs[value] +
|
(char *)(__stage2_params.config[value] +
|
||||||
(void *)&__stage2_params + TEXT_OFFSET));
|
(void *)&__stage2_params + TEXT_OFFSET));
|
||||||
|
|
||||||
/* append 'BOOT_IMAGE=<num>' to parmline */
|
/* append 'BOOT_IMAGE=<num>' to parmline */
|
||||||
|
|||||||
+3
-3
@@ -11,7 +11,7 @@
|
|||||||
#ifndef S390_H
|
#ifndef S390_H
|
||||||
#define S390_H
|
#define S390_H
|
||||||
|
|
||||||
#include "../../include/lib/zt_common.h"
|
#include "lib/zt_common.h"
|
||||||
#include "libc.h"
|
#include "libc.h"
|
||||||
|
|
||||||
#define __pa32(x) ((uint32_t)(unsigned long)(x))
|
#define __pa32(x) ((uint32_t)(unsigned long)(x))
|
||||||
@@ -452,7 +452,7 @@ static inline int test_facility(unsigned long nr)
|
|||||||
return __test_facility(nr, &S390_lowcore.stfle_fac_list);
|
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;
|
register unsigned long reg0 asm("0") = size - 1;
|
||||||
|
|
||||||
@@ -469,7 +469,7 @@ static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size)
|
|||||||
* @stfle_fac_list: array where facility list can be stored
|
* @stfle_fac_list: array where facility list can be stored
|
||||||
* @size: size of passed in array in double words
|
* @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;
|
unsigned long nr;
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -53,19 +53,21 @@ struct gds_subvector {
|
|||||||
uint8_t key;
|
uint8_t key;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
/* Structure must not have any padding */
|
||||||
struct sccb_header {
|
struct sccb_header {
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
uint8_t function_code;
|
uint8_t function_code;
|
||||||
uint8_t control_mask[3];
|
uint8_t control_mask[3];
|
||||||
uint16_t response_code;
|
uint16_t response_code;
|
||||||
} __packed;
|
};
|
||||||
|
|
||||||
|
/* Structure must not have any padding */
|
||||||
struct evbuf_header {
|
struct evbuf_header {
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint16_t _reserved;
|
uint16_t _reserved;
|
||||||
} __packed;
|
};
|
||||||
|
|
||||||
struct mto {
|
struct mto {
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
|
|||||||
@@ -104,7 +104,6 @@ int sclp_hsa_get_size(unsigned long *hsa_size)
|
|||||||
sccb = (void *)get_zeroed_page();
|
sccb = (void *)get_zeroed_page();
|
||||||
sccb->header.length = sizeof(*sccb);
|
sccb->header.length = sizeof(*sccb);
|
||||||
|
|
||||||
sccb->header.length = sizeof(*sccb);
|
|
||||||
sccb->evbuf.header.length = sizeof(struct sdias_evbuf);
|
sccb->evbuf.header.length = sizeof(struct sdias_evbuf);
|
||||||
sccb->evbuf.header.type = EVTYP_SDIAS;
|
sccb->evbuf.header.type = EVTYP_SDIAS;
|
||||||
sccb->evbuf.event_qual = EQ_SIZE;
|
sccb->evbuf.event_qual = EQ_SIZE;
|
||||||
|
|||||||
@@ -17,9 +17,6 @@
|
|||||||
#define SDIAS_EVSTATE_ALL_STORED 0x00
|
#define SDIAS_EVSTATE_ALL_STORED 0x00
|
||||||
#define SDIAS_EVSTATE_PART_STORED 0x10
|
#define SDIAS_EVSTATE_PART_STORED 0x10
|
||||||
|
|
||||||
#define SDIAS_EVSTATE_ALL_STORED 0x00
|
|
||||||
#define SDIAS_EVSTATE_PART_STORED 0x10
|
|
||||||
|
|
||||||
struct sdias_evbuf {
|
struct sdias_evbuf {
|
||||||
struct evbuf_header header;
|
struct evbuf_header header;
|
||||||
uint8_t event_qual;
|
uint8_t event_qual;
|
||||||
@@ -40,10 +37,11 @@ struct sdias_evbuf {
|
|||||||
uint16_t dbs;
|
uint16_t dbs;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
/* Structure must not have any padding */
|
||||||
struct sdias_sccb {
|
struct sdias_sccb {
|
||||||
struct sccb_header header;
|
struct sccb_header header;
|
||||||
struct sdias_evbuf evbuf;
|
struct sdias_evbuf evbuf;
|
||||||
} __packed;
|
};
|
||||||
|
|
||||||
|
|
||||||
int sclp_hsa_copy(void *, unsigned long, unsigned long);
|
int sclp_hsa_copy(void *, unsigned long, unsigned long);
|
||||||
|
|||||||
+3
-1
@@ -9,6 +9,8 @@
|
|||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "libc.h"
|
#include "libc.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
@@ -141,4 +143,4 @@ void panic_notify(unsigned long UNUSED(reason))
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t stage2_head __attribute__((section(".stage2.head")));
|
uint64_t __section(.stage2.head) stage2_head;
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "sclp.h"
|
#include "sclp.h"
|
||||||
#include "stage2dump.h"
|
#include "stage2dump.h"
|
||||||
@@ -34,8 +36,7 @@ struct ipib_info {
|
|||||||
/*
|
/*
|
||||||
* Tail parameters
|
* Tail parameters
|
||||||
*/
|
*/
|
||||||
struct stage2dump_parm_tail parm_tail
|
struct stage2dump_parm_tail parm_tail = {
|
||||||
__attribute__ ((section(".stage2dump.tail"))) = {
|
|
||||||
.mem_upper_limit = 0xffffffffffffffffULL,
|
.mem_upper_limit = 0xffffffffffffffffULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ struct stage2dump_parm_tail {
|
|||||||
uint64_t mem_upper_limit;
|
uint64_t mem_upper_limit;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
extern struct stage2dump_parm_tail parm_tail
|
extern struct stage2dump_parm_tail __section(.stage2dump.tail) parm_tail;
|
||||||
__attribute__ ((section(".stage2dump.tail")));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* S390 dump format defines
|
* S390 dump format defines
|
||||||
|
|||||||
+6
-5
@@ -13,6 +13,7 @@
|
|||||||
#include "s390.h"
|
#include "s390.h"
|
||||||
#include "stage3.h"
|
#include "stage3.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "zipl.h"
|
||||||
|
|
||||||
#define for_each_rb_entry(entry, rb) \
|
#define for_each_rb_entry(entry, rb) \
|
||||||
for (entry = rb->entries; \
|
for (entry = rb->entries; \
|
||||||
@@ -175,8 +176,7 @@ static void ebcdic_to_ascii(unsigned char *target, unsigned char *source,
|
|||||||
target[i] = ebc[source[i]];
|
target[i] = ebc[source[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static inline void __noreturn start_kernel(void)
|
||||||
start_kernel(void)
|
|
||||||
{
|
{
|
||||||
struct psw_t *psw = &S390_lowcore.program_new_psw;
|
struct psw_t *psw = &S390_lowcore.program_new_psw;
|
||||||
unsigned long addr, code;
|
unsigned long addr, code;
|
||||||
@@ -199,6 +199,7 @@ start_kernel(void)
|
|||||||
: [addr] "=&d" (addr),
|
: [addr] "=&d" (addr),
|
||||||
[code] "+&d" (code)
|
[code] "+&d" (code)
|
||||||
: [psw] "a" (psw) );
|
: [psw] "a" (psw) );
|
||||||
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
@@ -272,7 +273,7 @@ void start(void)
|
|||||||
* verified component. If it is not IPL is aborted.
|
* verified component. If it is not IPL is aborted.
|
||||||
*/
|
*/
|
||||||
if (secure_boot_enabled()) {
|
if (secure_boot_enabled()) {
|
||||||
if (_image_addr != DEFAULT_IMAGE_ADDR ||
|
if (_image_addr != IMAGE_LOAD_ADDRESS ||
|
||||||
_load_psw != DEFAULT_PSW_LOAD)
|
_load_psw != DEFAULT_PSW_LOAD)
|
||||||
panic(ESECUREBOOT, "%s", msg_sipl_inval);
|
panic(ESECUREBOOT, "%s", msg_sipl_inval);
|
||||||
|
|
||||||
@@ -283,8 +284,8 @@ void start(void)
|
|||||||
* cut the kernel header
|
* cut the kernel header
|
||||||
*/
|
*/
|
||||||
memmove((void *)_image_addr,
|
memmove((void *)_image_addr,
|
||||||
(void *)_image_addr + KERNEL_HEADER_SIZE,
|
(void *)_image_addr + IMAGE_LOAD_ADDRESS,
|
||||||
_image_len - KERNEL_HEADER_SIZE);
|
_image_len - IMAGE_LOAD_ADDRESS);
|
||||||
|
|
||||||
/* store subchannel ID into low core and into new kernel space */
|
/* store subchannel ID into low core and into new kernel space */
|
||||||
subchannel_id = S390_lowcore.subchannel_id;
|
subchannel_id = S390_lowcore.subchannel_id;
|
||||||
|
|||||||
+13
-13
@@ -15,12 +15,12 @@
|
|||||||
#include "libc.h"
|
#include "libc.h"
|
||||||
#include "s390.h"
|
#include "s390.h"
|
||||||
|
|
||||||
#define IPL_DEVICE 0x10404
|
#define IPL_DEVICE 0x10404UL
|
||||||
#define INITRD_START 0x10408
|
#define INITRD_START 0x10408UL
|
||||||
#define INITRD_SIZE 0x10410
|
#define INITRD_SIZE 0x10410UL
|
||||||
#define OLDMEM_BASE 0x10418
|
#define OLDMEM_BASE 0x10418UL
|
||||||
#define OLDMEM_SIZE 0x10420
|
#define OLDMEM_SIZE 0x10420UL
|
||||||
#define COMMAND_LINE 0x10480
|
#define COMMAND_LINE 0x10480UL
|
||||||
#define COMMAND_LINE_SIZE 896
|
#define COMMAND_LINE_SIZE 896
|
||||||
#define COMMAND_LINE_EXTRA 0xE000
|
#define COMMAND_LINE_EXTRA 0xE000
|
||||||
|
|
||||||
@@ -29,12 +29,10 @@
|
|||||||
|
|
||||||
#define IPL_FLAG_SECURE 0x40
|
#define IPL_FLAG_SECURE 0x40
|
||||||
|
|
||||||
#define DEFAULT_IMAGE_ADDR 0x10000
|
#define DEFAULT_PSW_LOAD 0x0008000080010000UL
|
||||||
#define DEFAULT_PSW_LOAD 0x0008000080010000L
|
#define PSW_ADDR_MASK 0x000000007FFFFFFFUL
|
||||||
#define PSW_ADDR_MASK 0x000000007FFFFFFFL
|
|
||||||
#define KERNEL_HEADER_SIZE 65536
|
|
||||||
|
|
||||||
#define UNSPECIFIED_ADDRESS -1ULL
|
#define UNSPECIFIED_ADDRESS -1UL
|
||||||
|
|
||||||
|
|
||||||
/* IPL Parameter List header */
|
/* IPL Parameter List header */
|
||||||
@@ -124,11 +122,12 @@ struct ipl_rl_hdr {
|
|||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
/* IPL Report Block header */
|
/* IPL Report Block header */
|
||||||
|
/* Structure must not have any padding */
|
||||||
struct ipl_rb_hdr {
|
struct ipl_rb_hdr {
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
uint8_t rbt;
|
uint8_t rbt;
|
||||||
uint8_t reserved1[11];
|
uint8_t reserved1[11];
|
||||||
} __packed;
|
};
|
||||||
|
|
||||||
/* IPL Report Block types */
|
/* IPL Report Block types */
|
||||||
enum ipl_rbt {
|
enum ipl_rbt {
|
||||||
@@ -162,12 +161,13 @@ struct ipl_rb_component_entry {
|
|||||||
#define IPL_RB_COMPONENT_FLAG_SIGNED 0x80
|
#define IPL_RB_COMPONENT_FLAG_SIGNED 0x80
|
||||||
#define IPL_RB_COMPONENT_FLAG_VERIFIED 0x40
|
#define IPL_RB_COMPONENT_FLAG_VERIFIED 0x40
|
||||||
|
|
||||||
|
/* Structure must not have any padding */
|
||||||
struct ipl_rb_components {
|
struct ipl_rb_components {
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
uint8_t rbt;
|
uint8_t rbt;
|
||||||
uint8_t reserved1[11];
|
uint8_t reserved1[11];
|
||||||
struct ipl_rb_component_entry entries[];
|
struct ipl_rb_component_entry entries[];
|
||||||
} __packed;
|
};
|
||||||
|
|
||||||
extern unsigned long long _parm_addr; /* address of parmline */
|
extern unsigned long long _parm_addr; /* address of parmline */
|
||||||
extern unsigned long long _initrd_addr; /* address of initrd */
|
extern unsigned long long _initrd_addr; /* address of initrd */
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#include "cio.h"
|
#include "cio.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "libc.h"
|
#include "libc.h"
|
||||||
@@ -33,7 +35,7 @@ struct tape_head {
|
|||||||
uint64_t ccw2;
|
uint64_t ccw2;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct tape_head tape_head __attribute__((section(".stage2.head"))) = {
|
struct tape_head __section(.stage2.head) tape_head = {
|
||||||
.psw = 0x0008000080002018ULL, /* Start code at 0x2018 */
|
.psw = 0x0008000080002018ULL, /* Start code at 0x2018 */
|
||||||
.ccw1 = 0x0700000060000001ULL, /* Rewind ccw */
|
.ccw1 = 0x0700000060000001ULL, /* Rewind ccw */
|
||||||
.ccw2 = 0x0200200020003000ULL, /* CCW to load dump tool to 0x2000 */
|
.ccw2 = 0x0200200020003000ULL, /* CCW to load dump tool to 0x2000 */
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# This is an example of a minimal zipl.conf file that can be used when the
|
||||||
|
# sections are defined in BootLoaderSpec fragments files.
|
||||||
|
#
|
||||||
|
# See the zipl and zipl.conf man page for more details.
|
||||||
|
[defaultboot]
|
||||||
|
defaultauto
|
||||||
|
prompt=1
|
||||||
|
timeout=5
|
||||||
|
secure=auto
|
||||||
|
target=/boot
|
||||||
+29
-27
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#include "disk.h"
|
#include "disk.h"
|
||||||
#include "job.h"
|
#include "job.h"
|
||||||
#include "zipl.h"
|
#include "zipl.h"
|
||||||
@@ -51,7 +53,7 @@ struct scsi_dump_sb {
|
|||||||
uint64_t csum_offset;
|
uint64_t csum_offset;
|
||||||
uint64_t csum_size;
|
uint64_t csum_size;
|
||||||
uint64_t csum;
|
uint64_t csum;
|
||||||
} __attribute((packed));
|
} __packed;
|
||||||
|
|
||||||
#define SCSI_DUMP_SB_MAGIC 0x5a46435044554d50ULL; /* ZFCPDUMP */
|
#define SCSI_DUMP_SB_MAGIC 0x5a46435044554d50ULL; /* ZFCPDUMP */
|
||||||
/* To avoid a csum entry of 0 a seed is used */
|
/* To avoid a csum entry of 0 a seed is used */
|
||||||
@@ -63,7 +65,7 @@ struct scsi_dump_sb {
|
|||||||
struct scsi_dump_param {
|
struct scsi_dump_param {
|
||||||
uint64_t block;
|
uint64_t block;
|
||||||
uint64_t reserved;
|
uint64_t reserved;
|
||||||
} __attribute((packed));
|
} __packed;
|
||||||
/* ECKD dump parameter */
|
/* ECKD dump parameter */
|
||||||
|
|
||||||
struct eckd_dump_param {
|
struct eckd_dump_param {
|
||||||
@@ -73,14 +75,14 @@ struct eckd_dump_param {
|
|||||||
uint8_t num_heads;
|
uint8_t num_heads;
|
||||||
uint8_t bpt;
|
uint8_t bpt;
|
||||||
char reserved[4];
|
char reserved[4];
|
||||||
} __attribute((packed, may_alias));
|
} __packed __may_alias;
|
||||||
|
|
||||||
/* FBA dump parameter */
|
/* FBA dump parameter */
|
||||||
|
|
||||||
struct fba_dump_param {
|
struct fba_dump_param {
|
||||||
uint64_t start_blk;
|
uint64_t start_blk;
|
||||||
uint64_t blockct;
|
uint64_t blockct;
|
||||||
} __attribute((packed));
|
} __packed;
|
||||||
|
|
||||||
struct boot_info_bp_dump {
|
struct boot_info_bp_dump {
|
||||||
union {
|
union {
|
||||||
@@ -89,7 +91,7 @@ struct boot_info_bp_dump {
|
|||||||
struct scsi_dump_param scsi;
|
struct scsi_dump_param scsi;
|
||||||
} param;
|
} param;
|
||||||
uint8_t unused[16];
|
uint8_t unused[16];
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Layout of block pointer for linear devices
|
* Layout of block pointer for linear devices
|
||||||
@@ -101,7 +103,7 @@ struct linear_blockptr {
|
|||||||
uint16_t size;
|
uint16_t size;
|
||||||
uint16_t blockct;
|
uint16_t blockct;
|
||||||
uint8_t reserved[4];
|
uint8_t reserved[4];
|
||||||
} __attribute((packed));
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Layout of block pointer for cylinder/head/sector devices
|
* Layout of block pointer for cylinder/head/sector devices
|
||||||
@@ -115,7 +117,7 @@ struct eckd_blockptr {
|
|||||||
uint16_t size;
|
uint16_t size;
|
||||||
uint8_t blockct;
|
uint8_t blockct;
|
||||||
uint8_t reserved[8];
|
uint8_t reserved[8];
|
||||||
} __attribute((packed));
|
} __packed;
|
||||||
|
|
||||||
struct boot_info_bp_ipl {
|
struct boot_info_bp_ipl {
|
||||||
union {
|
union {
|
||||||
@@ -123,7 +125,7 @@ struct boot_info_bp_ipl {
|
|||||||
struct linear_blockptr lin;
|
struct linear_blockptr lin;
|
||||||
} bm_ptr;
|
} bm_ptr;
|
||||||
uint8_t unused[16];
|
uint8_t unused[16];
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct boot_info {
|
struct boot_info {
|
||||||
char magic[4];
|
char magic[4];
|
||||||
@@ -135,7 +137,7 @@ struct boot_info {
|
|||||||
struct boot_info_bp_dump dump;
|
struct boot_info_bp_dump dump;
|
||||||
struct boot_info_bp_ipl ipl;
|
struct boot_info_bp_ipl ipl;
|
||||||
} bp;
|
} bp;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct boot_ccw0 {
|
struct boot_ccw0 {
|
||||||
uint8_t cmd;
|
uint8_t cmd;
|
||||||
@@ -144,21 +146,21 @@ struct boot_ccw0 {
|
|||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint8_t pad;
|
uint8_t pad;
|
||||||
uint16_t count;
|
uint16_t count;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
/* Boot data structures for FBA disks */
|
/* Boot data structures for FBA disks */
|
||||||
|
|
||||||
struct boot_fba_locread {
|
struct boot_fba_locread {
|
||||||
struct boot_ccw0 locate;
|
struct boot_ccw0 locate;
|
||||||
struct boot_ccw0 read;
|
struct boot_ccw0 read;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct boot_fba_locdata {
|
struct boot_fba_locdata {
|
||||||
uint8_t command;
|
uint8_t command;
|
||||||
uint8_t dummy;
|
uint8_t dummy;
|
||||||
uint16_t blockct;
|
uint16_t blockct;
|
||||||
uint32_t blocknr;
|
uint32_t blocknr;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct boot_fba_stage0 {
|
struct boot_fba_stage0 {
|
||||||
uint64_t psw;
|
uint64_t psw;
|
||||||
@@ -169,13 +171,13 @@ struct boot_fba_stage0 {
|
|||||||
struct boot_fba_locdata locdata[2];
|
struct boot_fba_locdata locdata[2];
|
||||||
uint64_t reserved[4];
|
uint64_t reserved[4];
|
||||||
struct boot_info boot_info;
|
struct boot_info boot_info;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct boot_fba_stage1b {
|
struct boot_fba_stage1b {
|
||||||
struct boot_fba_locread locread[STAGE2_BLK_CNT_MAX];
|
struct boot_fba_locread locread[STAGE2_BLK_CNT_MAX];
|
||||||
struct boot_fba_locdata locdata[STAGE2_BLK_CNT_MAX];
|
struct boot_fba_locdata locdata[STAGE2_BLK_CNT_MAX];
|
||||||
uint8_t unused[448];
|
uint8_t unused[448];
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
/* Boot data structures for ECKD disks */
|
/* Boot data structures for ECKD disks */
|
||||||
|
|
||||||
@@ -184,14 +186,14 @@ struct boot_eckd_ccw1 {
|
|||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint16_t count;
|
uint16_t count;
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct boot_eckd_ssrt {
|
struct boot_eckd_ssrt {
|
||||||
struct boot_ccw0 seek;
|
struct boot_ccw0 seek;
|
||||||
struct boot_ccw0 search;
|
struct boot_ccw0 search;
|
||||||
struct boot_ccw0 tic;
|
struct boot_ccw0 tic;
|
||||||
struct boot_ccw0 read;
|
struct boot_ccw0 read;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct boot_eckd_seekarg {
|
struct boot_eckd_seekarg {
|
||||||
uint16_t pad;
|
uint16_t pad;
|
||||||
@@ -199,32 +201,32 @@ struct boot_eckd_seekarg {
|
|||||||
uint16_t head;
|
uint16_t head;
|
||||||
uint8_t sec;
|
uint8_t sec;
|
||||||
uint8_t pad2;
|
uint8_t pad2;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct boot_eckd_cdl_stage0 {
|
struct boot_eckd_cdl_stage0 {
|
||||||
uint64_t psw;
|
uint64_t psw;
|
||||||
struct boot_ccw0 read;
|
struct boot_ccw0 read;
|
||||||
struct boot_ccw0 tic;
|
struct boot_ccw0 tic;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct boot_eckd_ldl_stage0 {
|
struct boot_eckd_ldl_stage0 {
|
||||||
uint64_t psw;
|
uint64_t psw;
|
||||||
struct boot_ccw0 read_r0;
|
struct boot_ccw0 read_r0;
|
||||||
struct boot_ccw0 read_r1;
|
struct boot_ccw0 read_r1;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct boot_eckd_stage1 {
|
struct boot_eckd_stage1 {
|
||||||
struct boot_eckd_ssrt ssrt[2];
|
struct boot_eckd_ssrt ssrt[2];
|
||||||
struct boot_ccw0 tic1b;
|
struct boot_ccw0 tic1b;
|
||||||
struct boot_eckd_seekarg seek[2];
|
struct boot_eckd_seekarg seek[2];
|
||||||
struct boot_info boot_info;
|
struct boot_info boot_info;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct boot_eckd_stage1b {
|
struct boot_eckd_stage1b {
|
||||||
struct boot_eckd_ssrt ssrt[STAGE2_BLK_CNT_MAX];
|
struct boot_eckd_ssrt ssrt[STAGE2_BLK_CNT_MAX];
|
||||||
struct boot_eckd_seekarg seek[STAGE2_BLK_CNT_MAX];
|
struct boot_eckd_seekarg seek[STAGE2_BLK_CNT_MAX];
|
||||||
uint8_t unused[64];
|
uint8_t unused[64];
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
/* Stage 2 boot menu parameter structure */
|
/* Stage 2 boot menu parameter structure */
|
||||||
|
|
||||||
@@ -236,7 +238,7 @@ struct boot_stage2_params {
|
|||||||
uint16_t banner;
|
uint16_t banner;
|
||||||
uint16_t config[BOOT_MENU_ENTRIES + 1];
|
uint16_t config[BOOT_MENU_ENTRIES + 1];
|
||||||
uint64_t config_kdump;
|
uint64_t config_kdump;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
|
|
||||||
/* Stage 3 bootloader parameter structure */
|
/* Stage 3 bootloader parameter structure */
|
||||||
@@ -251,7 +253,7 @@ struct boot_stage3_params {
|
|||||||
uint16_t reserved[3];
|
uint16_t reserved[3];
|
||||||
uint64_t image_len;
|
uint64_t image_len;
|
||||||
uint64_t image_addr;
|
uint64_t image_addr;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
#define STAGE3_FLAG_SCSI 0x0001
|
#define STAGE3_FLAG_SCSI 0x0001
|
||||||
#define STAGE3_FLAG_KDUMP 0x0002
|
#define STAGE3_FLAG_KDUMP 0x0002
|
||||||
@@ -275,7 +277,7 @@ struct mvdump_param {
|
|||||||
uint8_t blocksize;
|
uint8_t blocksize;
|
||||||
uint8_t bpt;
|
uint8_t bpt;
|
||||||
uint8_t num_heads;
|
uint8_t num_heads;
|
||||||
} __attribute__ ((packed));
|
} __packed;
|
||||||
|
|
||||||
struct mvdump_parm_table {
|
struct mvdump_parm_table {
|
||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
@@ -284,7 +286,7 @@ struct mvdump_parm_table {
|
|||||||
uint8_t ssid[MAX_DUMP_VOLUMES];
|
uint8_t ssid[MAX_DUMP_VOLUMES];
|
||||||
unsigned char reserved[512 - sizeof(uint64_t) - sizeof(uint16_t) -
|
unsigned char reserved[512 - sizeof(uint64_t) - sizeof(uint16_t) -
|
||||||
(MAX_DUMP_VOLUMES * (sizeof(struct mvdump_param) + 1))];
|
(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 boot_get_dump_info(struct boot_info *boot_info, uint8_t dev_type,
|
||||||
void *param);
|
void *param);
|
||||||
@@ -310,8 +312,8 @@ int boot_init_fba_stage1b(struct boot_fba_stage1b *stage1b,
|
|||||||
int boot_get_eckd_stage2(void** data, size_t* size, struct job_data* job);
|
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,
|
int boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr,
|
||||||
address_t initrd_addr, size_t initrd_len,
|
address_t initrd_addr, size_t initrd_len,
|
||||||
address_t load_addr, int extra_parm, uint16_t flags,
|
address_t entry, int extra_parm, uint16_t flags,
|
||||||
size_t image_len);
|
address_t image_addr, size_t image_len);
|
||||||
int boot_get_tape_ipl(void** data, size_t* size, address_t parm_addr,
|
int boot_get_tape_ipl(void** data, size_t* size, address_t parm_addr,
|
||||||
address_t initrd_addr, address_t image_addr);
|
address_t initrd_addr, address_t image_addr);
|
||||||
int boot_get_tape_dump(void** data, size_t* size, uint64_t mem);
|
int boot_get_tape_dump(void** data, size_t* size, uint64_t mem);
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
#ifndef BOOTMAP_H
|
#ifndef BOOTMAP_H
|
||||||
#define BOOTMAP_H
|
#define BOOTMAP_H
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#include "disk.h"
|
#include "disk.h"
|
||||||
#include "job.h"
|
#include "job.h"
|
||||||
#include "zipl.h"
|
#include "zipl.h"
|
||||||
@@ -23,7 +25,7 @@ struct signature_header {
|
|||||||
uint8_t format;
|
uint8_t format;
|
||||||
uint8_t reserved[3];
|
uint8_t reserved[3];
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
} __attribute((packed));
|
} __packed;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
uint64_t load_address;
|
uint64_t load_address;
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ char* scan_keyword_name(enum scan_keyword_id id);
|
|||||||
int scan_check_defaultboot(struct scan_token* scan);
|
int scan_check_defaultboot(struct scan_token* scan);
|
||||||
struct scan_token* scan_build_automenu(struct scan_token* scan);
|
struct scan_token* scan_build_automenu(struct scan_token* scan);
|
||||||
int scan_check(struct scan_token* scan);
|
int scan_check(struct scan_token* scan);
|
||||||
|
int scan_check_bls(struct scan_token *scan);
|
||||||
int scan_find_section(struct scan_token* scan, char* name, enum scan_id type,
|
int scan_find_section(struct scan_token* scan, char* name, enum scan_id type,
|
||||||
int offset);
|
int offset);
|
||||||
int scan_check_section_data(char* keyword[], int* line, char* name,
|
int scan_check_section_data(char* keyword[], int* line, char* name,
|
||||||
|
|||||||
+23
-19
@@ -19,27 +19,29 @@
|
|||||||
#define ZIPL_MAGIC_SIZE 4
|
#define ZIPL_MAGIC_SIZE 4
|
||||||
#define DISK_LAYOUT_ID 0x00000001
|
#define DISK_LAYOUT_ID 0x00000001
|
||||||
|
|
||||||
#define ZIPL_STAGE2_LOAD_ADDRESS 0x2000
|
#define STAGE3_ENTRY 0xa000UL
|
||||||
#define ZIPL_STAGE3_ENTRY_ADDRESS 0xa000LL
|
#define IMAGE_ENTRY 0x10000UL
|
||||||
#define DEFAULT_IMAGE_ADDRESS 0x10000LL
|
#define IMAGE_ENTRY_KDUMP 0x10010UL
|
||||||
#define KDUMP_IMAGE_ADDRESS 0x10010LL
|
|
||||||
#define DEFAULT_STAGE3_ADDRESS 0xa000LL
|
#define STAGE2_LOAD_ADDRESS 0x2000UL
|
||||||
#define DEFAULT_STAGE3_PARAMS_ADDRESS 0x9000LL
|
#define STAGE3_LOAD_ADDRESS 0xa000UL
|
||||||
#define MINIMUM_ADDRESS 0x10000LL
|
#define IMAGE_LOAD_ADDRESS IMAGE_ENTRY
|
||||||
#define ADDRESS_LIMIT 0x80000000LL
|
|
||||||
|
#define ADDRESS_LIMIT 0x80000000UL
|
||||||
#define ADDRESS_LIMIT_KDUMP 0x2000000UL /* HSA size: 32 MiB */
|
#define ADDRESS_LIMIT_KDUMP 0x2000000UL /* HSA size: 32 MiB */
|
||||||
#define UNSPECIFIED_ADDRESS -1ULL
|
#define UNSPECIFIED_ADDRESS -1UL
|
||||||
#define MAXIMUM_PARMLINE_SIZE 0x380
|
#define MAXIMUM_PARMLINE_SIZE 0x380UL
|
||||||
#define MAXIMUM_PHYSICAL_BLOCKSIZE 0x1000
|
#define MAXIMUM_PHYSICAL_BLOCKSIZE 0x1000UL
|
||||||
|
|
||||||
#define STAGE3_HEAP_SIZE 0x4000
|
#define STAGE3_HEAP_SIZE 0x4000UL
|
||||||
#define STAGE3_HEAP_ADDRESS 0x2000
|
#define STAGE3_HEAP_ADDRESS 0x2000UL
|
||||||
#define STAGE3_STACK_SIZE 0x1000
|
#define STAGE3_STACK_SIZE 0x1000UL
|
||||||
#define STAGE3_STACK_ADDRESS 0xF000
|
#define STAGE3_STACK_ADDRESS 0xF000UL
|
||||||
|
#define STAGE3_PARAMS_ADDRESS 0x9000UL
|
||||||
|
|
||||||
#define PSW_ADDRESS_MASK 0x000000007fffffffLL
|
#define PSW_ADDRESS_MASK 0x000000007fffffffUL
|
||||||
#define PSW_LOAD 0x0008000080000000LL
|
#define PSW_LOAD 0x0008000080000000UL
|
||||||
#define PSW_DISABLED_WAIT 0x000a000000000000LL
|
#define PSW_DISABLED_WAIT 0x000a000000000000UL
|
||||||
|
|
||||||
#define BOOTMAP_FILENAME "bootmap"
|
#define BOOTMAP_FILENAME "bootmap"
|
||||||
#define BOOTMAP_TEMPLATE_FILENAME "bootmap_temp.XXXXXX"
|
#define BOOTMAP_TEMPLATE_FILENAME "bootmap_temp.XXXXXX"
|
||||||
@@ -47,7 +49,9 @@
|
|||||||
#define DEFAULTBOOT_SECTION "defaultboot"
|
#define DEFAULTBOOT_SECTION "defaultboot"
|
||||||
|
|
||||||
#define ZIPL_CONF_VAR "ZIPLCONF"
|
#define ZIPL_CONF_VAR "ZIPLCONF"
|
||||||
#define ZIPL_DEFAULT_CONF "/etc/zipl.conf"
|
#define ZIPL_RUNTIME_CONF "/run/zipl/zipl.conf"
|
||||||
|
#define ZIPL_DEFAULT_CONF TOOLS_SYSCONFDIR "/zipl.conf"
|
||||||
|
#define ZIPL_MINIMAL_CONF TOOLS_LIBDIR "/zipl.conf"
|
||||||
#define ZIPL_DEFAULT_BLSDIR "/boot/loader/entries"
|
#define ZIPL_DEFAULT_BLSDIR "/boot/loader/entries"
|
||||||
#define ZIPL_STAGE3_PATH TOOLS_LIBDIR "/stage3.bin"
|
#define ZIPL_STAGE3_PATH TOOLS_LIBDIR "/stage3.bin"
|
||||||
#define ZIPL_SIPL_PATH "/sys/firmware/ipl/has_secure"
|
#define ZIPL_SIPL_PATH "/sys/firmware/ipl/has_secure"
|
||||||
|
|||||||
+8
-2
@@ -6,7 +6,13 @@ all:
|
|||||||
install:
|
install:
|
||||||
$(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man5
|
$(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man5
|
||||||
$(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man8
|
$(INSTALL) -d -m 755 $(DESTDIR)$(MANDIR)/man8
|
||||||
$(INSTALL) -m 644 -c zipl.8 $(DESTDIR)$(MANDIR)/man8
|
sed -e 's@%SYSCONFDIR%@$(SYSCONFDIR)@' \
|
||||||
$(INSTALL) -m 644 -c zipl.conf.5 $(DESTDIR)$(MANDIR)/man5
|
-e 's@%TOOLS_LIBDIR%@$(TOOLS_LIBDIR)@' zipl.8.in \
|
||||||
|
> $(DESTDIR)$(MANDIR)/man8/zipl.8
|
||||||
|
sed -e 's@%SYSCONFDIR%@$(SYSCONFDIR)@' \
|
||||||
|
-e 's@%TOOLS_LIBDIR%@$(TOOLS_LIBDIR)@' zipl.conf.5.in \
|
||||||
|
> $(DESTDIR)$(MANDIR)/man5/zipl.conf.5
|
||||||
|
chmod 644 $(DESTDIR)$(MANDIR)/man8/zipl.8 \
|
||||||
|
$(DESTDIR)$(MANDIR)/man5/zipl.conf.5
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ Print version information, then exit.
|
|||||||
.TP
|
.TP
|
||||||
.BR "\-c <CONFIG FILE>" " or " "\-\-config=<CONFIG FILE>"
|
.BR "\-c <CONFIG FILE>" " or " "\-\-config=<CONFIG FILE>"
|
||||||
Use the specified <CONFIG FILE>. If none is supplied, the environment
|
Use the specified <CONFIG FILE>. If none is supplied, the environment
|
||||||
variable ZIPLCONF is evaluated if set, otherwise /etc/zipl.conf is used.
|
variable ZIPLCONF is evaluated if set, otherwise %SYSCONFDIR%/zipl.conf is used.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR "\-b <BLS DIRECTORY>" " or " "\-\-blsdir=<BLS DIRECTORY>"
|
.BR "\-b <BLS DIRECTORY>" " or " "\-\-blsdir=<BLS DIRECTORY>"
|
||||||
@@ -17,8 +17,13 @@ boot loader tool
|
|||||||
.BR zipl (8)).
|
.BR zipl (8)).
|
||||||
.br
|
.br
|
||||||
|
|
||||||
By default this configuration file is located at /etc/zipl.conf. A different
|
By default
|
||||||
location may be specified either using the '\-\-config' option of
|
.B zipl
|
||||||
|
checks for
|
||||||
|
.I zipl.conf
|
||||||
|
at /run/zipl/zipl.conf, %SYSCONFDIR%/zipl.conf, %TOOLS_LIBDIR%/zipl.conf in that
|
||||||
|
order - whichever is found first will be used. Users can specifically choose a
|
||||||
|
location using the '\-\-config' option of
|
||||||
.B zipl
|
.B zipl
|
||||||
or by setting the ZIPLCONF shell environment variable.
|
or by setting the ZIPLCONF shell environment variable.
|
||||||
.br
|
.br
|
||||||
@@ -138,7 +143,13 @@ initrd /initramfs-4.15.9
|
|||||||
options root=/dev/dasda1 console=ttyS0
|
options root=/dev/dasda1 console=ttyS0
|
||||||
.PP
|
.PP
|
||||||
|
|
||||||
The location of the linux and initrd has to be specified relative to the boot partition. The BLS config files are only used to specify the IPL sections, a zipl.conf configuration files is still needed for global parameters.
|
The location of the linux and initrd has to be specified relative to the boot
|
||||||
|
partition. The BLS config files are only used to specify the IPL sections, a
|
||||||
|
zipl.conf configuration file is still needed for global parameters. For this
|
||||||
|
purpose, a minimal zipl.conf configuration file is shipped at
|
||||||
|
%TOOLS_LIBDIR%/zipl.conf which would help when used with BLS config files, by
|
||||||
|
not requiring users to create the traditional configuration file at
|
||||||
|
%SYSCONFDIR%/zipl.conf.
|
||||||
|
|
||||||
.B Boot menu
|
.B Boot menu
|
||||||
|
|
||||||
+3
-3
@@ -45,10 +45,10 @@ clean:
|
|||||||
.boot.o.d boot.o: ../boot/data.h
|
.boot.o.d boot.o: ../boot/data.h
|
||||||
|
|
||||||
../boot/data.h:
|
../boot/data.h:
|
||||||
make -C ../boot data.h
|
$(MAKE) -C ../boot data.h
|
||||||
|
|
||||||
../boot/data.o:
|
../boot/data.o:
|
||||||
make -C ../boot data.o
|
$(MAKE) -C ../boot data.o
|
||||||
|
|
||||||
../boot/stage3.bin:
|
../boot/stage3.bin:
|
||||||
make -C ../boot stage3.bin
|
$(MAKE) -C ../boot stage3.bin
|
||||||
|
|||||||
+7
-7
@@ -79,14 +79,14 @@ boot_check_data(void)
|
|||||||
int
|
int
|
||||||
boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr,
|
boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr,
|
||||||
address_t initrd_addr, size_t initrd_len,
|
address_t initrd_addr, size_t initrd_len,
|
||||||
address_t image_addr, int extra_parm, uint16_t flags,
|
address_t entry, int extra_parm, uint16_t flags,
|
||||||
size_t image_len)
|
address_t image_addr, size_t image_len)
|
||||||
{
|
{
|
||||||
struct boot_stage3_params params;
|
struct boot_stage3_params params;
|
||||||
void* data;
|
void* data;
|
||||||
|
|
||||||
if (image_addr != (image_addr & PSW_ADDRESS_MASK)) {
|
if (entry != (entry & PSW_ADDRESS_MASK)) {
|
||||||
error_reason("Kernel image load address to high (31 bit "
|
error_reason("Kernel image entry point to high (31 bit "
|
||||||
"addressing mode)");
|
"addressing mode)");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ boot_get_stage3_parms(void **buffer, size_t *bytecount, address_t parm_addr,
|
|||||||
params.parm_addr = (uint64_t) parm_addr;
|
params.parm_addr = (uint64_t) parm_addr;
|
||||||
params.initrd_addr = (uint64_t) initrd_addr;
|
params.initrd_addr = (uint64_t) initrd_addr;
|
||||||
params.initrd_len = (uint64_t) initrd_len;
|
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.extra_parm = (uint64_t) extra_parm;
|
||||||
params.flags = flags;
|
params.flags = flags;
|
||||||
params.image_len = (uint64_t) image_len;
|
params.image_len = (uint64_t) image_len;
|
||||||
@@ -195,7 +195,7 @@ boot_init_fba_stage1b(struct boot_fba_stage1b *stage1b,
|
|||||||
stage1b->locdata[i].blocknr =
|
stage1b->locdata[i].blocknr =
|
||||||
(uint32_t) stage2_list[i].linear.block;
|
(uint32_t) stage2_list[i].linear.block;
|
||||||
stage1b->locread[i].read.address_lo =
|
stage1b->locread[i].read.address_lo =
|
||||||
ZIPL_STAGE2_LOAD_ADDRESS + i * FBA_BLK_SIZE;
|
STAGE2_LOAD_ADDRESS + i * FBA_BLK_SIZE;
|
||||||
}
|
}
|
||||||
/* Terminate CCW chain */
|
/* Terminate CCW chain */
|
||||||
stage1b->locread[i - 1].read.flags &= ~CCW_FLAG_CC;
|
stage1b->locread[i - 1].read.flags &= ~CCW_FLAG_CC;
|
||||||
@@ -220,7 +220,7 @@ boot_init_eckd_stage1b(struct boot_eckd_stage1b *stage1b,
|
|||||||
stage1b->seek[i].head = stage2_list[i].chs.head |
|
stage1b->seek[i].head = stage2_list[i].chs.head |
|
||||||
((stage2_list[i].chs.cyl >> 12) & 0xfff0);
|
((stage2_list[i].chs.cyl >> 12) & 0xfff0);
|
||||||
stage1b->seek[i].sec = stage2_list[i].chs.sec;
|
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;
|
i * stage2_list[i].chs.size;
|
||||||
stage1b->ssrt[i].read.flags = CCW_FLAG_CC | CCW_FLAG_SLI;
|
stage1b->ssrt[i].read.flags = CCW_FLAG_CC | CCW_FLAG_SLI;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-10
@@ -18,6 +18,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
#include "lib/util_part.h"
|
#include "lib/util_part.h"
|
||||||
#include "lib/util_path.h"
|
#include "lib/util_path.h"
|
||||||
|
|
||||||
@@ -223,7 +224,7 @@ struct component_entry {
|
|||||||
uint8_t data[23];
|
uint8_t data[23];
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
component_data compdat;
|
component_data compdat;
|
||||||
} __attribute((packed));
|
} __packed;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
component_execute = 0x01,
|
component_execute = 0x01,
|
||||||
@@ -263,7 +264,7 @@ struct component_header {
|
|||||||
uint8_t magic[4];
|
uint8_t magic[4];
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t reserved[27];
|
uint8_t reserved[27];
|
||||||
} __attribute((packed));
|
} __packed;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
component_header_ipl = 0x00,
|
component_header_ipl = 0x00,
|
||||||
@@ -626,7 +627,7 @@ add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Add stage 3 loader to bootmap */
|
/* 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,
|
signature_size, VOID_ADD(table, offset), 1,
|
||||||
info, target, &comp_loc[comp_nr]);
|
info, target, &comp_loc[comp_nr]);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@@ -643,17 +644,17 @@ add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
|
|||||||
rc = boot_get_stage3_parms(&stage3_params, &stage3_params_size,
|
rc = boot_get_stage3_parms(&stage3_params, &stage3_params_size,
|
||||||
ipl->parm_addr, ipl->ramdisk_addr,
|
ipl->parm_addr, ipl->ramdisk_addr,
|
||||||
ramdisk_size,
|
ramdisk_size,
|
||||||
ipl->is_kdump ? ipl->image_addr + 0x10 :
|
ipl->is_kdump ? IMAGE_ENTRY_KDUMP :
|
||||||
ipl->image_addr,
|
IMAGE_ENTRY,
|
||||||
(info->type == disk_type_scsi) ? 0 : 1,
|
(info->type == disk_type_scsi) ? 0 : 1,
|
||||||
flags, image_size);
|
flags, ipl->image_addr, image_size);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
free(table);
|
free(table);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
rc = add_component_buffer(fd, stage3_params, stage3_params_size,
|
rc = add_component_buffer(fd, stage3_params, stage3_params_size,
|
||||||
(component_data) (uint64_t)
|
(component_data) (uint64_t)
|
||||||
DEFAULT_STAGE3_PARAMS_ADDRESS,
|
STAGE3_PARAMS_ADDRESS,
|
||||||
VOID_ADD(table, offset), info,
|
VOID_ADD(table, offset), info,
|
||||||
&comp_loc[comp_nr], component_load);
|
&comp_loc[comp_nr], component_load);
|
||||||
free(stage3_params);
|
free(stage3_params);
|
||||||
@@ -791,7 +792,7 @@ add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
|
|||||||
create_component_entry(VOID_ADD(table, offset), NULL,
|
create_component_entry(VOID_ADD(table, offset), NULL,
|
||||||
component_execute,
|
component_execute,
|
||||||
(component_data) (uint64_t)
|
(component_data) (uint64_t)
|
||||||
(ZIPL_STAGE3_ENTRY_ADDRESS | PSW_LOAD),
|
(STAGE3_ENTRY | PSW_LOAD),
|
||||||
info);
|
info);
|
||||||
/* Write component table */
|
/* Write component table */
|
||||||
rc = disk_write_block_aligned(fd, table, info->phy_block_size,
|
rc = disk_write_block_aligned(fd, table, info->phy_block_size,
|
||||||
@@ -1174,7 +1175,7 @@ bootmap_create(struct job_data *job, disk_blockptr_t *program_table,
|
|||||||
ulong unused_size;
|
ulong unused_size;
|
||||||
|
|
||||||
/* Use approximated stage 3 size as starting point */
|
/* Use approximated stage 3 size as starting point */
|
||||||
size = MINIMUM_ADDRESS;
|
size = IMAGE_LOAD_ADDRESS;
|
||||||
|
|
||||||
/* Ramdisk */
|
/* Ramdisk */
|
||||||
if (job->data.dump.ramdisk != NULL) {
|
if (job->data.dump.ramdisk != NULL) {
|
||||||
@@ -1186,7 +1187,7 @@ bootmap_create(struct job_data *job, disk_blockptr_t *program_table,
|
|||||||
/* Kernel */
|
/* Kernel */
|
||||||
if (stat(job->data.dump.image, &st))
|
if (stat(job->data.dump.image, &st))
|
||||||
goto out_misc_free_temp_dev;
|
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);
|
info->phy_block_size);
|
||||||
/* Parmfile */
|
/* Parmfile */
|
||||||
size += DIV_ROUND_UP(DUMP_PARAM_MAX_LEN, info->phy_block_size);
|
size += DIV_ROUND_UP(DUMP_PARAM_MAX_LEN, info->phy_block_size);
|
||||||
|
|||||||
+4
-2
@@ -198,8 +198,8 @@ disk_get_info(const char* device, struct job_target_data* target,
|
|||||||
long devsize;
|
long devsize;
|
||||||
FILE *fh;
|
FILE *fh;
|
||||||
char *script_pre = TOOLS_LIBDIR "/zipl_helper.";
|
char *script_pre = TOOLS_LIBDIR "/zipl_helper.";
|
||||||
char *script_file;
|
char *script_file = NULL;
|
||||||
char *ppn_cmd;
|
char *ppn_cmd = NULL;
|
||||||
char buffer[80];
|
char buffer[80];
|
||||||
char value[40];
|
char value[40];
|
||||||
int majnum, minnum;
|
int majnum, minnum;
|
||||||
@@ -443,10 +443,12 @@ type_determined:
|
|||||||
data->fs_block_size = -1;
|
data->fs_block_size = -1;
|
||||||
close(fd);
|
close(fd);
|
||||||
*info = data;
|
*info = data;
|
||||||
|
free(script_file);
|
||||||
return 0;
|
return 0;
|
||||||
out_close:
|
out_close:
|
||||||
close(fd);
|
close(fd);
|
||||||
free(ppn_cmd);
|
free(ppn_cmd);
|
||||||
|
free(script_file);
|
||||||
free(data);
|
free(data);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -23,6 +23,7 @@
|
|||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
#include "lib/util_sys.h"
|
#include "lib/util_sys.h"
|
||||||
|
|
||||||
#include "boot.h"
|
#include "boot.h"
|
||||||
@@ -89,7 +90,7 @@ update_scsi_mbr(void* bootblock, disk_blockptr_t* table,
|
|||||||
uint8_t program_table_pointer[16];
|
uint8_t program_table_pointer[16];
|
||||||
uint8_t reserved2[0x50];
|
uint8_t reserved2[0x50];
|
||||||
struct boot_info boot_info;
|
struct boot_info boot_info;
|
||||||
} __attribute__ ((packed))* mbr;
|
} __packed* mbr;
|
||||||
struct scsi_dump_param param;
|
struct scsi_dump_param param;
|
||||||
void* buffer;
|
void* buffer;
|
||||||
|
|
||||||
|
|||||||
+38
-13
@@ -23,6 +23,7 @@
|
|||||||
#include "job.h"
|
#include "job.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
|
#include "zipl.h"
|
||||||
|
|
||||||
/* Command line options */
|
/* Command line options */
|
||||||
static struct option options[] = {
|
static struct option options[] = {
|
||||||
@@ -59,6 +60,14 @@ static struct option options[] = {
|
|||||||
/* Command line option abbreviations */
|
/* Command line option abbreviations */
|
||||||
static const char option_string[] = "-c:b:t:i:r:p:P:d:D:M:s:S:m:hHnVvaT:fk:";
|
static const char option_string[] = "-c:b:t:i:r:p:P:d:D:M:s:S:m:hHnVvaT:fk:";
|
||||||
|
|
||||||
|
/* Locations of zipl.conf configuration file */
|
||||||
|
static const char *zipl_conf[] = {
|
||||||
|
ZIPL_RUNTIME_CONF,
|
||||||
|
ZIPL_DEFAULT_CONF,
|
||||||
|
ZIPL_MINIMAL_CONF,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
struct command_line {
|
struct command_line {
|
||||||
char* data[SCAN_KEYWORD_NUM];
|
char* data[SCAN_KEYWORD_NUM];
|
||||||
char* config;
|
char* config;
|
||||||
@@ -114,7 +123,7 @@ get_command_line(int argc, char* argv[], struct command_line* line)
|
|||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
error_reason("dumptofs has been deprecated, use "
|
error_reason("dumptofs has been deprecated, use "
|
||||||
"--dump instead");
|
"--dumpto instead");
|
||||||
rc = -1;
|
rc = -1;
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
@@ -559,7 +568,7 @@ get_dump_components(struct job_dump_data *dump,
|
|||||||
/* Fill in component data */
|
/* Fill in component data */
|
||||||
num = 0;
|
num = 0;
|
||||||
rc = set_cl_element(&cl[num++], "kernel image", dump->image,
|
rc = set_cl_element(&cl[num++], "kernel image", dump->image,
|
||||||
&dump->image_addr, 0, 0x10000,
|
&dump->image_addr, 0, 0x0,
|
||||||
MAXIMUM_PHYSICAL_BLOCKSIZE);
|
MAXIMUM_PHYSICAL_BLOCKSIZE);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto error;
|
goto error;
|
||||||
@@ -647,12 +656,12 @@ check_component_address_data(struct component_loc *cl, int num, char *name,
|
|||||||
address_limit);
|
address_limit);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (*cl[i].addrp < MINIMUM_ADDRESS) {
|
if (*cl[i].addrp < IMAGE_LOAD_ADDRESS) {
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
error_text("Section '%s'", name);
|
error_text("Section '%s'", name);
|
||||||
error_reason("Component '%s' falls below available "
|
error_reason("Component '%s' falls below available "
|
||||||
"address space (limit is 0x%08x)",
|
"address space (limit is 0x%08x)",
|
||||||
cl[i].name, MINIMUM_ADDRESS);
|
cl[i].name, IMAGE_LOAD_ADDRESS);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -690,12 +699,12 @@ finalize_component_address_data(struct component_loc *cl, int num,
|
|||||||
for (j = -1; j < i; j++) {
|
for (j = -1; j < i; j++) {
|
||||||
if (j < 0) {
|
if (j < 0) {
|
||||||
/* Try address before first component */
|
/* Try address before first component */
|
||||||
addr = MINIMUM_ADDRESS;
|
addr = IMAGE_LOAD_ADDRESS;
|
||||||
} else {
|
} else {
|
||||||
/* Try address after component j */
|
/* Try address after component j */
|
||||||
addr = *cl[j].addrp + cl[j].size;
|
addr = *cl[j].addrp + cl[j].size;
|
||||||
if (addr < MINIMUM_ADDRESS)
|
if (addr < IMAGE_LOAD_ADDRESS)
|
||||||
addr = MINIMUM_ADDRESS;
|
addr = IMAGE_LOAD_ADDRESS;
|
||||||
}
|
}
|
||||||
addr = ALIGN(addr, cl[i].align);
|
addr = ALIGN(addr, cl[i].align);
|
||||||
if (addr + cl[i].size > address_limit) {
|
if (addr + cl[i].size > address_limit) {
|
||||||
@@ -889,7 +898,7 @@ check_job_dump_images(struct job_dump_data* dump, char* name)
|
|||||||
dump->image = misc_strdup(ZFCPDUMP_IMAGE);
|
dump->image = misc_strdup(ZFCPDUMP_IMAGE);
|
||||||
if (dump->image == NULL)
|
if (dump->image == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
dump->image_addr = DEFAULT_IMAGE_ADDRESS;
|
dump->image_addr = IMAGE_LOAD_ADDRESS;
|
||||||
|
|
||||||
/* Ramdisk is no longer required with new initramfs dump system */
|
/* Ramdisk is no longer required with new initramfs dump system */
|
||||||
if (misc_check_readable_file(ZFCPDUMP_INITRD))
|
if (misc_check_readable_file(ZFCPDUMP_INITRD))
|
||||||
@@ -1339,7 +1348,7 @@ get_job_from_section_data(char* data[], struct job_data* job, char* section)
|
|||||||
return -1;
|
return -1;
|
||||||
if (extract_address(job->data.ipl.image,
|
if (extract_address(job->data.ipl.image,
|
||||||
&job->data.ipl.image_addr)) {
|
&job->data.ipl.image_addr)) {
|
||||||
job->data.ipl.image_addr = DEFAULT_IMAGE_ADDRESS;
|
job->data.ipl.image_addr = IMAGE_LOAD_ADDRESS;
|
||||||
}
|
}
|
||||||
/* Fill in parmline */
|
/* Fill in parmline */
|
||||||
rc = get_parmline(data[(int) scan_keyword_parmfile],
|
rc = get_parmline(data[(int) scan_keyword_parmfile],
|
||||||
@@ -1394,7 +1403,7 @@ get_job_from_section_data(char* data[], struct job_data* job, char* section)
|
|||||||
return -1;
|
return -1;
|
||||||
if (extract_address(job->data.ipl_tape.image,
|
if (extract_address(job->data.ipl_tape.image,
|
||||||
&job->data.ipl_tape.image_addr)) {
|
&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 */
|
/* Fill in parmline */
|
||||||
rc = get_parmline(data[(int) scan_keyword_parmfile],
|
rc = get_parmline(data[(int) scan_keyword_parmfile],
|
||||||
@@ -1780,10 +1789,10 @@ get_job_from_config_file(struct command_line* cmdline, struct job_data* job)
|
|||||||
{
|
{
|
||||||
struct scan_token* scan;
|
struct scan_token* scan;
|
||||||
struct scan_token* new_scan;
|
struct scan_token* new_scan;
|
||||||
char* filename;
|
const char *filename = NULL;
|
||||||
char *blsdir;
|
char *blsdir;
|
||||||
char* source;
|
char* source;
|
||||||
int rc, scan_size;
|
int i, rc, scan_size;
|
||||||
|
|
||||||
/* Read configuration file */
|
/* Read configuration file */
|
||||||
if (cmdline->config != NULL) {
|
if (cmdline->config != NULL) {
|
||||||
@@ -1797,7 +1806,16 @@ get_job_from_config_file(struct command_line* cmdline, struct job_data* job)
|
|||||||
ZIPL_CONF_VAR ")";
|
ZIPL_CONF_VAR ")";
|
||||||
} else {
|
} else {
|
||||||
/* Use default config file */
|
/* Use default config file */
|
||||||
filename = ZIPL_DEFAULT_CONF;
|
for (i = 0; zipl_conf[i]; i++) {
|
||||||
|
if (misc_check_readable_file(zipl_conf[i]) == 0) {
|
||||||
|
filename = zipl_conf[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (filename == NULL) {
|
||||||
|
error_text("No zipl configuration was readable");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
source = "";
|
source = "";
|
||||||
}
|
}
|
||||||
printf("Using config file '%s'%s\n", filename, source);
|
printf("Using config file '%s'%s\n", filename, source);
|
||||||
@@ -1840,6 +1858,12 @@ get_job_from_config_file(struct command_line* cmdline, struct job_data* job)
|
|||||||
scan_free(scan);
|
scan_free(scan);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
rc = scan_check_bls(scan);
|
||||||
|
if (rc) {
|
||||||
|
error_text("BLS parsing '%s'", blsdir);
|
||||||
|
scan_free(scan);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
/* Get job from config file data */
|
/* Get job from config file data */
|
||||||
if (cmdline->menu != NULL)
|
if (cmdline->menu != NULL)
|
||||||
rc = get_menu_job(scan, cmdline->menu, job);
|
rc = get_menu_job(scan, cmdline->menu, job);
|
||||||
@@ -1880,6 +1904,7 @@ job_get(int argc, char* argv[], struct job_data** data)
|
|||||||
job->add_files = cmdline.add_files;
|
job->add_files = cmdline.add_files;
|
||||||
job->data.mvdump.force = cmdline.force;
|
job->data.mvdump.force = cmdline.force;
|
||||||
job->dry_run = cmdline.dry_run;
|
job->dry_run = cmdline.dry_run;
|
||||||
|
job->is_secure = SECURE_BOOT_AUTO;
|
||||||
/* Get job data from user input */
|
/* Get job data from user input */
|
||||||
if (cmdline.help) {
|
if (cmdline.help) {
|
||||||
job->command_line = 1;
|
job->command_line = 1;
|
||||||
|
|||||||
+66
-2
@@ -755,8 +755,14 @@ scan_bls(const char* blsdir, struct scan_token** token, int scan_size)
|
|||||||
|
|
||||||
remaining = scan_size - count;
|
remaining = scan_size - count;
|
||||||
|
|
||||||
if (remaining < n) {
|
/* The array of scanned tokens is allocated when the zipl config file is
|
||||||
size = scan_size - remaining + n;
|
* parsed. Its size is a multiple of INITIAL_ARRAY_LENGTH so it may have
|
||||||
|
* enough space to scan all the tokens that are defined in the BLS files.
|
||||||
|
* Calculate if is enough assuming that a BLS fragment can contain up to
|
||||||
|
* 4 tokens: a section heading and 3 keywords (image, ramdisk, parameter).
|
||||||
|
*/
|
||||||
|
if (remaining < n * 4) {
|
||||||
|
size = scan_size - remaining + (n * 4);
|
||||||
buffer = (struct scan_token *)misc_malloc(size * sizeof(struct scan_token));
|
buffer = (struct scan_token *)misc_malloc(size * sizeof(struct scan_token));
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
goto err;
|
goto err;
|
||||||
@@ -1558,6 +1564,64 @@ scan_check(struct scan_token* scan)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if kernel and initrd image paths provided by BLS files are readable.
|
||||||
|
* If not, add value of 'scan_keyword_target' into search path and silently
|
||||||
|
* update scan list.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scan_check_bls(struct scan_token *scan)
|
||||||
|
{
|
||||||
|
int i, rc;
|
||||||
|
char *target_value = NULL;
|
||||||
|
char *img_value = NULL;
|
||||||
|
char *buffer = NULL;
|
||||||
|
/*
|
||||||
|
* In the BLS case, each BLS section heading inherits a keyword
|
||||||
|
* assignment target= from zipl.conf, and they are all the same.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
for (i = 0 ; scan[i].id != scan_id_empty; i++) {
|
||||||
|
if (scan[i].id == scan_id_keyword_assignment &&
|
||||||
|
scan[i].content.keyword.keyword == scan_keyword_target) {
|
||||||
|
target_value = scan[i].content.keyword.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!target_value)
|
||||||
|
return -1;
|
||||||
|
for (i = 0 ; scan[i].id != scan_id_empty; i++) {
|
||||||
|
if (scan[i].id != scan_id_keyword_assignment)
|
||||||
|
continue;
|
||||||
|
if (scan[i].content.keyword.keyword == scan_keyword_image ||
|
||||||
|
scan[i].content.keyword.keyword == scan_keyword_ramdisk) {
|
||||||
|
|
||||||
|
rc = misc_check_readable_file(
|
||||||
|
scan[i].content.keyword.value);
|
||||||
|
if (rc) {
|
||||||
|
misc_asprintf(&img_value, "%s%s",
|
||||||
|
target_value,
|
||||||
|
scan[i].content.keyword.value);
|
||||||
|
rc = misc_check_readable_file(img_value);
|
||||||
|
if (rc) {
|
||||||
|
error_text(
|
||||||
|
"Image file '%s' is not accessible",
|
||||||
|
scan[i].content.keyword.value);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
buffer = (char *)
|
||||||
|
misc_malloc(strlen(img_value) + 1);
|
||||||
|
if (buffer == NULL)
|
||||||
|
return -1;
|
||||||
|
memcpy(buffer, img_value, strlen(img_value));
|
||||||
|
buffer[strlen(img_value)] = 0;
|
||||||
|
free(scan[i].content.keyword.value);
|
||||||
|
scan[i].content.keyword.value = buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
scan_get_defaultboot_type(char* keyword[], int line[], int section_line,
|
scan_get_defaultboot_type(char* keyword[], int line[], int section_line,
|
||||||
|
|||||||
+8
-1
@@ -68,6 +68,8 @@ static const char* usage_text[] = {
|
|||||||
"-P, --parameters PARMLINE Use specified kernel PARMLINE",
|
"-P, --parameters PARMLINE Use specified kernel PARMLINE",
|
||||||
"-T, --tape TAPEDEV Install bootloader on tape device TAPEDEV",
|
"-T, --tape TAPEDEV Install bootloader on tape device TAPEDEV",
|
||||||
"-s, --segment SEGMENT,ADDR Install a segment from file SEGMENT",
|
"-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",
|
"-d, --dumpto DUMPDEV[,SIZE] Install a system dump record on tape device",
|
||||||
" or disk partition DUMPDEV",
|
" or disk partition DUMPDEV",
|
||||||
"-M, --mvdump DEVLIST[,SIZE] Install a multi-volume dump record on each",
|
"-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'",
|
"-n, --noninteractive Answer all confirmation questions with 'yes'",
|
||||||
"-V, --verbose Provide more verbose output",
|
"-V, --verbose Provide more verbose output",
|
||||||
"-a, --add-files Add all referenced files to bootmap file",
|
"-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"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+7
-5
@@ -64,18 +64,20 @@ zkey-cryptsetup-skip-jsonc:
|
|||||||
|
|
||||||
all: $(BUILD_TARGETS)
|
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
|
pkey.o: pkey.c 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
|
properties.o: check-dep-zkey properties.c properties.h
|
||||||
keystore.o: keystore.c keystore.h properties.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 misc.h
|
zkey-cryptsetup.o: check-dep-zkey-cryptsetup zkey-cryptsetup.c pkey.h cca.h misc.h
|
||||||
|
|
||||||
zkey: LDLIBS = -ldl -lcrypto
|
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 utils.o $(libs)
|
||||||
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
||||||
|
|
||||||
zkey-cryptsetup: LDLIBS = -ldl -lcryptsetup -ljson-c
|
zkey-cryptsetup: LDLIBS = -ldl -lcryptsetup -ljson-c
|
||||||
zkey-cryptsetup: zkey-cryptsetup.o pkey.o $(libs)
|
zkey-cryptsetup: zkey-cryptsetup.o pkey.o cca.o utils.o $(libs)
|
||||||
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
||||||
|
|
||||||
install-common:
|
install-common:
|
||||||
|
|||||||
+981
@@ -0,0 +1,981 @@
|
|||||||
|
/*
|
||||||
|
* 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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#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"
|
||||||
|
#include "pkey.h"
|
||||||
|
#include "utils.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"
|
||||||
|
#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
|
||||||
|
* 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;
|
||||||
|
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:
|
||||||
|
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");
|
||||||
|
|
||||||
|
/* 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");
|
||||||
|
|
||||||
|
/* 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");
|
||||||
|
|
||||||
|
/* 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_CSNBRKA == 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)
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
+146
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* 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_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,
|
||||||
|
unsigned char *exit_data,
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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;
|
||||||
|
unsigned int mod;
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
t_CSUACRD dll_CSUACRD;
|
||||||
|
t_CSNBKTR2 dll_CSNBKTR2;
|
||||||
|
t_CSNBRKA dll_CSNBRKA;
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
int restrict_key_export(struct cca_lib *cca, u8 *secure_key,
|
||||||
|
unsigned int secure_key_size, bool verbose);
|
||||||
|
|
||||||
|
#endif
|
||||||
+613
-256
File diff suppressed because it is too large
Load Diff
+10
-4
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "cca.h"
|
||||||
#include "pkey.h"
|
#include "pkey.h"
|
||||||
|
|
||||||
struct keystore {
|
struct keystore {
|
||||||
@@ -31,12 +32,13 @@ int keystore_generate_key(struct keystore *keystore, const char *name,
|
|||||||
const char *apqns, bool noapqncheck,
|
const char *apqns, bool noapqncheck,
|
||||||
size_t sector_size, size_t keybits, bool xts,
|
size_t sector_size, size_t keybits, bool xts,
|
||||||
const char *clear_key_file, const char *volume_type,
|
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,
|
int keystore_import_key(struct keystore *keystore, const char *name,
|
||||||
const char *description, const char *volumes,
|
const char *description, const char *volumes,
|
||||||
const char *apqns, bool noapqncheck, size_t sector_size,
|
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,
|
int keystore_change_key(struct keystore *keystore, const char *name,
|
||||||
const char *description, const char *volumes,
|
const char *description, const char *volumes,
|
||||||
@@ -54,7 +56,7 @@ int keystore_reencipher_key(struct keystore *keystore, const char *name_filter,
|
|||||||
const char *apqn_filter,
|
const char *apqn_filter,
|
||||||
bool from_old, bool to_new, bool inplace,
|
bool from_old, bool to_new, bool inplace,
|
||||||
bool staged, bool complete, int pkey_fd,
|
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,
|
int keystore_copy_key(struct keystore *keystore, const char *name,
|
||||||
const char *newname, const char *volumes);
|
const char *newname, const char *volumes);
|
||||||
@@ -67,7 +69,7 @@ int keystore_remove_key(struct keystore *keystore, const char *name,
|
|||||||
|
|
||||||
int keystore_list_keys(struct keystore *keystore, const char *name_filter,
|
int keystore_list_keys(struct keystore *keystore, const char *name_filter,
|
||||||
const char *volume_filter, const char *apqn_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,
|
int keystore_cryptsetup(struct keystore *keystore, const char *volume_filter,
|
||||||
bool execute, const char *volume_type,
|
bool execute, const char *volume_type,
|
||||||
@@ -79,6 +81,10 @@ int keystore_crypttab(struct keystore *keystore, const char *volume_filter,
|
|||||||
const char *volume_type, const char *keyfile,
|
const char *volume_type, const char *keyfile,
|
||||||
size_t keyfile_offset, size_t keyfile_size, size_t tries);
|
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);
|
void keystore_free(struct keystore *keystore);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1206
-328
File diff suppressed because it is too large
Load Diff
+171
-33
@@ -18,10 +18,23 @@
|
|||||||
/*
|
/*
|
||||||
* Definitions for the /dev/pkey kernel module interface
|
* Definitions for the /dev/pkey kernel module interface
|
||||||
*/
|
*/
|
||||||
struct secaeskeytoken {
|
struct tokenheader {
|
||||||
u8 type; /* 0x01 for internal key token */
|
u8 type;
|
||||||
u8 res0[3];
|
u8 res0[3];
|
||||||
u8 version; /* should be 0x04 */
|
u8 version;
|
||||||
|
u8 res1[3];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define TOKEN_TYPE_NON_CCA 0x00
|
||||||
|
#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 */
|
||||||
|
u8 res0[3];
|
||||||
|
u8 version; /* should be TOKEN_VERSION_AESDATA (0x04) */
|
||||||
u8 res1[1];
|
u8 res1[1];
|
||||||
u8 flag; /* key flags */
|
u8 flag; /* key flags */
|
||||||
u8 res2[1];
|
u8 res2[1];
|
||||||
@@ -33,22 +46,60 @@ struct secaeskeytoken {
|
|||||||
u8 tvv[4]; /* token validation value */
|
u8 tvv[4]; /* token validation value */
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define SECURE_KEY_SIZE sizeof(struct secaeskeytoken)
|
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 MAX(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE)
|
||||||
|
#define MIN_SECURE_KEY_SIZE MIN(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE)
|
||||||
|
|
||||||
struct pkey_seckey {
|
struct pkey_seckey {
|
||||||
u8 seckey[SECURE_KEY_SIZE]; /* the secure key blob */
|
u8 seckey[AESDATA_KEY_SIZE]; /* the secure key blob */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pkey_clrkey {
|
struct pkey_clrkey {
|
||||||
u8 clrkey[32]; /* 16, 24, or 32 byte clear key value */
|
u8 clrkey[32]; /* 16, 24, or 32 byte clear key value */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PKEY_IOCTL_MAGIC 'p'
|
#define PKEY_IOCTL_MAGIC 'p'
|
||||||
#define AUTOSELECT 0xFFFF
|
#define AUTOSELECT 0xFFFF
|
||||||
#define PKEYDEVICE "/dev/pkey"
|
#define PKEYDEVICE "/dev/pkey"
|
||||||
#define PKEY_KEYTYPE_AES_128 1
|
#define PKEY_KEYTYPE_AES_128 1
|
||||||
#define PKEY_KEYTYPE_AES_192 2
|
#define PKEY_KEYTYPE_AES_192 2
|
||||||
#define PKEY_KEYTYPE_AES_256 3
|
#define PKEY_KEYTYPE_AES_256 3
|
||||||
|
|
||||||
struct pkey_genseck {
|
struct pkey_genseck {
|
||||||
u16 cardnr; /* in: card to use or FFFF for any */
|
u16 cardnr; /* in: card to use or FFFF for any */
|
||||||
@@ -82,34 +133,114 @@ struct pkey_verifykey {
|
|||||||
|
|
||||||
#define PKEY_VERIFYKEY _IOWR(PKEY_IOCTL_MAGIC, 0x07, struct pkey_verifykey)
|
#define PKEY_VERIFYKEY _IOWR(PKEY_IOCTL_MAGIC, 0x07, struct pkey_verifykey)
|
||||||
|
|
||||||
#define METHOD_OLD_TO_CURRENT "RTCMK "
|
enum pkey_key_type {
|
||||||
#define METHOD_CURRENT_TO_NEW "RTNMK "
|
PKEY_TYPE_CCA_DATA = (u32) 1,
|
||||||
|
PKEY_TYPE_CCA_CIPHER = (u32) 2,
|
||||||
|
};
|
||||||
|
|
||||||
typedef void (*t_CSNBKTC)(long *return_code,
|
enum pkey_key_size {
|
||||||
long *reason_code,
|
PKEY_SIZE_AES_128 = (u32) 128,
|
||||||
long *exit_data_length,
|
PKEY_SIZE_AES_192 = (u32) 192,
|
||||||
unsigned char *exit_data,
|
PKEY_SIZE_AES_256 = (u32) 256,
|
||||||
long *rule_array_count,
|
PKEY_SIZE_UNKNOWN = (u32) 0xFFFFFFFF,
|
||||||
unsigned char *rule_array,
|
};
|
||||||
unsigned char *key_identifier);
|
|
||||||
|
#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 PAES_BLOCK_SIZE 16
|
||||||
#define ENC_ZERO_LEN (2 * PAES_BLOCK_SIZE)
|
#define ENC_ZERO_LEN (2 * PAES_BLOCK_SIZE)
|
||||||
#define VERIFICATION_PATTERN_LEN (2 * ENC_ZERO_LEN + 1)
|
#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 open_pkey_device(bool verbose);
|
||||||
|
|
||||||
int generate_secure_key_random(int pkey_fd, const char *keyfile,
|
int generate_secure_key_random(int pkey_fd, const char *keyfile,
|
||||||
size_t keybits, bool xts, u16 card, u16 domain,
|
size_t keybits, bool xts, const char *key_type,
|
||||||
bool verbose);
|
const char **apqns, bool verbose);
|
||||||
|
|
||||||
int generate_secure_key_clear(int pkey_fd, const char *keyfile,
|
int generate_secure_key_clear(int pkey_fd, const char *keyfile,
|
||||||
size_t keybits, bool xts,
|
size_t keybits, bool xts,
|
||||||
const char *clearkeyfile,
|
const char *clearkeyfile, const char *key_type,
|
||||||
u16 card, u16 domain,
|
const char **apqns, bool verbose);
|
||||||
bool verbose);
|
|
||||||
|
|
||||||
u8 *read_secure_key(const char *keyfile, size_t *secure_key_size,
|
u8 *read_secure_key(const char *keyfile, size_t *secure_key_size,
|
||||||
bool verbose);
|
bool verbose);
|
||||||
@@ -120,13 +251,20 @@ int write_secure_key(const char *keyfile, const u8 *secure_key,
|
|||||||
int validate_secure_key(int pkey_fd,
|
int validate_secure_key(int pkey_fd,
|
||||||
u8 *secure_key, size_t secure_key_size,
|
u8 *secure_key, size_t secure_key_size,
|
||||||
size_t *clear_key_bitsize, int *is_old_mk,
|
size_t *clear_key_bitsize, int *is_old_mk,
|
||||||
bool verbose);
|
const char **apqns, bool verbose);
|
||||||
|
|
||||||
int key_token_change(t_CSNBKTC dll_CSNBKTC,
|
int generate_key_verification_pattern(const u8 *key, size_t key_size,
|
||||||
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);
|
char *vp, size_t vp_len, 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);
|
||||||
|
int get_min_card_level_for_keytype(const char *key_type);
|
||||||
|
int check_aes_cipher_key(const u8 *key, size_t key_size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+26
-2
@@ -9,6 +9,7 @@
|
|||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -183,14 +184,16 @@ static struct property *properties_find(struct properties *properties,
|
|||||||
* @param[in] properties the properties object
|
* @param[in] properties the properties object
|
||||||
* @param[in] name the name of the property
|
* @param[in] name the name of the property
|
||||||
* @param[in] value the value of the property
|
* @param[in] value the value of the property
|
||||||
|
* @param[in] uppercase if true the value is set all uppercase
|
||||||
*
|
*
|
||||||
* @returns 0 on success,
|
* @returns 0 on success,
|
||||||
* -EINVAL if the name or value contains invalid characters
|
* -EINVAL if the name or value contains invalid characters
|
||||||
*/
|
*/
|
||||||
int properties_set(struct properties *properties,
|
int properties_set2(struct properties *properties,
|
||||||
const char *name, const char *value)
|
const char *name, const char *value, bool uppercase)
|
||||||
{
|
{
|
||||||
struct property *property;
|
struct property *property;
|
||||||
|
int i;
|
||||||
|
|
||||||
util_assert(properties != NULL, "Internal error: properties is NULL");
|
util_assert(properties != NULL, "Internal error: properties is NULL");
|
||||||
util_assert(name != NULL, "Internal error: name is NULL");
|
util_assert(name != NULL, "Internal error: name is NULL");
|
||||||
@@ -211,9 +214,30 @@ int properties_set(struct properties *properties,
|
|||||||
property->value = util_strdup(value);
|
property->value = util_strdup(value);
|
||||||
util_list_add_tail(&properties->list, property);
|
util_list_add_tail(&properties->list, property);
|
||||||
}
|
}
|
||||||
|
if (uppercase) {
|
||||||
|
for (i = 0; property->value[i] != '\0'; i++)
|
||||||
|
property->value[i] = toupper(property->value[i]);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds or updates a property
|
||||||
|
*
|
||||||
|
* @param[in] properties the properties object
|
||||||
|
* @param[in] name the name of the property
|
||||||
|
* @param[in] value the value of the property
|
||||||
|
*
|
||||||
|
* @returns 0 on success,
|
||||||
|
* -EINVAL if the name or value contains invalid characters
|
||||||
|
*/
|
||||||
|
int properties_set(struct properties *properties,
|
||||||
|
const char *name, const char *value)
|
||||||
|
{
|
||||||
|
return properties_set2(properties, name, value, false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a property
|
* Gets a property
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ void properties_free(struct properties *properties);
|
|||||||
int properties_set(struct properties *properties,
|
int properties_set(struct properties *properties,
|
||||||
const char *name, const char *value);
|
const char *name, const char *value);
|
||||||
|
|
||||||
|
int properties_set2(struct properties *properties,
|
||||||
|
const char *name, const char *value, bool uppercase);
|
||||||
|
|
||||||
char *properties_get(struct properties *properties, const char *name);
|
char *properties_get(struct properties *properties, const char *name);
|
||||||
|
|
||||||
int properties_remove(struct properties *properties, const char *name);
|
int properties_remove(struct properties *properties, const char *name);
|
||||||
|
|||||||
+819
@@ -0,0 +1,819 @@
|
|||||||
|
/*
|
||||||
|
* 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 <dirent.h>
|
||||||
|
#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 "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) \
|
||||||
|
warnx(fmt); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, 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) {
|
||||||
|
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", "?");
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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_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);
|
||||||
|
|
||||||
|
util_rec_free(info.rec);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
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, level;
|
||||||
|
|
||||||
|
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 (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 "
|
||||||
|
"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] 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
|
||||||
|
*
|
||||||
|
* @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, int min_level,
|
||||||
|
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.min_level = min_level;
|
||||||
|
info.verbose = verbose;
|
||||||
|
|
||||||
|
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)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
int sysfs_get_card_level(int card);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
int print_mk_info(const char *apqns, bool verbose);
|
||||||
|
|
||||||
|
int cross_check_apqns(const char *apqns, u64 mkvp, int min_level,
|
||||||
|
bool print_mks, bool verbose);
|
||||||
|
|
||||||
|
bool prompt_for_yes(bool verbose);
|
||||||
|
|
||||||
|
#endif
|
||||||
+40
-9
@@ -91,6 +91,8 @@ behave in the same way as with \fBcryptsetup\fP.
|
|||||||
.B zkey\-cryptsetup
|
.B zkey\-cryptsetup
|
||||||
.BR reencipher | re
|
.BR reencipher | re
|
||||||
.I device
|
.I device
|
||||||
|
.RB [ \-\-to\-new | \-N ]
|
||||||
|
.RB [ \-\-from\-old | \-O ]
|
||||||
.RB [ \-\-staged | \-s ]
|
.RB [ \-\-staged | \-s ]
|
||||||
.RB [ \-\-in\-place | \-i ]
|
.RB [ \-\-in\-place | \-i ]
|
||||||
.RB [ \-\-complete | \-c ]
|
.RB [ \-\-complete | \-c ]
|
||||||
@@ -128,17 +130,36 @@ register can still be used until the master key is changed again.
|
|||||||
The \fBNEW\fP register contains the new master key to be set.
|
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 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
|
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
|
.RE
|
||||||
.PP
|
.PP
|
||||||
\fBzkey\-cryptsetup\fP automatically detects whether the secure volume key
|
Use the
|
||||||
is currently enciphered with the master key in the \fBOLD\fP register or with
|
.B \-\-from\-old
|
||||||
the master key in the \fBCURRENT\fP register. If currently enciphered with the
|
option to re-encipher a secure volume key that is currently enciphered with
|
||||||
master key in the \fBOLD\fP register, it is re-enciphered with the master key
|
the master key in the \fBOLD\fP register with the master key in the
|
||||||
in the \fBCURRENT\fP register. If it is currently enciphered with the master
|
\fBCURRENT\fP register.
|
||||||
key in the \fBCURRENT\fP register, it is re-enciphered with the master key in
|
.PP
|
||||||
the \fBNEW\fP register. If for this case the \fBNEW\fP register does not
|
.PP
|
||||||
contain a valid master key, then the re-encipher operation fails.
|
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
|
.PP
|
||||||
Re-enciphering a secure volume key of a volume encrypted with
|
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
|
\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"
|
.SS "Options for the reencipher command"
|
||||||
.TP
|
.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
|
.BR \-i ", " \-\-in-place
|
||||||
Forces an in-place re-enciphering of a secure volume key in the LUKS2
|
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
|
header. This option immediately replaces the secure volume key in the LUKS2
|
||||||
|
|||||||
+189
-53
@@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "pkey.h"
|
#include "pkey.h"
|
||||||
|
#include "cca.h"
|
||||||
|
|
||||||
/* Detect if cryptsetup 2.1 or later is available */
|
/* Detect if cryptsetup 2.1 or later is available */
|
||||||
#ifdef CRYPT_LOG_DEBUG_JSON
|
#ifdef CRYPT_LOG_DEBUG_JSON
|
||||||
@@ -94,6 +95,8 @@ static struct zkey_cryptsetup_globals {
|
|||||||
long long keyfile_offset;
|
long long keyfile_offset;
|
||||||
long long keyfile_size;
|
long long keyfile_size;
|
||||||
long long tries;
|
long long tries;
|
||||||
|
bool tonew;
|
||||||
|
bool fromold;
|
||||||
bool complete;
|
bool complete;
|
||||||
bool inplace;
|
bool inplace;
|
||||||
bool staged;
|
bool staged;
|
||||||
@@ -101,8 +104,7 @@ static struct zkey_cryptsetup_globals {
|
|||||||
bool batch_mode;
|
bool batch_mode;
|
||||||
bool debug;
|
bool debug;
|
||||||
bool verbose;
|
bool verbose;
|
||||||
void *lib_csulcca;
|
struct cca_lib cca;
|
||||||
t_CSNBKTC dll_CSNBKTC;
|
|
||||||
int pkey_fd;
|
int pkey_fd;
|
||||||
struct crypt_device *cd;
|
struct crypt_device *cd;
|
||||||
} g = {
|
} g = {
|
||||||
@@ -162,6 +164,22 @@ static struct util_opt opt_vec[] = {
|
|||||||
.desc = "OPTIONS",
|
.desc = "OPTIONS",
|
||||||
.command = COMMAND_REENCIPHER,
|
.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'},
|
.option = {"staged", 0, NULL, 's'},
|
||||||
.desc = "Forces that the re-enciphering of a secure volume "
|
.desc = "Forces that the re-enciphering of a secure volume "
|
||||||
@@ -1275,7 +1293,7 @@ static int activate_unbound_keyslot(int token, int keyslot, const char *key,
|
|||||||
util_print_indented(complete_msg, 0);
|
util_print_indented(complete_msg, 0);
|
||||||
util_print_indented("All key slots containing the old volume key are "
|
util_print_indented("All key slots containing the old volume key are "
|
||||||
"now in unbound state. Do you want to remove "
|
"now in unbound state. Do you want to remove "
|
||||||
"these key slots?", 0);
|
"these key slots [y/N]?", 0);
|
||||||
|
|
||||||
if (!prompt_for_yes())
|
if (!prompt_for_yes())
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1311,22 +1329,25 @@ static int activate_unbound_keyslot(int token, int keyslot, const char *key,
|
|||||||
return rc;
|
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");
|
warnx("Invalid volume key size");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(crypt_get_cipher_mode(g.cd), "xts", 3) == 0) {
|
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 "
|
warnx("The volume key size %lu is not valid for the "
|
||||||
"cipher mode '%s'", keysize,
|
"cipher mode '%s'", keysize,
|
||||||
crypt_get_cipher_mode(g.cd));
|
crypt_get_cipher_mode(g.cd));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
} else {
|
} 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 "
|
warnx("The volume key size %lu is not valid for the "
|
||||||
"cipher mode '%s'", keysize,
|
"cipher mode '%s'", keysize,
|
||||||
crypt_get_cipher_mode(g.cd));
|
crypt_get_cipher_mode(g.cd));
|
||||||
@@ -1359,7 +1380,7 @@ static int open_keyslot(int keyslot, char **key, size_t *keysize,
|
|||||||
vkeysize = crypt_get_volume_key_size(g.cd);
|
vkeysize = crypt_get_volume_key_size(g.cd);
|
||||||
pr_verbose("Volume key size: %lu", vkeysize);
|
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)
|
if (rc != 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@@ -1471,7 +1492,7 @@ static int validate_keyslot(int keyslot, char **key, size_t *keysize,
|
|||||||
keyslot = rc;
|
keyslot = rc;
|
||||||
|
|
||||||
rc = validate_secure_key(g.pkey_fd, (u8 *)vkey, vkeysize, clear_keysize,
|
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 (rc != 0) {
|
||||||
if (invalid_msg != NULL)
|
if (invalid_msg != NULL)
|
||||||
warnx("%s", invalid_msg);
|
warnx("%s", invalid_msg);
|
||||||
@@ -1514,17 +1535,19 @@ static int reencipher_prepare(int token)
|
|||||||
char *password = NULL;
|
char *password = NULL;
|
||||||
size_t password_len;
|
size_t password_len;
|
||||||
char *key = NULL;
|
char *key = NULL;
|
||||||
|
int selected = 1;
|
||||||
size_t keysize;
|
size_t keysize;
|
||||||
int is_old_mk;
|
int is_old_mk;
|
||||||
char *prompt;
|
char *prompt;
|
||||||
char *msg;
|
char *msg;
|
||||||
|
u64 mkvp;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (token >= 0) {
|
if (token >= 0) {
|
||||||
util_asprintf(&msg, "Staged volume key re-enciphering is "
|
util_asprintf(&msg, "Staged volume key re-enciphering is "
|
||||||
"already initiated for device '%s'. Do you want to "
|
"already initiated for device '%s'. Do you want to "
|
||||||
"cancel the pending re-enciphering and start a "
|
"cancel the pending re-enciphering and start a "
|
||||||
"new re-enciphering process?", g.pos_arg);
|
"new re-enciphering process [y/N]?", g.pos_arg);
|
||||||
util_print_indented(msg, 0);
|
util_print_indented(msg, 0);
|
||||||
free(msg);
|
free(msg);
|
||||||
|
|
||||||
@@ -1551,7 +1574,7 @@ static int reencipher_prepare(int token)
|
|||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rc = generate_key_verification_pattern(key, keysize,
|
rc = generate_key_verification_pattern((u8 *)key, keysize,
|
||||||
reenc_tok.verification_pattern,
|
reenc_tok.verification_pattern,
|
||||||
sizeof(reenc_tok.verification_pattern),
|
sizeof(reenc_tok.verification_pattern),
|
||||||
g.verbose);
|
g.verbose);
|
||||||
@@ -1570,25 +1593,97 @@ static int reencipher_prepare(int token)
|
|||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
util_asprintf(&msg, "The secure volume key of device '%s' is "
|
if (!g.fromold && !g.tonew) {
|
||||||
"enciphered with the %s CCA master key and is being "
|
/* Autodetect reencipher mode */
|
||||||
"re-enciphered with the %s CCA master key.",
|
if (is_old_mk) {
|
||||||
g.pos_arg, is_old_mk ? "OLD" : "CURRENT",
|
g.fromold = 1;
|
||||||
is_old_mk ? "CURRENT" : "NEW");
|
util_asprintf(&msg, "The secure volume key of device "
|
||||||
util_print_indented(msg, 0);
|
"'%s' is enciphered with the OLD CCA "
|
||||||
free(msg);
|
"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 = key_token_change(g.dll_CSNBKTC, (u8 *)key, keysize,
|
rc = get_master_key_verification_pattern((u8 *)key, keysize, &mkvp,
|
||||||
is_old_mk ? METHOD_OLD_TO_CURRENT :
|
g.verbose);
|
||||||
METHOD_CURRENT_TO_NEW,
|
|
||||||
g.verbose);
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
warnx("Failed to re-encipher the secure volume key of device "
|
warnx("Failed to get the master key verification pattern: %s",
|
||||||
"'%s'", g.pos_arg);
|
strerror(-rc));
|
||||||
rc = -EINVAL;
|
|
||||||
goto out;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
rc = crypt_keyslot_add_by_key(g.cd, CRYPT_ANY_SLOT, key, keysize,
|
||||||
password, password_len,
|
password, password_len,
|
||||||
CRYPT_VOLUME_KEY_NO_SEGMENT);
|
CRYPT_VOLUME_KEY_NO_SEGMENT);
|
||||||
@@ -1651,10 +1746,12 @@ static int reencipher_complete(int token)
|
|||||||
char *password = NULL;
|
char *password = NULL;
|
||||||
size_t password_len;
|
size_t password_len;
|
||||||
char *key = NULL;
|
char *key = NULL;
|
||||||
|
int selected = 1;
|
||||||
size_t keysize;
|
size_t keysize;
|
||||||
int is_old_mk;
|
int is_old_mk;
|
||||||
char *prompt;
|
char *prompt;
|
||||||
char *msg;
|
char *msg;
|
||||||
|
u64 mkvp;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = get_reencipher_token(g.cd, token, &tok, true);
|
rc = get_reencipher_token(g.cd, token, &tok, true);
|
||||||
@@ -1690,7 +1787,7 @@ static int reencipher_complete(int token)
|
|||||||
"was completed.\n"
|
"was completed.\n"
|
||||||
"Do you want to re-encipher the secure key with "
|
"Do you want to re-encipher the secure key with "
|
||||||
"the CCA master key in the CURRENT master key "
|
"the CCA master key in the CURRENT master key "
|
||||||
"register?", g.pos_arg);
|
"register [y/N]?", g.pos_arg);
|
||||||
util_print_indented(msg, 0);
|
util_print_indented(msg, 0);
|
||||||
free(msg);
|
free(msg);
|
||||||
|
|
||||||
@@ -1700,11 +1797,38 @@ static int reencipher_complete(int token)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = key_token_change(g.dll_CSNBKTC, (u8 *)key, keysize,
|
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);
|
METHOD_OLD_TO_CURRENT, g.verbose);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
warnx("Failed to re-encipher the secure volume key for "
|
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;
|
rc = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1730,8 +1854,8 @@ static int reencipher_complete(int token)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = generate_key_verification_pattern(key, keysize, vp, sizeof(vp),
|
rc = generate_key_verification_pattern((u8 *)key, keysize, vp,
|
||||||
g.verbose);
|
sizeof(vp), g.verbose);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
warnx("Failed to generate the verification pattern: %s",
|
warnx("Failed to generate the verification pattern: %s",
|
||||||
strerror(-rc));
|
strerror(-rc));
|
||||||
@@ -1834,6 +1958,7 @@ static int command_validate(void)
|
|||||||
char *prompt;
|
char *prompt;
|
||||||
char *msg;
|
char *msg;
|
||||||
int token;
|
int token;
|
||||||
|
u64 mkvp;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
util_asprintf(&prompt, "Enter passphrase for '%s': ", g.pos_arg);
|
util_asprintf(&prompt, "Enter passphrase for '%s': ", g.pos_arg);
|
||||||
@@ -1847,7 +1972,7 @@ static int command_validate(void)
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rc = validate_secure_key(g.pkey_fd, (u8 *)key, keysize, &clear_keysize,
|
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);
|
is_valid = (rc == 0);
|
||||||
|
|
||||||
token = find_token(g.cd, PAES_REENC_TOKEN_NAME);
|
token = find_token(g.cd, PAES_REENC_TOKEN_NAME);
|
||||||
@@ -1864,18 +1989,29 @@ static int command_validate(void)
|
|||||||
vp_tok_avail = 1;
|
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("Validation of secure volume key of device '%s':\n", g.pos_arg);
|
||||||
printf(" Status: %s\n", is_valid ? "Valid" : "Invalid");
|
printf(" Status: %s\n", is_valid ? "Valid" : "Invalid");
|
||||||
printf(" Secure key size: %lu bytes\n", keysize);
|
printf(" Secure key size: %lu bytes\n", keysize);
|
||||||
printf(" XTS type key: %s\n",
|
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) {
|
if (is_valid) {
|
||||||
printf(" Clear key size: %lu bits\n", clear_keysize);
|
printf(" Clear key size: %lu bits\n", clear_keysize);
|
||||||
printf(" Enciphered with: %s CCA master key\n",
|
printf(" Enciphered with: %s CCA master key (MKVP: "
|
||||||
is_old_mk ? "OLD" : "CURRENT");
|
"%016llx)\n", is_old_mk ? "OLD" : "CURRENT", mkvp);
|
||||||
} else {
|
} else {
|
||||||
printf(" Clear key size: (unknown)\n");
|
printf(" Clear key size: (unknown)\n");
|
||||||
printf(" Enciphered with: (unknown)\n");
|
printf(" Enciphered with: (unknown, MKVP: %016llx)\n",
|
||||||
|
mkvp);
|
||||||
}
|
}
|
||||||
if (vp_tok_avail)
|
if (vp_tok_avail)
|
||||||
print_verification_pattern(vp_tok.verification_pattern);
|
print_verification_pattern(vp_tok.verification_pattern);
|
||||||
@@ -1943,7 +2079,7 @@ static int command_setvp(void)
|
|||||||
|
|
||||||
token = find_token(g.cd, PAES_VP_TOKEN_NAME);
|
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,
|
vp_tok.verification_pattern,
|
||||||
sizeof(vp_tok.verification_pattern),
|
sizeof(vp_tok.verification_pattern),
|
||||||
g.verbose);
|
g.verbose);
|
||||||
@@ -1998,12 +2134,12 @@ static int command_setkey(void)
|
|||||||
if (newkey == NULL)
|
if (newkey == NULL)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
rc = check_keysize_and_cipher_mode(newkey_size);
|
rc = check_keysize_and_cipher_mode(newkey, newkey_size);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rc = validate_secure_key(g.pkey_fd, newkey, newkey_size, NULL,
|
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) {
|
if (rc != 0) {
|
||||||
warnx("The secure key in file '%s' is not valid",
|
warnx("The secure key in file '%s' is not valid",
|
||||||
g.master_key_file);
|
g.master_key_file);
|
||||||
@@ -2014,12 +2150,13 @@ static int command_setkey(void)
|
|||||||
util_asprintf(&msg, "The secure key in file '%s' is "
|
util_asprintf(&msg, "The secure key in file '%s' is "
|
||||||
"enciphered with the CCA master key in the OLD "
|
"enciphered with the CCA master key in the OLD "
|
||||||
"master key register. Do you want to set this "
|
"master key register. Do you want to set this "
|
||||||
"key as the new volume key anyway?",
|
"key as the new volume key anyway [y/N]?",
|
||||||
g.master_key_file);
|
g.master_key_file);
|
||||||
util_print_indented(msg, 0);
|
util_print_indented(msg, 0);
|
||||||
free(msg);
|
free(msg);
|
||||||
|
|
||||||
if (!prompt_for_yes()) {
|
if (!prompt_for_yes()) {
|
||||||
|
warnx("Device '%s' is left unchanged", g.pos_arg);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -2032,21 +2169,14 @@ static int command_setkey(void)
|
|||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (keysize != newkey_size) {
|
if (keysize == newkey_size && memcmp(newkey, key, keysize) == 0) {
|
||||||
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) {
|
|
||||||
warnx("The secure key in file '%s' is equal to the current "
|
warnx("The secure key in file '%s' is equal to the current "
|
||||||
"volume key, setkey is ignored", g.master_key_file);
|
"volume key, setkey is ignored", g.master_key_file);
|
||||||
rc = 0;
|
rc = 0;
|
||||||
goto out;
|
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);
|
sizeof(vp), g.verbose);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
warnx("Failed to generate the verification pattern: %s",
|
warnx("Failed to generate the verification pattern: %s",
|
||||||
@@ -2078,12 +2208,13 @@ static int command_setkey(void)
|
|||||||
"be correct. You will lose all data on the "
|
"be correct. You will lose all data on the "
|
||||||
"volume if you set the wrong volume key!\n"
|
"volume if you set the wrong volume key!\n"
|
||||||
"Are you sure that the key in file '%s' is the "
|
"Are you sure that the key in file '%s' is the "
|
||||||
"correct volume key for volume '%s'?",
|
"correct volume key for volume '%s' [y/N]?",
|
||||||
g.master_key_file, g.pos_arg);
|
g.master_key_file, g.pos_arg);
|
||||||
util_print_indented(msg, 0);
|
util_print_indented(msg, 0);
|
||||||
free(msg);
|
free(msg);
|
||||||
|
|
||||||
if (!prompt_for_yes()) {
|
if (!prompt_for_yes()) {
|
||||||
|
warnx("Device '%s' is left unchanged", g.pos_arg);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -2204,6 +2335,12 @@ int main(int argc, char *argv[])
|
|||||||
if (c == -1)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
case 'N':
|
||||||
|
g.tonew = 1;
|
||||||
|
break;
|
||||||
|
case 'O':
|
||||||
|
g.fromold = 1;
|
||||||
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
g.complete = 1;
|
g.complete = 1;
|
||||||
break;
|
break;
|
||||||
@@ -2286,8 +2423,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (command->need_cca_library) {
|
if (command->need_cca_library) {
|
||||||
rc = load_cca_library(&g.lib_csulcca, &g.dll_CSNBKTC,
|
rc = load_cca_library(&g.cca, g.verbose);
|
||||||
g.verbose);
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
rc = EXIT_FAILURE;
|
rc = EXIT_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -2329,8 +2465,8 @@ int main(int argc, char *argv[])
|
|||||||
rc = command->function();
|
rc = command->function();
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (g.lib_csulcca)
|
if (g.cca.lib_csulcca)
|
||||||
dlclose(g.lib_csulcca);
|
dlclose(g.cca.lib_csulcca);
|
||||||
if (g.pkey_fd >= 0)
|
if (g.pkey_fd >= 0)
|
||||||
close(g.pkey_fd);
|
close(g.pkey_fd);
|
||||||
if (g.cd)
|
if (g.cd)
|
||||||
|
|||||||
+126
-2
@@ -62,7 +62,8 @@ in size.
|
|||||||
The \fBzkey\fP tool can operate in two modes. When argument
|
The \fBzkey\fP tool can operate in two modes. When argument
|
||||||
.I secure\-key\-file
|
.I secure\-key\-file
|
||||||
is specified then it operates on the secure key contained in the specified 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
|
When the
|
||||||
.B \-\-name
|
.B \-\-name
|
||||||
option is specified then it operates on a secure key contained in the secure
|
option is specified then it operates on a secure key contained in the secure
|
||||||
@@ -79,6 +80,8 @@ key repository.
|
|||||||
.RB [ \-\-xts | \-x ]
|
.RB [ \-\-xts | \-x ]
|
||||||
.RB [ \-\-clearkey | \-c
|
.RB [ \-\-clearkey | \-c
|
||||||
.IR clear\-key\-file ]
|
.IR clear\-key\-file ]
|
||||||
|
.RB [ \-\-key-type | \-K
|
||||||
|
.IR type ]
|
||||||
.RB [ \-\-verbose | \-V ]
|
.RB [ \-\-verbose | \-V ]
|
||||||
.
|
.
|
||||||
.PP
|
.PP
|
||||||
@@ -102,6 +105,8 @@ key repository.
|
|||||||
.RB [ \-\-xts | \-x ]
|
.RB [ \-\-xts | \-x ]
|
||||||
.RB [ \-\-clearkey | \-c
|
.RB [ \-\-clearkey | \-c
|
||||||
.IR clear\-key\-file ]
|
.IR clear\-key\-file ]
|
||||||
|
.RB [ \-\-key-type | \-K
|
||||||
|
.IR type ]
|
||||||
.RB [ \-\-verbose | \-V ]
|
.RB [ \-\-verbose | \-V ]
|
||||||
.PP
|
.PP
|
||||||
Use the
|
Use the
|
||||||
@@ -129,6 +134,15 @@ additional information can be associated with a secure key using the
|
|||||||
, or the
|
, or the
|
||||||
.B \-\-sector-size
|
.B \-\-sector-size
|
||||||
options.
|
options.
|
||||||
|
.PP
|
||||||
|
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"
|
.SS "Validating secure AES keys"
|
||||||
.
|
.
|
||||||
@@ -336,6 +350,12 @@ additional information can be associated with a secure key using the
|
|||||||
, or the
|
, or the
|
||||||
.B \-\-sector-size
|
.B \-\-sector-size
|
||||||
options.
|
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"
|
.SS "Export AES secure keys from the secure key repository"
|
||||||
.
|
.
|
||||||
@@ -368,6 +388,8 @@ The exported secure key also remains in the secure key repository.
|
|||||||
.IR card1.domain1[,card2.domain2[,...]] ]
|
.IR card1.domain1[,card2.domain2[,...]] ]
|
||||||
.RB [ \-\-volume-type | \-t
|
.RB [ \-\-volume-type | \-t
|
||||||
.IR type ]
|
.IR type ]
|
||||||
|
.RB [ \-\-key-type | \-K
|
||||||
|
.IR type ]
|
||||||
.RB [ \-\-verbose | \-V ]
|
.RB [ \-\-verbose | \-V ]
|
||||||
.
|
.
|
||||||
.PP
|
.PP
|
||||||
@@ -382,7 +404,7 @@ listed that are associated with the specified volume and device-mapper name.
|
|||||||
.PP
|
.PP
|
||||||
The
|
The
|
||||||
.B list
|
.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
|
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
|
description, associated cryptographic adapters (APQNs) and volumes, the
|
||||||
sector size, the key verification pattern, and timestamps for key creation, last
|
sector size, the key verification pattern, and timestamps for key creation, last
|
||||||
@@ -659,6 +681,72 @@ questions, you can specify the
|
|||||||
option. These options are passed to the generated command(s) and behave in the
|
option. These options are passed to the generated command(s) and behave in the
|
||||||
same way as with \fBcryptsetup\fP.
|
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
|
||||||
|
.
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
@@ -728,6 +816,13 @@ This option is only available if
|
|||||||
has been compiled with LUKS2 support enabled. If LUKS2 support is not enabled,
|
has been compiled with LUKS2 support enabled. If LUKS2 support is not enabled,
|
||||||
the default volume type is \fBplain\fP.
|
the default volume type is \fBplain\fP.
|
||||||
This option is only used for secure keys contained in the secure key repository.
|
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
|
||||||
|
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.
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
@@ -907,6 +1002,11 @@ This option is only available if
|
|||||||
.B zkey
|
.B zkey
|
||||||
has been compiled with LUKS2 support enabled.
|
has been compiled with LUKS2 support enabled.
|
||||||
This option is only used for secure keys contained in the secure key repository.
|
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
|
||||||
|
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.
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
@@ -1170,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"
|
.SS "General options"
|
||||||
.TP
|
.TP
|
||||||
.BR \-V ", " \-\-verbose
|
.BR \-V ", " \-\-verbose
|
||||||
|
|||||||
+381
-30
@@ -27,9 +27,11 @@
|
|||||||
#include "lib/util_prg.h"
|
#include "lib/util_prg.h"
|
||||||
#include "lib/zt_common.h"
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
|
#include "cca.h"
|
||||||
#include "keystore.h"
|
#include "keystore.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "pkey.h"
|
#include "pkey.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Program configuration
|
* Program configuration
|
||||||
@@ -71,6 +73,7 @@ static struct zkey_globals {
|
|||||||
long int sector_size;
|
long int sector_size;
|
||||||
char *volume_type;
|
char *volume_type;
|
||||||
char *newname;
|
char *newname;
|
||||||
|
char *key_type;
|
||||||
bool run;
|
bool run;
|
||||||
bool batch_mode;
|
bool batch_mode;
|
||||||
char *keyfile;
|
char *keyfile;
|
||||||
@@ -80,8 +83,7 @@ static struct zkey_globals {
|
|||||||
bool force;
|
bool force;
|
||||||
bool open;
|
bool open;
|
||||||
bool format;
|
bool format;
|
||||||
void *lib_csulcca;
|
struct cca_lib cca;
|
||||||
t_CSNBKTC dll_CSNBKTC;
|
|
||||||
int pkey_fd;
|
int pkey_fd;
|
||||||
struct keystore *keystore;
|
struct keystore *keystore;
|
||||||
} g = {
|
} g = {
|
||||||
@@ -104,6 +106,7 @@ static struct zkey_globals {
|
|||||||
#define COMMAND_COPY "copy "
|
#define COMMAND_COPY "copy "
|
||||||
#define COMMAND_CRYPTTAB "crypttab"
|
#define COMMAND_CRYPTTAB "crypttab"
|
||||||
#define COMMAND_CRYPTSETUP "cryptsetup"
|
#define COMMAND_CRYPTSETUP "cryptsetup"
|
||||||
|
#define COMMAND_CONVERT "convert"
|
||||||
|
|
||||||
#define ZKEY_COMMAND_MAX_LEN 10
|
#define ZKEY_COMMAND_MAX_LEN 10
|
||||||
|
|
||||||
@@ -161,7 +164,7 @@ static struct util_opt opt_vec[] = {
|
|||||||
.desc = "Name of the secure AES key in the repository. If "
|
.desc = "Name of the secure AES key in the repository. If "
|
||||||
"option --name/-N is specified, then the generated "
|
"option --name/-N is specified, then the generated "
|
||||||
"secure AES key is stored in the repository. Parameter "
|
"secure AES key is stored in the repository. Parameter "
|
||||||
"SECURE-KEY-FILE is not used when option --name/-M is "
|
"SECURE-KEY-FILE is not used when option --name/-N is "
|
||||||
"specified",
|
"specified",
|
||||||
.command = COMMAND_GENERATE,
|
.command = COMMAND_GENERATE,
|
||||||
},
|
},
|
||||||
@@ -215,6 +218,15 @@ static struct util_opt opt_vec[] = {
|
|||||||
.command = COMMAND_GENERATE,
|
.command = COMMAND_GENERATE,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
.option = { "key-type", required_argument, NULL, 'K'},
|
||||||
|
.argument = "type",
|
||||||
|
.desc = "The type of the key. Possible values are '"
|
||||||
|
KEY_TYPE_CCA_AESDATA"' and '"KEY_TYPE_CCA_AESCIPHER"'. "
|
||||||
|
"When this option is omitted, the default is '"
|
||||||
|
KEY_TYPE_CCA_AESDATA"'",
|
||||||
|
.command = COMMAND_GENERATE,
|
||||||
|
},
|
||||||
/***********************************************************/
|
/***********************************************************/
|
||||||
{
|
{
|
||||||
.flags = UTIL_OPT_FLAG_SECTION,
|
.flags = UTIL_OPT_FLAG_SECTION,
|
||||||
@@ -431,6 +443,15 @@ static struct util_opt opt_vec[] = {
|
|||||||
.command = COMMAND_LIST,
|
.command = COMMAND_LIST,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
.option = { "key-type", required_argument, NULL, 'K'},
|
||||||
|
.argument = "type",
|
||||||
|
.desc = "The type of the key. Possible values are '"
|
||||||
|
KEY_TYPE_CCA_AESDATA"' and '"KEY_TYPE_CCA_AESCIPHER"'. "
|
||||||
|
"Use this option to list all keys with the specified "
|
||||||
|
"key type.",
|
||||||
|
.command = COMMAND_LIST,
|
||||||
|
},
|
||||||
/***********************************************************/
|
/***********************************************************/
|
||||||
{
|
{
|
||||||
.flags = UTIL_OPT_FLAG_SECTION,
|
.flags = UTIL_OPT_FLAG_SECTION,
|
||||||
@@ -744,6 +765,38 @@ static struct util_opt opt_vec[] = {
|
|||||||
.flags = UTIL_OPT_FLAG_NOSHORT,
|
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
/***********************************************************/
|
||||||
|
{
|
||||||
|
.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,
|
.flags = UTIL_OPT_FLAG_SECTION,
|
||||||
@@ -792,6 +845,7 @@ static int command_rename(void);
|
|||||||
static int command_copy(void);
|
static int command_copy(void);
|
||||||
static int command_crypttab(void);
|
static int command_crypttab(void);
|
||||||
static int command_cryptsetup(void);
|
static int command_cryptsetup(void);
|
||||||
|
static int command_convert(void);
|
||||||
|
|
||||||
static struct zkey_command zkey_commands[] = {
|
static struct zkey_command zkey_commands[] = {
|
||||||
{
|
{
|
||||||
@@ -832,7 +886,7 @@ static struct zkey_command zkey_commands[] = {
|
|||||||
.need_pkey_device = 1,
|
.need_pkey_device = 1,
|
||||||
.short_desc = "Validate an existing secure AES key",
|
.short_desc = "Validate an existing secure AES key",
|
||||||
.long_desc = "Validate an existing secure AES key that is "
|
.long_desc = "Validate an existing secure AES key that is "
|
||||||
"either contained in SECURE-KEY-FILE or is stored"
|
"either contained in SECURE-KEY-FILE or is stored "
|
||||||
"in the repository and print information about "
|
"in the repository and print information about "
|
||||||
"the key",
|
"the key",
|
||||||
.has_options = 1,
|
.has_options = 1,
|
||||||
@@ -926,6 +980,21 @@ static struct zkey_command zkey_commands[] = {
|
|||||||
.has_options = 1,
|
.has_options = 1,
|
||||||
.need_keystore = 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 }
|
{ .command = NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1008,9 +1077,8 @@ static int command_generate_clear(void)
|
|||||||
|
|
||||||
rc = generate_secure_key_clear(g.pkey_fd, g.pos_arg,
|
rc = generate_secure_key_clear(g.pkey_fd, g.pos_arg,
|
||||||
g.keybits, g.xts,
|
g.keybits, g.xts,
|
||||||
g.clearkeyfile,
|
g.clearkeyfile, g.key_type,
|
||||||
AUTOSELECT, AUTOSELECT,
|
NULL, g.verbose);
|
||||||
g.verbose);
|
|
||||||
|
|
||||||
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -1025,9 +1093,8 @@ static int command_generate_random(void)
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = generate_secure_key_random(g.pkey_fd, g.pos_arg,
|
rc = generate_secure_key_random(g.pkey_fd, g.pos_arg,
|
||||||
g.keybits, g.xts,
|
g.keybits, g.xts, g.key_type,
|
||||||
AUTOSELECT, AUTOSELECT,
|
NULL, g.verbose);
|
||||||
g.verbose);
|
|
||||||
|
|
||||||
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -1047,7 +1114,7 @@ static int command_generate_repository(void)
|
|||||||
rc = keystore_generate_key(g.keystore, g.name, g.description, g.volumes,
|
rc = keystore_generate_key(g.keystore, g.name, g.description, g.volumes,
|
||||||
g.apqns, g.noapqncheck, g.sector_size,
|
g.apqns, g.noapqncheck, g.sector_size,
|
||||||
g.keybits, g.xts, g.clearkeyfile,
|
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;
|
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -1060,6 +1127,8 @@ static int command_generate_repository(void)
|
|||||||
*/
|
*/
|
||||||
static int command_generate(void)
|
static int command_generate(void)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (g.pos_arg != NULL && g.name != NULL) {
|
if (g.pos_arg != NULL && g.name != NULL) {
|
||||||
warnx(" Option '--name|-N' is not valid for generating a key "
|
warnx(" Option '--name|-N' is not valid for generating a key "
|
||||||
"outside of the repository");
|
"outside of the repository");
|
||||||
@@ -1072,6 +1141,8 @@ static int command_generate(void)
|
|||||||
util_prg_print_parse_error();
|
util_prg_print_parse_error();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
if (g.key_type == NULL)
|
||||||
|
g.key_type = KEY_TYPE_CCA_AESDATA;
|
||||||
if (g.name != NULL)
|
if (g.name != NULL)
|
||||||
return command_generate_repository();
|
return command_generate_repository();
|
||||||
if (g.pos_arg != NULL) {
|
if (g.pos_arg != NULL) {
|
||||||
@@ -1100,6 +1171,16 @@ static int command_generate(void)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
warnx("Your master key setup is improper");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
return g.clearkeyfile ? command_generate_clear()
|
return g.clearkeyfile ? command_generate_clear()
|
||||||
: command_generate_random();
|
: command_generate_random();
|
||||||
}
|
}
|
||||||
@@ -1117,7 +1198,9 @@ static int command_reencipher_file(void)
|
|||||||
{
|
{
|
||||||
size_t secure_key_size;
|
size_t secure_key_size;
|
||||||
int rc, is_old_mk;
|
int rc, is_old_mk;
|
||||||
|
int selected = 1;
|
||||||
u8 *secure_key;
|
u8 *secure_key;
|
||||||
|
u64 mkvp;
|
||||||
|
|
||||||
if (g.name != NULL) {
|
if (g.name != NULL) {
|
||||||
warnx("Option '--name|-N' is not valid for "
|
warnx("Option '--name|-N' is not valid for "
|
||||||
@@ -1156,13 +1239,22 @@ static int command_reencipher_file(void)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
rc = validate_secure_key(g.pkey_fd, secure_key, secure_key_size, NULL,
|
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) {
|
if (rc != 0) {
|
||||||
warnx("The secure key in file '%s' is not valid", g.pos_arg);
|
warnx("The secure key in file '%s' is not valid", g.pos_arg);
|
||||||
rc = EXIT_FAILURE;
|
rc = EXIT_FAILURE;
|
||||||
goto out;
|
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) {
|
if (!g.fromold && !g.tonew) {
|
||||||
/* Autodetect reencipher option */
|
/* Autodetect reencipher option */
|
||||||
if (is_old_mk) {
|
if (is_old_mk) {
|
||||||
@@ -1194,13 +1286,28 @@ static int command_reencipher_file(void)
|
|||||||
pr_verbose("Secure key will be re-enciphered from OLD to the "
|
pr_verbose("Secure key will be re-enciphered from OLD to the "
|
||||||
"CURRENT CCA master key");
|
"CURRENT CCA master key");
|
||||||
|
|
||||||
rc = key_token_change(g.dll_CSNBKTC,
|
rc = select_cca_adapter_by_mkvp(&g.cca, mkvp, NULL,
|
||||||
secure_key, secure_key_size,
|
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,
|
METHOD_OLD_TO_CURRENT,
|
||||||
g.verbose);
|
g.verbose);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
warnx("Re-encipher from OLD to CURRENT CCA "
|
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;
|
rc = EXIT_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1209,12 +1316,30 @@ static int command_reencipher_file(void)
|
|||||||
pr_verbose("Secure key will be re-enciphered from CURRENT "
|
pr_verbose("Secure key will be re-enciphered from CURRENT "
|
||||||
"to the NEW CCA master key");
|
"to the NEW CCA master key");
|
||||||
|
|
||||||
rc = key_token_change(g.dll_CSNBKTC,
|
rc = select_cca_adapter_by_mkvp(&g.cca, mkvp, NULL,
|
||||||
secure_key, secure_key_size,
|
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);
|
METHOD_CURRENT_TO_NEW, g.verbose);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
warnx("Re-encipher from CURRENT to NEW CCA "
|
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;
|
rc = EXIT_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1270,7 +1395,7 @@ static int command_reencipher_repository(void)
|
|||||||
|
|
||||||
rc = keystore_reencipher_key(g.keystore, g.name, g.apqns, g.fromold,
|
rc = keystore_reencipher_key(g.keystore, g.name, g.apqns, g.fromold,
|
||||||
g.tonew, g.inplace, g.staged, g.complete,
|
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;
|
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -1302,6 +1427,7 @@ static int command_validate_file(void)
|
|||||||
size_t clear_key_size;
|
size_t clear_key_size;
|
||||||
u8 *secure_key;
|
u8 *secure_key;
|
||||||
int is_old_mk;
|
int is_old_mk;
|
||||||
|
u64 mkvp;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (g.name != NULL) {
|
if (g.name != NULL) {
|
||||||
@@ -1329,14 +1455,14 @@ static int command_validate_file(void)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
rc = validate_secure_key(g.pkey_fd, secure_key, secure_key_size,
|
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) {
|
if (rc != 0) {
|
||||||
warnx("The secure key in file '%s' is not valid", g.pos_arg);
|
warnx("The secure key in file '%s' is not valid", g.pos_arg);
|
||||||
rc = EXIT_FAILURE;
|
rc = EXIT_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = generate_key_verification_pattern((char *)secure_key,
|
rc = generate_key_verification_pattern(secure_key,
|
||||||
secure_key_size, vp, sizeof(vp),
|
secure_key_size, vp, sizeof(vp),
|
||||||
g.verbose);
|
g.verbose);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
@@ -1348,19 +1474,42 @@ static int command_validate_file(void)
|
|||||||
goto out;
|
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("Validation of secure key in file '%s':\n", g.pos_arg);
|
||||||
printf(" Status: Valid\n");
|
printf(" Status: Valid\n");
|
||||||
printf(" Secure key size: %lu bytes\n", secure_key_size);
|
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(" Clear key size: %lu bits\n", clear_key_size);
|
||||||
printf(" XTS type key: %s\n",
|
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\n",
|
printf(" Enciphered with: %s CCA master key (MKVP: %016llx)\n",
|
||||||
is_old_mk ? "OLD" : "CURRENT");
|
is_old_mk ? "OLD" : "CURRENT", mkvp);
|
||||||
printf(" Verification pattern: %.*s\n", VERIFICATION_PATTERN_LEN / 2,
|
printf(" Verification pattern: %.*s\n", VERIFICATION_PATTERN_LEN / 2,
|
||||||
vp);
|
vp);
|
||||||
printf(" %.*s\n", VERIFICATION_PATTERN_LEN / 2,
|
printf(" %.*s\n", VERIFICATION_PATTERN_LEN / 2,
|
||||||
&vp[VERIFICATION_PATTERN_LEN / 2]);
|
&vp[VERIFICATION_PATTERN_LEN / 2]);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
warnx("Your master key setup is improper");
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free(secure_key);
|
free(secure_key);
|
||||||
return rc;
|
return rc;
|
||||||
@@ -1422,7 +1571,7 @@ static int command_import(void)
|
|||||||
|
|
||||||
rc = keystore_import_key(g.keystore, g.name, g.description, g.volumes,
|
rc = keystore_import_key(g.keystore, g.name, g.description, g.volumes,
|
||||||
g.apqns, g.noapqncheck, g.sector_size,
|
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;
|
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -1456,7 +1605,7 @@ static int command_list(void)
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = keystore_list_keys(g.keystore, g.name, g.volumes, g.apqns,
|
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;
|
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -1591,6 +1740,206 @@ static int command_cryptsetup(void)
|
|||||||
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
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
|
* Opens the keystore. The keystore directory is either the
|
||||||
* default directory or as specified in an environment variable
|
* default directory or as specified in an environment variable
|
||||||
@@ -1777,6 +2126,9 @@ int main(int argc, char *argv[])
|
|||||||
case 'r':
|
case 'r':
|
||||||
g.run = 1;
|
g.run = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'K':
|
||||||
|
g.key_type = optarg;
|
||||||
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
g.force = 1;
|
g.force = 1;
|
||||||
break;
|
break;
|
||||||
@@ -1867,8 +2219,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (command->need_cca_library) {
|
if (command->need_cca_library) {
|
||||||
rc = load_cca_library(&g.lib_csulcca, &g.dll_CSNBKTC,
|
rc = load_cca_library(&g.cca, g.verbose);
|
||||||
g.verbose);
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
rc = EXIT_FAILURE;
|
rc = EXIT_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1887,8 +2238,8 @@ int main(int argc, char *argv[])
|
|||||||
rc = command->function();
|
rc = command->function();
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (g.lib_csulcca)
|
if (g.cca.lib_csulcca)
|
||||||
dlclose(g.lib_csulcca);
|
dlclose(g.cca.lib_csulcca);
|
||||||
if (g.pkey_fd >= 0)
|
if (g.pkey_fd >= 0)
|
||||||
close(g.pkey_fd);
|
close(g.pkey_fd);
|
||||||
if (g.keystore)
|
if (g.keystore)
|
||||||
|
|||||||
Reference in New Issue
Block a user