diff --git a/genprotimg/man/genprotimg.8 b/genprotimg/man/genprotimg.8 index 8a481c4b..81929926 100644 --- a/genprotimg/man/genprotimg.8 +++ b/genprotimg/man/genprotimg.8 @@ -94,6 +94,16 @@ this only if you trust the specified certificate. Optional. Do not require the host-key documents to be valid. For testing purposes, do not use for a production image. Optional. .TP +\fB\-\-comm\-key\fR=\fI\,FILE\/\fR +Specifies the encryption key you want to use for the PV guest dump. Use a +secure, random, plaintext AES-256 GCM key. Optional. +.TP +\fB\-\-enable\-dump\fR +Enable PV guest dumps. Requires the \fB\-\-comm-key\fR option. Optional. +.TP +\fB\-\-disable\-dump\fR +Disable PV guest dumps. This is the default. Optional. +.TP \fB\-\-enable\-pckmo\fR Enable the support for the DEA, TDEA, AES, and ECC PCKMO key encryption functions. This is the default. Optional. @@ -105,21 +115,25 @@ functions. Optional. \fB\-v\fR, \fB\-\-version\fR Prints version information, then exits. -.SH EXAMPLE +.SH EXAMPLES + +These are examples to generate a protected virtualization image in +\fI\,/boot/vmlinuz.pv\/\fR, using the kernel file \fI\,vmlinuz\/\fR, the +initrd in \fI\,initramfs\/\fR, the kernel parameters contained in +\fI\,parmfile\/\fR, the intermediate CA in \fI\,DigiCertCA.crt\/\fR, the +IBM Z signing key in \fI\,ibm-z-host-key-signing.crt\/\fR, and the +host-key document in \fI\,host_key.crt\/\fR. An AES-256 GCM key is stored in +\fI\,comm-key\/\fR, which is used for the PV guest dump support in the second +example. + +Generate a protected virtualization image: + .PP -Generate a protected virtualization image in -\fI\,/boot/vmlinuz.pv\/\fR, using the kernel file \fI\,vmlinuz\/\fR, -the initrd in \fI\,initramfs\/\fR, the kernel parameters contained in -\fI\,parmfile\/\fR, the intermediate CA in \fI\,DigiCertCA.crt\/\fR, -the IBM Z signing key in \fI\,ibm-z-host-key-signing.crt\/\fR, and the -host-key document in \fI\,host_key.crt\/\fR: -.PP -.Vb 1 -.EX -\& genprotimg \-i \fI\,vmlinuz\/\fR \-r \fI\,initramfs\/\fR \-p \fI\,parmfile\/\fR \-k \fI\,host_key.crt\/\fR \-C \fI\,ibm-z-host-key-signing.crt\/\fR \-C \fI\,DigiCertCA.crt \-o \fI\,/boot/vmlinuz.pv\/\fR -.EE -.Ve +.B genprotimg \-i \fI\,vmlinuz\/\fR \-r \fI\,initramfs\/\fR \-p \fI\,parmfile\/\fR \-k \fI\,host_key.crt\/\fR \-C \fI\,ibm-z-host-key-signing.crt\/\fR \-C \fI\,DigiCertCA.crt\fR \-o \fI\,/boot/vmlinuz.pv\/\fR + +Generate a protected virtualization image with PV guest dump support: .PP +.B genprotimg \-i \fI\,vmlinuz\/\fR \-r \fI\,initramfs\/\fR \-p \fI\,parmfile\/\fR \-k \fI\,host_key.crt\/\fR \-C \fI\,ibm-z-host-key-signing.crt\/\fR \-C \fI\,DigiCertCA.crt\fR \-o \fI\,/boot/vmlinuz.pv\/\fR \-\-enable\-dump \-\-comm\-key \fI\,comm-key\fR .SH NOTES .IP "1." 4 diff --git a/genprotimg/src/include/pv_hdr_def.h b/genprotimg/src/include/pv_hdr_def.h index 270de0d0..1a839a6d 100644 --- a/genprotimg/src/include/pv_hdr_def.h +++ b/genprotimg/src/include/pv_hdr_def.h @@ -28,6 +28,7 @@ #define __PV_BIT(nr) (1ULL << (63 - (nr))) /* Plaintext control flags */ +#define PV_PCF_ALLOW_DUMPING __PV_BIT(34) /* dumping of the configuration is allowed */ #define PV_PCF_NO_DECRYPTION __PV_BIT(35) /* prevent Ultravisor decryption during unpack operation */ #define PV_PCF_PCKMO_DEA_TDEA __PV_BIT(56) /* PCKMO encrypt-DEA/TDEA-key functions allowed */ #define PV_PCF_PCKMO_AES __PV_BIT(57) /* PCKMO encrypt-AES-key functions allowed */ diff --git a/genprotimg/src/pv/pv_args.c b/genprotimg/src/pv/pv_args.c index 5cda3a8d..000eb9a0 100644 --- a/genprotimg/src/pv/pv_args.c +++ b/genprotimg/src/pv/pv_args.c @@ -64,13 +64,17 @@ static gint pv_args_validate_options(PvArgs *args, GError **err) { PvComponentType KERNEL = PV_COMP_TYPE_KERNEL; - if (args->pcf && args->allow_pckmo != PV_NOT_SET) { - g_set_error(err, PV_PARSE_ERROR, PV_PARSE_ERROR_SYNTAX, - _("The '--x-pcf' and '--(enable|disable)-pckmo' options are mutually" - " exclusive.\nUse 'genprotimg --help' for more information")); + /* Check for mutually exclusive arguments */ + if (args->pcf && !(args->allow_pckmo == PV_NOT_SET && + args->allow_dump == PV_NOT_SET)) { + g_set_error( + err, PV_PARSE_ERROR, PV_PARSE_ERROR_SYNTAX, + _("The '--x-pcf' option cannot be used with the '--(enable|disable)-pckmo' or" + " '--(enable|disable)-dump' flags.\nUse 'genprotimg --help' for more information")); return -1; } + /* Check for unused arguments */ if (args->unused_values->len > 0) { g_autofree gchar *unused = NULL; @@ -88,6 +92,14 @@ static gint pv_args_validate_options(PvArgs *args, GError **err) return -1; } + /* Check for mandatory arguments */ + if (args->allow_dump == PV_TRUE && !args->cust_comm_key_path) { + g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT, + _("Option '--allow-dump' requires the '--comm-key' option.\nUse 'genprotimg " + "--help' for more information")); + return -1; + } + if (!args->output_path) { g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT, _("Option '--output' is required.\nUse 'genprotimg --help' for more information")); @@ -155,14 +167,14 @@ static gboolean cb_set_string_option(const gchar *option, const gchar *value, { gchar **args_option = NULL; + if (g_str_equal(option, "--comm-key")) + args_option = &args->cust_comm_key_path; if (g_str_equal(option, "--root-ca")) args_option = &args->root_ca_path; if (g_str_equal(option, "-o") || g_str_equal(option, "--output")) args_option = &args->output_path; if (g_str_equal(option, "--x-comp-key")) args_option = &args->xts_key_path; - if (g_str_equal(option, "--x-comm-key")) - args_option = &args->cust_comm_key_path; if (g_str_equal(option, "--x-header-key")) args_option = &args->cust_root_key_path; if (g_str_equal(option, "--x-pcf")) @@ -246,6 +258,7 @@ static gboolean cb_remaining_values(const gchar *option G_GNUC_UNUSED, #define INDENT " " /* Define the callbacks for mutually exclusive command line flags */ +DEFINE_MUT_EXCL_BOOL_FLAG_CBS(dump) DEFINE_MUT_EXCL_BOOL_FLAG_CBS(pckmo) gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[], @@ -311,6 +324,11 @@ gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[], .description = _("Use the kernel parameters stored in PARMFILE\n" INDENT "(optional)."), .arg_description = _("PARMFILE") }, + MUT_EXCL_BOOL_FLAG( + dump, + _("Enable PV guest dumps (optional). This option\n" INDENT + "requires the '--comm-key' option."), + _("Disable PV guest dumps (default) (optional).")), MUT_EXCL_BOOL_FLAG( pckmo, _("Enable the support for the DEA, TDEA, AES, and\n" INDENT @@ -318,6 +336,16 @@ gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[], "(optional)."), _("Disable the support for the DEA, TDEA, AES, and\n" INDENT "ECC PCKMO key encryption functions (optional).")), + { .long_name = "comm-key", + .short_name = 0, + .flags = G_OPTION_FLAG_FILENAME, + .arg = G_OPTION_ARG_CALLBACK, + .arg_data = cb_set_string_option, + .description = _( + "FILE contains the key with which you encrypt\n" INDENT + "the PV guest dump (optional). Required by\n" INDENT + "the '--enable-dump' option."), + .arg_description = _("FILE") }, { .long_name = "crl", .short_name = 0, .flags = G_OPTION_FLAG_NONE, @@ -376,15 +404,6 @@ gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[], }; GOptionEntry x_entries[] = { - { .long_name = "x-comm-key", - .short_name = 0, - .flags = G_OPTION_FLAG_FILENAME, - .arg = G_OPTION_ARG_CALLBACK, - .arg_data = cb_set_string_option, - .description = _( - "Use FILE as the customer communication key.\n" INDENT - "Optional; default: auto-generated."), - .arg_description = _("FILE") }, { .long_name = "x-comp-key", .short_name = 0, .flags = G_OPTION_FLAG_FILENAME, @@ -467,6 +486,7 @@ PvArgs *pv_args_new(void) g_autoptr(PvArgs) args = g_new0(PvArgs, 1); args->unused_values = g_ptr_array_new_with_free_func(g_free); + args->allow_dump = PV_NOT_SET; args->allow_pckmo = PV_NOT_SET; return g_steal_pointer(&args); } diff --git a/genprotimg/src/pv/pv_args.h b/genprotimg/src/pv/pv_args.h index 77f55396..ef659fd8 100644 --- a/genprotimg/src/pv/pv_args.h +++ b/genprotimg/src/pv/pv_args.h @@ -34,6 +34,7 @@ typedef struct { gboolean offline; gchar *pcf; gchar *scf; + PvTristate allow_dump; PvTristate allow_pckmo; gchar *psw_addr; /* PSW address which will be used for the start of * the actual component (e.g. Linux kernel) diff --git a/genprotimg/src/pv/pv_image.c b/genprotimg/src/pv/pv_image.c index 73592401..1ccb0fce 100644 --- a/genprotimg/src/pv/pv_image.c +++ b/genprotimg/src/pv/pv_image.c @@ -229,7 +229,9 @@ static gint pv_img_set_psw_addr(PvImage *img, const gchar *psw_addr_s, } static gint pv_img_set_control_flags(PvImage *img, const gchar *pcf_s, - const gchar *scf_s, PvTristate allow_pckmo, GError **err) + const gchar *scf_s, + PvTristate allow_dump, + PvTristate allow_pckmo, GError **err) { uint64_t flags; @@ -247,6 +249,11 @@ static gint pv_img_set_control_flags(PvImage *img, const gchar *pcf_s, img->scf = flags; } + if (allow_dump == PV_TRUE) + img->pcf |= PV_PCF_ALLOW_DUMPING; + else if (allow_dump == PV_FALSE) + img->pcf &= ~PV_PCF_ALLOW_DUMPING; + if (allow_pckmo == PV_TRUE) img->pcf |= PV_PCF_PCKM_ECC | PV_PCF_PCKMO_AES | PV_PCF_PCKMO_DEA_TDEA; else if (allow_pckmo == PV_FALSE) @@ -608,7 +615,9 @@ PvImage *pv_img_new(PvArgs *args, const gchar *stage3a_path, GError **err) return NULL; /* set the control flags: PCF and SCF */ - if (pv_img_set_control_flags(ret, args->pcf, args->scf, args->allow_pckmo, err) < 0) + if (pv_img_set_control_flags(ret, args->pcf, args->scf, + args->allow_dump, args->allow_pckmo, + err) < 0) return NULL; /* read in the keys */