mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zkey: Support EP11 AES keys with prepended header to retain EP11 session
The pkey kernel module supports two key blob formats for EP11 AES keys. The first one (PKEY_TYPE_EP11) contains a 16 bytes header that overlays the first 32 bytes of the key blob which usually contain the ID of the EP11 session to which the key is bound. For zkey/dm-crypt that session ID used to be all zeros. The second blob format (PKEY_TYPE_EP11_AES) prepends the 16 bytes header to the blob, an thus does not overlay the blob. This format can be used for key blobs that are session-bound, i.e. have a non-zero session ID in the first 32 bytes. Change zkey to generate EP11 keys using the new format (i.e. pkey type PKEY_TYPE_EP11_AES), but existing key blobs using the old format can still be used. Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com> Reviewed-by: Joerg Schmidbauer <jschmidb@de.ibm.com> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
This commit is contained in:
committed by
Steffen Eiden
parent
f46f6d34d3
commit
1b044b8a40
@@ -5278,9 +5278,11 @@ static int _ep11_unwrap_key_rsa(struct plugin_handle *ph,
|
||||
m_UnwrapKey_t dll_m_UnwrapKey;
|
||||
const unsigned char *key_blob;
|
||||
struct ep11keytoken *ep11key;
|
||||
struct ep11kblob_header *hdr;
|
||||
CK_MECHANISM mech = { 0 };
|
||||
CK_BYTE csum[7] = { 0 };
|
||||
CK_BBOOL ck_true = true;
|
||||
int pkey_fd, rc;
|
||||
CK_RV rv;
|
||||
|
||||
CK_ATTRIBUTE template[] = {
|
||||
@@ -5306,7 +5308,8 @@ static int _ep11_unwrap_key_rsa(struct plugin_handle *ph,
|
||||
pr_verbose(&ph->pd, "Wrap hashing algorithm: %d",
|
||||
ph->profile->wrap_hashing_algo);
|
||||
|
||||
if (*unwrapped_key_len < sizeof(struct ep11keytoken)) {
|
||||
if (*unwrapped_key_len < sizeof(struct ep11kblob_header) +
|
||||
sizeof(struct ep11keytoken)) {
|
||||
_set_error(ph, "Key buffer is too small");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -5381,19 +5384,68 @@ static int _ep11_unwrap_key_rsa(struct plugin_handle *ph,
|
||||
256 * 256 * csum[csum_len - 3] +
|
||||
256 * 256 * 256 * csum[csum_len - 4];
|
||||
|
||||
/* Setup the EP11 token header */
|
||||
ep11key = (struct ep11keytoken *)unwrapped_key;
|
||||
memset(&ep11key->session, 0, sizeof(ep11key->session));
|
||||
ep11key->head.type = TOKEN_TYPE_NON_CCA;
|
||||
ep11key->head.length = *unwrapped_key_len;
|
||||
ep11key->head.version = TOKEN_VERSION_EP11_AES;
|
||||
ep11key->head.keybitlen = bit_len;
|
||||
/* Prepend and setup the EP11 token header */
|
||||
hdr = (struct ep11kblob_header *)unwrapped_key;
|
||||
ep11key = (struct ep11keytoken *)
|
||||
(unwrapped_key + sizeof(struct ep11kblob_header));
|
||||
memmove(ep11key, unwrapped_key, *unwrapped_key_len);
|
||||
*unwrapped_key_len += sizeof(struct ep11kblob_header);
|
||||
memset(hdr, 0, sizeof(struct ep11kblob_header));
|
||||
hdr->type = TOKEN_TYPE_NON_CCA;
|
||||
hdr->hver = 0;
|
||||
hdr->len = *unwrapped_key_len;
|
||||
hdr->version = TOKEN_VERSION_EP11_AES_WITH_HEADER;
|
||||
hdr->bitlen = bit_len;
|
||||
|
||||
pr_verbose(&ph->pd, "unwrapped bit length: %u",
|
||||
ep11key->head.keybitlen);
|
||||
pr_verbose(&ph->pd, "unwrapped bit length: %u", hdr->bitlen);
|
||||
|
||||
/* return full length, blob is already zero padded */
|
||||
*unwrapped_key_len = sizeof(struct ep11keytoken);
|
||||
*unwrapped_key_len =
|
||||
sizeof(struct ep11kblob_header) + sizeof(struct ep11keytoken);
|
||||
|
||||
/*
|
||||
* Check if the pkey module supports keys of type
|
||||
* TOKEN_VERSION_EP11_AES_WITH_HEADER, older kernels may not support
|
||||
* such keys. If it does not support such keys, convert the key to
|
||||
* TOKEN_VERSION_EP11_AES type, if its session field is all zero
|
||||
* (i.e. the key is not session bound).
|
||||
*/
|
||||
pkey_fd = open_pkey_device(ph->pd.verbose);
|
||||
if (pkey_fd < 0) {
|
||||
_set_error(ph, "Failed to open pkey device");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = validate_secure_key(pkey_fd, unwrapped_key, *unwrapped_key_len,
|
||||
NULL, NULL, NULL, ph->pd.verbose);
|
||||
close(pkey_fd);
|
||||
if (rc == -EINVAL || rc == -ENODEV) {
|
||||
pr_verbose(&ph->pd, "The pkey kernel module does not support "
|
||||
"PKEY_TYPE_EP11_AES, fall back to PKEY_TYPE_EP11");
|
||||
|
||||
if (is_ep11_key_session_bound(unwrapped_key,
|
||||
*unwrapped_key_len)) {
|
||||
_set_error(ph, "The unwrapped key is session bound. "
|
||||
"Kernel support is required for such keys");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
key_blob_len = hdr->len;
|
||||
*unwrapped_key_len -= sizeof(struct ep11kblob_header);
|
||||
memmove(unwrapped_key,
|
||||
unwrapped_key + sizeof(struct ep11kblob_header),
|
||||
*unwrapped_key_len);
|
||||
ep11key = (struct ep11keytoken *)unwrapped_key;
|
||||
memset(&ep11key->session, 0, sizeof(ep11key->session));
|
||||
ep11key->head.type = TOKEN_TYPE_NON_CCA;
|
||||
ep11key->head.len = key_blob_len -
|
||||
sizeof(struct ep11kblob_header);
|
||||
ep11key->head.version = TOKEN_VERSION_EP11_AES;
|
||||
ep11key->head.bitlen = bit_len;
|
||||
} else if (rc != 0) {
|
||||
_set_error(ph, "Failed to validate unwrapped key");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user