diff --git a/zkey/pvsecrets.c b/zkey/pvsecrets.c index 2874fdf1..7f28feba 100644 --- a/zkey/pvsecrets.c +++ b/zkey/pvsecrets.c @@ -7,6 +7,7 @@ * it under the terms of the MIT license. See LICENSE for details. */ +#include #include #include #include @@ -17,14 +18,60 @@ #include #include +#include + #include "lib/util_base.h" #include "lib/util_file.h" #include "lib/util_libc.h" #include "lib/util_panic.h" #include "lib/util_path.h" +#include "lib/util_rec.h" #include "pvsecrets.h" +struct pvsecret_type_info { + u16 type; + const char *name; + bool zkey_usage; +}; + +static const struct pvsecret_type_info pvsecret_type_info[] = { + { .type = UV_SECRET_TYPE_NULL, .name = "NULL", + .zkey_usage = false }, + { .type = UV_SECRET_TYPE_AP_ASSOCIATION, .name = "AP-ASSOCIATION", + .zkey_usage = false }, + { .type = UV_SECRET_TYPE_PLAIN_TEXT, .name = "PLAIN-TEXT", + .zkey_usage = false }, + { .type = UV_SECRET_TYPE_AES_128, .name = "AES-128", + .zkey_usage = true }, + { .type = UV_SECRET_TYPE_AES_192, .name = "AES-192", + .zkey_usage = true }, + { .type = UV_SECRET_TYPE_AES_256, .name = "AES-256", + .zkey_usage = true }, + { .type = UV_SECRET_TYPE_AES_XTS_128, .name = "AES-XTS-128", + .zkey_usage = true }, + { .type = UV_SECRET_TYPE_AES_XTS_256, .name = "AES-XTS-256", + .zkey_usage = true }, + { .type = UV_SECRET_TYPE_HMAC_SHA_256, .name = "HMAC-SHA-256", + .zkey_usage = false }, + { .type = UV_SECRET_TYPE_HMAC_SHA_512, .name = "HMAC-SHA-512", + .zkey_usage = false }, + { .type = UV_SECRET_TYPE_ECDSA_P256, .name = "ECDSA-P256", + .zkey_usage = false }, + { .type = UV_SECRET_TYPE_ECDSA_P384, .name = "ECDSA-P384", + .zkey_usage = false }, + { .type = UV_SECRET_TYPE_ECDSA_P521, .name = "ECDSA-P521", + .zkey_usage = false }, + { .type = UV_SECRET_TYPE_EDDSA_ED25519, .name = "EDDSA-ED25519", + .zkey_usage = false }, + { .type = UV_SECRET_TYPE_EDDSA_ED448, .name = "EDDSA-ED448", + .zkey_usage = false }, + { .type = UV_SECRET_TYPE_INVALID, } +}; + +#define PVSECRETS_REC_ID "Secret ID" +#define PVSECRETS_REC_TYPE "Type" + #define pr_verbose(verbose, fmt...) do { \ if (verbose) \ warnx(fmt); \ @@ -159,3 +206,349 @@ out: return rc; } + +/** + * Returns true if the secret type is supported by zkey + * + * @param type the secret type + * + * @returns true if the type is supported, false otherwise + */ +static bool is_pvsecret_type_supported(u16 type) +{ + unsigned int i; + + for (i = 0; pvsecret_type_info[i].type != UV_SECRET_TYPE_INVALID; i++) { + if (pvsecret_type_info[i].type == type) + return pvsecret_type_info[i].zkey_usage; + } + + return false; +} + +/** + * Returns the secret type name for the specified secret type + * + * @param type the secret type + * + * @returns a constant string containing the type name + */ +static const char *get_pvsecret_type_name(u16 type) +{ + unsigned int i; + + for (i = 0; pvsecret_type_info[i].type != UV_SECRET_TYPE_INVALID; i++) { + if (pvsecret_type_info[i].type == type) + return pvsecret_type_info[i].name; + } + + return "[UNKNOWN]"; +} + +/** + * Returns the secret type for the specified type name + * + * @param name the secret type name + * + * @returns the secret type or UV_SECRET_TYPE_INVALID if unknown. + */ +static u16 get_pvsecret_type_by_name(const char *name) +{ + unsigned int i; + + for (i = 0; pvsecret_type_info[i].type != UV_SECRET_TYPE_INVALID; i++) { + if (strcasecmp(pvsecret_type_info[i].name, name) == 0) + return pvsecret_type_info[i].type; + } + + return UV_SECRET_TYPE_INVALID; +} + +/** + * Parses a 32 byte hex string into a 32 byte binary secret ID + * + * @param id_str the hex string to parse + * @param id the output buffer to store the secret ID + * + * @returns 0 for success or a negative errno in case of an error + */ +static int parse_secret_id_str(const char *id_str, + unsigned char id[UV_SECRET_ID_LEN]) +{ + char hex[3] = { 0 }; + unsigned long val; + unsigned int i; + char *endptr; + + util_assert(id_str != NULL, "Internal error: id_str is NULL"); + util_assert(id != NULL, "Internal error: id is NULL"); + + if (strncasecmp(id_str, "0x", 2) == 0) + id_str += 2; + + if (strlen(id_str) != UV_SECRET_ID_LEN * 2) + return -EINVAL; + + for (i = 0; i < UV_SECRET_ID_LEN; i++) { + hex[0] = id_str[i * 2]; + hex[1] = id_str[i * 2 + 1]; + + errno = 0; + val = strtoul(hex, &endptr, 16); + if (errno != 0 || *endptr != '\0' || val > 0xff) + return -EINVAL; + + id[i] = val; + } + + return 0; +} + +/** + * Get the 32 byte binary secret ID from the secret name by calculating the + * SHA-256 has from the name. + * + * @param name the name of the secret + * @param id the output buffer to store the secret ID + * + * @returns 0 for success or a negative errno in case of an error + */ +static int get_secret_id_from_name(const char *name, + unsigned char id[UV_SECRET_ID_LEN]) +{ + util_assert(name != NULL, "Internal error: id_str is NULL"); + util_assert(id != NULL, "Internal error: id is NULL"); + util_assert(UV_SECRET_ID_LEN == SHA256_DIGEST_LENGTH, + "Internal error: UV_SECRET_ID_LEN != SHA256_DIGEST_LENGTH"); + + if (SHA256((const unsigned char *)name, strlen(name), id) != id) + return -EIO; + + return 0; +} + +/** + * Gets the binary 32 byte secret id from either a hex string or a secret name. + * + * @param hex the secret id as hex string. Can be NULL. + * @param name the secret name. Can be NULL. If the id + * parameter is non-NULL, then this parameter is + * ignored. + * @param id Output: the 32 byte binary secret id. + * @param id_str Output: the secret id in printable ascii chars + * form, if name is non-NULL and the name length is + * less than UV_SECRET_ID_LEN. + * + * @returns 0 on success, a negative errno in case of an error. + * If neither the hex string nor the secret name is specified, 1 is returned, + * and the id parameter is not modified. + */ +static int get_secret_id_from_hex_or_name(const char *hex, const char *name, + unsigned char id[UV_SECRET_ID_LEN], + char id_name[UV_SECRET_ID_LEN]) +{ + int rc; + + util_assert(id != NULL, "Internal error: id is NULL"); + + if (hex != NULL) { + rc = parse_secret_id_str(hex, id); + if (rc != 0) { + warnx("Invalid pvsecret id specified: '%s'", hex); + return rc; + } + + return 0; + } + + if (name != NULL) { + rc = get_secret_id_from_name(name, id); + if (rc != 0) { + warnx("Failed to get the ID from pvsecret name: '%s'", + name); + return rc; + } + + if (strlen(name) < UV_SECRET_ID_LEN) { + strncpy(id_name, name, UV_SECRET_ID_LEN); + id_name[UV_SECRET_ID_LEN - 1] = '\0'; + } + + return 0; + } + + return 1; +} + +/** + * Checks if the secret id is printable. To be printable, all characters up to + * the first zero byte must be printable. All bytes after the first zero byte + * must be all zero. There must be at least one zero byte as the very last byte + * of the id. + * + * @param id the ID of the secret + * @param name Output: the id in the printable form and enclosed + * in single quotes if the id is printable. The max + * length of the name buffer is UV_SECRET_ID_LEN + 2: + * A starting quote, up to UV_SECRET_ID_LEN-1 chars, + * an ending quote and a zero termination byte. + * + * @returns true if the id is printable, false otherwise. + */ +static bool is_printable_name(const u8 id[UV_SECRET_ID_LEN], + char name[UV_SECRET_ID_LEN + 2]) +{ + bool end_found = false, printable_name = false; + unsigned int i; + + name[0] = '\''; + for (i = 0; i < UV_SECRET_ID_LEN; i++) { + if (!end_found) { + if (id[i] == '\0') { + name[1 + i] = '\''; + end_found = true; + } else if (isprint(id[i])) { + name[1 + i] = id[i]; + printable_name = true; + } else { + printable_name = false; + end_found = true; + } + } else if (id[i] != '\0') { + printable_name = false; + } + } + if (!end_found) + printable_name = false; + + return printable_name; +} + +struct list_secrets_data { + struct util_rec *rec; + bool all; + bool hex; + u16 type_filter; + bool id_filter; + char name[UV_SECRET_ID_LEN]; + unsigned char id[UV_SECRET_ID_LEN]; + unsigned int matched; +}; + +/** + * Callback used with pvsecrets_list function. Called for each secret. + * + * @param idx the index of the secret + * @param type the type of the secret + * @param id the ID of the secret + * @param cb_private callback private data + * + * @returns 0 on success, a negative errno in case of an error + */ +static int pvsecrets_list_cb(u16 UNUSED(idx), u16 type, u32 UNUSED(len), + const u8 id[UV_SECRET_ID_LEN], void *cb_private) +{ + struct list_secrets_data *list_data = cb_private; + char name[2 + UV_SECRET_ID_LEN] = { 0 }; + char hex[2 * UV_SECRET_ID_LEN + 1] = { 0 }; + unsigned int i; + + if (!list_data->all && !is_pvsecret_type_supported(type)) + return 0; + + if (list_data->type_filter != 0 && type != list_data->type_filter) + return 0; + + if (list_data->id_filter && + memcmp(id, list_data->name, UV_SECRET_ID_LEN) != 0 && + memcmp(id, list_data->id, UV_SECRET_ID_LEN) != 0) + return 0; + + for (i = 0; i < UV_SECRET_ID_LEN; i++) + sprintf(&hex[i * 2], "%02x", id[i]); + + if (!list_data->hex && is_printable_name(id, name)) + util_rec_set(list_data->rec, PVSECRETS_REC_ID, name); + else + util_rec_set(list_data->rec, PVSECRETS_REC_ID, hex); + util_rec_set(list_data->rec, PVSECRETS_REC_TYPE, + get_pvsecret_type_name(type)); + + if (list_data->matched == 0) + util_rec_print_hdr(list_data->rec); + + util_rec_print(list_data->rec); + + list_data->matched++; + + return 0; +} + +/** + * Lists protected virtualization secrets. + * + * @param uv_fd the file descriptor of the ultravisor device + * @param all if true, all secret types are listed + * @param hex if true, list the secret ID in hex, even if the + * secret ID would be printable + * @param type_filter only display secrets of the specified secret type. + * Can be NULL. + * @param secret_id the secret id to list. Can be NULL. + * @param secret_name the secret name to list. Can be NULL. If the id + * parameter is non-NULL, then this parameter is + * ignored. + * @param verbose if true, verbose messages are printed + * + * @returns 0 on success, a negative errno in case of an error + */ +int pvsecrets_list(int uv_fd, bool all, bool hex, const char *type_filter, + const char *secret_id, const char *secret_name, + bool verbose) +{ + struct list_secrets_data list_data = { 0 }; + int rc; + + util_assert(uv_fd != -1, "Internal error: uv_fd is -1"); + + list_data.all = all; + list_data.hex = hex; + list_data.type_filter = UV_SECRET_TYPE_INVALID; + + if (type_filter != NULL) { + list_data.type_filter = get_pvsecret_type_by_name(type_filter); + if (list_data.type_filter == UV_SECRET_TYPE_INVALID) { + warnx("Invalid pvsecret type specified: %s", + type_filter); + return -EINVAL; + } + } + + if (secret_id != NULL || secret_name != NULL) { + rc = get_secret_id_from_hex_or_name(secret_id, secret_name, + list_data.id, + list_data.name); + if (rc < 0) + return rc; + + list_data.id_filter = true; + } + + list_data.rec = util_rec_new_wide("-"); + util_rec_def(list_data.rec, PVSECRETS_REC_ID, UTIL_REC_ALIGN_LEFT, + UV_SECRET_ID_LEN * 2, PVSECRETS_REC_ID); + util_rec_def(list_data.rec, PVSECRETS_REC_TYPE, UTIL_REC_ALIGN_LEFT, + 12, PVSECRETS_REC_TYPE); + + rc = uv_list_secrets(uv_fd, pvsecrets_list_cb, &list_data, verbose); + if (rc != 0) { + warnx("Failed to list protected virtualization secrets: %s", + strerror(-rc)); + } + + util_rec_free(list_data.rec); + + if (list_data.matched == 0) + rc = -ENOENT; + + return rc; +} diff --git a/zkey/pvsecrets.h b/zkey/pvsecrets.h index 2667e859..6acebfdd 100644 --- a/zkey/pvsecrets.h +++ b/zkey/pvsecrets.h @@ -86,4 +86,8 @@ struct uvio_list_secrets { int uv_open_device(bool verbose); +int pvsecrets_list(int uv_fd, bool all, bool hex, const char *type_filter, + const char *secret_id, const char *secret_name, + bool verbose); + #endif diff --git a/zkey/zkey.1 b/zkey/zkey.1 index 8c5a09a7..4386629f 100644 --- a/zkey/zkey.1 +++ b/zkey/zkey.1 @@ -1,8 +1,8 @@ -.\" Copyright IBM Corp. 2017, 2020 +.\" Copyright IBM Corp. 2017, 2024 .\" s390-tools is free software; you can redistribute it and/or modify .\" it under the terms of the MIT license. See LICENSE for details. .\" -.TH ZKEY 1 "July 2020" "s390-tools" +.TH ZKEY 1 "February 2024" "s390-tools" .SH NAME zkey \- Manage secure AES keys . @@ -1162,6 +1162,54 @@ fails. Use option \fB\-\-no\-volume\-check\fP to omit the volume check, and refresh the keys even if the associated volume(s) do not exist. . . +.SH COMMANDS FOR PROTECTED VIRTUALIZATION +. +Use the \fBpvsecrets\fP command to work with protected virtualization (PV) +secrets. Protected virtualization secrets can be made available to a secure +execution guest and can be used only within that guest. +The \fBpvsecrets\fP command provides subcommands for protected +virtualization specific operations. Use \fBzkey pvsecrets \-\-help\fP to show +the available subcommands. These subcommands only work when running in a +secure execution guest. Only the \fBroot\fP user is allowed to perform these +subcommands. +. +.SS "List available protected virtualization secrets" +. +.B zkey pvsecrets +.BR list | li +.RB [ \-\-all | \-A ] +.RB [ \-\-hex | \-H ] +.RB [ \-\-pvsecret\-type | \-T +.IR pvsecret\-type ] +.RB [ \-\-pvsecret\-id | \-I +.IR pvsecret\-id ] +.RB [ \-\-pvsecret\-name | \-e +.IR pvsecret\-name ] +.RB [ \-\-verbose | \-V ] +. +.PP +Use the +.B pvsecrets list +command to display a list of protected virtualization (PV) secrets. It displays +the pvsecret ID as hex string of 32 bytes or as printable name enclosed in +single quotes (\fB'\fP), if the pvsecret ID consists of only printable +characters. Specify the \fB\-\-hex\fP option to list all pvsecret IDs as hex +string. The +.B pvsecrets list +command also shows the pvsecret type of each secret. +.PP +You can filter the list of pvsecrets by pvsecret ID, pvsecret name and pvsecret +type. Either the \fB\-\-pvsecret\-id\fP option or the +\fB\-\-pvsecret\-name\fP option can be specified. By default the +\fBpvsecrets list\fP command displays only those pvsecrets with types that +are supported by the \fBzkey\fP tool. To list all pvsecret types, specify the +\fB\-\-all\fP option. +.PP +This command is only available when running in a secure execution guest. +Only the \fBroot\fP user is allowed to perform this command. +. +. +. . .SH OPTIONS .SS "Options for the generate command" @@ -2030,6 +2078,45 @@ repository. This option only has an effect when specified together with option . . . +.SS "Options for the pvsecrets list command" +.TP +.BR \-A ", " \-\-all +List all protected virtualization (PV) secret types, not only those that can be +used with zkey. +.TP +.BR \-H ", " \-\-hex +Show all protected virtualization (PV) secret IDs in hex, even if the ID +contains only printable characters. +.TP +.BR \-T ", " \-\-pvsecret\-type\~\fIpvsecret\-type\fP +Type of the protected virtualization (PV) secret to list. If omitted, all +secret types are listed. Possible values are: \fBPLAIN\-TEXT\fP, \fBAES\-128\fP, +\fBAES\-192\fP, \fBAES\-256\fP, \fBAES\-XTS\-128\fP, \fBAES\-XTS\-256\fP, +\fBHMAC\-SHA\-256\fP, \fBHMAC\-SHA\-512\fP, \fBECDSA\-P256\fP, +\fBECDSA\-P384\fP, \fBECDSA\-P521\fP, \fBEDDSA\-ED25519\fP, and +\fBEDDSA\-ED448\fP. +.TP +.BR \-I ", " \-\-pvsecret\-id\~\fIpvsecret\-id\fP +ID of the protected virtualization (PV) secret to list. The pvsecret ID is a 32 +byte hex string, optionally prefixed by \fB0x\fP. You can use the YAML file that +was created when using the \fBpvsecret create\fP command for adding the +protected virtualization secret: +\fB\-\-pvsecret\-id "$(yq .id \fP\fIYAML\-FILE\fP\fB)"\fP. +You might have to install the \fByq\fP package first. +Either the \fB\-\-pvsecret\-id\fP option or the \fB\-\-pvsecret\-name\fP option +can be specified, but not both. +.TP +.BR \-e ", " \-\-pvsecret\-name\~\fIpvsecret\-name\fP +Name of the protected virtualization (PV) secret to list. You can use the YAML +file that was created when using the \fBpvsecret create\fP command for adding +the protected virtualization secret: +\fB\-\-pvsecret\-name "$(yq .name \fP\fIYAML\-FILE\fP\fB)"\fP. +You might have to install the \fByq\fP package first. +Either the \fB\-\-pvsecret\-id\fP option or the \fB\-\-pvsecret\-name\fP option +can be specified, but not both. +. +. +. .SS "General options" .TP .BR \-V ", " \-\-verbose diff --git a/zkey/zkey.c b/zkey/zkey.c index 7c909ff0..adc48d60 100644 --- a/zkey/zkey.c +++ b/zkey/zkey.c @@ -1,7 +1,7 @@ /* * zkey - Generate, re-encipher, and validate secure keys * - * Copyright IBM Corp. 2017, 2020 + * Copyright IBM Corp. 2017, 2024 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -34,6 +34,7 @@ #include "pkey.h" #include "utils.h" #include "kms.h" +#include "pvsecrets.h" /* * Program configuration @@ -46,7 +47,7 @@ static const struct util_prg prg = { { .owner = "IBM Corp.", .pub_first = 2017, - .pub_last = 2020, + .pub_last = 2024, }, UTIL_PRG_COPYRIGHT_END } @@ -93,10 +94,16 @@ static struct zkey_globals { bool open; bool format; bool refresh_properties; + bool all; + bool hex; + char *secret_type; + char *secret_id; + char *secret_name; struct ext_lib lib; struct cca_lib cca; struct ep11_lib ep11; int pkey_fd; + int uv_fd; struct keystore *keystore; struct kms_info kms_info; int first_kms_option; @@ -104,6 +111,7 @@ static struct zkey_globals { size_t num_kms_options; } g = { .pkey_fd = -1, + .uv_fd = -1, .sector_size = -1, .lib.cca = &g.cca, .lib.ep11 = &g.ep11, @@ -135,6 +143,8 @@ static struct zkey_globals { #define COMMAND_KMS_LIST "list" #define COMMAND_KMS_IMPORT "import" #define COMMAND_KMS_REFRESH "refresh" +#define COMMAND_PVSECRETS "pvsecrets" +#define COMMAND_PVSECRETS_LIST "list" #define OPT_COMMAND_PLACEHOLDER "PLACEHOLDER" @@ -1182,6 +1192,48 @@ static struct util_opt opt_vec[] = { .flags = UTIL_OPT_FLAG_NOSHORT, }, /***********************************************************/ + { + .flags = UTIL_OPT_FLAG_SECTION, + .desc = "OPTIONS", + .command = COMMAND_PVSECRETS " " COMMAND_PVSECRETS_LIST, + }, + { + .option = {"all", 0, NULL, 'A'}, + .desc = "List all protected virtualization (PV) secret types, " + "not only those that can be used with zkey.", + .command = COMMAND_PVSECRETS " " COMMAND_PVSECRETS_LIST, + }, + { + .option = {"hex", 0, NULL, 'H'}, + .desc = "Show all protected virtualization (PV) secret IDs in " + "hex, even if the ID contains only printable " + "characters.", + .command = COMMAND_PVSECRETS " " COMMAND_PVSECRETS_LIST, + }, + { + .option = { "pvsecret-type", required_argument, NULL, 'T'}, + .argument = "PVSECRET-TYPE", + .desc = "Type of the protected virtualization (PV) secret to " + "list. If omitted, all pvsecret types are listed.", + .command = COMMAND_PVSECRETS " " COMMAND_PVSECRETS_LIST, + }, + { + .option = { "pvsecret-id", required_argument, NULL, 'I'}, + .argument = "PVSECRET-ID", + .desc = "ID of the protected virtualization (PV) secret to " + "list. Either '--pvsecret-id/-I' or " + "'--pvsecret-name/-e' can be specified, but not both.", + .command = COMMAND_PVSECRETS " " COMMAND_PVSECRETS_LIST, + }, + { + .option = { "pvsecret-name", required_argument, NULL, 'e'}, + .argument = "PVSECRET-NAME", + .desc = "Name of the protected virtualization (PV) secret to " + "list. Either '--pvsecret-name/-e' or " + "'--pvsecret-id/-I' can be specified, but not both.", + .command = COMMAND_PVSECRETS " " COMMAND_PVSECRETS_LIST, + }, + /***********************************************************/ OPT_PLACEHOLDER, OPT_PLACEHOLDER, OPT_PLACEHOLDER, @@ -1249,6 +1301,7 @@ struct zkey_command { int need_cca_library; int need_ep11_library; int need_pkey_device; + int need_uv_device; char *short_desc; char *long_desc; int has_options; @@ -1285,6 +1338,7 @@ static int command_kms_reencipher(void); static int command_kms_list(void); static int command_kms_import(void); static int command_kms_refresh(void); +static int command_pvsecrets_list(void); static struct zkey_command zkey_kms_commands[] = { { @@ -1402,6 +1456,22 @@ static struct zkey_command zkey_kms_commands[] = { { .command = NULL } }; +static struct zkey_command zkey_pvsecrets_commands[] = { + { + .command = COMMAND_PVSECRETS_LIST, + .abbrev_len = 2, + .function = command_pvsecrets_list, + .short_desc = "Lists protected virtualization (PV) secrets", + .long_desc = "Lists available protected virtualization (PV) " + "secrets. This command is only available when " + "running in a secure execution guest. Only the " + "'root' user is allowed to perform this command", + .has_options = 1, + .need_uv_device = 1, + }, + { .command = NULL } +}; + static struct zkey_command zkey_commands[] = { { .command = COMMAND_GENERATE, @@ -1565,6 +1635,21 @@ static struct zkey_command zkey_commands[] = { .has_options = 1, .sub_commands = zkey_kms_commands, }, + { + .command = COMMAND_PVSECRETS, + .abbrev_len = 2, + .short_desc = "Protected virtualization (PV) support", + .long_desc = "Provides subcommands for working with protected " + "virtualization (PV) secrets. Protected " + "virtualization secrets can be made available to " + "a secure execution guest and can be used only " + "within that guest. Thus, these subcommands are " + "only available when running in a secure " + "execution guest. Only the 'root' user is allowed " + "to perform these subcommands.", + .has_options = 1, + .sub_commands = zkey_pvsecrets_commands, + }, { .command = NULL } }; @@ -2899,6 +2984,28 @@ static int command_kms_refresh(void) return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS; } +/* + * Command handler for 'pvsecrets list'. + * + * Lists available protected virtualization secrets + */ +static int command_pvsecrets_list(void) +{ + int rc; + + if (g.secret_id != NULL && g.secret_name != NULL) { + warnx("Either '--pvsecret-id/-I' or '--pvsecret-name/-e' can " + "be specified, but not both"); + util_prg_print_parse_error(); + return EXIT_FAILURE; + } + + rc = pvsecrets_list(g.uv_fd, g.all, g.hex, g.secret_type, g.secret_id, + g.secret_name, g.verbose); + + return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} + /** * Opens the keystore. The keystore directory is either the * default directory or as specified in an environment variable @@ -3234,6 +3341,21 @@ int main(int argc, char *argv[]) case OPT_REMOVE_DUMMY_PASSPHRASE: g.remove_passphrase = 1; break; + case 'A': + g.all = 1; + break; + case 'H': + g.hex = 1; + break; + case 'T': + g.secret_type = optarg; + break; + case 'I': + g.secret_id = optarg; + break; + case 'e': + g.secret_name = optarg; + break; case 'h': print_help(command, sub_command); return EXIT_SUCCESS; @@ -3294,6 +3416,13 @@ int main(int argc, char *argv[]) goto out; } } + if (cmd->need_uv_device) { + g.uv_fd = uv_open_device(g.verbose); + if (g.uv_fd == -1) { + rc = EXIT_FAILURE; + goto out; + } + } if (g.kms_info.plugin_lib != NULL) { rc = init_kms_plugin(&g.kms_info, g.verbose); @@ -3323,6 +3452,8 @@ out: dlclose(g.ep11.lib_ep11); if (g.pkey_fd >= 0) close(g.pkey_fd); + if (g.uv_fd >= 0) + close(g.uv_fd); if (g.keystore) keystore_free(g.keystore); if (g.kms_options != NULL)