mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zkey: Add EP11 library helper routines
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 <ifranzki@linux.ibm.com> Reviewed-by: Harald Freudenberger <freude@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
d91e728e3c
commit
b48aa5f435
@@ -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:
|
||||
|
||||
339
zkey/ep11.c
Normal file
339
zkey/ep11.c
Normal file
@@ -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 <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 "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;
|
||||
}
|
||||
119
zkey/ep11.h
Normal file
119
zkey/ep11.h
Normal file
@@ -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 <stdint.h>
|
||||
|
||||
#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
|
||||
@@ -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 "
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
21
zkey/zkey.c
21
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)
|
||||
|
||||
Reference in New Issue
Block a user