Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:15-SP4
s390-tools.15659
s390-tools-sles15sp2-22-zkey-Introduce-the-CCA-...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File s390-tools-sles15sp2-22-zkey-Introduce-the-CCA-AESCIPHER-key-type.patch of Package s390-tools.15659
Subject: zkey: Introduce the CCA-AESCIPHER key type From: Ingo Franzki <ifranzki@linux.ibm.com> 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: ddde3f354f3506521877a4e2a6082c4d597629cb Problem-ID: SEC1717 Upstream-Description: 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 Hoeppner <hoeppner@linux.ibm.com> Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com> --- zkey/keystore.c | 2 zkey/pkey.c | 91 +++++++++++++++++++++++++++++---- zkey/pkey.h | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++----- zkey/zkey.1 | 20 ++++--- zkey/zkey.c | 4 - 5 files changed, 235 insertions(+), 32 deletions(-) --- a/zkey/keystore.c +++ b/zkey/keystore.c @@ -341,6 +341,8 @@ static int _keystore_valid_key_type(cons { if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) == 0) return 1; + if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0) + return 1; return 0; } --- a/zkey/pkey.c +++ b/zkey/pkey.c @@ -782,23 +782,21 @@ out: return rc; } -int get_master_key_verification_pattern(const u8 *secure_key, - size_t secure_key_size, u64 *mkvp, - bool verbose) +int get_master_key_verification_pattern(const u8 *key, size_t key_size, + u64 *mkvp, bool UNUSED(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"); - if (secure_key_size < AESDATA_KEY_SIZE) { - pr_verbose(verbose, "Size of secure key is too small: " - "%lu expected %lu", secure_key_size, - AESDATA_KEY_SIZE); + if (is_cca_aes_data_key(key, key_size)) + *mkvp = datakey->mkvp; + else if (is_cca_aes_cipher_key(key, key_size)) + memcpy(mkvp, cipherkey->kvp, sizeof(*mkvp)); + else return -EINVAL; - } - - *mkvp = token->mkvp; return 0; } @@ -827,6 +825,56 @@ bool is_cca_aes_data_key(const u8 *key, } /** + * 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 * * @param[in] key the secure key token @@ -841,6 +889,11 @@ bool is_xts_key(const u8 *key, size_t ke is_cca_aes_data_key(key + AESDATA_KEY_SIZE, key_size - AESDATA_KEY_SIZE)) 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; @@ -860,6 +913,7 @@ bool is_xts_key(const u8 *key, size_t ke 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; util_assert(bitsize != NULL, "Internal error: bitsize is NULL"); @@ -870,6 +924,17 @@ int get_key_bit_size(const u8 *key, size AESDATA_KEY_SIZE; *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 { return -EINVAL; } @@ -889,6 +954,8 @@ const char *get_key_type(const u8 *key, { if (is_cca_aes_data_key(key, key_size)) return KEY_TYPE_CCA_AESDATA; + if (is_cca_aes_cipher_key(key, key_size)) + return KEY_TYPE_CCA_AESCIPHER; return NULL; } --- a/zkey/pkey.h +++ b/zkey/pkey.h @@ -29,6 +29,7 @@ struct tokenheader { #define TOKEN_TYPE_CCA_INTERNAL 0x01 #define TOKEN_VERSION_AESDATA 0x04 +#define TOKEN_VERSION_AESCIPHER 0x05 struct aesdatakeytoken { u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */ @@ -45,10 +46,45 @@ struct aesdatakeytoken { u8 tvv[4]; /* token validation value */ } __packed; +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 AESDATA_KEY_SIZE sizeof(struct aesdatakeytoken) +#define AESCIPHER_KEY_SIZE sizeof(struct aescipherkeytoken) -#define MAX_SECURE_KEY_SIZE AESDATA_KEY_SIZE -#define MIN_SECURE_KEY_SIZE AESDATA_KEY_SIZE +#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 { 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 */ }; -#define PKEY_IOCTL_MAGIC 'p' -#define AUTOSELECT 0xFFFF -#define PKEYDEVICE "/dev/pkey" -#define PKEY_KEYTYPE_AES_128 1 -#define PKEY_KEYTYPE_AES_192 2 -#define PKEY_KEYTYPE_AES_256 3 +#define PKEY_IOCTL_MAGIC 'p' +#define AUTOSELECT 0xFFFF +#define PKEYDEVICE "/dev/pkey" +#define PKEY_KEYTYPE_AES_128 1 +#define PKEY_KEYTYPE_AES_192 2 +#define PKEY_KEYTYPE_AES_256 3 struct pkey_genseck { 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) +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_AESCIPHER "CCA-AESCIPHER" #define PAES_BLOCK_SIZE 16 #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, char *vp, size_t vp_len, bool verbose); -int get_master_key_verification_pattern(const u8 *secure_key, - size_t secure_key_size, u64 *mkvp, - bool verbose); +int get_master_key_verification_pattern(const u8 *key, size_t key_size, + u64 *mkvp, bool verbose); 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); 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); --- a/zkey/zkey.1 +++ b/zkey/zkey.1 @@ -134,10 +134,14 @@ additional information can be associated .B \-\-sector-size options. .PP -You can generate different types of secure keys: \fBCCA-AESDATA\fP keys. -Specify the type of the secure key using the +You can generate different types of secure keys: \fBCCA-AESDATA\fP keys, and +\fBCCA-AESCIPHER\fP keys. Specify the type of the secure key using the .B \-\-key\-type 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" . @@ -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. .TP .BR \-K ", " \-\-key-type\~\fItype\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 -CCA-AESDATA is generated. +Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP +and \fBCCA-AESCIPHER\fP. If this option is omitted, then a secure key of type +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 ena This option is only used for secure keys contained in the secure key repository. .TP .BR \-K ", " \-\-key-type\~\fItype\fP -Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP. -Only keys with the specified key type are listed. +Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP +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. . . --- a/zkey/zkey.c +++ b/zkey/zkey.c @@ -221,7 +221,7 @@ 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"'. " + KEY_TYPE_CCA_AESDATA"' and '"KEY_TYPE_CCA_AESCIPHER"'. " "When this option is omitted, the default is '" KEY_TYPE_CCA_AESDATA"'", .command = COMMAND_GENERATE, @@ -446,7 +446,7 @@ 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"'. " + KEY_TYPE_CCA_AESDATA"' and '"KEY_TYPE_CCA_AESCIPHER"'. " "Use this option to list all keys with the specified " "key type.", .command = COMMAND_LIST,
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor