zkey: Introduce the CCA-AESCIPHER key type

Add definitions and helper functions to support the new
CCA-AESCIPHER key type. Also enhance existing helper functions
to support CCA-AESCIPHER 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-07-24 10:47:44 +02:00
committed by Jan Höppner
parent 298fab68fe
commit ddde3f354f
5 changed files with 236 additions and 33 deletions

View File

@@ -341,6 +341,8 @@ static int _keystore_valid_key_type(const char *key_type)
{ {
if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) == 0) if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) == 0)
return 1; return 1;
if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0)
return 1;
return 0; return 0;
} }

View File

@@ -782,23 +782,21 @@ out:
return rc; return rc;
} }
int get_master_key_verification_pattern(const u8 *secure_key, int get_master_key_verification_pattern(const u8 *key, size_t key_size,
size_t secure_key_size, u64 *mkvp, u64 *mkvp, bool UNUSED(verbose))
bool verbose)
{ {
struct aesdatakeytoken *token = (struct aesdatakeytoken *)secure_key; struct aesdatakeytoken *datakey = (struct aesdatakeytoken *)key;
struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key;
util_assert(secure_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");
if (secure_key_size < AESDATA_KEY_SIZE) { if (is_cca_aes_data_key(key, key_size))
pr_verbose(verbose, "Size of secure key is too small: " *mkvp = datakey->mkvp;
"%lu expected %lu", secure_key_size, else if (is_cca_aes_cipher_key(key, key_size))
AESDATA_KEY_SIZE); memcpy(mkvp, cipherkey->kvp, sizeof(*mkvp));
else
return -EINVAL; return -EINVAL;
}
*mkvp = token->mkvp;
return 0; return 0;
} }
@@ -826,6 +824,56 @@ bool is_cca_aes_data_key(const u8 *key, size_t key_size)
return true; return true;
} }
/**
* Check if the specified key is a CCA AESCIPHER 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 AESCIPHER token type
*/
bool is_cca_aes_cipher_key(const u8 *key, size_t key_size)
{
struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key;
if (key == NULL || key_size < AESCIPHER_KEY_SIZE)
return false;
if (cipherkey->type != TOKEN_TYPE_CCA_INTERNAL)
return false;
if (cipherkey->version != TOKEN_VERSION_AESCIPHER)
return false;
if (cipherkey->length > key_size)
return false;
if (cipherkey->kms != 0x03) /* key wrapped by master key */
return false;
if (cipherkey->kwm != 0x02) /* key wrapped using AESKW */
return false;
if (cipherkey->pfv != 0x00 && cipherkey->pfv != 0x01) /* V0 or V1 */
return false;
if (cipherkey->adv != 0x01) /* Should have ass. data sect. version 1 */
return false;
if (cipherkey->at != 0x02) /* Algorithm: AES */
return false;
if (cipherkey->kt != 0x0001) /* Key type: CIPHER */
return false;
if (cipherkey->adl != 26) /* Ass. data section length should be 26 */
return false;
if (cipherkey->kll != 0) /* Should have no key label */
return false;
if (cipherkey->eadl != 0) /* Should have no ext associated data */
return false;
if (cipherkey->uadl != 0) /* Should have no user associated data */
return false;
if (cipherkey->kufc != 2) /* Should have 2 KUFs */
return false;
if (cipherkey->kmfc != 3) /* Should have 3 KMFs */
return false;
return true;
}
/** /**
* Check if the specified key is an XTS type key * Check if the specified key is an XTS type key
* *
@@ -841,6 +889,11 @@ bool is_xts_key(const u8 *key, size_t key_size)
is_cca_aes_data_key(key + AESDATA_KEY_SIZE, is_cca_aes_data_key(key + AESDATA_KEY_SIZE,
key_size - AESDATA_KEY_SIZE)) key_size - AESDATA_KEY_SIZE))
return true; return true;
} else if (is_cca_aes_cipher_key(key, key_size)) {
if (key_size == 2 * AESCIPHER_KEY_SIZE &&
is_cca_aes_cipher_key(key + AESCIPHER_KEY_SIZE,
key_size - AESCIPHER_KEY_SIZE))
return true;
} }
return false; return false;
@@ -860,6 +913,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) 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;
util_assert(bitsize != NULL, "Internal error: bitsize is NULL"); util_assert(bitsize != NULL, "Internal error: bitsize is NULL");
@@ -870,6 +924,17 @@ int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize)
AESDATA_KEY_SIZE; AESDATA_KEY_SIZE;
*bitsize += datakey->bitsize; *bitsize += datakey->bitsize;
} }
} else if (is_cca_aes_cipher_key(key, key_size)) {
if (cipherkey->pfv == 0x00) /* V0 payload */
*bitsize = cipherkey->pl - 384;
else
*bitsize = 0; /* Unknown */
if (key_size > cipherkey->length) {
cipherkey = (struct aescipherkeytoken *)key +
cipherkey->length;
if (cipherkey->pfv == 0x00) /* V0 payload */
*bitsize += cipherkey->pl - 384;
}
} else { } else {
return -EINVAL; return -EINVAL;
} }
@@ -889,6 +954,8 @@ const char *get_key_type(const u8 *key, size_t key_size)
{ {
if (is_cca_aes_data_key(key, key_size)) if (is_cca_aes_data_key(key, key_size))
return KEY_TYPE_CCA_AESDATA; return KEY_TYPE_CCA_AESDATA;
if (is_cca_aes_cipher_key(key, key_size))
return KEY_TYPE_CCA_AESCIPHER;
return NULL; return NULL;
} }

