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;
|
||||
if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
|
||||
return 1;
|
||||
if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
73
zkey/pkey.c
73
zkey/pkey.c
@@ -691,6 +691,10 @@ static int build_apqn_list_for_key_type(int pkey_fd, enum pkey_key_type type,
|
||||
apqn_entries,
|
||||
verbose);
|
||||
return rc;
|
||||
case -EINVAL:
|
||||
/* This is usually due to an unsupported key type */
|
||||
rc = -ENOTSUP;
|
||||
goto out;
|
||||
default:
|
||||
goto out;
|
||||
}
|
||||
@@ -799,6 +803,10 @@ static int build_apqn_list_for_key(int pkey_fd, u8 *key, u32 keylen, u32 flags,
|
||||
apqn_entries,
|
||||
verbose);
|
||||
return rc;
|
||||
case -EINVAL:
|
||||
/* This is usually due to an unsupported key type */
|
||||
rc = -ENOTSUP;
|
||||
goto out;
|
||||
default:
|
||||
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;
|
||||
if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
|
||||
return PKEY_TYPE_CCA_CIPHER;
|
||||
if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0)
|
||||
return PKEY_TYPE_EP11;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -868,6 +878,8 @@ static size_t key_size_for_type(enum pkey_key_type type)
|
||||
return AESDATA_KEY_SIZE;
|
||||
case PKEY_TYPE_CCA_CIPHER:
|
||||
return AESCIPHER_KEY_SIZE;
|
||||
case PKEY_TYPE_EP11:
|
||||
return EP11_KEY_SIZE;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -1227,6 +1239,7 @@ int validate_secure_key(int pkey_fd,
|
||||
struct pkey_apqn *list = NULL;
|
||||
u32 i, list_entries = 0;
|
||||
bool xts, valid;
|
||||
u32 flags;
|
||||
int rc;
|
||||
|
||||
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);
|
||||
|
||||
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,
|
||||
HALF_KEYSIZE_FOR_XTS(secure_key_size, xts),
|
||||
PKEY_FLAGS_MATCH_CUR_MKVP |
|
||||
PKEY_FLAGS_MATCH_ALT_MKVP,
|
||||
apqns, &list, &list_entries, verbose);
|
||||
flags, apqns, &list, &list_entries,
|
||||
verbose);
|
||||
if (rc != 0) {
|
||||
pr_verbose(verbose, "Failed to build a list of APQNs that can "
|
||||
"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 aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key;
|
||||
struct ep11keytoken *ep11key = (struct ep11keytoken *)key;
|
||||
|
||||
util_assert(key != NULL, "Internal error: secure_key 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));
|
||||
else if (is_cca_aes_cipher_key(key, key_size))
|
||||
memcpy(mkvp, &cipherkey->kvp, sizeof(cipherkey->kvp));
|
||||
else if (is_ep11_aes_key(key, key_size))
|
||||
memcpy(mkvp, &ep11key->wkvp, sizeof(ep11key->wkvp));
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1539,6 +1559,34 @@ bool is_cca_aes_cipher_key(const u8 *key, size_t key_size)
|
||||
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
|
||||
*
|
||||
@@ -1559,6 +1607,11 @@ bool is_xts_key(const u8 *key, size_t key_size)
|
||||
is_cca_aes_cipher_key(key + AESCIPHER_KEY_SIZE,
|
||||
key_size - AESCIPHER_KEY_SIZE))
|
||||
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;
|
||||
@@ -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 aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key;
|
||||
struct ep11keytoken *ep11key = (struct ep11keytoken *)key;
|
||||
|
||||
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 */
|
||||
*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 {
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1621,7 +1681,8 @@ const char *get_key_type(const u8 *key, size_t key_size)
|
||||
return KEY_TYPE_CCA_AESDATA;
|
||||
if (is_cca_aes_cipher_key(key, key_size))
|
||||
return KEY_TYPE_CCA_AESCIPHER;
|
||||
|
||||
if (is_ep11_aes_key(key, key_size))
|
||||
return KEY_TYPE_EP11_AES;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1641,6 +1702,8 @@ int get_min_card_level_for_keytype(const char *key_type)
|
||||
return 3;
|
||||
if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
|
||||
return 6;
|
||||
if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0)
|
||||
return 7;
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -1661,6 +1724,8 @@ enum card_type get_card_type_for_keytype(const char *key_type)
|
||||
return CARD_TYPE_CCA;
|
||||
if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
|
||||
return CARD_TYPE_CCA;
|
||||
if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0)
|
||||
return CARD_TYPE_EP11;
|
||||
|
||||
return CARD_TYPE_ANY;
|
||||
}
|
||||
|
||||
46
zkey/pkey.h
46
zkey/pkey.h
@@ -28,11 +28,17 @@ struct tokenheader {
|
||||
u8 res1[3];
|
||||
} __packed;
|
||||
|
||||
#define TOKEN_TYPE_NON_CCA 0x00
|
||||
#define TOKEN_TYPE_CCA_INTERNAL 0x01
|
||||
#define TOKEN_TYPE_NON_CCA 0x00
|
||||
#define TOKEN_TYPE_CCA_INTERNAL 0x01
|
||||
|
||||
#define TOKEN_VERSION_AESDATA 0x04
|
||||
#define TOKEN_VERSION_AESCIPHER 0x05
|
||||
/* CCA-Internal token versions */
|
||||
#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 {
|
||||
u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */
|
||||
@@ -83,11 +89,36 @@ struct aescipherkeytoken {
|
||||
u8 varpart[80]; /* variable part */
|
||||
} __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 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 MIN_SECURE_KEY_SIZE MIN(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE)
|
||||
#define MAX_SECURE_KEY_SIZE MAX(EP11_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 {
|
||||
u8 seckey[AESDATA_KEY_SIZE]; /* the secure key blob */
|
||||
@@ -139,6 +170,7 @@ struct pkey_verifykey {
|
||||
enum pkey_key_type {
|
||||
PKEY_TYPE_CCA_DATA = (u32) 1,
|
||||
PKEY_TYPE_CCA_CIPHER = (u32) 2,
|
||||
PKEY_TYPE_EP11 = (u32) 3,
|
||||
};
|
||||
|
||||
enum pkey_key_size {
|
||||
@@ -229,6 +261,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 PAES_BLOCK_SIZE 16
|
||||
#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_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);
|
||||
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);
|
||||
|
||||
12
zkey/zkey.c
12
zkey/zkey.c
@@ -227,9 +227,9 @@ static struct util_opt opt_vec[] = {
|
||||
.option = { "key-type", required_argument, NULL, 'K'},
|
||||
.argument = "type",
|
||||
.desc = "The type of the key. Possible values are '"
|
||||
KEY_TYPE_CCA_AESDATA"' and '"KEY_TYPE_CCA_AESCIPHER"'. "
|
||||
"When this option is omitted, the default is '"
|
||||
KEY_TYPE_CCA_AESDATA"'",
|
||||
KEY_TYPE_CCA_AESDATA"', '"KEY_TYPE_CCA_AESCIPHER"' "
|
||||
"and '"KEY_TYPE_EP11_AES"'. When this option is "
|
||||
"omitted, the default is '"KEY_TYPE_CCA_AESDATA"'",
|
||||
.command = COMMAND_GENERATE,
|
||||
},
|
||||
/***********************************************************/
|
||||
@@ -452,9 +452,9 @@ static struct util_opt opt_vec[] = {
|
||||
.option = { "key-type", required_argument, NULL, 'K'},
|
||||
.argument = "type",
|
||||
.desc = "The type of the key. Possible values are '"
|
||||
KEY_TYPE_CCA_AESDATA"' and '"KEY_TYPE_CCA_AESCIPHER"'. "
|
||||
"Use this option to list all keys with the specified "
|
||||
"key type.",
|
||||
KEY_TYPE_CCA_AESDATA"', '"KEY_TYPE_CCA_AESCIPHER"' "
|
||||
"and '"KEY_TYPE_EP11_AES"'. Use this option to list "
|
||||
"all keys with the specified key type.",
|
||||
.command = COMMAND_LIST,
|
||||
},
|
||||
/***********************************************************/
|
||||
|
||||
Reference in New Issue
Block a user