From b48aa5f4355c4547012bb60620ed4fa52e241e9d Mon Sep 17 00:00:00 2001 From: Ingo Franzki Date: Tue, 12 Nov 2019 12:35:58 +0100 Subject: [PATCH] zkey: Add EP11 library helper routines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new source file that contains EP11 specific helper routines. These routines require to load the EP11 host library. Signed-off-by: Ingo Franzki Reviewed-by: Harald Freudenberger Signed-off-by: Jan Höppner --- zkey/Makefile | 17 ++- zkey/ep11.c | 339 +++++++++++++++++++++++++++++++++++++++++ zkey/ep11.h | 119 +++++++++++++++ zkey/keystore.c | 44 +++--- zkey/keystore.h | 7 +- zkey/pkey.h | 8 + zkey/zkey-cryptsetup.c | 13 ++ zkey/zkey.c | 21 ++- 8 files changed, 531 insertions(+), 37 deletions(-) create mode 100644 zkey/ep11.c create mode 100644 zkey/ep11.h diff --git a/zkey/Makefile b/zkey/Makefile index d09762d3..4e65da10 100644 --- a/zkey/Makefile +++ b/zkey/Makefile @@ -64,21 +64,22 @@ zkey-cryptsetup-skip-jsonc: all: $(BUILD_TARGETS) -zkey.o: zkey.c pkey.h cca.h misc.h -pkey.o: pkey.c pkey.h -cca.o: cca.c cca.h pkey.h utils.h -utils.o: utils.h pkey.h +zkey.o: zkey.c pkey.h cca.h ep11.h misc.h +pkey.o: pkey.c pkey.h cca.h ep11.h +cca.o: cca.c cca.h pkey.h ep11.h utils.h +ep11.o: ep11.c ep11.h pkey.h cca.h utils.h +utils.o: utils.h pkey.h cca.h ep11.h properties.o: check-dep-zkey properties.c properties.h -keystore.o: keystore.c keystore.h properties.h pkey.h cca.h utils.h +keystore.o: keystore.c keystore.h properties.h pkey.h cca.h ep11.h utils.h zkey-cryptsetup.o: check-dep-zkey-cryptsetup zkey-cryptsetup.c pkey.h cca.h \ - misc.h utils.h + ep11.h misc.h utils.h zkey: LDLIBS = -ldl -lcrypto -zkey: zkey.o pkey.o cca.o properties.o keystore.o utils.o $(libs) +zkey: zkey.o pkey.o cca.o ep11.o properties.o keystore.o utils.o $(libs) $(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@ zkey-cryptsetup: LDLIBS = -ldl -lcryptsetup -ljson-c -lcrypto -zkey-cryptsetup: zkey-cryptsetup.o pkey.o cca.o utils.o $(libs) +zkey-cryptsetup: zkey-cryptsetup.o pkey.o cca.o ep11.o utils.o $(libs) $(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@ install-common: diff --git a/zkey/ep11.c b/zkey/ep11.c new file mode 100644 index 00000000..e6ef1957 --- /dev/null +++ b/zkey/ep11.c @@ -0,0 +1,339 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lib/util_base.h" +#include "lib/util_libc.h" +#include "lib/util_panic.h" + +#include "ep11.h" +#include "pkey.h" +#include "utils.h" + +#define pr_verbose(verbose, fmt...) do { \ + if (verbose) \ + warnx(fmt); \ + } while (0) + +/* + * Definitions for the EP11 library + */ +#define EP11_LIBRARY_NAME "libep11.so" +#define EP11_LIBRARY_VERSION 3 +#define EP11_WEB_PAGE "http://www.ibm.com/security/cryptocards" + +/** + * Returns the major and minor version of the of the used EP11 host library. + * + * @param[in] ep11 the EP11 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_ep11_version(struct ep11_lib *ep11, bool verbose) +{ + unsigned int host_version; + CK_ULONG version_len = sizeof(host_version); + CK_RV rc; + + rc = ep11->dll_m_get_xcp_info(&host_version, &version_len, + CK_IBM_XCPHQ_VERSION, 0, 0); + if (rc != CKR_OK) { + pr_verbose(verbose, "Failed to obtain the EP11 host library " + "version: m_get_xcp_info: 0x%lx", rc); + return -EIO; + } + + pr_verbose(verbose, "host_version: 0x%08x", host_version); + + ep11->version.major = (host_version & 0x00FF0000) >> 16; + ep11->version.minor = host_version & 0x000000FF; + /* + * EP11 host library < v2.0 returns an invalid version (i.e. 0x100). + * This can safely be treated as version 1.0 + */ + if (ep11->version.major == 0) { + ep11->version.major = 1; + ep11->version.minor = 0; + } + + pr_verbose(verbose, "EP11 library version: %u.%u", + ep11->version.major, ep11->version.minor); + + return 0; +} + +/** + * Loads the EP11 library and provides the entry points of several functions. + * + * @param[out] ep11 on return this contains the address of the EP11 + * library and certain EP11 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_ep11_library(struct ep11_lib *ep11, bool verbose) +{ + char lib_name[256]; + int libver; + int rc; + + util_assert(ep11 != NULL, "Internal error: ep11 is NULL"); + + /* Load the EP11 library with highest available version'd SO name */ + for (libver = EP11_LIBRARY_VERSION; libver >= 0; libver--) { + if (libver > 0) + sprintf(lib_name, "%s.%d", EP11_LIBRARY_NAME, libver); + else + sprintf(lib_name, "%s", EP11_LIBRARY_NAME); + + ep11->lib_ep11 = dlopen(lib_name, RTLD_GLOBAL | RTLD_NOW); + if (ep11->lib_ep11 != NULL) + break; + } + if (ep11->lib_ep11 == NULL) { + pr_verbose(verbose, "%s", dlerror()); + warnx("The command requires the IBM Z Enterprise PKCS #11 " + "(EP11) Support Program (EP11 host library).\n" + "For the supported environments and downloads, see:\n%s", + EP11_WEB_PAGE); + return -ELIBACC; + } + + /* Get several EP11 host library functions */ + ep11->dll_m_init = (m_init_t)dlsym(ep11->lib_ep11, "m_init"); + ep11->dll_m_add_module = (m_add_module_t)dlsym(ep11->lib_ep11, + "m_add_module"); + ep11->dll_m_rm_module = (m_rm_module_t)dlsym(ep11->lib_ep11, + "m_rm_module"); + ep11->dll_m_get_xcp_info = (m_get_xcp_info_t)dlsym(ep11->lib_ep11, + "m_get_xcp_info"); + + /* dll_m_add_module and dll_m_rm_module may be NULL for V1 EP11 lib */ + if (ep11->dll_m_init == NULL || + ep11->dll_m_get_xcp_info == NULL) { + pr_verbose(verbose, "%s", dlerror()); + warnx("The command requires the IBM Z Enterprise PKCS #11 " + "(EP11) Support Program (EP11 host library).\n" + "For the supported environments and downloads, see:\n%s", + EP11_WEB_PAGE); + dlclose(ep11->lib_ep11); + ep11->lib_ep11 = NULL; + return -ELIBACC; + } + + /* Initialize the EP11 library */ + rc = ep11->dll_m_init(); + if (rc != 0) { + pr_verbose(verbose, "Failed to initialize the EP11 host " + "library: m_init: 0x%x", rc); + dlclose(ep11->lib_ep11); + ep11->lib_ep11 = NULL; + return -ELIBACC; + } + + pr_verbose(verbose, "EP11 library '%s' has been loaded successfully", + lib_name); + + return get_ep11_version(ep11, verbose); +} + +/** + * Get an EP11 target handle for a specific APQN (card and domain) + * + * @param[in] ep11 the EP11 library structure + * @param[in] card the card number + * @param[in] domain the domain number + * @param[out] target on return: the target handle for the APQN + * @param verbose if true, verbose messages are printed + * + * @returns 0 on success, a negative errno in case of errors + */ +int get_ep11_target_for_apqn(struct ep11_lib *ep11, int card, int domain, + target_t *target, bool verbose) +{ + ep11_target_t *target_list; + struct XCP_Module module; + CK_RV rc; + + util_assert(ep11 != NULL, "Internal error: ep11 is NULL"); + util_assert(target != NULL, "Internal error: target is NULL"); + + *target = XCP_TGT_INIT; + + if (ep11->dll_m_add_module != NULL) { + memset(&module, 0, sizeof(module)); + module.version = ep11->version.major >= 3 ? XCP_MOD_VERSION_2 + : XCP_MOD_VERSION_1; + module.flags = XCP_MFL_MODULE; + module.module_nr = card; + XCPTGTMASK_SET_DOM(module.domainmask, domain); + rc = ep11->dll_m_add_module(&module, target); + if (rc != 0) { + pr_verbose(verbose, "Failed to add APQN %02x.%04x: " + "m_add_module rc=0x%lx", card, domain, rc); + return -EIO; + } + } else { + /* Fall back to old target handling */ + target_list = (ep11_target_t *)calloc(1, sizeof(ep11_target_t)); + if (target_list == NULL) + return -ENOMEM; + target_list->length = 1; + target_list->apqns[0] = card; + target_list->apqns[1] = domain; + *target = (target_t)target_list; + } + + return 0; +} + +/** + * Free an EP11 target handle + * + * @param[in] ep11 the EP11 library structure + * @param[in] target the target handle to free + * + * @returns 0 on success, a negative errno in case of errors + */ +void free_ep11_target_for_apqn(struct ep11_lib *ep11, target_t target) +{ + util_assert(ep11 != NULL, "Internal error: ep11 is NULL"); + + if (ep11->dll_m_rm_module != NULL) { + ep11->dll_m_rm_module(NULL, target); + } else { + /* + * With the old target handling, target is a pointer to + * ep11_target_t + */ + free((ep11_target_t *)target); + } +} + +struct find_mkvp_info { + u8 mkvp[MKVP_LENGTH]; + 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_EP11_MATCH_CUR_MKVP) + if (mk_info.cur_mk.mk_state == MK_STATE_VALID && + MKVP_EQ(mk_info.cur_mk.mkvp, info->mkvp)) + found = true; + + if (info->flags & FLAG_SEL_EP11_NEW_MUST_BE_SET) + if (mk_info.new_mk.mk_state != MK_STATE_COMMITTED) + 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_EP11_NEW_MUST_BE_SET ? + " and NEW MK set" : ""); + + return 1; + } + + return 0; +} + +/** + * Selects an APQN to be used for the Ep11 host library that has the specified + * master key verification pattern + * + * @param[in] ep11 the EP11 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 EP11 APQNs are + * checked. + * @param[in] flags Flags that control the MKVM matching and NEW register + * checking. Multiple flags can be combined. + * @param[out] target on return: the target handle for the APQN. If this is + * NULL, then no target is built. + * @param[out] card on return: the card that was selected (can be NULL) + * @param[out] domain on return: the domain that was selected (can be NULL) + * @param[in] verbose if true, verbose messages are printed + * + * @returns 0 on success, a negative errno in case of errors + */ +int select_ep11_apqn_by_mkvp(struct ep11_lib *ep11, u8 *mkvp, + const char *apqns, unsigned int flags, + target_t *target, int *card, int *domain, + bool verbose) +{ + struct find_mkvp_info info; + int rc; + + util_assert(ep11 != NULL, "Internal error: ep11 is NULL"); + util_assert(mkvp != NULL, "Internal error: mkvp is NULL"); + + pr_verbose(verbose, "Select mkvp %s in APQNs %s for the EP11 host " + "library", printable_mkvp(CARD_TYPE_EP11, mkvp), + apqns == 0 ? "ANY" : apqns); + + memcpy(info.mkvp, mkvp, sizeof(info.mkvp)); + info.flags = flags; + info.found = false; + info.card = 0; + info.domain = 0; + info.verbose = verbose; + + rc = handle_apqns(apqns, CARD_TYPE_EP11, find_mkvp, &info, verbose); + if (rc < 0) + return rc; + + if (!info.found) + return -ENODEV; + + if (target != NULL) { + rc = get_ep11_target_for_apqn(ep11, info.card, info.domain, + target, verbose); + if (rc != 0) + return rc; + } + + if (card != NULL) + *card = info.card; + if (domain != NULL) + *domain = info.domain; + + return 0; +} diff --git a/zkey/ep11.h b/zkey/ep11.h new file mode 100644 index 00000000..212c9f9f --- /dev/null +++ b/zkey/ep11.h @@ -0,0 +1,119 @@ +/* + * zkey - Generate, re-encipher, and validate secure keys + * + * This header file defines the interface to the EP11 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 EP11_H +#define EP11_H + +#include + +#include "lib/zt_common.h" + +/* EP11 definitions */ + +typedef uint64_t target_t; +typedef unsigned long int CK_ULONG; +typedef CK_ULONG CK_RV; +typedef unsigned char CK_BYTE; +typedef CK_BYTE CK_CHAR; +typedef CK_ULONG *CK_ULONG_PTR; +typedef void *CK_VOID_PTR; + +typedef struct XCP_ModuleSocket { + char host[256 + 1]; + uint32_t port; +} *XCP_ModuleSocket_t; + +typedef struct XCP_DomainPerf { + unsigned int lastperf[256]; +} *XCP_DomainPerf_t; + +typedef struct XCP_Module { + uint32_t version; + uint64_t flags; + uint32_t domains; + unsigned char domainmask[256 / 8]; + struct XCP_ModuleSocket socket; + uint32_t module_nr; + void *mhandle; + struct XCP_DomainPerf perf; + /* ----- end of v1 fields ----- */ + uint32_t api; + /* ----- end of v2 fields ----- */ +} *XCP_Module_t; + +typedef enum { + XCP_MFL_SOCKET = 1, + XCP_MFL_MODULE = 2, + XCP_MFL_MHANDLE = 4, + XCP_MFL_PERF = 8, + XCP_MFL_VIRTUAL = 0x10, + XCP_MFL_STRICT = 0x20, + XCP_MFL_PROBE = 0x40, + XCP_MFL_ALW_TGT_ADD = 0x80, + XCP_MFL_MAX = 0xff +} XCP_Module_Flags; + +#define XCP_MOD_VERSION_1 1 +#define XCP_MOD_VERSION_2 2 +#define XCP_TGT_INIT ~0UL + +#define XCPTGTMASK_SET_DOM(mask, domain) \ + mask[((domain)/8)] |= (1 << (7-(domain)%8)) + +#define CK_IBM_XCPHQ_VERSION 0xff000001 + +#define MAX_APQN 256 + +typedef struct { + short format; + short length; + short apqns[2 * MAX_APQN]; +} __packed ep11_target_t; + +#define CKR_OK 0x00000000 + +typedef int (*m_init_t) (void); +typedef int (*m_add_module_t) (XCP_Module_t module, target_t *target); +typedef int (*m_rm_module_t) (XCP_Module_t module, target_t target); +typedef CK_RV (*m_get_xcp_info_t)(CK_VOID_PTR pinfo, CK_ULONG_PTR infbytes, + unsigned int query, unsigned int subquery, + target_t target); + +struct ep11_version { + unsigned int minor; + unsigned int major; +}; + +struct ep11_lib { + void *lib_ep11; + m_init_t dll_m_init; + m_add_module_t dll_m_add_module; + m_rm_module_t dll_m_rm_module; + m_get_xcp_info_t dll_m_get_xcp_info; + struct ep11_version version; +}; + +int load_ep11_library(struct ep11_lib *ep11, bool verbose); + +int get_ep11_target_for_apqn(struct ep11_lib *ep11, int card, int domain, + target_t *target, bool verbose); + +void free_ep11_target_for_apqn(struct ep11_lib *ep11, target_t target); + +#define FLAG_SEL_EP11_MATCH_CUR_MKVP 0x01 +#define FLAG_SEL_EP11_NEW_MUST_BE_SET 0x80 + +int select_ep11_apqn_by_mkvp(struct ep11_lib *ep11, u8 *mkvp, + const char *apqns, unsigned int flags, + target_t *target, int *card, int *domain, + bool verbose); + +#endif diff --git a/zkey/keystore.c b/zkey/keystore.c index 2ccc71ef..eda2339c 100644 --- a/zkey/keystore.c +++ b/zkey/keystore.c @@ -1808,7 +1808,7 @@ out_free_key_filenames: * default is used. * @param[in] import_file The name of a secure key containing the key to import * @param[in] volume_type the type of volume - * @param[in] cca the CCA library struct + * @param[in] lib the external library struct * * @returns 0 for success or a negative errno in case of an error */ @@ -1816,7 +1816,7 @@ int keystore_import_key(struct keystore *keystore, const char *name, const char *description, const char *volumes, const char *apqns, bool noapqncheck, size_t sector_size, const char *import_file, const char *volume_type, - struct cca_lib *cca) + struct ext_lib *lib) { struct key_filenames file_names = { NULL, NULL, NULL }; struct properties *key_props = NULL; @@ -1874,13 +1874,13 @@ int keystore_import_key(struct keystore *keystore, const char *name, } if (is_cca_aes_cipher_key(secure_key, secure_key_size)) { - if (cca->lib_csulcca == NULL) { - rc = load_cca_library(cca, keystore->verbose); + if (lib->cca->lib_csulcca == NULL) { + rc = load_cca_library(lib->cca, keystore->verbose); if (rc != 0) goto out_free_key; } - rc = select_cca_adapter_by_mkvp(cca, mkvp, apqns, + rc = select_cca_adapter_by_mkvp(lib->cca, mkvp, apqns, FLAG_SEL_CCA_MATCH_CUR_MKVP | FLAG_SEL_CCA_MATCH_OLD_MKVP, keystore->verbose); @@ -1895,7 +1895,7 @@ int keystore_import_key(struct keystore *keystore, const char *name, goto out_free_key; } - rc = restrict_key_export(cca, secure_key, secure_key_size, + rc = restrict_key_export(lib->cca, secure_key, secure_key_size, keystore->verbose); if (rc != 0) { warnx("Failed to export-restrict the imported secure " @@ -2662,7 +2662,7 @@ struct reencipher_params { struct reencipher_info { struct reencipher_params params; int pkey_fd; - struct cca_lib *cca; + struct ext_lib *lib; unsigned long num_reenciphered; unsigned long num_failed; unsigned long num_skipped; @@ -2673,7 +2673,7 @@ struct reencipher_info { * * @param[in] keystore the keystore * @param[in] name the name of the key - * @param[in] cca the CCA library struct + * @param[in] lib the external library struct * @param[in] params reenciphering parameters * @param[in] secure_key a buffer containing the secure key * @param[in] secure_key_size the size of the secure key @@ -2685,7 +2685,7 @@ struct reencipher_info { */ static int _keystore_perform_reencipher(struct keystore *keystore, const char *name, - struct cca_lib *cca, + struct ext_lib *lib, struct reencipher_params *params, u8 *secure_key, size_t secure_key_size, bool is_old_mk, const char *apqns) @@ -2728,7 +2728,7 @@ static int _keystore_perform_reencipher(struct keystore *keystore, "Secure key '%s' will be re-enciphered from OLD " "to the CURRENT master key", name); - rc = select_cca_adapter_by_mkvp(cca, mkvp, apqns, + rc = select_cca_adapter_by_mkvp(lib->cca, mkvp, apqns, FLAG_SEL_CCA_MATCH_OLD_MKVP, keystore->verbose); if (rc == -ENOTSUP) { @@ -2741,7 +2741,7 @@ static int _keystore_perform_reencipher(struct keystore *keystore, return rc; } - rc = key_token_change(cca, secure_key, secure_key_size, + rc = key_token_change(lib->cca, secure_key, secure_key_size, METHOD_OLD_TO_CURRENT, keystore->verbose); if (rc != 0) { @@ -2760,7 +2760,7 @@ static int _keystore_perform_reencipher(struct keystore *keystore, if (params->inplace == -1) params->inplace = 0; - rc = select_cca_adapter_by_mkvp(cca, mkvp, apqns, + rc = select_cca_adapter_by_mkvp(lib->cca, mkvp, apqns, FLAG_SEL_CCA_MATCH_CUR_MKVP | FLAG_SEL_CCA_NEW_MUST_BE_SET, keystore->verbose); @@ -2776,7 +2776,7 @@ static int _keystore_perform_reencipher(struct keystore *keystore, return rc; } - rc = key_token_change(cca, secure_key, secure_key_size, + rc = key_token_change(lib->cca, secure_key, secure_key_size, METHOD_CURRENT_TO_NEW, keystore->verbose); if (rc != 0) { @@ -2877,7 +2877,7 @@ static int _keystore_process_reencipher(struct keystore *keystore, if (!params.complete) { printf("Re-enciphering key '%s'\n", name); - rc = _keystore_perform_reencipher(keystore, name, info->cca, + rc = _keystore_perform_reencipher(keystore, name, info->lib, ¶ms, secure_key, secure_key_size, is_old_mk, properties_get(properties, @@ -2989,7 +2989,7 @@ out: * @param[in] staged if true, the key will be re-enciphere not in-place * @param[in] complete if true, a pending re-encipherment is completed * @param[in] pkey_fd the file descriptor of /dev/pkey - * @param[in] cca the CCA library struct + * @param[in] lib the external library struct * Note: if both fromOld and toNew are FALSE, then the reencipherement mode is * detected automatically. If both are TRUE then the key is reenciphered * from the OLD to the NEW master key. @@ -3002,7 +3002,7 @@ int keystore_reencipher_key(struct keystore *keystore, const char *name_filter, const char *apqn_filter, bool from_old, bool to_new, bool inplace, bool staged, bool complete, int pkey_fd, - struct cca_lib *cca) + struct ext_lib *lib) { struct reencipher_info info; int rc; @@ -3018,7 +3018,7 @@ int keystore_reencipher_key(struct keystore *keystore, const char *name_filter, info.params.inplace = 0; info.params.complete = complete; info.pkey_fd = pkey_fd; - info.cca = cca; + info.lib = lib; info.num_failed = 0; info.num_reenciphered = 0; info.num_skipped = 0; @@ -3971,13 +3971,13 @@ int keystore_crypttab(struct keystore *keystore, const char *volume_filter, * @param[in] noapqncheck if true, the specified APQN(s) are not checked for * existence and type. * @param[in] pkey_fd the file descriptor of /dev/pkey - * @param[in] cca the CCA library struct + * @param[in] lib the external library struct * * @returns 0 for success or a negative errno in case of an error */ int keystore_convert_key(struct keystore *keystore, const char *name, const char *key_type, bool noapqncheck, bool quiet, - int pkey_fd, struct cca_lib *cca) + int pkey_fd, struct ext_lib *lib) { struct key_filenames file_names = { NULL, NULL, NULL }; u8 output_key[2 * MAX_SECURE_KEY_SIZE]; @@ -4065,7 +4065,7 @@ int keystore_convert_key(struct keystore *keystore, const char *name, if (rc) goto out; - rc = select_cca_adapter_by_mkvp(cca, mkvp, apqns, + rc = select_cca_adapter_by_mkvp(lib->cca, mkvp, apqns, FLAG_SEL_CCA_MATCH_CUR_MKVP, keystore->verbose); if (rc == -ENOTSUP) { @@ -4095,7 +4095,7 @@ int keystore_convert_key(struct keystore *keystore, const char *name, memset(output_key, 0, sizeof(output_key)); output_key_size = sizeof(output_key); - rc = convert_aes_data_to_cipher_key(cca, secure_key, + rc = convert_aes_data_to_cipher_key(lib->cca, secure_key, secure_key_size, output_key, &output_key_size, keystore->verbose); @@ -4107,7 +4107,7 @@ int keystore_convert_key(struct keystore *keystore, const char *name, goto out; } - rc = restrict_key_export(cca, output_key, output_key_size, + rc = restrict_key_export(lib->cca, output_key, output_key_size, keystore->verbose); if (rc != 0) { warnx("Export restricting the converted secure key '%s' has " diff --git a/zkey/keystore.h b/zkey/keystore.h index b17a575b..d9528144 100644 --- a/zkey/keystore.h +++ b/zkey/keystore.h @@ -14,7 +14,6 @@ #include -#include "cca.h" #include "pkey.h" struct keystore { @@ -38,7 +37,7 @@ int keystore_import_key(struct keystore *keystore, const char *name, const char *description, const char *volumes, const char *apqns, bool noapqncheck, size_t sector_size, const char *import_file, const char *volume_type, - struct cca_lib *cca); + struct ext_lib *lib); int keystore_change_key(struct keystore *keystore, const char *name, const char *description, const char *volumes, @@ -56,7 +55,7 @@ int keystore_reencipher_key(struct keystore *keystore, const char *name_filter, const char *apqn_filter, bool from_old, bool to_new, bool inplace, bool staged, bool complete, int pkey_fd, - struct cca_lib *cca); + struct ext_lib *lib); int keystore_copy_key(struct keystore *keystore, const char *name, const char *newname, const char *volumes); @@ -83,7 +82,7 @@ int keystore_crypttab(struct keystore *keystore, const char *volume_filter, 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); + int pkey_fd, struct ext_lib *lib); void keystore_free(struct keystore *keystore); diff --git a/zkey/pkey.h b/zkey/pkey.h index d06f3cf0..71845c7f 100644 --- a/zkey/pkey.h +++ b/zkey/pkey.h @@ -15,6 +15,9 @@ #include "lib/zt_common.h" +#include "cca.h" +#include "ep11.h" + /* * Definitions for the /dev/pkey kernel module interface */ @@ -244,6 +247,11 @@ enum card_type { CARD_TYPE_EP11 = 2, }; +struct ext_lib { + struct cca_lib *cca; + struct ep11_lib *ep11; +}; + int open_pkey_device(bool verbose); int generate_secure_key_random(int pkey_fd, const char *keyfile, diff --git a/zkey/zkey-cryptsetup.c b/zkey/zkey-cryptsetup.c index 74bc5687..e72d3c6c 100644 --- a/zkey/zkey-cryptsetup.c +++ b/zkey/zkey-cryptsetup.c @@ -35,6 +35,7 @@ #include "misc.h" #include "pkey.h" #include "cca.h" +#include "ep11.h" #include "utils.h" /* Detect if cryptsetup 2.1 or later is available */ @@ -105,12 +106,16 @@ static struct zkey_cryptsetup_globals { bool batch_mode; bool debug; bool verbose; + struct ext_lib lib; struct cca_lib cca; + struct ep11_lib ep11; int pkey_fd; struct crypt_device *cd; } g = { .tries = 3, .pkey_fd = -1, + .lib.cca = &g.cca, + .lib.ep11 = &g.ep11, }; /* @@ -269,6 +274,7 @@ struct zkey_cryptsetup_command { unsigned int abbrev_len; int (*function)(void); int need_cca_library; + int need_ep11_library; int need_pkey_device; char *short_desc; char *long_desc; @@ -2435,6 +2441,13 @@ int main(int argc, char *argv[]) goto out; } } + if (command->need_ep11_library) { + rc = load_ep11_library(&g.ep11, g.verbose); + if (rc != 0) { + rc = EXIT_FAILURE; + goto out; + } + } if (command->need_pkey_device) { g.pkey_fd = open_pkey_device(g.verbose); if (g.pkey_fd == -1) { diff --git a/zkey/zkey.c b/zkey/zkey.c index ab0e0149..22f66ce9 100644 --- a/zkey/zkey.c +++ b/zkey/zkey.c @@ -28,6 +28,7 @@ #include "lib/zt_common.h" #include "cca.h" +#include "ep11.h" #include "keystore.h" #include "misc.h" #include "pkey.h" @@ -83,12 +84,16 @@ static struct zkey_globals { bool force; bool open; bool format; + struct ext_lib lib; struct cca_lib cca; + struct ep11_lib ep11; int pkey_fd; struct keystore *keystore; } g = { .pkey_fd = -1, .sector_size = -1, + .lib.cca = &g.cca, + .lib.ep11 = &g.ep11, }; /* @@ -822,6 +827,7 @@ struct zkey_command { unsigned int abbrev_len; int (*function)(void); int need_cca_library; + int need_ep11_library; int need_pkey_device; char *short_desc; char *long_desc; @@ -1396,7 +1402,7 @@ static int command_reencipher_repository(void) rc = keystore_reencipher_key(g.keystore, g.name, g.apqns, g.fromold, g.tonew, g.inplace, g.staged, g.complete, - g.pkey_fd, &g.cca); + g.pkey_fd, &g.lib); return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS; } @@ -1575,7 +1581,7 @@ static int command_import(void) rc = keystore_import_key(g.keystore, g.name, g.description, g.volumes, g.apqns, g.noapqncheck, g.sector_size, - g.pos_arg, g.volume_type, &g.cca); + g.pos_arg, g.volume_type, &g.lib); return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS; } @@ -1916,7 +1922,7 @@ static int command_convert_repository(void) } rc = keystore_convert_key(g.keystore, g.name, g.key_type, g.noapqncheck, - g.force, g.pkey_fd, &g.cca); + g.force, g.pkey_fd, &g.lib); return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS; } @@ -2231,6 +2237,13 @@ int main(int argc, char *argv[]) goto out; } } + if (command->need_ep11_library) { + rc = load_ep11_library(&g.ep11, g.verbose); + if (rc != 0) { + rc = EXIT_FAILURE; + goto out; + } + } if (command->need_pkey_device) { g.pkey_fd = open_pkey_device(g.verbose); if (g.pkey_fd == -1) { @@ -2246,6 +2259,8 @@ int main(int argc, char *argv[]) out: if (g.cca.lib_csulcca) dlclose(g.cca.lib_csulcca); + if (g.ep11.lib_ep11) + dlclose(g.ep11.lib_ep11); if (g.pkey_fd >= 0) close(g.pkey_fd); if (g.keystore)