forked from pool/s390-tools
* s390-tools-01-zkey-Add-support-for-retrieving-a-list-of-ultravisor-secrets.patch * s390-tools-02-zkey-Add-the--pvsecrets-list-command.patch * s390-tools-03-zkey-Add-PVSECRETS-AES-key-type.patch * s390-tools-04-zkey-Add-the-pvsecrets-import-command.patch * s390-tools-05-zkey-Reject-key-generation-and-APQN-association-for-PVSECRET-AES-keys.patch * s390-tools-06-zkey-Reject-re-enciphering-of-PVSECRET-AES-keys.patch * s390-tools-07-zkey-Support-validation-of-key-of-type-PVSECRET-AES.patch - Revendored vendor.tar.gz OBS-URL: https://build.opensuse.org/package/show/Base:System/s390-tools?expand=0&rev=245
341 lines
10 KiB
Diff
341 lines
10 KiB
Diff
From fdf66dc148c09f1d3300cd3378e3f75a83c6214e Mon Sep 17 00:00:00 2001
|
|
From: Ingo Franzki <ifranzki@linux.ibm.com>
|
|
Date: Thu, 15 Feb 2024 16:56:04 +0100
|
|
Subject: [PATCH] zkey: Add PVSECRETS-AES key type
|
|
|
|
Add the definitions and utility functions for the PVSECRETS-AES key type.
|
|
A PVSECRETS-AES key token contains the secret id of a protected
|
|
virtualization secret. It does not contain the key material, just a
|
|
reference to the key in the ultravisor.
|
|
|
|
When such a key token is used to perform crypto operations later on, the
|
|
PAES kernel cipher will obtain the protected key belonging to this secret
|
|
id with the help of the pkey kernel module.
|
|
|
|
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
|
|
Reviewed-by: Jorg Schmidbauer <jschmidb@de.ibm.com>
|
|
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
|
|
---
|
|
zkey/keystore.c | 4 +-
|
|
zkey/pkey.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++-
|
|
zkey/pkey.h | 38 ++++++++++++----
|
|
zkey/pvsecrets.h | 4 +-
|
|
4 files changed, 143 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/zkey/keystore.c b/zkey/keystore.c
|
|
index 9589d82d..771bc08d 100644
|
|
--- a/zkey/keystore.c
|
|
+++ b/zkey/keystore.c
|
|
@@ -3,7 +3,7 @@
|
|
*
|
|
* Keystore handling functions
|
|
*
|
|
- * Copyright IBM Corp. 2018, 2020
|
|
+ * Copyright IBM Corp. 2018, 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.
|
|
@@ -360,6 +360,8 @@ static int _keystore_valid_key_type(const char *key_type)
|
|
return 1;
|
|
if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0)
|
|
return 1;
|
|
+ if (strcasecmp(key_type, KEY_TYPE_PVSECRET_AES) == 0)
|
|
+ return 1;
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/zkey/pkey.c b/zkey/pkey.c
|
|
index 821978bd..53c0a550 100644
|
|
--- a/zkey/pkey.c
|
|
+++ b/zkey/pkey.c
|
|
@@ -1,7 +1,7 @@
|
|
/*
|
|
* zkey - Generate, re-encipher, and validate secure keys
|
|
*
|
|
- * Copyright IBM Corp. 2018
|
|
+ * Copyright IBM Corp. 2018, 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.
|
|
@@ -26,6 +26,7 @@
|
|
#include "lib/util_panic.h"
|
|
|
|
#include "pkey.h"
|
|
+#include "pvsecrets.h"
|
|
#include "utils.h"
|
|
|
|
#ifndef AF_ALG
|
|
@@ -1719,6 +1720,38 @@ bool is_ep11_key_session_bound(const u8 *key, size_t key_size)
|
|
}
|
|
}
|
|
|
|
+/**
|
|
+ * Check if the specified key is a PVSECRET-AES key token.
|
|
+ *
|
|
+ * @param[in] key the secure key token
|
|
+ * @param[in] key_size the size of the secure key
|
|
+ *
|
|
+ * @returns true if the key is a PVSECRET token type
|
|
+ */
|
|
+bool is_pvsecret_aes_key(const u8 *key, size_t key_size)
|
|
+{
|
|
+ struct pvsecrettoken *pvsecret = (struct pvsecrettoken *)key;
|
|
+
|
|
+ if (key == NULL || key_size < PVSECRET_KEY_SIZE)
|
|
+ return false;
|
|
+
|
|
+ if (pvsecret->hdr.type != TOKEN_TYPE_NON_CCA)
|
|
+ return false;
|
|
+ if (pvsecret->hdr.version != TOKEN_VERSION_PVSECRET)
|
|
+ return false;
|
|
+
|
|
+ switch (pvsecret->secret_type) {
|
|
+ case UV_SECRET_TYPE_AES_128:
|
|
+ case UV_SECRET_TYPE_AES_192:
|
|
+ case UV_SECRET_TYPE_AES_256:
|
|
+ case UV_SECRET_TYPE_AES_XTS_128:
|
|
+ case UV_SECRET_TYPE_AES_XTS_256:
|
|
+ return true;
|
|
+ default:
|
|
+ return false;
|
|
+ }
|
|
+}
|
|
+
|
|
/**
|
|
* Check if the specified key is an XTS type key
|
|
*
|
|
@@ -1729,6 +1762,8 @@ bool is_ep11_key_session_bound(const u8 *key, size_t key_size)
|
|
*/
|
|
bool is_xts_key(const u8 *key, size_t key_size)
|
|
{
|
|
+ struct pvsecrettoken *pvsecret = (struct pvsecrettoken *)key;
|
|
+
|
|
if (is_cca_aes_data_key(key, key_size)) {
|
|
if (key_size == 2 * AESDATA_KEY_SIZE &&
|
|
is_cca_aes_data_key(key + AESDATA_KEY_SIZE,
|
|
@@ -1749,11 +1784,41 @@ bool is_xts_key(const u8 *key, size_t key_size)
|
|
is_ep11_aes_key_with_header(key + EP11_AES_KEY_SIZE,
|
|
key_size - EP11_AES_KEY_SIZE))
|
|
return true;
|
|
+ } else if (is_pvsecret_aes_key(key, key_size)) {
|
|
+ switch (pvsecret->secret_type) {
|
|
+ case UV_SECRET_TYPE_AES_XTS_128:
|
|
+ case UV_SECRET_TYPE_AES_XTS_256:
|
|
+ return true;
|
|
+ default:
|
|
+ return false;
|
|
+ }
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
+/**
|
|
+ * Check if the specified key is a secure key type (i.e. requires a crypto card)
|
|
+ *
|
|
+ * @param[in] key the secure key token
|
|
+ * @param[in] key_size the size of the secure key
|
|
+ *
|
|
+ * @returns true if the key is a secure key type
|
|
+ */
|
|
+bool is_secure_key(const u8 *key, size_t key_size)
|
|
+{
|
|
+ if (is_cca_aes_data_key(key, key_size))
|
|
+ return true;
|
|
+ if (is_cca_aes_cipher_key(key, key_size))
|
|
+ return true;
|
|
+ if (is_ep11_aes_key(key, key_size))
|
|
+ return true;
|
|
+ if (is_ep11_aes_key_with_header(key, key_size))
|
|
+ return true;
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
/**
|
|
* Gets the size in bits of the effective key of the specified secure key
|
|
*
|
|
@@ -1771,6 +1836,7 @@ int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize)
|
|
struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key;
|
|
struct ep11keytoken *ep11key = (struct ep11keytoken *)key;
|
|
struct ep11kblob_header *hdr = (struct ep11kblob_header *)key;
|
|
+ struct pvsecrettoken *pvsecret = (struct pvsecrettoken *)key;
|
|
|
|
util_assert(bitsize != NULL, "Internal error: bitsize is NULL");
|
|
|
|
@@ -1805,6 +1871,26 @@ int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize)
|
|
(key + EP11_AES_KEY_SIZE);
|
|
*bitsize += hdr->bitlen;
|
|
}
|
|
+ } else if (is_pvsecret_aes_key(key, key_size)) {
|
|
+ switch (pvsecret->secret_type) {
|
|
+ case UV_SECRET_TYPE_AES_128:
|
|
+ *bitsize = 128;
|
|
+ break;
|
|
+ case UV_SECRET_TYPE_AES_192:
|
|
+ *bitsize = 192;
|
|
+ break;
|
|
+ case UV_SECRET_TYPE_AES_256:
|
|
+ *bitsize = 256;
|
|
+ break;
|
|
+ case UV_SECRET_TYPE_AES_XTS_128:
|
|
+ *bitsize = 128 * 2;
|
|
+ break;
|
|
+ case UV_SECRET_TYPE_AES_XTS_256:
|
|
+ *bitsize = 256 * 2;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
} else {
|
|
return -EINVAL;
|
|
}
|
|
@@ -1830,9 +1916,31 @@ const char *get_key_type(const u8 *key, size_t key_size)
|
|
return KEY_TYPE_EP11_AES;
|
|
if (is_ep11_aes_key_with_header(key, key_size))
|
|
return KEY_TYPE_EP11_AES;
|
|
+ if (is_pvsecret_aes_key(key, key_size))
|
|
+ return KEY_TYPE_PVSECRET_AES;
|
|
+
|
|
return NULL;
|
|
}
|
|
|
|
+/**
|
|
+ * Returns true if the key type is a secure key type
|
|
+ *
|
|
+ * @param[in] key_type the type of the key
|
|
+ *
|
|
+ * @returns true if the key type is a secure key type, false otherwise
|
|
+ */
|
|
+bool is_secure_key_type(const char *key_type)
|
|
+{
|
|
+ if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
|
|
+ return true;
|
|
+ if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) == 0)
|
|
+ return true;
|
|
+ if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0)
|
|
+ return true;
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
/**
|
|
* Returns the minimum card level for a specific key type
|
|
*
|
|
diff --git a/zkey/pkey.h b/zkey/pkey.h
|
|
index 3b57c5f0..ce3bd8bd 100644
|
|
--- a/zkey/pkey.h
|
|
+++ b/zkey/pkey.h
|
|
@@ -4,7 +4,7 @@
|
|
* This header file defines the interface to the pkey kernel module.
|
|
* It defines a set of IOCTL commands with its associated structures.
|
|
*
|
|
- * Copyright IBM Corp. 2017, 2018
|
|
+ * 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.
|
|
@@ -41,6 +41,8 @@ struct tokenheader {
|
|
#define TOKEN_VERSION_EP11_AES 0x03
|
|
#define TOKEN_VERSION_EP11_AES_WITH_HEADER 0x06
|
|
#define TOKEN_VERSION_EP11_ECC_WITH_HEADER 0x07
|
|
+/* 0x08 is reserved for internal use */
|
|
+#define TOKEN_VERSION_PVSECRET 0x09
|
|
|
|
struct aesdatakeytoken {
|
|
u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */
|
|
@@ -116,6 +118,15 @@ struct ep11keytoken {
|
|
u8 padding[64];
|
|
} __packed;
|
|
|
|
+#define UV_SECRET_ID_LEN 32
|
|
+
|
|
+struct pvsecrettoken {
|
|
+ struct tokenheader hdr;
|
|
+ u16 secret_type; /* the secret type as the UV told us */
|
|
+ u16 secret_len; /* length in bytes of the secret */
|
|
+ u8 secretid[UV_SECRET_ID_LEN]; /* the secret id for this secret */
|
|
+} __packed;
|
|
+
|
|
#define ZERO_SESSION \
|
|
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
|
|
|
@@ -124,21 +135,26 @@ struct ep11keytoken {
|
|
#define EP11_KEY_SIZE sizeof(struct ep11keytoken)
|
|
#define EP11_AES_KEY_SIZE (sizeof(struct ep11kblob_header) + \
|
|
sizeof(struct ep11keytoken))
|
|
+#define PVSECRET_KEY_SIZE sizeof(struct pvsecrettoken)
|
|
|
|
/* MAX/MIN from zt_common.h produces warnings for variable length arrays */
|
|
#define _MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
#define _MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
|
|
#define MAX_SECURE_KEY_SIZE _MAX( \
|
|
- _MAX(EP11_KEY_SIZE, \
|
|
- EP11_AES_KEY_SIZE), \
|
|
- _MAX(AESDATA_KEY_SIZE, \
|
|
- AESCIPHER_KEY_SIZE))
|
|
+ _MAX( \
|
|
+ _MAX(EP11_KEY_SIZE, \
|
|
+ EP11_AES_KEY_SIZE), \
|
|
+ _MAX(AESDATA_KEY_SIZE, \
|
|
+ AESCIPHER_KEY_SIZE)), \
|
|
+ PVSECRET_KEY_SIZE)
|
|
#define MIN_SECURE_KEY_SIZE _MIN( \
|
|
- _MIN(EP11_KEY_SIZE, \
|
|
- EP11_AES_KEY_SIZE), \
|
|
- _MIN(AESDATA_KEY_SIZE, \
|
|
- AESCIPHER_KEY_SIZE))
|
|
+ _MIN( \
|
|
+ _MIN(EP11_KEY_SIZE, \
|
|
+ EP11_AES_KEY_SIZE), \
|
|
+ _MIN(AESDATA_KEY_SIZE, \
|
|
+ AESCIPHER_KEY_SIZE)), \
|
|
+ PVSECRET_KEY_SIZE)
|
|
|
|
struct pkey_seckey {
|
|
u8 seckey[AESDATA_KEY_SIZE]; /* the secure key blob */
|
|
@@ -285,6 +301,7 @@ struct pkey_apqns4keytype {
|
|
#define KEY_TYPE_CCA_AESDATA "CCA-AESDATA"
|
|
#define KEY_TYPE_CCA_AESCIPHER "CCA-AESCIPHER"
|
|
#define KEY_TYPE_EP11_AES "EP11-AES"
|
|
+#define KEY_TYPE_PVSECRET_AES "PVSECRET-AES"
|
|
|
|
#define DEFAULT_KEYBITS 256
|
|
#define PAES_BLOCK_SIZE 16
|
|
@@ -342,9 +359,12 @@ bool is_cca_aes_cipher_key(const u8 *key, size_t key_size);
|
|
bool is_ep11_aes_key(const u8 *key, size_t key_size);
|
|
bool is_ep11_aes_key_with_header(const u8 *key, size_t key_size);
|
|
bool is_ep11_key_session_bound(const u8 *key, size_t key_size);
|
|
+bool is_pvsecret_aes_key(const u8 *key, size_t key_size);
|
|
bool is_xts_key(const u8 *key, size_t key_size);
|
|
+bool is_secure_key(const u8 *key, size_t key_size);
|
|
int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize);
|
|
const char *get_key_type(const u8 *key, size_t key_size);
|
|
+bool is_secure_key_type(const char *key_type);
|
|
int get_min_card_level_for_keytype(const char *key_type);
|
|
const struct fw_version *get_min_fw_version_for_keytype(const char *key_type);
|
|
enum card_type get_card_type_for_keytype(const char *key_type);
|
|
diff --git a/zkey/pvsecrets.h b/zkey/pvsecrets.h
|
|
index 6acebfdd..ad844035 100644
|
|
--- a/zkey/pvsecrets.h
|
|
+++ b/zkey/pvsecrets.h
|
|
@@ -15,6 +15,8 @@
|
|
|
|
#include "lib/zt_common.h"
|
|
|
|
+#include "pkey.h"
|
|
+
|
|
/*
|
|
* Definitions for the /dev/uv kernel module interface
|
|
*/
|
|
@@ -60,8 +62,6 @@ struct uvio_ioctl_cb {
|
|
#define UV_SECRET_TYPE_EDDSA_ED25519 0x14
|
|
#define UV_SECRET_TYPE_EDDSA_ED448 0x15
|
|
|
|
-#define UV_SECRET_ID_LEN 32
|
|
-
|
|
#define UVIO_LIST_SECRETS_MAX_LEN 0x8000
|
|
|
|
struct uvio_list_secret_entry {
|