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:
Ingo Franzki
2019-11-12 10:48:32 +01:00
committed by Jan Höppner
parent b48aa5f435
commit a7e47685e0
4 changed files with 117 additions and 16 deletions

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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,
},
/***********************************************************/