zkey: Add support for different crypto card types

As preparation for adding support for EP11 secure keys,
generalize the code to support different crypto card types.

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:31:19 +01:00
committed by Jan Höppner
parent e7f446432b
commit 82c86fa8bd
8 changed files with 182 additions and 70 deletions

View File

@@ -67,7 +67,7 @@ all: $(BUILD_TARGETS)
zkey.o: zkey.c pkey.h cca.h misc.h
pkey.o: pkey.c pkey.h
cca.o: cca.c cca.h pkey.h utils.h
utils.o: utils.h
utils.o: utils.h pkey.h
properties.o: check-dep-zkey properties.c properties.h
keystore.o: keystore.c keystore.h properties.h pkey.h cca.h utils.h
zkey-cryptsetup.o: check-dep-zkey-cryptsetup zkey-cryptsetup.c pkey.h cca.h misc.h

View File

@@ -718,7 +718,7 @@ int select_cca_adapter_by_mkvp(struct cca_lib *cca, u64 mkvp, const char *apqns,
info.domain = 0;
info.verbose = verbose;
rc = handle_apqns(apqns, find_mkvp, &info, verbose);
rc = handle_apqns(apqns, CARD_TYPE_CCA, find_mkvp, &info, verbose);
if (rc < 0)
return rc;

View File

@@ -1085,6 +1085,7 @@ free:
struct apqn_check {
bool noonlinecheck;
bool nomsg;
enum card_type cardtype;
};
/**
@@ -1136,11 +1137,11 @@ static int _keystore_apqn_check(const char *apqn, bool remove, bool UNUSED(set),
goto out;
}
rc = sysfs_is_apqn_online(card, domain);
rc = sysfs_is_apqn_online(card, domain, info->cardtype);
if (rc != 1) {
if (info->nomsg == 0)
warnx("The APQN %02x.%04x is %s", card, domain,
rc == -1 ? "not a CCA card" : "not online");
rc == -1 ? "not the correct type" : "not online");
rc = -EIO;
goto out;
} else {
@@ -1577,7 +1578,9 @@ static int _keystore_create_info_file(struct keystore *keystore,
struct volume_check vol_check = { .keystore = keystore, .name = name,
.set = 0 };
struct apqn_check apqn_check = { .noonlinecheck = noapqncheck,
.nomsg = 0 };
.nomsg = 0,
.cardtype = get_card_type_for_keytype(
key_type), };
struct properties *key_props;
char temp[10];
int rc;
@@ -1726,7 +1729,8 @@ int keystore_generate_key(struct keystore *keystore, const char *name,
goto out_free_key_filenames;
rc = cross_check_apqns(apqns, 0,
get_min_card_level_for_keytype(key_type), true,
get_min_card_level_for_keytype(key_type),
get_card_type_for_keytype(key_type), true,
keystore->verbose);
if (rc == -EINVAL)
goto out_free_key_filenames;
@@ -1859,7 +1863,8 @@ int keystore_import_key(struct keystore *keystore, const char *name,
}
rc = cross_check_apqns(apqns, mkvp,
get_min_card_level_for_keytype(key_type), true,
get_min_card_level_for_keytype(key_type),
get_card_type_for_keytype(key_type), true,
keystore->verbose);
if (rc == -EINVAL)
goto out_free_key;
@@ -2063,6 +2068,7 @@ int keystore_change_key(struct keystore *keystore, const char *name,
key_type = properties_get(key_props, PROP_NAME_KEY_TYPE);
rc = cross_check_apqns(apqns_prop, mkvp,
get_min_card_level_for_keytype(key_type),
get_card_type_for_keytype(key_type),
true, keystore->verbose);
free(apqns_prop);
free(key_type);
@@ -2440,7 +2446,8 @@ static int _keystore_display_apqn_status(struct keystore *keystore,
apqns = properties_get(properties, PROP_NAME_APQNS);
key_type = properties_get(properties, PROP_NAME_KEY_TYPE);
rc = cross_check_apqns(apqns, mkvp,
get_min_card_level_for_keytype(key_type), true,
get_min_card_level_for_keytype(key_type),
get_card_type_for_keytype(key_type), true,
keystore->verbose);
if (rc != 0 && rc != -ENOTSUP)
warning = 1;
@@ -4030,7 +4037,9 @@ int keystore_convert_key(struct keystore *keystore, const char *name,
if (apqns != NULL)
apqn_list = str_list_split(apqns);
rc = cross_check_apqns(apqns, 0, min_level, true, keystore->verbose);
rc = cross_check_apqns(apqns, 0, min_level,
get_card_type_for_keytype(key_type), true,
keystore->verbose);
if (rc == -EINVAL)
goto out;
if (rc != 0 && rc != -ENOTSUP && !noapqncheck) {

View File

@@ -1651,6 +1651,26 @@ int get_min_card_level_for_keytype(const char *key_type)
return -1;
}
/**
* Returns the card type required for a specific key type
*
* @param[in] key_type the type of the key
*
* @returns the card type, or CARD_TYPE_ANY for unknown key types
*/
enum card_type get_card_type_for_keytype(const char *key_type)
{
if (key_type == NULL)
return CARD_TYPE_ANY;
if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) == 0)
return CARD_TYPE_CCA;
if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
return CARD_TYPE_CCA;
return CARD_TYPE_ANY;
}
/**
* Performs extended checks on an AES CIPHER key. It checks the key usage
* fields (KUFs) and key management fields (KMFs) of the key. The function

View File

@@ -231,6 +231,12 @@ struct pkey_apqns4keytype {
#define ENC_ZERO_LEN (2 * PAES_BLOCK_SIZE)
#define VERIFICATION_PATTERN_LEN (2 * ENC_ZERO_LEN + 1)
enum card_type {
CARD_TYPE_ANY = -1,
CARD_TYPE_CCA = 1,
CARD_TYPE_EP11 = 2,
};
int open_pkey_device(bool verbose);
int generate_secure_key_random(int pkey_fd, const char *keyfile,
@@ -265,6 +271,7 @@ 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);
int get_min_card_level_for_keytype(const char *key_type);
enum card_type get_card_type_for_keytype(const char *key_type);
int check_aes_cipher_key(const u8 *key, size_t key_size);
#endif

View File

@@ -34,14 +34,16 @@
} while (0)
/**
* Checks if the specified card is of type CCA and is online
* Checks if the specified card is of the specified type and is online
*
* @param[in] card card number
* @param[in] cardtype card type (CCA, EP11 or ANY)
*
* @returns 1 if its a CCA card and is online, 0 if offline and -1 if its
* not a CCA card.
* @returns 1 if its card of the specified type and is online,
* 0 if offline,
* -1 if its not the specified type.
*/
int sysfs_is_card_online(int card)
int sysfs_is_card_online(int card, enum card_type cardtype)
{
long int online;
char *dev_path;
@@ -69,9 +71,21 @@ int sysfs_is_card_online(int card)
rc = 0;
goto out;
}
if (type[4] != 'C') {
rc = -1;
goto out;
switch (cardtype) {
case CARD_TYPE_CCA:
if (type[4] != 'C') {
rc = -1;
goto out;
}
break;
case CARD_TYPE_EP11:
if (type[4] != 'P') {
rc = -1;
goto out;
}
break;
default:
break;
}
out:
@@ -80,21 +94,22 @@ out:
}
/**
* Checks if the specified APQN is of type CCA and is online
* Checks if the specified APQN is of the specified type and is online
*
* @param[in] card card number
* @param[in] domain the domain
*
* @returns 1 if its a CCA card and is online, 0 if offline and -1 if its
* not a CCA card.
* @returns 1 if its card of the specified type and is online,
* 0 if offline,
* -1 if its not the specified type.
*/
int sysfs_is_apqn_online(int card, int domain)
int sysfs_is_apqn_online(int card, int domain, enum card_type cardtype)
{
long int online;
char *dev_path;
int rc = 1;
rc = sysfs_is_card_online(card);
rc = sysfs_is_card_online(card, cardtype);
if (rc != 1)
return rc;
@@ -145,7 +160,7 @@ int sysfs_get_card_level(int card)
rc = -1;
goto out;
}
if (type[4] != 'C') {
if (type[4] != 'C' && type[4] != 'P') {
rc = -1;
goto out;
}
@@ -161,6 +176,50 @@ out:
return rc;
}
/**
* Returns the type of the card. For a CEXnC CARD_TYPE_CCA is returned,
* for a CEXnP CARD_TYPE_EP11.
*
* @param[in] card card number
*
* @returns The card type, or -1 of the type can not be determined.
*/
enum card_type sysfs_get_card_type(int card)
{
char *dev_path;
char type[20];
enum card_type cardtype;
dev_path = util_path_sysfs("bus/ap/devices/card%02x", card);
if (!util_path_is_dir(dev_path)) {
cardtype = -1;
goto out;
}
if (util_file_read_line(type, sizeof(type), "%s/type", dev_path) != 0) {
cardtype = -1;
goto out;
}
if (strncmp(type, "CEX", 3) != 0 || strlen(type) < 5) {
cardtype = -1;
goto out;
}
switch (type[4]) {
case 'C':
cardtype = CARD_TYPE_CCA;
break;
case 'P':
cardtype = CARD_TYPE_EP11;
break;
default:
cardtype = -1;
break;
}
out:
free(dev_path);
return cardtype;
}
/**
* Gets the 8 character ASCII serial number string of an card from the sysfs.
*
@@ -169,9 +228,9 @@ out:
* @param[in] verbose if true, verbose messages are printed
*
* @returns 0 if the serial number was returned. -ENODEV if the APQN is not
* available, or is not a CCA card. -ENOTSUP if the serialnr sysfs
* attribute is not available, because the zcrypt kernel module is
* on an older level.
* available, or is not a CCA or EP11 card.
* -ENOTSUP if the serialnr sysfs attribute is not available, because
* the zcrypt kernel module is on an older level.
*/
int sysfs_get_serialnr(int card, char serialnr[9], bool verbose)
{
@@ -181,7 +240,7 @@ int sysfs_get_serialnr(int card, char serialnr[9], bool verbose)
if (serialnr == NULL)
return -EINVAL;
if (sysfs_is_card_online(card) != 1)
if (sysfs_is_card_online(card, CARD_TYPE_ANY) != 1)
return -ENODEV;
dev_path = util_path_sysfs("bus/ap/devices/card%02x", card);
@@ -272,9 +331,9 @@ static int parse_mk_info(char *line, struct mk_info *mk_info)
* @param[in] verbose if true, verbose messages are printed
*
* @returns 0 if the master key info was returned. -ENODEV if the APQN is not
* available, or is not a CCA card. -ENOTSUP if the mkvps sysfs
* attribute is not available, because the zcrypt kernel module is
* on an older level.
* available, or is not a CCA or EP11 card.
* -ENOTSUP if the mkvps sysfs attribute is not available, because the
* zcrypt kernel module is on an older level.
*/
int sysfs_get_mkvps(int card, int domain, struct mk_info *mk_info, bool verbose)
{
@@ -292,7 +351,7 @@ int sysfs_get_mkvps(int card, int domain, struct mk_info *mk_info, bool verbose)
mk_info->cur_mk.mk_state = MK_STATE_UNKNOWN;
mk_info->old_mk.mk_state = MK_STATE_UNKNOWN;
if (sysfs_is_apqn_online(card, domain) != 1)
if (sysfs_is_apqn_online(card, domain, CARD_TYPE_ANY) != 1)
return -ENODEV;
dev_path = util_path_sysfs("bus/ap/devices/card%02x/%02x.%04x/mkvps",
@@ -349,8 +408,9 @@ out:
return rc;
}
static int scan_for_domains(int card, apqn_handler_t handler,
void *handler_data, bool verbose)
static int scan_for_domains(int card, enum card_type cardtype,
apqn_handler_t handler, void *handler_data,
bool verbose)
{
struct dirent **namelist;
char fname[290];
@@ -369,9 +429,9 @@ static int scan_for_domains(int card, apqn_handler_t handler,
pr_verbose(verbose, "Found %02x.%04x", card, domain);
if (sysfs_is_apqn_online(card, domain) != 1) {
if (sysfs_is_apqn_online(card, domain, cardtype) != 1) {
pr_verbose(verbose, "APQN %02x.%04x is offline or not "
"CCA", card, domain);
"the correct type", card, domain);
continue;
}
@@ -385,8 +445,8 @@ static int scan_for_domains(int card, apqn_handler_t handler,
}
static int scan_for_apqns(apqn_handler_t handler, void *handler_data,
bool verbose)
static int scan_for_apqns(enum card_type cardtype, apqn_handler_t handler,
void *handler_data, bool verbose)
{
struct dirent **namelist;
int i, n, card, rc = 0;
@@ -405,13 +465,14 @@ static int scan_for_apqns(apqn_handler_t handler, void *handler_data,
pr_verbose(verbose, "Found card %02x", card);
if (sysfs_is_card_online(card) != 1) {
pr_verbose(verbose, "Card %02x is offline or not CCA",
card);
if (sysfs_is_card_online(card, cardtype) != 1) {
pr_verbose(verbose, "Card %02x is offline or not the "
"correct type", card);
continue;
}
rc = scan_for_domains(card, handler, handler_data, verbose);
rc = scan_for_domains(card, cardtype, handler, handler_data,
verbose);
if (rc != 0)
break;
}
@@ -421,21 +482,22 @@ static int scan_for_apqns(apqn_handler_t handler, void *handler_data,
}
/**
* Calls the handler for all APQNs specified in the apqns parameter, or of this
* is NULL, for all online CCA APQNs found in sysfs. In case sysfs is inspected,
* the cards and domains are processed in alphabetical order.
* Calls the handler for all APQNs specified in the apqns parameter, or if this
* is NULL, for all online CCA or EP11 APQNs found in sysfs. In case sysfs is
* inspected, the cards and domains are processed in alphabetical order.
*
* @param[in] apqns a comma separated list of APQNs. If NULL is specified,
* or an empty string, then all online CCA APQNs are
* handled.
* or an empty string, then all online CCA or EP11 APQNs
* are handled.
* @param[in] cardtype card type (CCA, EP11 or ANY)
* @param[in] handler a handler function that is called for each APQN
* @param[in] handler_data private data that is passed to the handler
* @param[in] verbose if true, verbose messages are printed
*
* @returns 0 for success or a negative errno in case of an error
*/
int handle_apqns(const char *apqns, apqn_handler_t handler, void *handler_data,
bool verbose)
int handle_apqns(const char *apqns, enum card_type cardtype,
apqn_handler_t handler, void *handler_data, bool verbose)
{
int card, domain;
char *copy, *tok;
@@ -443,7 +505,7 @@ int handle_apqns(const char *apqns, apqn_handler_t handler, void *handler_data,
int rc = 0;
if (apqns == NULL || (apqns != NULL && strlen(apqns) == 0)) {
rc = scan_for_apqns(handler, handler_data, verbose);
rc = scan_for_apqns(cardtype, handler, handler_data, verbose);
} else {
copy = util_strdup(apqns);
tok = strtok_r(copy, ",", &save);
@@ -480,12 +542,14 @@ static int print_apqn_mk_info(int card, int domain, void *handler_data)
struct print_apqn_info *info = (struct print_apqn_info *)handler_data;
struct mk_info mk_info;
int rc, level;
enum card_type type;
rc = sysfs_get_mkvps(card, domain, &mk_info, info->verbose);
if (rc == -ENOTSUP)
return rc;
level = sysfs_get_card_level(card);
type = sysfs_get_card_type(card);
util_rec_set(info->rec, "APQN", "%02x.%04x", card, domain);
@@ -515,8 +579,9 @@ static int print_apqn_mk_info(int card, int domain, void *handler_data)
util_rec_set(info->rec, "OLD", "?");
}
if (level > 0)
util_rec_set(info->rec, "TYPE", "CEX%dC", level);
if (level > 0 && type != CARD_TYPE_ANY)
util_rec_set(info->rec, "TYPE", "CEX%d%c", level,
type == CARD_TYPE_CCA ? 'C' : 'P');
else
util_rec_set(info->rec, "TYPE", "?");
@@ -529,15 +594,16 @@ static int print_apqn_mk_info(int card, int domain, void *handler_data)
* Prints master key information for all specified APQNs
*
* @param[in] apqns a comma separated list of APQNs. If NULL is specified,
* or an empty string, then all online CCA APQNs are
* printed.
* or an empty string, then all online CCA or EP11 APQNs
* are printed.
* @param[in] cardtype card type (CCA, EP11 or ANY)
* @param[in] verbose if true, verbose messages are printed
*
* @returns 0 for success or a negative errno in case of an error. -ENOTSUP is
* returned when the mkvps sysfs attribute is not available, because
* the zcrypt kernel module is on an older level.
*/
int print_mk_info(const char *apqns, bool verbose)
int print_mk_info(const char *apqns, enum card_type cardtype, bool verbose)
{
struct print_apqn_info info;
int rc;
@@ -552,7 +618,7 @@ int print_mk_info(const char *apqns, bool verbose)
util_rec_def(info.rec, "TYPE", UTIL_REC_ALIGN_LEFT, 6, "TYPE");
util_rec_print_hdr(info.rec);
rc = handle_apqns(apqns, print_apqn_mk_info, &info, verbose);
rc = handle_apqns(apqns, cardtype, print_apqn_mk_info, &info, verbose);
util_rec_free(info.rec);
return rc;
@@ -583,7 +649,7 @@ static int cross_check_mk_info(int card, int domain, void *handler_data)
if (rc == -ENODEV) {
info->print_mks = 1;
printf("WARNING: APQN %02x.%04x: Not available or not of "
"type CCA\n", card, domain);
"the correct type\n", card, domain);
return 0;
}
if (rc != 0)
@@ -729,6 +795,7 @@ static int cross_check_mk_info(int card, int domain, void *handler_data)
* matched against it.
* @param[in] min_level The minimum card level required. If min_level is -1 then
* the card level is not checked.
* @param[in] cardtype card type (CCA, EP11 or ANY)
* @param[in] print_mks if true, then a the full master key info of all
* specified APQns is printed, in case of a mismatch.
* @param[in] verbose if true, verbose messages are printed
@@ -739,7 +806,7 @@ static int cross_check_mk_info(int card, int domain, void *handler_data)
* available, because the zcrypt kernel module is on an older level.
*/
int cross_check_apqns(const char *apqns, u64 mkvp, int min_level,
bool print_mks, bool verbose)
enum card_type cardtype, bool print_mks, bool verbose)
{
struct cross_check_info info;
char temp[200];
@@ -755,7 +822,7 @@ int cross_check_apqns(const char *apqns, u64 mkvp, int min_level,
"min-level %d: %s", mkvp, min_level,
apqns != NULL ? apqns : "ANY");
rc = handle_apqns(apqns, cross_check_mk_info, &info, verbose);
rc = handle_apqns(apqns, cardtype, cross_check_mk_info, &info, verbose);
if (rc != 0)
return rc;
@@ -771,7 +838,7 @@ int cross_check_apqns(const char *apqns, u64 mkvp, int min_level,
}
if (info.num_checked == 0) {
printf("WARNING: None of the APQNs is available or of "
"type CCA\n");
"the correct type\n");
rc = -ENODEV;
}
if (info.num_old_match > 0 && info.num_new_match > 0) {
@@ -787,7 +854,7 @@ int cross_check_apqns(const char *apqns, u64 mkvp, int min_level,
if (print_mks && info.print_mks) {
printf("\n");
print_mk_info(apqns, verbose);
print_mk_info(apqns, cardtype, verbose);
printf("\n");
}

View File

@@ -14,12 +14,16 @@
#include "lib/zt_common.h"
int sysfs_is_card_online(int card);
#include "pkey.h"
int sysfs_is_apqn_online(int card, int domain);
int sysfs_is_card_online(int card, enum card_type cardtype);
int sysfs_is_apqn_online(int card, int domain, enum card_type cardtype);
int sysfs_get_card_level(int card);
enum card_type sysfs_get_card_type(int card);
int sysfs_get_serialnr(int card, char serialnr[9], bool verbose);
#define MK_STATE_EMPTY 0
@@ -45,13 +49,13 @@ int sysfs_get_mkvps(int card, int domain, struct mk_info *mk_info,
typedef int(*apqn_handler_t) (int card, int domain, void *handler_data);
int handle_apqns(const char *apqns, apqn_handler_t handler, void *handler_data,
bool verbose);
int handle_apqns(const char *apqns, enum card_type cardtype,
apqn_handler_t handler, void *handler_data, bool verbose);
int print_mk_info(const char *apqns, bool verbose);
int print_mk_info(const char *apqns, enum card_type cardtype, bool verbose);
int cross_check_apqns(const char *apqns, u64 mkvp, int min_level,
bool print_mks, bool verbose);
enum card_type cardtype, bool print_mks, bool verbose);
bool prompt_for_yes(bool verbose);

View File

@@ -1173,6 +1173,7 @@ static int command_generate(void)
rc = cross_check_apqns(NULL, 0,
get_min_card_level_for_keytype(g.key_type),
get_card_type_for_keytype(g.key_type),
true, g.verbose);
if (rc == -EINVAL)
return EXIT_FAILURE;
@@ -1425,6 +1426,7 @@ static int command_validate_file(void)
char vp[VERIFICATION_PATTERN_LEN];
size_t secure_key_size;
size_t clear_key_size;
const char *key_type;
u8 *secure_key;
int is_old_mk;
u64 mkvp;
@@ -1483,11 +1485,12 @@ static int command_validate_file(void)
goto out;
}
key_type = get_key_type(secure_key, secure_key_size);
printf("Validation of secure key in file '%s':\n", g.pos_arg);
printf(" Status: Valid\n");
printf(" Secure key size: %lu bytes\n", secure_key_size);
printf(" Key type: %s\n",
get_key_type(secure_key, secure_key_size));
printf(" Key type: %s\n", key_type);
printf(" Clear key size: %lu bits\n", clear_key_size);
printf(" XTS type key: %s\n",
is_xts_key(secure_key, secure_key_size) ? "Yes" : "No");
@@ -1499,8 +1502,8 @@ static int command_validate_file(void)
&vp[VERIFICATION_PATTERN_LEN / 2]);
rc = cross_check_apqns(NULL, mkvp,
get_min_card_level_for_keytype(
get_key_type(secure_key, secure_key_size)),
get_min_card_level_for_keytype(key_type),
get_card_type_for_keytype(key_type),
true, g.verbose);
if (rc == -EINVAL)
return EXIT_FAILURE;
@@ -1775,7 +1778,9 @@ static int command_convert_file(void)
return EXIT_FAILURE;
}
rc = cross_check_apqns(NULL, 0, min_level, true, g.verbose);
rc = cross_check_apqns(NULL, 0, min_level,
get_card_type_for_keytype(g.key_type), true,
g.verbose);
if (rc == -EINVAL)
return EXIT_FAILURE;
if (rc != 0 && rc != -ENOTSUP) {