Subject: zkey: Display key type with list and validate commands From: Ingo Franzki Summary: zkey: Add support for CCA AES CIPHER keys Description: With CCA 5 there is a new secure key type, the so called variable length symmetric cipher key token. This token format can hold AES keys with size 128, 192 and 256 bits together with additional attributes cryptographic bound to the key token. The attributes may limit the usage of the key, for example restrict export or usability scope. So this key type is considered to be even more secure than the traditional secure key token. This key token type is also called "CCA AES CIPHER key", where the formerly used key token is called "CCA AES DATA key". The zkey as well as the zkey-cryptsetup tools are enhanced to support AES CIPHER keys. That is, zkey can manage AES DATA keys, as well as AES CIPHER keys. The key type must be specified at key generation time, the default is to generate AED DATA keys. Upstream-ID: 9de85f42951e0b1a3d083363d7000b1950aebcd7 Problem-ID: SEC1717 Upstream-Description: zkey: Display key type with list and validate commands For the 'zkey list', 'zkey validate' and 'zkey-cryptsetup validate' commands, display the key type. As of today there is only one possible key type (CCA-AESDATA), but in the future there might be additional key types. Signed-off-by: Ingo Franzki Reviewed-by: Harald Freudenberger Signed-off-by: Jan Hoeppner Signed-off-by: Ingo Franzki --- zkey/keystore.c | 7 +++++++ zkey/pkey.c | 39 +++++++++++++++++++++++++++++++++++++++ zkey/pkey.h | 17 +++++++++++++++++ zkey/zkey-cryptsetup.c | 2 ++ zkey/zkey.c | 2 ++ 5 files changed, 67 insertions(+) --- a/zkey/keystore.c +++ b/zkey/keystore.c @@ -77,6 +77,7 @@ struct key_filenames { #define REC_SEC_KEY_SIZE "Secure key size" #define REC_CLR_KEY_SIZE "Clear key size" #define REC_XTS "XTS type key" +#define REC_KEY_TYPE "Key type" #define REC_VOLUMES "Volumes" #define REC_APQNS "APQNs" #define REC_KEY_FILE "Key file name" @@ -2140,6 +2141,7 @@ static struct util_rec *_keystore_setup_ util_rec_def(rec, REC_CLR_KEY_SIZE, UTIL_REC_ALIGN_LEFT, 20, REC_CLR_KEY_SIZE); util_rec_def(rec, REC_XTS, UTIL_REC_ALIGN_LEFT, 3, REC_XTS); + util_rec_def(rec, REC_KEY_TYPE, UTIL_REC_ALIGN_LEFT, 54, REC_KEY_TYPE); if (validation) util_rec_def(rec, REC_MASTERKEY, UTIL_REC_ALIGN_LEFT, 54, REC_MASTERKEY); @@ -2178,6 +2180,7 @@ static void _keystore_print_record(struc char *description; char *volume_type; char *reencipher; + char *key_type; char *creation; char *volumes; char *change; @@ -2212,6 +2215,7 @@ static void _keystore_print_record(struc reencipher = properties_get(properties, PROP_NAME_REENC_TIME); vp = properties_get(properties, PROP_NAME_KEY_VP); volume_type = _keystore_get_volume_type(properties); + key_type = properties_get(properties, PROP_NAME_KEY_TYPE); util_rec_set(rec, REC_KEY, name); if (validation) @@ -2226,6 +2230,7 @@ static void _keystore_print_record(struc util_rec_set(rec, REC_CLR_KEY_SIZE, "(unknown)"); util_rec_set(rec, REC_XTS, IS_XTS(secure_key_size) ? "Yes" : "No"); + util_rec_set(rec, REC_KEY_TYPE, key_type); if (validation) { if (valid) util_rec_set(rec, REC_MASTERKEY, @@ -2290,6 +2295,8 @@ static void _keystore_print_record(struc free(vp); if (volume_type != NULL) free(volume_type); + if (key_type != NULL) + free(key_type); } struct validate_info { --- a/zkey/pkey.c +++ b/zkey/pkey.c @@ -790,3 +790,42 @@ int get_master_key_verification_pattern( return 0; } + +/** + * Check if the specified key is a CCA AESDATA 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 CCA AESDATA token type + */ +bool is_cca_aes_data_key(const u8 *key, size_t key_size) +{ + struct tokenheader *hdr = (struct tokenheader *)key; + + if (key == NULL || key_size < SECURE_KEY_SIZE) + return false; + + if (hdr->type != TOKEN_TYPE_CCA_INTERNAL) + return false; + if (hdr->version != TOKEN_VERSION_AESDATA) + return false; + + return true; +} + +/** + * Returns the type of the key + * + * @param[in] key the secure key token + * @param[in] key_size the size of the secure key + * + * @returns a static string on success, NULL in case of an error + */ +const char *get_key_type(const u8 *key, size_t key_size) +{ + if (is_cca_aes_data_key(key, key_size)) + return KEY_TYPE_CCA_AESDATA; + + return NULL; +} --- a/zkey/pkey.h +++ b/zkey/pkey.h @@ -18,6 +18,18 @@ /* * Definitions for the /dev/pkey kernel module interface */ +struct tokenheader { + u8 type; + u8 res0[3]; + u8 version; + u8 res1[3]; +} __packed; + +#define TOKEN_TYPE_NON_CCA 0x00 +#define TOKEN_TYPE_CCA_INTERNAL 0x01 + +#define TOKEN_VERSION_AESDATA 0x04 + struct secaeskeytoken { u8 type; /* 0x01 for internal key token */ u8 res0[3]; @@ -82,6 +94,8 @@ struct pkey_verifykey { #define PKEY_VERIFYKEY _IOWR(PKEY_IOCTL_MAGIC, 0x07, struct pkey_verifykey) +#define KEY_TYPE_CCA_AESDATA "CCA-AESDATA" + #define PAES_BLOCK_SIZE 16 #define ENC_ZERO_LEN (2 * PAES_BLOCK_SIZE) #define VERIFICATION_PATTERN_LEN (2 * ENC_ZERO_LEN + 1) @@ -116,4 +130,7 @@ int get_master_key_verification_pattern( size_t secure_key_size, u64 *mkvp, bool verbose); +bool is_cca_aes_data_key(const u8 *key, size_t key_size); +const char *get_key_type(const u8 *key, size_t key_size); + #endif --- a/zkey/zkey-cryptsetup.c +++ b/zkey/zkey-cryptsetup.c @@ -1999,6 +1999,8 @@ static int command_validate(void) printf(" Secure key size: %lu bytes\n", keysize); printf(" XTS type key: %s\n", keysize > SECURE_KEY_SIZE ? "Yes" : "No"); + printf(" Key type: %s\n", + get_key_type((u8 *)key, keysize)); if (is_valid) { printf(" Clear key size: %lu bits\n", clear_keysize); printf(" Enciphered with: %s CCA master key (MKVP: " --- a/zkey/zkey.c +++ b/zkey/zkey.c @@ -1416,6 +1416,8 @@ static int command_validate_file(void) 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(" Clear key size: %lu bits\n", clear_key_size); printf(" XTS type key: %s\n", secure_key_size > SECURE_KEY_SIZE ? "Yes" : "No");