Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:FrontRunner
s390-tools.19914
s390-tools-sles15sp2-23-zkey-Add-wrappers-for-t...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File s390-tools-sles15sp2-23-zkey-Add-wrappers-for-the-new-IOCTLs-with-fallback-t.patch of Package s390-tools.19914
Subject: zkey: Add wrappers for the new IOCTLs with fallback to the old once 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: d4027e6506963fbf995992e32490d56a6f7ea587 Problem-ID: SEC1717 Upstream-Description: zkey: Add wrappers for the new IOCTLs with fallback to the old once By default the new pkey IOCTL are used. In case the pkey device does not support the new IOCTLs (i.e. errno ENOTTY is returned), then the wrapper falls back to the old IOCTLs. The old IOCTLs only support secure keys of type CCA-AESDATA. 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/pkey.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) --- a/zkey/pkey.c +++ b/zkey/pkey.c @@ -270,6 +270,234 @@ out: } /** + * Returns the PKEY_KEYTYPE_xxx value for the specified key size. + * + * @param[in] keysize the key size in bits + * + * @returns the PKEY_KEYTYPE_xxx value or 0 for an unknown key size + */ +static u32 keysize_to_keytype(enum pkey_key_size keysize) +{ + switch (keysize) { + case PKEY_SIZE_AES_128: + return PKEY_KEYTYPE_AES_128; + case PKEY_SIZE_AES_192: + return PKEY_KEYTYPE_AES_192; + case PKEY_SIZE_AES_256: + return PKEY_KEYTYPE_AES_256; + default: + return 0; + } +} + +/** + * Returns the PKEY_SIZE_xxx value for the specified keybits. + * + * @param[in] keybits the key size in bits + * + * @returns thePKEY_SIZE_xxx value or 0 for an unknown key size + */ +static enum pkey_key_size keybits_to_keysize(u32 keybits) +{ + switch (keybits) { + case 128: + return PKEY_SIZE_AES_128; + case 192: + return PKEY_SIZE_AES_192; + case 256: + return PKEY_SIZE_AES_256; + default: + return PKEY_SIZE_UNKNOWN; + } +} + +/* + * Wrapper for the PKEY_GENSECK/PKEY_GENSECK2 IOCTL to generate a secure + * key of any type by random. If the newer PKEY_GENSECK2 IOCTL is not supported + * by the pkey device, then it falls back to the older PKEY_GENSECK IOCTL + * + * @param[in] pkey_fd the pkey file descriptor + * @param[in/out] genseck info about key to generate + * @param[in] verbose if true, verbose messages are printed + * + * @returns 0 on success, a negative errno in case of an error + */ +static int pkey_genseck2(int pkey_fd, struct pkey_genseck2 *genseck2, + bool verbose) +{ + struct pkey_genseck genseck; + int rc; + u32 i; + + util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1"); + util_assert(genseck2 != NULL, "Internal error: genseck2 is NULL"); + + rc = ioctl(pkey_fd, PKEY_GENSECK2, genseck2); + if (rc != 0 && errno != ENOTTY) + return -errno; + if (rc == 0) + return 0; + + /* New IOCTL is not available, fall back to old one */ + pr_verbose(verbose, "ioctl PKEY_GENSECK2 not supported, fall back to " + "PKEY_GENSECK"); + + if (genseck2->type != PKEY_TYPE_CCA_DATA) { + warnx("Key-type is not supported"); + return -ENOTSUP; + } + + if (genseck2->keylen < AESDATA_KEY_SIZE) + return -EINVAL; + + memset(&genseck, 0, sizeof(genseck)); + + genseck.keytype = keysize_to_keytype(genseck2->size); + if (genseck.keytype == 0) + return -EINVAL; + + for (i = 0; i < genseck2->apqn_entries; i++) { + genseck.cardnr = genseck2->apqns[i].card; + genseck.domain = genseck2->apqns[i].domain; + + rc = ioctl(pkey_fd, PKEY_GENSECK, &genseck); + if (rc != 0) + continue; + + memcpy(genseck2->key, &genseck.seckey.seckey, AESDATA_KEY_SIZE); + genseck2->keylen = AESDATA_KEY_SIZE; + return 0; + } + + return -errno; +} + +/* + * Wrapper for the PKEY_CLR2SECK/PKEY_CLR2SECK2 IOCTL to generate a secure + * key of any type from a clear key. If the newer PKEY_CLR2SECK2 IOCTL is not + * supported by the pkey device, then it falls back to the older PKEY_CLR2SECK + * IOCTL + * + * @param[in] pkey_fd the pkey file descriptor + * @param[in/out] clr2seck2 info about key to generate + * @param[in] verbose if true, verbose messages are printed + * + * @returns 0 on success, a negative errno in case of an error + */ +static int pkey_clr2seck2(int pkey_fd, struct pkey_clr2seck2 *clr2seck2, + bool verbose) +{ + struct pkey_clr2seck clr2seck; + int rc; + u32 i; + + util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1"); + util_assert(clr2seck2 != NULL, "Internal error: clr2seck2 is NULL"); + + rc = ioctl(pkey_fd, PKEY_CLR2SECK2, clr2seck2); + if (rc != 0 && errno != ENOTTY) + return -errno; + if (rc == 0) + return 0; + + /* New IOCTL is not available, fall back to old one */ + pr_verbose(verbose, "ioctl PKEY_CLR2SECK2 not supported, fall back to " + "PKEY_CLR2SECK"); + + if (clr2seck2->type != PKEY_TYPE_CCA_DATA) { + warnx("Key-type is not supported"); + return -ENOTSUP; + } + + if (clr2seck2->keylen < AESDATA_KEY_SIZE) + return -EINVAL; + + memset(&clr2seck, 0, sizeof(clr2seck)); + clr2seck.clrkey = clr2seck2->clrkey; + + clr2seck.keytype = keysize_to_keytype(clr2seck2->size); + if (clr2seck.keytype == 0) + return -EINVAL; + + for (i = 0; i < clr2seck2->apqn_entries; i++) { + clr2seck.cardnr = clr2seck2->apqns[i].card; + clr2seck.domain = clr2seck2->apqns[i].domain; + + rc = ioctl(pkey_fd, PKEY_CLR2SECK, &clr2seck); + if (rc != 0) + continue; + + memcpy(clr2seck2->key, &clr2seck.seckey.seckey, + AESDATA_KEY_SIZE); + clr2seck2->keylen = AESDATA_KEY_SIZE; + return 0; + } + + return -errno; +} + +/* + * Wrapper for the PKEY_VERIFYKEY/PKEY_VERIFYKEY2 IOCTL to verify a secure + * key of any type. If the newer PKEY_VERIFYKEY2 IOCTL is not supported + * by the pkey device, then it falls back to the older PKEY_VERIFYKEY IOCTL + * + * @param[in] pkey_fd the pkey file descriptor + * @param[in/out] verifykey2 info about key to verify + * @param[in] verbose if true, verbose messages are printed + * + * @returns 0 on success, a negative errno in case of an error + */ +static int pkey_verifyseck2(int pkey_fd, struct pkey_verifykey2 *verifykey2, + bool verbose) +{ + struct pkey_verifykey verifykey; + int rc; + + util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1"); + util_assert(verifykey2 != NULL, "Internal error: verifyseck2 is NULL"); + + rc = ioctl(pkey_fd, PKEY_VERIFYKEY2, verifykey2); + if (rc != 0 && errno != ENOTTY) + return -errno; + if (rc == 0) + return 0; + + /* New IOCTL is not available, fall back to old one */ + pr_verbose(verbose, "ioctl PKEY_VERIFYKEY2 not supported, fall back to " + "PKEY_VERIFYKEY"); + + if (!is_cca_aes_data_key(verifykey2->key, verifykey2->keylen)) + return -ENODEV; + + memset(&verifykey, 0, sizeof(verifykey)); + memcpy(&verifykey.seckey, verifykey2->key, sizeof(verifykey.seckey)); + + /* + * Note: the old IOCTL does not support to check a specific card and + * domain. If falling back to the old IOCTL, this input is silently + * ignored, and all APQNs currently available in the system are used. + */ + rc = ioctl(pkey_fd, PKEY_VERIFYKEY, &verifykey); + if (rc != 0) + return -errno; + + if ((verifykey.attributes & PKEY_VERIFY_ATTR_AES) == 0) + return -ENODEV; + + verifykey2->type = PKEY_TYPE_CCA_DATA; + verifykey2->cardnr = verifykey.cardnr; + verifykey2->domain = verifykey.domain; + verifykey2->size = keybits_to_keysize(verifykey.keysize); + + if (verifykey.attributes & PKEY_VERIFY_ATTR_OLD_MKVP) + verifykey2->flags = PKEY_FLAGS_MATCH_ALT_MKVP; + else + verifykey2->flags = PKEY_FLAGS_MATCH_CUR_MKVP; + + return 0; +} + +/** * Generate a secure key by random * * @param[in] pkey_fd the pkey file descriptor
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