mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zkey: Add a new key type for EP11 secure keys
Add key type EP11-AES to support EP11 secure keys. 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
b48aa5f435
commit
a7e47685e0
@@ -343,6 +343,8 @@ static int _keystore_valid_key_type(const char *key_type)
|
|||||||
return 1;
|
return 1;
|
||||||
if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
|
if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+69
-4
@@ -691,6 +691,10 @@ static int build_apqn_list_for_key_type(int pkey_fd, enum pkey_key_type type,
|
|||||||
apqn_entries,
|
apqn_entries,
|
||||||
verbose);
|
verbose);
|
||||||
return rc;
|
return rc;
|
||||||
|
case -EINVAL:
|
||||||
|
/* This is usually due to an unsupported key type */
|
||||||
|
rc = -ENOTSUP;
|
||||||
|
goto out;
|
||||||
default:
|
default:
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -799,6 +803,10 @@ static int build_apqn_list_for_key(int pkey_fd, u8 *key, u32 keylen, u32 flags,
|
|||||||
apqn_entries,
|
apqn_entries,
|
||||||
verbose);
|
verbose);
|
||||||
return rc;
|
return rc;
|
||||||
|
case -EINVAL:
|
||||||
|
/* This is usually due to an unsupported key type */
|
||||||
|
rc = -ENOTSUP;
|
||||||
|
goto out;
|
||||||
default:
|
default:
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -850,6 +858,8 @@ static enum pkey_key_type key_type_to_pkey_type(const char *key_type)
|
|||||||
return PKEY_TYPE_CCA_DATA;
|
return PKEY_TYPE_CCA_DATA;
|
||||||
if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
|
if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
|
||||||
return PKEY_TYPE_CCA_CIPHER;
|
return PKEY_TYPE_CCA_CIPHER;
|
||||||
|
if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0)
|
||||||
|
return PKEY_TYPE_EP11;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -868,6 +878,8 @@ static size_t key_size_for_type(enum pkey_key_type type)
|
|||||||
return AESDATA_KEY_SIZE;
|
return AESDATA_KEY_SIZE;
|
||||||
case PKEY_TYPE_CCA_CIPHER:
|
case PKEY_TYPE_CCA_CIPHER:
|
||||||
return AESCIPHER_KEY_SIZE;
|
return AESCIPHER_KEY_SIZE;
|
||||||
|
case PKEY_TYPE_EP11:
|
||||||
|
return EP11_KEY_SIZE;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1227,6 +1239,7 @@ int validate_secure_key(int pkey_fd,
|
|||||||
struct pkey_apqn *list = NULL;
|
struct pkey_apqn *list = NULL;
|
||||||
u32 i, list_entries = 0;
|
u32 i, list_entries = 0;
|
||||||
bool xts, valid;
|
bool xts, valid;
|
||||||
|
u32 flags;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
|
util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
|
||||||
@@ -1234,11 +1247,15 @@ int validate_secure_key(int pkey_fd,
|
|||||||
|
|
||||||
xts = is_xts_key(secure_key, secure_key_size);
|
xts = is_xts_key(secure_key, secure_key_size);
|
||||||
|
|
||||||
|
flags = PKEY_FLAGS_MATCH_CUR_MKVP;
|
||||||
|
if (is_cca_aes_data_key(secure_key, secure_key_size) ||
|
||||||
|
is_cca_aes_cipher_key(secure_key, secure_key_size))
|
||||||
|
flags |= PKEY_FLAGS_MATCH_ALT_MKVP;
|
||||||
|
|
||||||
rc = build_apqn_list_for_key(pkey_fd, secure_key,
|
rc = build_apqn_list_for_key(pkey_fd, secure_key,
|
||||||
HALF_KEYSIZE_FOR_XTS(secure_key_size, xts),
|
HALF_KEYSIZE_FOR_XTS(secure_key_size, xts),
|
||||||
PKEY_FLAGS_MATCH_CUR_MKVP |
|
flags, apqns, &list, &list_entries,
|
||||||
PKEY_FLAGS_MATCH_ALT_MKVP,
|
verbose);
|
||||||
apqns, &list, &list_entries, verbose);
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
pr_verbose(verbose, "Failed to build a list of APQNs that can "
|
pr_verbose(verbose, "Failed to build a list of APQNs that can "
|
||||||
"validate this secure key: %s", strerror(-rc));
|
"validate this secure key: %s", strerror(-rc));
|
||||||
@@ -1451,6 +1468,7 @@ int get_master_key_verification_pattern(const u8 *key, size_t key_size,
|
|||||||
{
|
{
|
||||||
struct aesdatakeytoken *datakey = (struct aesdatakeytoken *)key;
|
struct aesdatakeytoken *datakey = (struct aesdatakeytoken *)key;
|
||||||
struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key;
|
struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key;
|
||||||
|
struct ep11keytoken *ep11key = (struct ep11keytoken *)key;
|
||||||
|
|
||||||
util_assert(key != NULL, "Internal error: secure_key is NULL");
|
util_assert(key != NULL, "Internal error: secure_key is NULL");
|
||||||
util_assert(mkvp != NULL, "Internal error: mkvp is NULL");
|
util_assert(mkvp != NULL, "Internal error: mkvp is NULL");
|
||||||
@@ -1460,6 +1478,8 @@ int get_master_key_verification_pattern(const u8 *key, size_t key_size,
|
|||||||
memcpy(mkvp, &datakey->mkvp, sizeof(datakey->mkvp));
|
memcpy(mkvp, &datakey->mkvp, sizeof(datakey->mkvp));
|
||||||
else if (is_cca_aes_cipher_key(key, key_size))
|
else if (is_cca_aes_cipher_key(key, key_size))
|
||||||
memcpy(mkvp, &cipherkey->kvp, sizeof(cipherkey->kvp));
|
memcpy(mkvp, &cipherkey->kvp, sizeof(cipherkey->kvp));
|
||||||
|
else if (is_ep11_aes_key(key, key_size))
|
||||||
|
memcpy(mkvp, &ep11key->wkvp, sizeof(ep11key->wkvp));
|
||||||
else
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -1539,6 +1559,34 @@ bool is_cca_aes_cipher_key(const u8 *key, size_t key_size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the specified key is a EP11 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 an EP11 AES token type
|
||||||
|
*/
|
||||||
|
bool is_ep11_aes_key(const u8 *key, size_t key_size)
|
||||||
|
{
|
||||||
|
struct ep11keytoken *ep11key = (struct ep11keytoken *)key;
|
||||||
|
|
||||||
|
if (key == NULL || key_size < EP11_KEY_SIZE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ep11key->head.type != TOKEN_TYPE_NON_CCA)
|
||||||
|
return false;
|
||||||
|
if (ep11key->head.version != TOKEN_VERSION_EP11_AES)
|
||||||
|
return false;
|
||||||
|
if (ep11key->head.length > key_size)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ep11key->version != 0x1234)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the specified key is an XTS type key
|
* Check if the specified key is an XTS type key
|
||||||
*
|
*
|
||||||
@@ -1559,6 +1607,11 @@ bool is_xts_key(const u8 *key, size_t key_size)
|
|||||||
is_cca_aes_cipher_key(key + AESCIPHER_KEY_SIZE,
|
is_cca_aes_cipher_key(key + AESCIPHER_KEY_SIZE,
|
||||||
key_size - AESCIPHER_KEY_SIZE))
|
key_size - AESCIPHER_KEY_SIZE))
|
||||||
return true;
|
return true;
|
||||||
|
} else if (is_ep11_aes_key(key, key_size)) {
|
||||||
|
if (key_size == 2 * EP11_KEY_SIZE &&
|
||||||
|
is_ep11_aes_key(key + EP11_KEY_SIZE,
|
||||||
|
key_size - EP11_KEY_SIZE))
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -1579,6 +1632,7 @@ int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize)
|
|||||||
{
|
{
|
||||||
struct aesdatakeytoken *datakey = (struct aesdatakeytoken *)key;
|
struct aesdatakeytoken *datakey = (struct aesdatakeytoken *)key;
|
||||||
struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key;
|
struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key;
|
||||||
|
struct ep11keytoken *ep11key = (struct ep11keytoken *)key;
|
||||||
|
|
||||||
util_assert(bitsize != NULL, "Internal error: bitsize is NULL");
|
util_assert(bitsize != NULL, "Internal error: bitsize is NULL");
|
||||||
|
|
||||||
@@ -1600,6 +1654,12 @@ int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize)
|
|||||||
if (cipherkey->pfv == 0x00) /* V0 payload */
|
if (cipherkey->pfv == 0x00) /* V0 payload */
|
||||||
*bitsize += cipherkey->pl - 384;
|
*bitsize += cipherkey->pl - 384;
|
||||||
}
|
}
|
||||||
|
} else if (is_ep11_aes_key(key, key_size)) {
|
||||||
|
*bitsize = ep11key->head.keybitlen;
|
||||||
|
if (key_size == 2 * AESDATA_KEY_SIZE) {
|
||||||
|
ep11key = (struct ep11keytoken *)(key + EP11_KEY_SIZE);
|
||||||
|
*bitsize += ep11key->head.keybitlen;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -1621,7 +1681,8 @@ const char *get_key_type(const u8 *key, size_t key_size)
|
|||||||
return KEY_TYPE_CCA_AESDATA;
|
return KEY_TYPE_CCA_AESDATA;
|
||||||
if (is_cca_aes_cipher_key(key, key_size))
|
if (is_cca_aes_cipher_key(key, key_size))
|
||||||
return KEY_TYPE_CCA_AESCIPHER;
|
return KEY_TYPE_CCA_AESCIPHER;
|
||||||
|
if (is_ep11_aes_key(key, key_size))
|
||||||
|
return KEY_TYPE_EP11_AES;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1641,6 +1702,8 @@ int get_min_card_level_for_keytype(const char *key_type)
|
|||||||
return 3;
|
return 3;
|
||||||
if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
|
if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
|
||||||
return 6;
|
return 6;
|
||||||
|
if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0)
|
||||||
|
return 7;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1661,6 +1724,8 @@ enum card_type get_card_type_for_keytype(const char *key_type)
|
|||||||
return CARD_TYPE_CCA;
|
return CARD_TYPE_CCA;
|
||||||
if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
|
if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
|
||||||
return CARD_TYPE_CCA;
|
return CARD_TYPE_CCA;
|
||||||
|
if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0)
|
||||||
|
return CARD_TYPE_EP11;
|
||||||
|
|
||||||
return CARD_TYPE_ANY;
|
return CARD_TYPE_ANY;
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-6
@@ -28,11 +28,17 @@ struct tokenheader {
|
|||||||
u8 res1[3];
|
u8 res1[3];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define TOKEN_TYPE_NON_CCA 0x00
|
#define TOKEN_TYPE_NON_CCA 0x00
|
||||||
#define TOKEN_TYPE_CCA_INTERNAL 0x01
|
#define TOKEN_TYPE_CCA_INTERNAL 0x01
|
||||||
|
|
||||||
#define TOKEN_VERSION_AESDATA 0x04
|
/* CCA-Internal token versions */
|
||||||
#define TOKEN_VERSION_AESCIPHER 0x05
|
#define TOKEN_VERSION_AESDATA 0x04
|
||||||
|
#define TOKEN_VERSION_AESCIPHER 0x05
|
||||||
|
|
||||||
|
/* Non-CCA token versions */
|
||||||
|
#define TOKEN_VERSION_PROTECTED_KEY 0x01
|
||||||
|
#define TOKEN_VERSION_CLEAR_KEY 0x02
|
||||||
|
#define TOKEN_VERSION_EP11_AES 0x03
|
||||||
|
|
||||||
struct aesdatakeytoken {
|
struct aesdatakeytoken {
|
||||||
u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */
|
u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */
|
||||||
@@ -83,11 +89,36 @@ struct aescipherkeytoken {
|
|||||||
u8 varpart[80]; /* variable part */
|
u8 varpart[80]; /* variable part */
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
struct ep11keytoken {
|
||||||
|
union {
|
||||||
|
u8 session[32];
|
||||||
|
struct {
|
||||||
|
u8 type; /* TOKEN_TYPE_NON_CCA (0x00) */
|
||||||
|
u8 res0; /* unused */
|
||||||
|
u16 length; /* length of token */
|
||||||
|
u8 version; /* TOKEN_VERSION_EP11_AES (0x03) */
|
||||||
|
u8 res1; /* unused */
|
||||||
|
u16 keybitlen; /* clear key bit len, 0 for unknown */
|
||||||
|
} head;
|
||||||
|
};
|
||||||
|
u8 wkvp[16]; /* wrapping key verification pattern */
|
||||||
|
u64 attr; /* boolean key attributes */
|
||||||
|
u64 mode; /* mode bits */
|
||||||
|
u16 version; /* 0x1234, ep11 blob struct version */
|
||||||
|
u8 iv[14];
|
||||||
|
u8 encrypted_key_data[144];
|
||||||
|
u8 mac[32];
|
||||||
|
u8 padding[64];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
#define AESDATA_KEY_SIZE sizeof(struct aesdatakeytoken)
|
#define AESDATA_KEY_SIZE sizeof(struct aesdatakeytoken)
|
||||||
#define AESCIPHER_KEY_SIZE sizeof(struct aescipherkeytoken)
|
#define AESCIPHER_KEY_SIZE sizeof(struct aescipherkeytoken)
|
||||||
|
#define EP11_KEY_SIZE sizeof(struct ep11keytoken)
|
||||||
|
|
||||||
#define MAX_SECURE_KEY_SIZE MAX(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE)
|
#define MAX_SECURE_KEY_SIZE MAX(EP11_KEY_SIZE, \
|
||||||
#define MIN_SECURE_KEY_SIZE MIN(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE)
|
MAX(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE))
|
||||||
|
#define MIN_SECURE_KEY_SIZE MIN(EP11_KEY_SIZE, \
|
||||||
|
MIN(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE))
|
||||||
|
|
||||||
struct pkey_seckey {
|
struct pkey_seckey {
|
||||||
u8 seckey[AESDATA_KEY_SIZE]; /* the secure key blob */
|
u8 seckey[AESDATA_KEY_SIZE]; /* the secure key blob */
|
||||||
@@ -139,6 +170,7 @@ struct pkey_verifykey {
|
|||||||
enum pkey_key_type {
|
enum pkey_key_type {
|
||||||
PKEY_TYPE_CCA_DATA = (u32) 1,
|
PKEY_TYPE_CCA_DATA = (u32) 1,
|
||||||
PKEY_TYPE_CCA_CIPHER = (u32) 2,
|
PKEY_TYPE_CCA_CIPHER = (u32) 2,
|
||||||
|
PKEY_TYPE_EP11 = (u32) 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum pkey_key_size {
|
enum pkey_key_size {
|
||||||
@@ -229,6 +261,7 @@ struct pkey_apqns4keytype {
|
|||||||
|
|
||||||
#define KEY_TYPE_CCA_AESDATA "CCA-AESDATA"
|
#define KEY_TYPE_CCA_AESDATA "CCA-AESDATA"
|
||||||
#define KEY_TYPE_CCA_AESCIPHER "CCA-AESCIPHER"
|
#define KEY_TYPE_CCA_AESCIPHER "CCA-AESCIPHER"
|
||||||
|
#define KEY_TYPE_EP11_AES "EP11-AES"
|
||||||
|
|
||||||
#define PAES_BLOCK_SIZE 16
|
#define PAES_BLOCK_SIZE 16
|
||||||
#define ENC_ZERO_LEN (2 * PAES_BLOCK_SIZE)
|
#define ENC_ZERO_LEN (2 * PAES_BLOCK_SIZE)
|
||||||
@@ -282,6 +315,7 @@ int get_master_key_verification_pattern(const u8 *key, size_t key_size,
|
|||||||
|
|
||||||
bool is_cca_aes_data_key(const u8 *key, size_t key_size);
|
bool is_cca_aes_data_key(const u8 *key, size_t key_size);
|
||||||
bool is_cca_aes_cipher_key(const u8 *key, size_t key_size);
|
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_xts_key(const u8 *key, size_t key_size);
|
bool is_xts_key(const u8 *key, size_t key_size);
|
||||||
int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize);
|
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);
|
const char *get_key_type(const u8 *key, size_t key_size);
|
||||||
|
|||||||
+6
-6
@@ -227,9 +227,9 @@ static struct util_opt opt_vec[] = {
|
|||||||
.option = { "key-type", required_argument, NULL, 'K'},
|
.option = { "key-type", required_argument, NULL, 'K'},
|
||||||
.argument = "type",
|
.argument = "type",
|
||||||
.desc = "The type of the key. Possible values are '"
|
.desc = "The type of the key. Possible values are '"
|
||||||
KEY_TYPE_CCA_AESDATA"' and '"KEY_TYPE_CCA_AESCIPHER"'. "
|
KEY_TYPE_CCA_AESDATA"', '"KEY_TYPE_CCA_AESCIPHER"' "
|
||||||
"When this option is omitted, the default is '"
|
"and '"KEY_TYPE_EP11_AES"'. When this option is "
|
||||||
KEY_TYPE_CCA_AESDATA"'",
|
"omitted, the default is '"KEY_TYPE_CCA_AESDATA"'",
|
||||||
.command = COMMAND_GENERATE,
|
.command = COMMAND_GENERATE,
|
||||||
},
|
},
|
||||||
/***********************************************************/
|
/***********************************************************/
|
||||||
@@ -452,9 +452,9 @@ static struct util_opt opt_vec[] = {
|
|||||||
.option = { "key-type", required_argument, NULL, 'K'},
|
.option = { "key-type", required_argument, NULL, 'K'},
|
||||||
.argument = "type",
|
.argument = "type",
|
||||||
.desc = "The type of the key. Possible values are '"
|
.desc = "The type of the key. Possible values are '"
|
||||||
KEY_TYPE_CCA_AESDATA"' and '"KEY_TYPE_CCA_AESCIPHER"'. "
|
KEY_TYPE_CCA_AESDATA"', '"KEY_TYPE_CCA_AESCIPHER"' "
|
||||||
"Use this option to list all keys with the specified "
|
"and '"KEY_TYPE_EP11_AES"'. Use this option to list "
|
||||||
"key type.",
|
"all keys with the specified key type.",
|
||||||
.command = COMMAND_LIST,
|
.command = COMMAND_LIST,
|
||||||
},
|
},
|
||||||
/***********************************************************/
|
/***********************************************************/
|
||||||
|
|||||||
Reference in New Issue
Block a user