View File

@@ -29,6 +29,7 @@ struct tokenheader {
#define TOKEN_TYPE_CCA_INTERNAL 0x01 #define TOKEN_TYPE_CCA_INTERNAL 0x01
#define TOKEN_VERSION_AESDATA 0x04 #define TOKEN_VERSION_AESDATA 0x04
#define TOKEN_VERSION_AESCIPHER 0x05
struct aesdatakeytoken { struct aesdatakeytoken {
u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */ u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */
@@ -45,10 +46,45 @@ struct aesdatakeytoken {
u8 tvv[4]; /* token validation value */ u8 tvv[4]; /* token validation value */
} __packed; } __packed;
#define AESDATA_KEY_SIZE sizeof(struct aesdatakeytoken) struct aescipherkeytoken {
u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */
u8 res0;
u16 length; /* length of token */
u8 version; /* should be TOKEN_VERSION_CIPHER (0x05) */
u8 res1[3];
u8 kms; /* key material state, should be 0x03 */
u8 kvptype; /* key verification pattern type */
u8 kvp[16]; /* key verification pattern */
u8 kwm; /* key wrapping method, should be 0x02 */
u8 kwh; /* key wrapping hash algorithm */
u8 pfv; /* payload format version, should be 0x00*/
u8 res2;
u8 adv; /* associated data section version */
u8 res3;
u16 adl; /* associated data length */
u8 kll; /* length of optional key label */
u8 eadl; /* extended associated data length */
u8 uadl; /* user associated data length */
u8 res4;
u16 pl; /* payload bit length */
u8 res5;
u8 at; /* algorithm type, should be 0x02 (AES) */
u16 kt; /* key type, should be 0x001 (CIPHER) */
u8 kufc; /* key usage field count */
u16 kuf1; /* key usage field 1 */
u16 kuf2; /* key usage field 2 */
u8 kmfc; /* key management field count */
u16 kmf1; /* key management field 1 */
u16 kmf2; /* key management field 2 */
u16 kmf3; /* key management field 3 */
u8 varpart[80]; /* variable part */
} __packed;
#define MAX_SECURE_KEY_SIZE AESDATA_KEY_SIZE #define AESDATA_KEY_SIZE sizeof(struct aesdatakeytoken)
#define MIN_SECURE_KEY_SIZE AESDATA_KEY_SIZE #define AESCIPHER_KEY_SIZE sizeof(struct aescipherkeytoken)
#define MAX_SECURE_KEY_SIZE MAX(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE)
#define MIN_SECURE_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 */
@@ -58,12 +94,12 @@ struct pkey_clrkey {
u8 clrkey[32]; /* 16, 24, or 32 byte clear key value */ u8 clrkey[32]; /* 16, 24, or 32 byte clear key value */
}; };
#define PKEY_IOCTL_MAGIC 'p' #define PKEY_IOCTL_MAGIC 'p'
#define AUTOSELECT 0xFFFF #define AUTOSELECT 0xFFFF
#define PKEYDEVICE "/dev/pkey" #define PKEYDEVICE "/dev/pkey"
#define PKEY_KEYTYPE_AES_128 1 #define PKEY_KEYTYPE_AES_128 1
#define PKEY_KEYTYPE_AES_192 2 #define PKEY_KEYTYPE_AES_192 2
#define PKEY_KEYTYPE_AES_256 3 #define PKEY_KEYTYPE_AES_256 3
struct pkey_genseck { struct pkey_genseck {
u16 cardnr; /* in: card to use or FFFF for any */ u16 cardnr; /* in: card to use or FFFF for any */
@@ -97,7 +133,99 @@ struct pkey_verifykey {
#define PKEY_VERIFYKEY _IOWR(PKEY_IOCTL_MAGIC, 0x07, struct pkey_verifykey) #define PKEY_VERIFYKEY _IOWR(PKEY_IOCTL_MAGIC, 0x07, struct pkey_verifykey)
enum pkey_key_type {
PKEY_TYPE_CCA_DATA = (u32) 1,
PKEY_TYPE_CCA_CIPHER = (u32) 2,
};
enum pkey_key_size {
PKEY_SIZE_AES_128 = (u32) 128,
PKEY_SIZE_AES_192 = (u32) 192,
PKEY_SIZE_AES_256 = (u32) 256,
PKEY_SIZE_UNKNOWN = (u32) 0xFFFFFFFF,
};
#define PKEY_FLAGS_MATCH_CUR_MKVP 0x00000002
#define PKEY_FLAGS_MATCH_ALT_MKVP 0x00000004
#define PKEY_KEYGEN_XPRT_SYM 0x00008000
#define PKEY_KEYGEN_XPRT_UASY 0x00004000
#define PKEY_KEYGEN_XPRT_AASY 0x00002000
#define PKEY_KEYGEN_XPRT_RAW 0x00001000
#define PKEY_KEYGEN_XPRT_CPAC 0x00000800
#define PKEY_KEYGEN_XPRT_DES 0x00000080
#define PKEY_KEYGEN_XPRT_AES 0x00000040
#define PKEY_KEYGEN_XPRT_RSA 0x00000008
struct pkey_apqn {
u16 card;
u16 domain;
};
struct pkey_genseck2 {
struct pkey_apqn *apqns; /* in: ptr to list of apqn targets */
u32 apqn_entries; /* in: # of apqn target list entries */
enum pkey_key_type type; /* in: key type to generate */
enum pkey_key_size size; /* in: key size to generate */
u32 keygenflags; /* in: key generation flags */
u8 *key; /* in: pointer to key blob buffer */
u32 keylen; /* in: available key blob buffer size */
/* out: actual key blob size */
};
#define PKEY_GENSECK2 _IOWR(PKEY_IOCTL_MAGIC, 0x11, struct pkey_genseck2)
struct pkey_clr2seck2 {
struct pkey_apqn *apqns; /* in: ptr to list of apqn targets */
u32 apqn_entries; /* in: # of apqn target list entries */
enum pkey_key_type type; /* in: key type to generate */
enum pkey_key_size size; /* in: key size to generate */
u32 keygenflags; /* in: key generation flags */
struct pkey_clrkey clrkey; /* in: the clear key value */
u8 *key; /* in: pointer to key blob buffer */
u32 keylen; /* in: available key blob buffer size */
/* out: actual key blob size */
};
#define PKEY_CLR2SECK2 _IOWR(PKEY_IOCTL_MAGIC, 0x12, struct pkey_clr2seck2)
struct pkey_verifykey2 {
u8 *key; /* in: pointer to key blob */
u32 keylen; /* in: key blob size */
u16 cardnr; /* in/out: card number */
u16 domain; /* in/out: domain number */
enum pkey_key_type type; /* out: the key type */
enum pkey_key_size size; /* out: the key size */
u32 flags; /* out: additional key info flags */
};
#define PKEY_VERIFYKEY2 _IOWR(PKEY_IOCTL_MAGIC, 0x17, struct pkey_verifykey2)
struct pkey_apqns4key {
u8 *key; /* in: pointer to key blob */
u32 keylen; /* in: key blob size */
u32 flags; /* in: match controlling flags */
struct pkey_apqn *apqns; /* in/out: ptr to list of apqn targets*/
u32 apqn_entries; /* in: max # of apqn entries in list */
/* out: # apqns stored into the list */
};
#define PKEY_APQNS4K _IOWR(PKEY_IOCTL_MAGIC, 0x1B, struct pkey_apqns4key)
struct pkey_apqns4keytype {
enum pkey_key_type type; /* in: key type */
u8 cur_mkvp[32]; /* in: current mkvp */
u8 alt_mkvp[32]; /* in: alternate mkvp */
u32 flags; /* in: match controlling flags */
struct pkey_apqn *apqns; /* in/out: ptr to list of apqn targets*/
u32 apqn_entries; /* in: max # of apqn entries in list */
/* out: # apqns stored into the list */
};
#define PKEY_APQNS4KT _IOWR(PKEY_IOCTL_MAGIC, 0x1C, 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 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)
@@ -129,11 +257,11 @@ int validate_secure_key(int pkey_fd,
int generate_key_verification_pattern(const u8 *key, size_t key_size, int generate_key_verification_pattern(const u8 *key, size_t key_size,
char *vp, size_t vp_len, bool verbose); char *vp, size_t vp_len, bool verbose);
int get_master_key_verification_pattern(const u8 *secure_key, int get_master_key_verification_pattern(const u8 *key, size_t key_size,
size_t secure_key_size, u64 *mkvp, u64 *mkvp, bool verbose);
bool verbose);
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_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);

View File

@@ -134,10 +134,14 @@ additional information can be associated with a secure key using the
.B \-\-sector-size .B \-\-sector-size
options. options.
.PP .PP
You can generate different types of secure keys: \fBCCA-AESDATA\fP keys. You can generate different types of secure keys: \fBCCA-AESDATA\fP keys, and
Specify the type of the secure key using the \fBCCA-AESCIPHER\fP keys. Specify the type of the secure key using the
.B \-\-key\-type .B \-\-key\-type
option. The default key type is CCA-AESDATA. option. The default key type is CCA-AESDATA.
.PP
.B Note:
Secure keys of type \fBCCA-AESCIPHER\fP require an IBM cryptographic
adapter in CCA coprocessor mode of version 6 or later, e.g. a CEX6C.
. .
.SS "Validating secure AES keys" .SS "Validating secure AES keys"
. .
@@ -741,9 +745,11 @@ the default volume type is \fBplain\fP.
This option is only used for secure keys contained in the secure key repository. This option is only used for secure keys contained in the secure key repository.
.TP .TP
.BR \-K ", " \-\-key-type\~\fItype\fP .BR \-K ", " \-\-key-type\~\fItype\fP
Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP. Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP
If this option is omitted, then a secure key of type and \fBCCA-AESCIPHER\fP. If this option is omitted, then a secure key of type
CCA-AESDATA is generated. CCA-AESDATA is generated. Secure keys of type \fBCCA-AESCIPHER\fP require an
IBM cryptographic adapter in CCA coprocessor mode of version 6 or later, e.g.
a CEX6C.
. .
. .
. .
@@ -925,8 +931,8 @@ has been compiled with LUKS2 support enabled.
This option is only used for secure keys contained in the secure key repository. This option is only used for secure keys contained in the secure key repository.
.TP .TP
.BR \-K ", " \-\-key-type\~\fItype\fP .BR \-K ", " \-\-key-type\~\fItype\fP
Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP. Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP
Only keys with the specified key type are listed. and \fBCCA-AESCIPHER\fP. Only keys with the specified key type are listed.
This option is only used for secure keys contained in the secure key repository. This option is only used for secure keys contained in the secure key repository.
. .
. .

View File

@@ -221,7 +221,7 @@ 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"'. " KEY_TYPE_CCA_AESDATA"' and '"KEY_TYPE_CCA_AESCIPHER"'. "
"When this option is omitted, the default is '" "When this option is omitted, the default is '"
KEY_TYPE_CCA_AESDATA"'", KEY_TYPE_CCA_AESDATA"'",
.command = COMMAND_GENERATE, .command = COMMAND_GENERATE,
@@ -446,7 +446,7 @@ 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"'. " KEY_TYPE_CCA_AESDATA"' and '"KEY_TYPE_CCA_AESCIPHER"'. "
"Use this option to list all keys with the specified " "Use this option to list all keys with the specified "
"key type.", "key type.",
.command = COMMAND_LIST, .command = COMMAND_LIST,