mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zkey: Add support for re-enciphering EP11 secure keys
Re-encipher EP11 secure keys using 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
88e6a18f96
commit
0be7efc956
173
zkey/ep11.c
173
zkey/ep11.c
@@ -126,9 +126,25 @@ int load_ep11_library(struct ep11_lib *ep11, bool verbose)
|
||||
ep11->dll_m_get_xcp_info = (m_get_xcp_info_t)dlsym(ep11->lib_ep11,
|
||||
"m_get_xcp_info");
|
||||
|
||||
ep11->dll_m_admin = (m_admin_t)dlsym(ep11->lib_ep11, "m_admin");
|
||||
ep11->dll_xcpa_cmdblock = (xcpa_cmdblock_t)dlsym(ep11->lib_ep11,
|
||||
"xcpa_cmdblock");
|
||||
if (ep11->dll_xcpa_cmdblock == NULL)
|
||||
ep11->dll_xcpa_cmdblock = (xcpa_cmdblock_t)dlsym(ep11->lib_ep11,
|
||||
"ep11a_cmdblock");
|
||||
ep11->dll_xcpa_internal_rv = (xcpa_internal_rv_t)dlsym(ep11->lib_ep11,
|
||||
"xcpa_internal_rv");
|
||||
if (ep11->dll_xcpa_internal_rv == NULL)
|
||||
ep11->dll_xcpa_internal_rv =
|
||||
(xcpa_internal_rv_t)dlsym(ep11->lib_ep11,
|
||||
"ep11a_internal_rv");
|
||||
|
||||
/* 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) {
|
||||
ep11->dll_m_get_xcp_info == NULL ||
|
||||
ep11->dll_m_admin == NULL ||
|
||||
ep11->dll_xcpa_cmdblock == NULL ||
|
||||
ep11->dll_xcpa_internal_rv == NULL) {
|
||||
pr_verbose(verbose, "%s", dlerror());
|
||||
warnx("The command requires the IBM Z Enterprise PKCS #11 "
|
||||
"(EP11) Support Program (EP11 host library).\n"
|
||||
@@ -337,3 +353,158 @@ int select_ep11_apqn_by_mkvp(struct ep11_lib *ep11, u8 *mkvp,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an EP11 administrative request to Re-encrypt a single EP11 secure
|
||||
* key with a new EP11 master key (wrapping key).
|
||||
*
|
||||
* @param[in] ep11 the EP11 library structure
|
||||
* @param[in] target the target handle to use for the re-encipher operation
|
||||
* @param[in] card the card that corresponds to the target handle
|
||||
* @param[in] domain the domain that corresponds to the target handle
|
||||
* @param[in/out] ep11key the EP11 key token to reencipher. The re-enciphered
|
||||
* secure key will be returned in this buffer.
|
||||
* @param[in] ep11key_size the size of the secure key
|
||||
* @param[in] verbose if true, verbose messages are printed
|
||||
*
|
||||
* @returns 0 on success, a negative errno in case of errors
|
||||
*/
|
||||
static int ep11_adm_reencrypt(struct ep11_lib *ep11, target_t target, int card,
|
||||
int domain, struct ep11keytoken *ep11key,
|
||||
unsigned int ep11key_size, bool verbose)
|
||||
{
|
||||
CK_BYTE resp[MAX_BLOBSIZE];
|
||||
CK_BYTE req[MAX_BLOBSIZE];
|
||||
char ep11_token_header[sizeof(ep11key->head)];
|
||||
struct XCPadmresp lrb;
|
||||
struct XCPadmresp rb;
|
||||
size_t resp_len;
|
||||
size_t blob_len;
|
||||
long req_len;
|
||||
CK_RV rv;
|
||||
int rc;
|
||||
|
||||
blob_len = ep11key->head.length;
|
||||
if (blob_len > ep11key_size) {
|
||||
pr_verbose(verbose, "Blob length larger than secure key size");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rb.domain = domain;
|
||||
lrb.domain = domain;
|
||||
|
||||
/* The token header is an overlay over the (all zero) session field */
|
||||
memcpy(ep11_token_header, ep11key, sizeof(ep11_token_header));
|
||||
memset(ep11key->session, 0, sizeof(ep11key->session));
|
||||
|
||||
resp_len = sizeof(resp);
|
||||
req_len = ep11->dll_xcpa_cmdblock(req, sizeof(req), XCP_ADM_REENCRYPT,
|
||||
&rb, NULL, (unsigned char *)ep11key,
|
||||
blob_len);
|
||||
if (req_len < 0) {
|
||||
pr_verbose(verbose, "Failed to build XCP command block");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rv = ep11->dll_m_admin(resp, &resp_len, NULL, 0, req, req_len, NULL, 0,
|
||||
target);
|
||||
if (rv != CKR_OK || resp_len == 0) {
|
||||
pr_verbose(verbose, "Command XCP_ADM_REENCRYPT failed. "
|
||||
"rc = 0x%lx, resp_len = %ld", rv, resp_len);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = ep11->dll_xcpa_internal_rv(resp, resp_len, &lrb, &rv);
|
||||
if (rc != 0) {
|
||||
pr_verbose(verbose, "Failed to parse response. rc = %d", rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (rv != CKR_OK) {
|
||||
pr_verbose(verbose, "Failed to re-encrypt the EP11 secure key. "
|
||||
"rc = 0x%lx", rv);
|
||||
switch (rv) {
|
||||
case CKR_IBM_WKID_MISMATCH:
|
||||
warnx("The EP11 secure key is currently encrypted "
|
||||
"under a different master that does not match "
|
||||
"the master key in the CURRENT master key "
|
||||
"register of APQN %02X.%04X", card, domain);
|
||||
break;
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (blob_len != lrb.pllen) {
|
||||
pr_verbose(verbose, "Re-encrypted EP11 secure key size has "
|
||||
"changed: org-len: %lu, new-len: %lu", blob_len,
|
||||
lrb.pllen);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
memcpy(ep11key, lrb.payload, blob_len);
|
||||
memcpy(ep11key, ep11_token_header, sizeof(ep11_token_header));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-encipher an EP11 secure key with a new EP11 master key (wrapping key).
|
||||
*
|
||||
* @param[in] ep11 the EP11 library structure
|
||||
* @param[in] target the target handle to use for the re-encipher operation
|
||||
* @param[in] card the card that corresponds to the target handle
|
||||
* @param[in] domain the domain that corresponds to the target handle
|
||||
* @param[in/out] secure_key the EP11 key token to reencipher. The re-enciphered
|
||||
* secure key will be returned in this buffer.
|
||||
* @param[in] secure_key_size the size of the secure key
|
||||
* @param[in] verbose if true, verbose messages are printed
|
||||
*
|
||||
* @returns 0 on success, a negative errno in case of errors
|
||||
*/
|
||||
int reencipher_ep11_key(struct ep11_lib *ep11, target_t target, int card,
|
||||
int domain, u8 *secure_key,
|
||||
unsigned int secure_key_size, bool verbose)
|
||||
{
|
||||
struct ep11keytoken *ep11key = (struct ep11keytoken *)secure_key;
|
||||
CK_IBM_DOMAIN_INFO dinf;
|
||||
CK_ULONG dinf_len = sizeof(dinf);
|
||||
CK_RV rv;
|
||||
int rc;
|
||||
|
||||
util_assert(ep11 != NULL, "Internal error: ep11 is NULL");
|
||||
util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
|
||||
|
||||
rv = ep11->dll_m_get_xcp_info(&dinf, &dinf_len, CK_IBM_XCPQ_DOMAIN, 0,
|
||||
target);
|
||||
if (rv != CKR_OK) {
|
||||
pr_verbose(verbose, "Failed to query domain information for "
|
||||
"%02X.%04X: m_get_xcp_info rc: 0x%lx", card, domain,
|
||||
rv);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if ((dinf.flags & CK_IBM_DOM_COMMITTED_NWK) == 0) {
|
||||
warnx("The NEW master key register of APQN %02X.%04X is not "
|
||||
"in COMMITTED state", card, domain);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rc = ep11_adm_reencrypt(ep11, target, card, domain, ep11key,
|
||||
secure_key_size, verbose);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
if (is_xts_key(secure_key, secure_key_size)) {
|
||||
secure_key += EP11_KEY_SIZE;
|
||||
secure_key_size -= EP11_KEY_SIZE;
|
||||
ep11key = (struct ep11keytoken *)secure_key;
|
||||
|
||||
rc = ep11_adm_reencrypt(ep11, target, card, domain, ep11key,
|
||||
secure_key_size, verbose);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
59
zkey/ep11.h
59
zkey/ep11.h
@@ -68,7 +68,48 @@ typedef enum {
|
||||
#define XCPTGTMASK_SET_DOM(mask, domain) \
|
||||
mask[((domain)/8)] |= (1 << (7-(domain)%8))
|
||||
|
||||
#define XCP_SERIALNR_CHARS 8
|
||||
#define XCP_ADMCTR_BYTES ((size_t) (128/8))
|
||||
#define XCP_KEYCSUM_BYTES (256/8)
|
||||
|
||||
#define XCP_ADM_REENCRYPT 25 /* transform blobs to next WK */
|
||||
|
||||
#define MAX_BLOBSIZE 8192
|
||||
|
||||
#define CKR_VENDOR_DEFINED 0x80000000
|
||||
#define CKR_IBM_WKID_MISMATCH CKR_VENDOR_DEFINED + 0x10001
|
||||
|
||||
typedef struct XCPadmresp {
|
||||
uint32_t fn;
|
||||
uint32_t domain;
|
||||
uint32_t domainInst;
|
||||
|
||||
/* module ID || module instance */
|
||||
unsigned char module[XCP_SERIALNR_CHARS + XCP_SERIALNR_CHARS];
|
||||
unsigned char modNr[XCP_SERIALNR_CHARS];
|
||||
unsigned char modInst[XCP_SERIALNR_CHARS];
|
||||
|
||||
unsigned char tctr[XCP_ADMCTR_BYTES]; /* transaction counter */
|
||||
|
||||
CK_RV rv;
|
||||
uint32_t reason;
|
||||
|
||||
const unsigned char *payload;
|
||||
size_t pllen;
|
||||
} *XCPadmresp_t;
|
||||
|
||||
typedef struct CK_IBM_DOMAIN_INFO {
|
||||
CK_ULONG domain;
|
||||
CK_BYTE wk[XCP_KEYCSUM_BYTES];
|
||||
CK_BYTE nextwk[XCP_KEYCSUM_BYTES];
|
||||
CK_ULONG flags;
|
||||
CK_BYTE mode[8];
|
||||
} CK_IBM_DOMAIN_INFO;
|
||||
|
||||
#define CK_IBM_DOM_COMMITTED_NWK 8
|
||||
|
||||
#define CK_IBM_XCPHQ_VERSION 0xff000001
|
||||
#define CK_IBM_XCPQ_DOMAIN 3
|
||||
|
||||
#define MAX_APQN 256
|
||||
|
||||
@@ -86,6 +127,17 @@ 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);
|
||||
typedef unsigned long int (*m_admin_t)(unsigned char *resp1, size_t *r1len,
|
||||
unsigned char *resp2, size_t *r2len,
|
||||
const unsigned char *cmd, size_t clen,
|
||||
const unsigned char *sigs, size_t slen,
|
||||
target_t target);
|
||||
typedef long (*xcpa_cmdblock_t)(unsigned char *blk, size_t blen,
|
||||
unsigned int fn, const struct XCPadmresp *minf,
|
||||
const unsigned char *tctr,
|
||||
const unsigned char *payload, size_t plen);
|
||||
typedef long (*xcpa_internal_rv_t)(const unsigned char *rsp, size_t rlen,
|
||||
struct XCPadmresp *rspblk, CK_RV *rv);
|
||||
|
||||
struct ep11_version {
|
||||
unsigned int minor;
|
||||
@@ -98,6 +150,9 @@ struct ep11_lib {
|
||||
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;
|
||||
m_admin_t dll_m_admin;
|
||||
xcpa_cmdblock_t dll_xcpa_cmdblock;
|
||||
xcpa_internal_rv_t dll_xcpa_internal_rv;
|
||||
struct ep11_version version;
|
||||
};
|
||||
|
||||
@@ -116,4 +171,8 @@ int select_ep11_apqn_by_mkvp(struct ep11_lib *ep11, u8 *mkvp,
|
||||
target_t *target, int *card, int *domain,
|
||||
bool verbose);
|
||||
|
||||
int reencipher_ep11_key(struct ep11_lib *ep11, target_t target, int card,
|
||||
int domain, u8 *secure_key,
|
||||
unsigned int secure_key_size, bool verbose);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user