diff options
-rw-r--r-- | arch/s390/configs/debug_defconfig | 3 | ||||
-rw-r--r-- | arch/s390/configs/defconfig | 3 | ||||
-rw-r--r-- | arch/s390/include/uapi/asm/pkey.h | 1 | ||||
-rw-r--r-- | drivers/crypto/Kconfig | 75 | ||||
-rw-r--r-- | drivers/s390/crypto/Makefile | 16 | ||||
-rw-r--r-- | drivers/s390/crypto/pkey_api.c | 690 | ||||
-rw-r--r-- | drivers/s390/crypto/pkey_base.c | 293 | ||||
-rw-r--r-- | drivers/s390/crypto/pkey_base.h | 130 | ||||
-rw-r--r-- | drivers/s390/crypto/pkey_cca.c | 489 | ||||
-rw-r--r-- | drivers/s390/crypto/pkey_ep11.c | 418 | ||||
-rw-r--r-- | drivers/s390/crypto/pkey_pckmo.c | 412 | ||||
-rw-r--r-- | drivers/s390/crypto/pkey_sysfs.c | 121 |
12 files changed, 1508 insertions, 1143 deletions
diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index 6c57f024acae..7ec1b8cd0de9 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig @@ -797,6 +797,9 @@ CONFIG_CRYPTO_CHACHA_S390=m CONFIG_CRYPTO_HMAC_S390=m CONFIG_ZCRYPT=m CONFIG_PKEY=m +CONFIG_PKEY_CCA=m +CONFIG_PKEY_EP11=m +CONFIG_PKEY_PCKMO=m CONFIG_CRYPTO_PAES_S390=m CONFIG_CRYPTO_DEV_VIRTIO=m CONFIG_SYSTEM_BLACKLIST_KEYRING=y diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig index c75e375570fa..df4addd1834a 100644 --- a/arch/s390/configs/defconfig +++ b/arch/s390/configs/defconfig @@ -784,6 +784,9 @@ CONFIG_CRYPTO_CHACHA_S390=m CONFIG_CRYPTO_HMAC_S390=m CONFIG_ZCRYPT=m CONFIG_PKEY=m +CONFIG_PKEY_CCA=m +CONFIG_PKEY_EP11=m +CONFIG_PKEY_PCKMO=m CONFIG_CRYPTO_PAES_S390=m CONFIG_CRYPTO_DEV_VIRTIO=m CONFIG_SYSTEM_BLACKLIST_KEYRING=y diff --git a/arch/s390/include/uapi/asm/pkey.h b/arch/s390/include/uapi/asm/pkey.h index 5ad76471e73f..04183080cdbb 100644 --- a/arch/s390/include/uapi/asm/pkey.h +++ b/arch/s390/include/uapi/asm/pkey.h @@ -50,6 +50,7 @@ enum pkey_key_type { PKEY_TYPE_CCA_ECC = (__u32) 0x1f, PKEY_TYPE_EP11_AES = (__u32) 6, PKEY_TYPE_EP11_ECC = (__u32) 7, + PKEY_TYPE_PROTKEY = (__u32) 8, }; /* the newer ioctls use a pkey_key_size enum for key size information */ diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 94f23c6fc93b..08b1238bcd7b 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -21,7 +21,7 @@ config CRYPTO_DEV_PADLOCK (so called VIA PadLock ACE, Advanced Cryptography Engine) that provides instructions for very fast cryptographic operations with supported algorithms. - + The instructions are used only when the CPU supports them. Otherwise software encryption is used. @@ -78,18 +78,79 @@ config ZCRYPT config PKEY tristate "Kernel API for protected key handling" depends on S390 - depends on ZCRYPT help - With this option enabled the pkey kernel module provides an API + With this option enabled the pkey kernel modules provide an API for creation and handling of protected keys. Other parts of the kernel or userspace applications may use these functions. + The protected key support is distributed into: + - A pkey base and API kernel module (pkey.ko) which offers the + infrastructure for the pkey handler kernel modules, the ioctl + and the sysfs API and the in-kernel API to the crypto cipher + implementations using protected key. + - A pkey pckmo kernel module (pkey-pckmo.ko) which is automatically + loaded when pckmo support (that is generation of protected keys + from clear key values) is available. + - A pkey CCA kernel module (pkey-cca.ko) which is automatically + loaded when a CEX crypto card is available. + - A pkey EP11 kernel module (pkey-ep11.ko) which is automatically + loaded when a CEX crypto card is available. + Select this option if you want to enable the kernel and userspace - API for proteced key handling. + API for protected key handling. + +config PKEY_CCA + tristate "PKEY CCA support handler" + depends on PKEY + depends on ZCRYPT + help + This is the CCA support handler for deriving protected keys + from CCA (secure) keys. Also this handler provides an alternate + way to make protected keys from clear key values. + + The PKEY CCA support handler needs a Crypto Express card (CEX) + in CCA mode. + + If you have selected the PKEY option then you should also enable + this option unless you are sure you never need to derive protected + keys from CCA key material. + +config PKEY_EP11 + tristate "PKEY EP11 support handler" + depends on PKEY + depends on ZCRYPT + help + This is the EP11 support handler for deriving protected keys + from EP11 (secure) keys. Also this handler provides an alternate + way to make protected keys from clear key values. + + The PKEY EP11 support handler needs a Crypto Express card (CEX) + in EP11 mode. + + If you have selected the PKEY option then you should also enable + this option unless you are sure you never need to derive protected + keys from EP11 key material. + +config PKEY_PCKMO + tristate "PKEY PCKMO support handler" + depends on PKEY + help + This is the PCKMO support handler for deriving protected keys + from clear key values via invoking the PCKMO instruction. + + The PCKMO instruction can be enabled and disabled in the crypto + settings at the LPAR profile. This handler checks for availability + during initialization and if build as a kernel module unloads + itself if PCKMO is disabled. + + The PCKMO way of deriving protected keys from clear key material + is especially used during self test of protected key ciphers like + PAES but the CCA and EP11 handler provide alternate ways to + generate protected keys from clear key values. - Please note that creation of protected keys from secure keys - requires to have at least one CEX card in coprocessor mode - available at runtime. + If you have selected the PKEY option then you should also enable + this option unless you are sure you never need to derive protected + keys from clear key values directly via PCKMO. config CRYPTO_PAES_S390 tristate "PAES cipher algorithms" diff --git a/drivers/s390/crypto/Makefile b/drivers/s390/crypto/Makefile index 863d6fbd2e79..c88b6e071847 100644 --- a/drivers/s390/crypto/Makefile +++ b/drivers/s390/crypto/Makefile @@ -13,10 +13,22 @@ obj-$(CONFIG_ZCRYPT) += zcrypt.o # adapter drivers depend on ap.o and zcrypt.o obj-$(CONFIG_ZCRYPT) += zcrypt_cex4.o -# pkey kernel module -pkey-objs := pkey_api.o pkey_cca.o pkey_ep11.o pkey_pckmo.o pkey_sysfs.o +# pkey base and api module +pkey-objs := pkey_base.o pkey_api.o pkey_sysfs.o obj-$(CONFIG_PKEY) += pkey.o +# pkey cca handler module +pkey-cca-objs := pkey_cca.o +obj-$(CONFIG_PKEY_CCA) += pkey-cca.o + +# pkey ep11 handler module +pkey-ep11-objs := pkey_ep11.o +obj-$(CONFIG_PKEY_EP11) += pkey-ep11.o + +# pkey pckmo handler module +pkey-pckmo-objs := pkey_pckmo.o +obj-$(CONFIG_PKEY_PCKMO) += pkey-pckmo.o + # adjunct processor matrix vfio_ap-objs := vfio_ap_drv.o vfio_ap_ops.o obj-$(CONFIG_VFIO_AP) += vfio_ap.o diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index 31382c23ec14..c59051ab1cfb 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -10,271 +10,26 @@ #define KMSG_COMPONENT "pkey" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt -#include <linux/fs.h> #include <linux/init.h> #include <linux/miscdevice.h> -#include <linux/module.h> #include <linux/slab.h> -#include <linux/kallsyms.h> -#include <linux/debugfs.h> -#include <linux/cpufeature.h> -#include <asm/zcrypt.h> -#include <asm/cpacf.h> -#include <asm/pkey.h> #include "zcrypt_api.h" #include "zcrypt_ccamisc.h" -#include "zcrypt_ep11misc.h" #include "pkey_base.h" -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("s390 protected key interface"); - -/* - * Debug feature data and functions - */ - -debug_info_t *pkey_dbf_info; - -static void __init pkey_debug_init(void) -{ - /* 5 arguments per dbf entry (including the format string ptr) */ - pkey_dbf_info = debug_register("pkey", 1, 1, 5 * sizeof(long)); - debug_register_view(pkey_dbf_info, &debug_sprintf_view); - debug_set_level(pkey_dbf_info, 3); -} - -static void __exit pkey_debug_exit(void) -{ - debug_unregister(pkey_dbf_info); -} - /* * Helper functions */ -static int apqns4key(const u8 *key, size_t keylen, u32 flags, - struct pkey_apqn *apqns, size_t *nr_apqns) -{ - if (pkey_is_cca_key(key, keylen)) { - return pkey_cca_apqns4key(key, keylen, flags, - apqns, nr_apqns); - } else if (pkey_is_ep11_key(key, keylen)) { - return pkey_ep11_apqns4key(key, keylen, flags, - apqns, nr_apqns); - } else { - struct keytoken_header *hdr = (struct keytoken_header *)key; - - PKEY_DBF_ERR("%s unknown/unsupported key type %d version %d\n", - __func__, hdr->type, hdr->version); - return -EINVAL; - } -} - -static int apqns4keytype(enum pkey_key_type ktype, - u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, - struct pkey_apqn *apqns, size_t *nr_apqns) -{ - if (pkey_is_cca_keytype(ktype)) { - return pkey_cca_apqns4type(ktype, cur_mkvp, alt_mkvp, flags, - apqns, nr_apqns); - } else if (pkey_is_ep11_keytype(ktype)) { - return pkey_ep11_apqns4type(ktype, cur_mkvp, alt_mkvp, flags, - apqns, nr_apqns); - } else { - PKEY_DBF_ERR("%s unknown/unsupported key type %d\n", - __func__, ktype); - return -EINVAL; - } -} - -static int genseck2(const struct pkey_apqn *apqns, size_t nr_apqns, - enum pkey_key_type keytype, enum pkey_key_size keybitsize, - u32 flags, u8 *keybuf, u32 *keybuflen) -{ - int i, rc; - u32 u; - - if (pkey_is_cca_keytype(keytype)) { - /* As of now only CCA AES key generation is supported */ - u = pkey_aes_bitsize_to_keytype(keybitsize); - if (!u) { - PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n", - __func__, keybitsize); - return -EINVAL; - } - for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { - rc = pkey_cca_gen_key(apqns[i].card, - apqns[i].domain, - u, keytype, keybitsize, flags, - keybuf, keybuflen, NULL); - } - } else if (pkey_is_ep11_keytype(keytype)) { - /* As of now only EP11 AES key generation is supported */ - u = pkey_aes_bitsize_to_keytype(keybitsize); - if (!u) { - PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n", - __func__, keybitsize); - return -EINVAL; - } - for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { - rc = pkey_ep11_gen_key(apqns[i].card, - apqns[i].domain, - u, keytype, keybitsize, flags, - keybuf, keybuflen, NULL); - } - } else { - PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n", - __func__, keytype); - return -EINVAL; - } - - return rc; -} - -static int clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, - enum pkey_key_type keytype, enum pkey_key_size kbitsize, - u32 flags, const u8 *clrkey, u8 *keybuf, u32 *keybuflen) -{ - int i, rc; - u32 u; - - if (pkey_is_cca_keytype(keytype)) { - /* As of now only CCA AES key generation is supported */ - u = pkey_aes_bitsize_to_keytype(kbitsize); - if (!u) { - PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n", - __func__, kbitsize); - return -EINVAL; - } - for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { - rc = pkey_cca_clr2key(apqns[i].card, - apqns[i].domain, - u, keytype, kbitsize, flags, - clrkey, kbitsize / 8, - keybuf, keybuflen, NULL); - } - } else if (pkey_is_ep11_keytype(keytype)) { - /* As of now only EP11 AES key generation is supported */ - u = pkey_aes_bitsize_to_keytype(kbitsize); - if (!u) { - PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n", - __func__, kbitsize); - return -EINVAL; - } - for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { - rc = pkey_ep11_clr2key(apqns[i].card, - apqns[i].domain, - u, keytype, kbitsize, flags, - clrkey, kbitsize / 8, - keybuf, keybuflen, NULL); - } - } else { - PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n", - __func__, keytype); - return -EINVAL; - } - - return rc; -} - -static int ccakey2protkey(const struct pkey_apqn *apqns, size_t nr_apqns, - const u8 *key, size_t keylen, - u8 *protkey, u32 *protkeylen, u32 *protkeytype) -{ - struct pkey_apqn *local_apqns = NULL; - int i, j, rc; - - /* alloc space for list of apqns if no list given */ - if (!apqns || (nr_apqns == 1 && - apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { - nr_apqns = MAXAPQNSINLIST; - local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), - GFP_KERNEL); - if (!local_apqns) - return -ENOMEM; - apqns = local_apqns; - } - - /* try two times in case of failure */ - for (i = 0, rc = -ENODEV; i < 2 && rc; i++) { - if (local_apqns) { - /* gather list of apqns able to deal with this key */ - nr_apqns = MAXAPQNSINLIST; - rc = pkey_cca_apqns4key(key, keylen, 0, - local_apqns, &nr_apqns); - if (rc) - continue; - } - /* go through the list of apqns until success or end */ - for (j = 0, rc = -ENODEV; j < nr_apqns && rc; j++) { - rc = pkey_cca_key2protkey(apqns[j].card, - apqns[j].domain, - key, keylen, - protkey, protkeylen, - protkeytype); - } - } - - kfree(local_apqns); - - return rc; -} - -static int ep11key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns, - const u8 *key, size_t keylen, - u8 *protkey, u32 *protkeylen, u32 *protkeytype) -{ - struct pkey_apqn *local_apqns = NULL; - int i, j, rc; - - /* alloc space for list of apqns if no list given */ - if (!apqns || (nr_apqns == 1 && - apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { - nr_apqns = MAXAPQNSINLIST; - local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), - GFP_KERNEL); - if (!local_apqns) - return -ENOMEM; - apqns = local_apqns; - } - - /* try two times in case of failure */ - for (i = 0, rc = -ENODEV; i < 2 && rc; i++) { - if (local_apqns) { - /* gather list of apqns able to deal with this key */ - nr_apqns = MAXAPQNSINLIST; - rc = pkey_ep11_apqns4key(key, keylen, 0, - local_apqns, &nr_apqns); - if (rc) - continue; - } - /* go through the list of apqns until success or end */ - for (j = 0, rc = -ENODEV; j < nr_apqns && rc; j++) { - rc = pkey_ep11_key2protkey(apqns[j].card, - apqns[j].domain, - key, keylen, - protkey, protkeylen, - protkeytype); - } - } - - kfree(local_apqns); - - return rc; -} - -static int pckmokey2protkey_fallback(const struct clearkeytoken *t, - u8 *protkey, u32 *protkeylen, u32 *protkeytype) +static int key2protkey_fallback(const struct clearkeytoken *t, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { size_t tmpbuflen = max_t(size_t, SECKEYBLOBSIZE, MAXEP11AESKEYBLOBSIZE); - struct pkey_apqn *apqns = NULL; - u32 keysize, tmplen; + u32 keysize, keybitsize, tmplen; u8 *tmpbuf = NULL; - size_t nr_apqns; - int i, j, rc; + int i, rc; /* As of now only for AES keys a fallback is available */ @@ -289,110 +44,53 @@ static int pckmokey2protkey_fallback(const struct clearkeytoken *t, __func__, t->len); return -EINVAL; } + keybitsize = 8 * keysize; - /* alloc tmp buffer and space for apqns */ + /* alloc tmp key buffer */ tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); if (!tmpbuf) return -ENOMEM; - nr_apqns = MAXAPQNSINLIST; - apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), GFP_KERNEL); - if (!apqns) { - kfree(tmpbuf); - return -ENOMEM; - } /* try two times in case of failure */ for (i = 0, rc = -ENODEV; i < 2 && rc; i++) { /* CCA secure key way */ - nr_apqns = MAXAPQNSINLIST; - rc = pkey_cca_apqns4type(PKEY_TYPE_CCA_DATA, - NULL, NULL, 0, apqns, &nr_apqns); - pr_debug("pkey_cca_apqns4type(CCA_DATA)=%d\n", rc); - if (rc) - goto try_via_ep11; - for (j = 0, rc = -ENODEV; j < nr_apqns && rc; j++) { - tmplen = tmpbuflen; - rc = pkey_cca_clr2key(apqns[j].card, apqns[j].domain, - t->keytype, PKEY_TYPE_CCA_DATA, - 8 * keysize, 0, - t->clearkey, t->len, - tmpbuf, &tmplen, NULL); - pr_debug("pkey_cca_clr2key()=%d\n", rc); - } + tmplen = tmpbuflen; + rc = pkey_handler_clr_to_key(NULL, 0, + t->keytype, PKEY_TYPE_CCA_DATA, + keybitsize, 0, + t->clearkey, t->len, + tmpbuf, &tmplen, NULL); + pr_debug("clr_to_key()=%d\n", rc); if (rc) goto try_via_ep11; - for (j = 0, rc = -ENODEV; j < nr_apqns && rc; j++) { - rc = pkey_cca_key2protkey(apqns[j].card, - apqns[j].domain, - tmpbuf, tmplen, - protkey, protkeylen, - protkeytype); - pr_debug("pkey_cca_key2protkey()=%d\n", rc); - } + rc = pkey_handler_key_to_protkey(NULL, 0, + tmpbuf, tmplen, + protkey, protkeylen, + protkeytype); + pr_debug("key_to_protkey()=%d\n", rc); if (!rc) break; try_via_ep11: /* the CCA way failed, try via EP11 */ - nr_apqns = MAXAPQNSINLIST; - rc = pkey_ep11_apqns4type(PKEY_TYPE_EP11_AES, - NULL, NULL, 0, apqns, &nr_apqns); - pr_debug("pkey_ep11_apqns4type(EP11_AES)=%d\n", rc); - if (rc) - continue; - for (j = 0, rc = -ENODEV; j < nr_apqns && rc; j++) { - tmplen = tmpbuflen; - rc = pkey_ep11_clr2key(apqns[j].card, apqns[j].domain, - t->keytype, PKEY_TYPE_EP11_AES, - 8 * keysize, 0, - t->clearkey, t->len, - tmpbuf, &tmplen, NULL); - pr_debug("pkey_ep11_clr2key()=%d\n", rc); - } + tmplen = tmpbuflen; + rc = pkey_handler_clr_to_key(NULL, 0, + t->keytype, PKEY_TYPE_EP11_AES, + keybitsize, 0, + t->clearkey, t->len, + tmpbuf, &tmplen, NULL); + pr_debug("clr_to_key()=%d\n", rc); if (rc) continue; - for (j = 0, rc = -ENODEV; j < nr_apqns && rc; j++) { - rc = pkey_ep11_key2protkey(apqns[j].card, - apqns[j].domain, - tmpbuf, tmplen, - protkey, protkeylen, - protkeytype); - pr_debug("pkey_ep11_key2protkey()=%d\n", rc); - } + rc = pkey_handler_key_to_protkey(NULL, 0, + tmpbuf, tmplen, + protkey, protkeylen, + protkeytype); + pr_debug("key_to_protkey()=%d\n", rc); } kfree(tmpbuf); - kfree(apqns); - - return rc; -} - -static int pckmokey2protkey(const u8 *key, size_t keylen, - u8 *protkey, u32 *protkeylen, u32 *protkeytype) -{ - int rc; - - rc = pkey_pckmo_key2protkey(0, 0, key, keylen, - protkey, protkeylen, protkeytype); - if (rc == -ENODEV) { - struct keytoken_header *hdr = (struct keytoken_header *)key; - struct clearkeytoken *t = (struct clearkeytoken *)key; - - /* maybe a fallback is possible */ - if (hdr->type == TOKTYPE_NON_CCA && - hdr->version == TOKVER_CLEAR_KEY) { - rc = pckmokey2protkey_fallback(t, protkey, - protkeylen, - protkeytype); - if (rc) - rc = -ENODEV; - } - } - - if (rc) - PKEY_DBF_ERR("%s unable to build protected key from clear, rc=%d", - __func__, rc); return rc; } @@ -401,22 +99,26 @@ static int key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns, const u8 *key, size_t keylen, u8 *protkey, u32 *protkeylen, u32 *protkeytype) { - if (pkey_is_cca_key(key, keylen)) { - return ccakey2protkey(apqns, nr_apqns, key, keylen, - protkey, protkeylen, protkeytype); - } else if (pkey_is_ep11_key(key, keylen)) { - return ep11key2protkey(apqns, nr_apqns, key, keylen, - protkey, protkeylen, protkeytype); - } else if (pkey_is_pckmo_key(key, keylen)) { - return pckmokey2protkey(key, keylen, - protkey, protkeylen, protkeytype); - } else { - struct keytoken_header *hdr = (struct keytoken_header *)key; - - PKEY_DBF_ERR("%s unknown/unsupported key type %d version %d\n", - __func__, hdr->type, hdr->version); - return -EINVAL; + struct keytoken_header *hdr = (struct keytoken_header *)key; + int i, rc; + + /* retry two times */ + for (rc = -ENODEV, i = 0; rc && i < 2; i++) { + /* First try the direct way */ + rc = pkey_handler_key_to_protkey(apqns, nr_apqns, + key, keylen, + protkey, protkeylen, + protkeytype); + /* For some clear key tokens there exists a fallback way */ + if (rc && + hdr->type == TOKTYPE_NON_CCA && + hdr->version == TOKVER_CLEAR_KEY) + rc = key2protkey_fallback((struct clearkeytoken *)key, + protkey, protkeylen, + protkeytype); } + + return rc; } /* @@ -453,16 +155,20 @@ static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) static int pkey_ioctl_genseck(struct pkey_genseck __user *ugs) { struct pkey_genseck kgs; + struct pkey_apqn apqn; u32 keybuflen; int rc; if (copy_from_user(&kgs, ugs, sizeof(kgs))) return -EFAULT; + + apqn.card = kgs.cardnr; + apqn.domain = kgs.domain; keybuflen = sizeof(kgs.seckey.seckey); - rc = pkey_cca_gen_key(kgs.cardnr, kgs.domain, - kgs.keytype, PKEY_TYPE_CCA_DATA, 0, 0, - kgs.seckey.seckey, &keybuflen, NULL); - pr_debug("pkey_cca_gen_key()=%d\n", rc); + rc = pkey_handler_gen_key(&apqn, 1, + kgs.keytype, PKEY_TYPE_CCA_DATA, 0, 0, + kgs.seckey.seckey, &keybuflen, NULL); + pr_debug("gen_key()=%d\n", rc); if (!rc && copy_to_user(ugs, &kgs, sizeof(kgs))) rc = -EFAULT; memzero_explicit(&kgs, sizeof(kgs)); @@ -473,18 +179,22 @@ static int pkey_ioctl_genseck(struct pkey_genseck __user *ugs) static int pkey_ioctl_clr2seck(struct pkey_clr2seck __user *ucs) { struct pkey_clr2seck kcs; + struct pkey_apqn apqn; u32 keybuflen; int rc; if (copy_from_user(&kcs, ucs, sizeof(kcs))) return -EFAULT; + + apqn.card = kcs.cardnr; + apqn.domain = kcs.domain; keybuflen = sizeof(kcs.seckey.seckey); - rc = pkey_cca_clr2key(kcs.cardnr, kcs.domain, - kcs.keytype, PKEY_TYPE_CCA_DATA, 0, 0, - kcs.clrkey.clrkey, - pkey_keytype_aes_to_size(kcs.keytype), - kcs.seckey.seckey, &keybuflen, NULL); - pr_debug("pkey_cca_clr2key()=%d\n", rc); + rc = pkey_handler_clr_to_key(&apqn, 1, + kcs.keytype, PKEY_TYPE_CCA_DATA, 0, 0, + kcs.clrkey.clrkey, + pkey_keytype_aes_to_size(kcs.keytype), + kcs.seckey.seckey, &keybuflen, NULL); + pr_debug("clr_to_key()=%d\n", rc); if (!rc && copy_to_user(ucs, &kcs, sizeof(kcs))) rc = -EFAULT; memzero_explicit(&kcs, sizeof(kcs)); @@ -495,16 +205,21 @@ static int pkey_ioctl_clr2seck(struct pkey_clr2seck __user *ucs) static int pkey_ioctl_sec2protk(struct pkey_sec2protk __user *usp) { struct pkey_sec2protk ksp; + struct pkey_apqn apqn; int rc; if (copy_from_user(&ksp, usp, sizeof(ksp))) return -EFAULT; + + apqn.card = ksp.cardnr; + apqn.domain = ksp.domain; ksp.protkey.len = sizeof(ksp.protkey.protkey); - rc = pkey_cca_key2protkey(ksp.cardnr, ksp.domain, - ksp.seckey.seckey, sizeof(ksp.seckey.seckey), - ksp.protkey.protkey, - &ksp.protkey.len, &ksp.protkey.type); - pr_debug("pkey_cca_key2protkey()=%d\n", rc); + rc = pkey_handler_key_to_protkey(&apqn, 1, + ksp.seckey.seckey, + sizeof(ksp.seckey.seckey), + ksp.protkey.protkey, + &ksp.protkey.len, &ksp.protkey.type); + pr_debug("key_to_protkey()=%d\n", rc); if (!rc && copy_to_user(usp, &ksp, sizeof(ksp))) rc = -EFAULT; memzero_explicit(&ksp, sizeof(ksp)); @@ -515,16 +230,43 @@ static int pkey_ioctl_sec2protk(struct pkey_sec2protk __user *usp) static int pkey_ioctl_clr2protk(struct pkey_clr2protk __user *ucp) { struct pkey_clr2protk kcp; + struct clearkeytoken *t; + u32 keylen; + u8 *tmpbuf; int rc; if (copy_from_user(&kcp, ucp, sizeof(kcp))) return -EFAULT; + + /* build a 'clear key token' from the clear key value */ + keylen = pkey_keytype_aes_to_size(kcp.keytype); + if (!keylen) { + PKEY_DBF_ERR("%s unknown/unsupported keytype %u\n", + __func__, kcp.keytype); + memzero_explicit(&kcp, sizeof(kcp)); + return -EINVAL; + } + tmpbuf = kzalloc(sizeof(*t) + keylen, GFP_KERNEL); + if (!tmpbuf) { + memzero_explicit(&kcp, sizeof(kcp)); + return -ENOMEM; + } + t = (struct clearkeytoken *)tmpbuf; + t->type = TOKTYPE_NON_CCA; + t->version = TOKVER_CLEAR_KEY; + t->keytype = (keylen - 8) >> 3; + t->len = keylen; + memcpy(t->clearkey, kcp.clrkey.clrkey, keylen); kcp.protkey.len = sizeof(kcp.protkey.protkey); - rc = pkey_pckmo_clr2key(0, 0, kcp.keytype, 0, 0, 0, - kcp.clrkey.clrkey, 0, - kcp.protkey.protkey, - &kcp.protkey.len, &kcp.protkey.type); - pr_debug("pkey_pckmo_clr2key()=%d\n", rc); + + rc = key2protkey(NULL, 0, + tmpbuf, sizeof(*t) + keylen, + kcp.protkey.protkey, + &kcp.protkey.len, &kcp.protkey.type); + pr_debug("key2protkey()=%d\n", rc); + + kfree_sensitive(tmpbuf); + if (!rc && copy_to_user(ucp, &kcp, sizeof(kcp))) rc = -EFAULT; memzero_explicit(&kcp, sizeof(kcp)); @@ -542,23 +284,21 @@ static int pkey_ioctl_findcard(struct pkey_findcard __user *ufc) if (copy_from_user(&kfc, ufc, sizeof(kfc))) return -EFAULT; - if (!pkey_is_cca_key(kfc.seckey.seckey, sizeof(kfc.seckey.seckey))) - return -EINVAL; - nr_apqns = MAXAPQNSINLIST; apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), GFP_KERNEL); if (!apqns) return -ENOMEM; - rc = pkey_cca_apqns4key(kfc.seckey.seckey, - sizeof(kfc.seckey.seckey), - PKEY_FLAGS_MATCH_CUR_MKVP, - apqns, &nr_apqns); - if (rc == -ENODEV) - rc = pkey_cca_apqns4key(kfc.seckey.seckey, + + rc = pkey_handler_apqns_for_key(kfc.seckey.seckey, sizeof(kfc.seckey.seckey), - PKEY_FLAGS_MATCH_ALT_MKVP, + PKEY_FLAGS_MATCH_CUR_MKVP, apqns, &nr_apqns); - pr_debug("pkey_cca_apqns4key()=%d\n", rc); + if (rc == -ENODEV) + rc = pkey_handler_apqns_for_key(kfc.seckey.seckey, + sizeof(kfc.seckey.seckey), + PKEY_FLAGS_MATCH_ALT_MKVP, + apqns, &nr_apqns); + pr_debug("apqns_for_key()=%d\n", rc); if (rc) { kfree(apqns); return rc; @@ -575,38 +315,19 @@ static int pkey_ioctl_findcard(struct pkey_findcard __user *ufc) static int pkey_ioctl_skey2pkey(struct pkey_skey2pkey __user *usp) { struct pkey_skey2pkey ksp; - struct pkey_apqn *apqns; - size_t nr_apqns; - int i, rc; + int rc; if (copy_from_user(&ksp, usp, sizeof(ksp))) return -EFAULT; - if (!pkey_is_cca_key(ksp.seckey.seckey, sizeof(ksp.seckey.seckey))) - return -EINVAL; - - nr_apqns = MAXAPQNSINLIST; - apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), GFP_KERNEL); - if (!apqns) - return -ENOMEM; - rc = pkey_cca_apqns4key(ksp.seckey.seckey, sizeof(ksp.seckey.seckey), - 0, apqns, &nr_apqns); - pr_debug("pkey_cca_apqns4key()=%d\n", rc); - if (rc) { - kfree(apqns); - return rc; - } ksp.protkey.len = sizeof(ksp.protkey.protkey); - for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { - rc = pkey_cca_key2protkey(apqns[i].card, apqns[i].domain, - ksp.seckey.seckey, - sizeof(ksp.seckey.seckey), - ksp.protkey.protkey, - &ksp.protkey.len, - &ksp.protkey.type); - pr_debug("pkey_cca_key2protkey()=%d\n", rc); - } - kfree(apqns); + rc = pkey_handler_key_to_protkey(NULL, 0, + ksp.seckey.seckey, + sizeof(ksp.seckey.seckey), + ksp.protkey.protkey, + &ksp.protkey.len, + &ksp.protkey.type); + pr_debug("key_to_protkey()=%d\n", rc); if (!rc && copy_to_user(usp, &ksp, sizeof(ksp))) rc = -EFAULT; memzero_explicit(&ksp, sizeof(ksp)); @@ -622,12 +343,14 @@ static int pkey_ioctl_verifykey(struct pkey_verifykey __user *uvk) if (copy_from_user(&kvk, uvk, sizeof(kvk))) return -EFAULT; + kvk.cardnr = 0xFFFF; kvk.domain = 0xFFFF; - rc = pkey_cca_verifykey(kvk.seckey.seckey, sizeof(kvk.seckey.seckey), - &kvk.cardnr, &kvk.domain, - &keytype, &keybitsize, &flags); - pr_debug("pkey_cca_verifykey()=%d\n", rc); + rc = pkey_handler_verify_key(kvk.seckey.seckey, + sizeof(kvk.seckey.seckey), + &kvk.cardnr, &kvk.domain, + &keytype, &keybitsize, &flags); + pr_debug("verify_key()=%d\n", rc); if (!rc && keytype != PKEY_TYPE_CCA_DATA) rc = -EINVAL; kvk.attributes = PKEY_VERIFY_ATTR_AES; @@ -648,11 +371,13 @@ static int pkey_ioctl_genprotk(struct pkey_genprotk __user *ugp) if (copy_from_user(&kgp, ugp, sizeof(kgp))) return -EFAULT; + kgp.protkey.len = sizeof(kgp.protkey.protkey); - rc = pkey_pckmo_gen_key(0, 0, kgp.keytype, 0, 0, 0, - kgp.protkey.protkey, - &kgp.protkey.len, &kgp.protkey.type); - pr_debug("pkey_pckmo_gen_key()=%d\n", rc); + rc = pkey_handler_gen_key(NULL, 0, kgp.keytype, + PKEY_TYPE_PROTKEY, 0, 0, + kgp.protkey.protkey, &kgp.protkey.len, + &kgp.protkey.type); + pr_debug("gen_key()=%d\n", rc); if (!rc && copy_to_user(ugp, &kgp, sizeof(kgp))) rc = -EFAULT; memzero_explicit(&kgp, sizeof(kgp)); @@ -663,13 +388,40 @@ static int pkey_ioctl_genprotk(struct pkey_genprotk __user *ugp) static int pkey_ioctl_verifyprotk(struct pkey_verifyprotk __user *uvp) { struct pkey_verifyprotk kvp; + struct protaeskeytoken *t; + u32 keytype; + u8 *tmpbuf; int rc; if (copy_from_user(&kvp, uvp, sizeof(kvp))) return -EFAULT; - rc = pkey_pckmo_verifykey(kvp.protkey.protkey, kvp.protkey.len, - 0, 0, &kvp.protkey.type, 0, 0); - pr_debug("pkey_pckmo_verifykey()=%d\n", rc); + + keytype = pkey_aes_bitsize_to_keytype(8 * kvp.protkey.len); + if (!keytype) { + PKEY_DBF_ERR("%s unknown/unsupported protkey length %u\n", + __func__, kvp.protkey.len); + memzero_explicit(&kvp, sizeof(kvp)); + return -EINVAL; + } + + /* build a 'protected key token' from the raw protected key */ + tmpbuf = kzalloc(sizeof(*t), GFP_KERNEL); + if (!tmpbuf) { + memzero_explicit(&kvp, sizeof(kvp)); + return -ENOMEM; + } + t = (struct protaeskeytoken *)tmpbuf; + t->type = TOKTYPE_NON_CCA; + t->version = TOKVER_PROTECTED_KEY; + t->keytype = keytype; + t->len = kvp.protkey.len; + memcpy(t->protkey, kvp.protkey.protkey, kvp.protkey.len); + + rc = pkey_handler_verify_key(tmpbuf, sizeof(*t), + NULL, NULL, NULL, NULL, NULL); + pr_debug("verify_key()=%d\n", rc); + + kfree_sensitive(tmpbuf); memzero_explicit(&kvp, sizeof(kvp)); return rc; @@ -706,9 +458,16 @@ static int pkey_ioctl_genseck2(struct pkey_genseck2 __user *ugs) struct pkey_apqn *apqns; u8 *kkey; int rc; + u32 u; if (copy_from_user(&kgs, ugs, sizeof(kgs))) return -EFAULT; + u = pkey_aes_bitsize_to_keytype(kgs.size); + if (!u) { + PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n", + __func__, kgs.size); + return -EINVAL; + } apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); if (IS_ERR(apqns)) return PTR_ERR(apqns); @@ -717,10 +476,10 @@ static int pkey_ioctl_genseck2(struct pkey_genseck2 __user *ugs) kfree(apqns); return -ENOMEM; } - rc = genseck2(apqns, kgs.apqn_entries, - kgs.type, kgs.size, kgs.keygenflags, - kkey, &klen); - pr_debug("genseckey2()=%d\n", rc); + rc = pkey_handler_gen_key(apqns, kgs.apqn_entries, + u, kgs.type, kgs.size, kgs.keygenflags, + kkey, &klen, NULL); + pr_debug("gen_key()=%d\n", rc); kfree(apqns); if (rc) { kfree_sensitive(kkey); @@ -751,9 +510,17 @@ static int pkey_ioctl_clr2seck2(struct pkey_clr2seck2 __user *ucs) struct pkey_apqn *apqns; u8 *kkey; int rc; + u32 u; if (copy_from_user(&kcs, ucs, sizeof(kcs))) return -EFAULT; + u = pkey_aes_bitsize_to_keytype(kcs.size); + if (!u) { + PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n", + __func__, kcs.size); + memzero_explicit(&kcs, sizeof(kcs)); + return -EINVAL; + } apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); if (IS_ERR(apqns)) { memzero_explicit(&kcs, sizeof(kcs)); @@ -765,10 +532,11 @@ static int pkey_ioctl_clr2seck2(struct pkey_clr2seck2 __user *ucs) memzero_explicit(&kcs, sizeof(kcs)); return -ENOMEM; } - rc = clr2seckey2(apqns, kcs.apqn_entries, - kcs.type, kcs.size, kcs.keygenflags, - kcs.clrkey.clrkey, kkey, &klen); - pr_debug("clr2seckey2()=%d\n", rc); + rc = pkey_handler_clr_to_key(apqns, kcs.apqn_entries, + u, kcs.type, kcs.size, kcs.keygenflags, + kcs.clrkey.clrkey, kcs.size / 8, + kkey, &klen, NULL); + pr_debug("clr_to_key()=%d\n", rc); kfree(apqns); if (rc) { kfree_sensitive(kkey); @@ -807,26 +575,17 @@ static int pkey_ioctl_verifykey2(struct pkey_verifykey2 __user *uvk) kkey = _copy_key_from_user(kvk.key, kvk.keylen); if (IS_ERR(kkey)) return PTR_ERR(kkey); - if (pkey_is_cca_key(kkey, kvk.keylen)) { - rc = pkey_cca_verifykey(kkey, kvk.keylen, - &kvk.cardnr, &kvk.domain, - &kvk.type, &kvk.size, &kvk.flags); - pr_debug("pkey_cca_verifykey()=%d\n", rc); - } else if (pkey_is_ep11_key(kkey, kvk.keylen)) { - rc = pkey_ep11_verifykey(kkey, kvk.keylen, - &kvk.cardnr, &kvk.domain, - &kvk.type, &kvk.size, &kvk.flags); - pr_debug("pkey_ep11_verifykey()=%d\n", rc); - } else { - rc = -EINVAL; - } + + rc = pkey_handler_verify_key(kkey, kvk.keylen, + &kvk.cardnr, &kvk.domain, + &kvk.type, &kvk.size, &kvk.flags); + pr_debug("verify_key()=%d\n", rc); + kfree_sensitive(kkey); - if (rc) - return rc; - if (copy_to_user(uvk, &kvk, sizeof(kvk))) + if (!rc && copy_to_user(uvk, &kvk, sizeof(kvk))) return -EFAULT; - return 0; + return rc; } static int pkey_ioctl_kblob2protk2(struct pkey_kblob2pkey2 __user *utp) @@ -883,9 +642,9 @@ static int pkey_ioctl_apqns4k(struct pkey_apqns4key __user *uak) kfree(apqns); return PTR_ERR(kkey); } - rc = apqns4key(kkey, kak.keylen, kak.flags, - apqns, &nr_apqns); - pr_debug("apqns4key()=%d\n", rc); + rc = pkey_handler_apqns_for_key(kkey, kak.keylen, kak.flags, + apqns, &nr_apqns); + pr_debug("apqns_for_key()=%d\n", rc); kfree_sensitive(kkey); if (rc && rc != -ENOSPC) { kfree(apqns); @@ -929,9 +688,10 @@ static int pkey_ioctl_apqns4kt(struct pkey_apqns4keytype __user *uat) if (!apqns) return -ENOMEM; } - rc = apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, - kat.flags, apqns, &nr_apqns); - pr_debug("apqns4keytype()=%d\n", rc); + rc = pkey_handler_apqns_for_keytype(kat.type, + kat.cur_mkvp, kat.alt_mkvp, + kat.flags, apqns, &nr_apqns); + pr_debug("apqns_for_keytype()=%d\n", rc); if (rc && rc != -ENOSPC) { kfree(apqns); return rc; @@ -1092,43 +852,13 @@ static struct miscdevice pkey_dev = { .groups = pkey_attr_groups, }; -/* - * Module init - */ -static int __init pkey_init(void) +int __init pkey_api_init(void) { - cpacf_mask_t func_mask; - - /* - * The pckmo instruction should be available - even if we don't - * actually invoke it. This instruction comes with MSA 3 which - * is also the minimum level for the kmc instructions which - * are able to work with protected keys. - */ - if (!cpacf_query(CPACF_PCKMO, &func_mask)) - return -ENODEV; - - /* check for kmc instructions available */ - if (!cpacf_query(CPACF_KMC, &func_mask)) - return -ENODEV; - if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) || - !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) || - !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256)) - return -ENODEV; - - pkey_debug_init(); - + /* register as a misc device */ return misc_register(&pkey_dev); } -/* - * Module exit - */ -static void __exit pkey_exit(void) +void __exit pkey_api_exit(void) { misc_deregister(&pkey_dev); - pkey_debug_exit(); } - -module_cpu_feature_match(S390_CPU_FEATURE_MSA, pkey_init); -module_exit(pkey_exit); diff --git a/drivers/s390/crypto/pkey_base.c b/drivers/s390/crypto/pkey_base.c new file mode 100644 index 000000000000..e7abc32ca5f9 --- /dev/null +++ b/drivers/s390/crypto/pkey_base.c @@ -0,0 +1,293 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * pkey base: debug feature, pkey handler registry + * + * Copyright IBM Corp. 2024 + */ + +#define KMSG_COMPONENT "pkey" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + +#include <linux/cpufeature.h> +#include <linux/init.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/rculist.h> + +#include "pkey_base.h" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("IBM Corporation"); +MODULE_DESCRIPTION("s390 protected key base and api"); + +/* + * pkey debug feature + */ +debug_info_t *pkey_dbf_info; +EXPORT_SYMBOL(pkey_dbf_info); + +/* + * pkey handler registry + */ + +static DEFINE_SPINLOCK(handler_list_write_lock); +static LIST_HEAD(handler_list); + +int pkey_handler_register(struct pkey_handler *handler) +{ + const struct pkey_handler *h; + + if (!handler || + !handler->is_supported_key || + !handler->is_supported_keytype) + return -EINVAL; + + if (!try_module_get(handler->module)) + return -ENXIO; + + spin_lock(&handler_list_write_lock); + + rcu_read_lock(); + list_for_each_entry_rcu(h, &handler_list, list) { + if (h == handler) { + rcu_read_unlock(); + spin_unlock(&handler_list_write_lock); + module_put(handler->module); + return -EEXIST; + } + } + rcu_read_unlock(); + + list_add_rcu(&handler->list, &handler_list); + spin_unlock(&handler_list_write_lock); + synchronize_rcu(); + + module_put(handler->module); + + PKEY_DBF_INFO("%s pkey handler '%s' registered\n", __func__, + handler->name ?: "<no name>"); + + return 0; +} +EXPORT_SYMBOL(pkey_handler_register); + +int pkey_handler_unregister(struct pkey_handler *handler) +{ + spin_lock(&handler_list_write_lock); + list_del_rcu(&handler->list); + INIT_LIST_HEAD_RCU(&handler->list); + spin_unlock(&handler_list_write_lock); + synchronize_rcu(); + + PKEY_DBF_INFO("%s pkey handler '%s' unregistered\n", __func__, + handler->name ?: "<no name>"); + + return 0; +} +EXPORT_SYMBOL(pkey_handler_unregister); + +/* + * Handler invocation functions. + */ + +const struct pkey_handler *pkey_handler_get_keybased(const u8 *key, u32 keylen) +{ + const struct pkey_handler *h; + + rcu_read_lock(); + list_for_each_entry_rcu(h, &handler_list, list) { + if (!try_module_get(h->module)) + continue; + if (h->is_supported_key(key, keylen)) { + rcu_read_unlock(); + return h; + } + module_put(h->module); + } + rcu_read_unlock(); + + return NULL; +} +EXPORT_SYMBOL(pkey_handler_get_keybased); + +const struct pkey_handler *pkey_handler_get_keytypebased(enum pkey_key_type kt) +{ + const struct pkey_handler *h; + + rcu_read_lock(); + list_for_each_entry_rcu(h, &handler_list, list) { + if (!try_module_get(h->module)) + continue; + if (h->is_supported_keytype(kt)) { + rcu_read_unlock(); + return h; + } + module_put(h->module); + } + rcu_read_unlock(); + + return NULL; +} +EXPORT_SYMBOL(pkey_handler_get_keytypebased); + +void pkey_handler_put(const struct pkey_handler *handler) +{ + const struct pkey_handler *h; + + if (!handler) + return; + + rcu_read_lock(); + list_for_each_entry_rcu(h, &handler_list, list) { + if (h == handler) { + module_put(h->module); + break; + } + } + rcu_read_unlock(); +} +EXPORT_SYMBOL(pkey_handler_put); + +int pkey_handler_key_to_protkey(const struct pkey_apqn *apqns, size_t nr_apqns, + const u8 *key, u32 keylen, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) +{ + const struct pkey_handler *h; + int rc = -ENODEV; + + h = pkey_handler_get_keybased(key, keylen); + if (h && h->key_to_protkey) { + rc = h->key_to_protkey(apqns, nr_apqns, key, keylen, + protkey, protkeylen, + protkeytype); + } + pkey_handler_put(h); + + return rc; +} +EXPORT_SYMBOL(pkey_handler_key_to_protkey); + +int pkey_handler_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns, + u32 keytype, u32 keysubtype, + u32 keybitsize, u32 flags, + u8 *keybuf, u32 *keybuflen, u32 *keyinfo) +{ + const struct pkey_handler *h; + int rc = -ENODEV; + + h = pkey_handler_get_keytypebased(keysubtype); + if (h && h->gen_key) { + rc = h->gen_key(apqns, nr_apqns, keytype, keysubtype, + keybitsize, flags, + keybuf, keybuflen, keyinfo); + } + pkey_handler_put(h); + + return rc; +} +EXPORT_SYMBOL(pkey_handler_gen_key); + +int pkey_handler_clr_to_key(const struct pkey_apqn *apqns, size_t nr_apqns, + u32 keytype, u32 keysubtype, + u32 keybitsize, u32 flags, + const u8 *clrkey, u32 clrkeylen, + u8 *keybuf, u32 *keybuflen, u32 *keyinfo) +{ + const struct pkey_handler *h; + int rc = -ENODEV; + + h = pkey_handler_get_keytypebased(keysubtype); + if (h && h->clr_to_key) { + rc = h->clr_to_key(apqns, nr_apqns, keytype, keysubtype, + keybitsize, flags, clrkey, clrkeylen, + keybuf, keybuflen, keyinfo); + } + pkey_handler_put(h); + + return rc; +} +EXPORT_SYMBOL(pkey_handler_clr_to_key); + +int pkey_handler_verify_key(const u8 *key, u32 keylen, + u16 *card, u16 *dom, + u32 *keytype, u32 *keybitsize, u32 *flags) +{ + const struct pkey_handler *h; + int rc = -ENODEV; + + h = pkey_handler_get_keybased(key, keylen); + if (h && h->verify_key) { + rc = h->verify_key(key, keylen, card, dom, + keytype, keybitsize, flags); + } + pkey_handler_put(h); + + return rc; +} +EXPORT_SYMBOL(pkey_handler_verify_key); + +int pkey_handler_apqns_for_key(const u8 *key, u32 keylen, u32 flags, + struct pkey_apqn *apqns, size_t *nr_apqns) +{ + const struct pkey_handler *h; + int rc = -ENODEV; + + h = pkey_handler_get_keybased(key, keylen); + if (h && h->apqns_for_key) + rc = h->apqns_for_key(key, keylen, flags, apqns, nr_apqns); + pkey_handler_put(h); + + return rc; +} +EXPORT_SYMBOL(pkey_handler_apqns_for_key); + +int pkey_handler_apqns_for_keytype(enum pkey_key_type keysubtype, + u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, + struct pkey_apqn *apqns, size_t *nr_apqns) +{ + const struct pkey_handler *h; + int rc = -ENODEV; + + h = pkey_handler_get_keytypebased(keysubtype); + if (h && h->apqns_for_keytype) { + rc = h->apqns_for_keytype(keysubtype, + cur_mkvp, alt_mkvp, flags, + apqns, nr_apqns); + } + pkey_handler_put(h); + + return rc; +} +EXPORT_SYMBOL(pkey_handler_apqns_for_keytype); + +/* + * Module init + */ +static int __init pkey_init(void) +{ + int rc; + + /* init debug feature */ + pkey_dbf_info = debug_register("pkey", 1, 1, 5 * sizeof(long)); + debug_register_view(pkey_dbf_info, &debug_sprintf_view); + debug_set_level(pkey_dbf_info, 4); + + /* the handler registry does not need any init */ + + rc = pkey_api_init(); + if (rc) + debug_unregister(pkey_dbf_info); + + return rc; +} + +/* + * Module exit + */ +static void __exit pkey_exit(void) +{ + pkey_api_exit(); +} + +module_cpu_feature_match(S390_CPU_FEATURE_MSA, pkey_init); +module_exit(pkey_exit); diff --git a/drivers/s390/crypto/pkey_base.h b/drivers/s390/crypto/pkey_base.h index 560106cbd450..7f97c6e598da 100644 --- a/drivers/s390/crypto/pkey_base.h +++ b/drivers/s390/crypto/pkey_base.h @@ -86,84 +86,84 @@ static inline u32 pkey_aes_bitsize_to_keytype(u32 keybitsize) } /* - * pkey_cca.c: + * pkey_api.c: */ - -bool pkey_is_cca_key(const u8 *key, u32 keylen); -bool pkey_is_cca_keytype(enum pkey_key_type); -int pkey_cca_key2protkey(u16 card, u16 dom, - const u8 *key, u32 keylen, - u8 *protkey, u32 *protkeylen, u32 *protkeytype); -int pkey_cca_gen_key(u16 card, u16 dom, - u32 keytype, u32 keysubtype, - u32 keybitsize, u32 flags, - u8 *keybuf, u32 *keybuflen, u32 *_keyinfo); -int pkey_cca_clr2key(u16 card, u16 dom, - u32 keytype, u32 keysubtype, - u32 keybitsize, u32 flags, - const u8 *clrkey, u32 clrkeylen, - u8 *keybuf, u32 *keybuflen, u32 *_keyinfo); -int pkey_cca_verifykey(const u8 *key, u32 keylen, - u16 *card, u16 *dom, - u32 *keytype, u32 *keybitsize, u32 *flags); -int pkey_cca_apqns4key(const u8 *key, u32 keylen, u32 flags, - struct pkey_apqn *apqns, size_t *nr_apqns); -int pkey_cca_apqns4type(enum pkey_key_type ktype, - u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, - struct pkey_apqn *apqns, size_t *nr_apqns); +int __init pkey_api_init(void); +void __exit pkey_api_exit(void); /* - * pkey_ep11.c: + * pkey_sysfs.c: */ -bool pkey_is_ep11_key(const u8 *key, u32 keylen); -bool pkey_is_ep11_keytype(enum pkey_key_type); -int pkey_ep11_key2protkey(u16 card, u16 dom, - const u8 *key, u32 keylen, - u8 *protkey, u32 *protkeylen, u32 *protkeytype); -int pkey_ep11_gen_key(u16 card, u16 dom, - u32 keytype, u32 keysubtype, - u32 keybitsize, u32 flags, - u8 *keybuf, u32 *keybuflen, u32 *_keyinfo); -int pkey_ep11_clr2key(u16 card, u16 dom, - u32 keytype, u32 keysubtype, - u32 keybitsize, u32 flags, - const u8 *clrkey, u32 clrkeylen, - u8 *keybuf, u32 *keybuflen, u32 *_keyinfo); -int pkey_ep11_verifykey(const u8 *key, u32 keylen, - u16 *card, u16 *dom, - u32 *keytype, u32 *keybitsize, u32 *flags); -int pkey_ep11_apqns4key(const u8 *key, u32 keylen, u32 flags, - struct pkey_apqn *apqns, size_t *nr_apqns); -int pkey_ep11_apqns4type(enum pkey_key_type ktype, - u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, - struct pkey_apqn *apqns, size_t *nr_apqns); +extern const struct attribute_group *pkey_attr_groups[]; /* - * pkey_pckmo.c: + * pkey handler registry */ -bool pkey_is_pckmo_key(const u8 *key, u32 keylen); -int pkey_pckmo_key2protkey(u16 _card, u16 _dom, - const u8 *key, u32 keylen, - u8 *protkey, u32 *protkeylen, u32 *protkeytype); -int pkey_pckmo_gen_key(u16 _card, u16 _dom, - u32 keytype, u32 _keysubtype, - u32 _keybitsize, u32 _flags, +struct pkey_handler { + struct module *module; + const char *name; + /* + * is_supported_key() and is_supported_keytype() are called + * within an rcu_read_lock() scope and thus must not sleep! + */ + bool (*is_supported_key)(const u8 *key, u32 keylen); + bool (*is_supported_keytype)(enum pkey_key_type); + int (*key_to_protkey)(const struct pkey_apqn *apqns, size_t nr_apqns, + const u8 *key, u32 keylen, + u8 *protkey, u32 *protkeylen, u32 *protkeytype); + int (*gen_key)(const struct pkey_apqn *apqns, size_t nr_apqns, + u32 keytype, u32 keysubtype, + u32 keybitsize, u32 flags, u8 *keybuf, u32 *keybuflen, u32 *keyinfo); -int pkey_pckmo_clr2key(u16 _card, u16 _dom, - u32 keytype, u32 _keysubtype, - u32 _keybitsize, u32 _flags, - const u8 *clrkey, u32 clrkeylen, - u8 *keybuf, u32 *keybuflen, u32 *keyinfo); -int pkey_pckmo_verifykey(const u8 *key, u32 keylen, - u16 *_card, u16 *_dom, - u32 *keytype, u32 *_keybitsize, u32 *_flags); + int (*clr_to_key)(const struct pkey_apqn *apqns, size_t nr_apqns, + u32 keytype, u32 keysubtype, + u32 keybitsize, u32 flags, + const u8 *clrkey, u32 clrkeylen, + u8 *keybuf, u32 *keybuflen, u32 *keyinfo); + int (*verify_key)(const u8 *key, u32 keylen, + u16 *card, u16 *dom, + u32 *keytype, u32 *keybitsize, u32 *flags); + int (*apqns_for_key)(const u8 *key, u32 keylen, u32 flags, + struct pkey_apqn *apqns, size_t *nr_apqns); + int (*apqns_for_keytype)(enum pkey_key_type ktype, + u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, + struct pkey_apqn *apqns, size_t *nr_apqns); + /* used internal by pkey base */ + struct list_head list; +}; + +int pkey_handler_register(struct pkey_handler *handler); +int pkey_handler_unregister(struct pkey_handler *handler); /* - * pkey_sysfs.c: + * invocation function for the registered pkey handlers */ -extern const struct attribute_group *pkey_attr_groups[]; +const struct pkey_handler *pkey_handler_get_keybased(const u8 *key, u32 keylen); +const struct pkey_handler *pkey_handler_get_keytypebased(enum pkey_key_type kt); +void pkey_handler_put(const struct pkey_handler *handler); + +int pkey_handler_key_to_protkey(const struct pkey_apqn *apqns, size_t nr_apqns, + const u8 *key, u32 keylen, + u8 *protkey, u32 *protkeylen, u32 *protkeytype); +int pkey_handler_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns, + u32 keytype, u32 keysubtype, + u32 keybitsize, u32 flags, + u8 *keybuf, u32 *keybuflen, u32 *keyinfo); +int pkey_handler_clr_to_key(const struct pkey_apqn *apqns, size_t nr_apqns, + u32 keytype, u32 keysubtype, + u32 keybitsize, u32 flags, + const u8 *clrkey, u32 clrkeylen, + u8 *keybuf, u32 *keybuflen, u32 *keyinfo); +int pkey_handler_verify_key(const u8 *key, u32 keylen, + u16 *card, u16 *dom, + u32 *keytype, u32 *keybitsize, u32 *flags); +int pkey_handler_apqns_for_key(const u8 *key, u32 keylen, u32 flags, + struct pkey_apqn *apqns, size_t *nr_apqns); +int pkey_handler_apqns_for_keytype(enum pkey_key_type ktype, + u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, + struct pkey_apqn *apqns, size_t *nr_apqns); #endif /* _PKEY_BASE_H_ */ diff --git a/drivers/s390/crypto/pkey_cca.c b/drivers/s390/crypto/pkey_cca.c index 1bf9019ec561..ba2ae253b2ba 100644 --- a/drivers/s390/crypto/pkey_cca.c +++ b/drivers/s390/crypto/pkey_cca.c @@ -8,15 +8,34 @@ #define KMSG_COMPONENT "pkey" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt +#include <linux/init.h> +#include <linux/module.h> +#include <linux/cpufeature.h> + #include "zcrypt_api.h" #include "zcrypt_ccamisc.h" - #include "pkey_base.h" +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("IBM Corporation"); +MODULE_DESCRIPTION("s390 protected key CCA handler"); + +#if IS_MODULE(CONFIG_PKEY_CCA) +static struct ap_device_id pkey_cca_card_ids[] = { + { .dev_type = AP_DEVICE_TYPE_CEX4 }, + { .dev_type = AP_DEVICE_TYPE_CEX5 }, + { .dev_type = AP_DEVICE_TYPE_CEX6 }, + { .dev_type = AP_DEVICE_TYPE_CEX7 }, + { .dev_type = AP_DEVICE_TYPE_CEX8 }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(ap, pkey_cca_card_ids); +#endif + /* * Check key blob for known and supported CCA key. */ -bool pkey_is_cca_key(const u8 *key, u32 keylen) +static bool is_cca_key(const u8 *key, u32 keylen) { struct keytoken_header *hdr = (struct keytoken_header *)key; @@ -39,7 +58,7 @@ bool pkey_is_cca_key(const u8 *key, u32 keylen) } } -bool pkey_is_cca_keytype(enum pkey_key_type key_type) +static bool is_cca_keytype(enum pkey_key_type key_type) { switch (key_type) { case PKEY_TYPE_CCA_DATA: @@ -51,18 +70,158 @@ bool pkey_is_cca_keytype(enum pkey_key_type key_type) } } -int pkey_cca_key2protkey(u16 card, u16 dom, - const u8 *key, u32 keylen, - u8 *protkey, u32 *protkeylen, u32 *protkeytype) +static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags, + struct pkey_apqn *apqns, size_t *nr_apqns) { struct keytoken_header *hdr = (struct keytoken_header *)key; + u32 _nr_apqns, *_apqns = NULL; int rc; - if (keylen < sizeof(*hdr)) + if (!flags) + flags = PKEY_FLAGS_MATCH_CUR_MKVP | PKEY_FLAGS_MATCH_ALT_MKVP; + + if (keylen < sizeof(struct keytoken_header)) return -EINVAL; zcrypt_wait_api_operational(); + if (hdr->type == TOKTYPE_CCA_INTERNAL) { + u64 cur_mkvp = 0, old_mkvp = 0; + int minhwtype = ZCRYPT_CEX3C; + + if (hdr->version == TOKVER_CCA_AES) { + struct secaeskeytoken *t = (struct secaeskeytoken *)key; + + if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) + cur_mkvp = t->mkvp; + if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) + old_mkvp = t->mkvp; + } else if (hdr->version == TOKVER_CCA_VLSC) { + struct cipherkeytoken *t = (struct cipherkeytoken *)key; + + minhwtype = ZCRYPT_CEX6; + if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) + cur_mkvp = t->mkvp0; + if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) + old_mkvp = t->mkvp0; + } else { + /* unknown CCA internal token type */ + return -EINVAL; + } + rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, + minhwtype, AES_MK_SET, + cur_mkvp, old_mkvp, 1); + if (rc) + goto out; + + } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { + struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; + u64 cur_mkvp = 0, old_mkvp = 0; + + if (t->secid == 0x20) { + if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) + cur_mkvp = t->mkvp; + if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) + old_mkvp = t->mkvp; + } else { + /* unknown CCA internal 2 token type */ + return -EINVAL; + } + rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, + ZCRYPT_CEX7, APKA_MK_SET, + cur_mkvp, old_mkvp, 1); + if (rc) + goto out; + + } else { + PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n", + __func__, hdr->type, hdr->version); + return -EINVAL; + } + + if (apqns) { + if (*nr_apqns < _nr_apqns) + rc = -ENOSPC; + else + memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); + } + *nr_apqns = _nr_apqns; + +out: + kfree(_apqns); + pr_debug("rc=%d\n", rc); + return rc; +} + +static int cca_apqns4type(enum pkey_key_type ktype, + u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, + struct pkey_apqn *apqns, size_t *nr_apqns) +{ + u32 _nr_apqns, *_apqns = NULL; + int rc; + + zcrypt_wait_api_operational(); + + if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { + u64 cur_mkvp = 0, old_mkvp = 0; + int minhwtype = ZCRYPT_CEX3C; + + if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) + cur_mkvp = *((u64 *)cur_mkvp); + if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) + old_mkvp = *((u64 *)alt_mkvp); + if (ktype == PKEY_TYPE_CCA_CIPHER) + minhwtype = ZCRYPT_CEX6; + rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, + minhwtype, AES_MK_SET, + cur_mkvp, old_mkvp, 1); + if (rc) + goto out; + + } else if (ktype == PKEY_TYPE_CCA_ECC) { + u64 cur_mkvp = 0, old_mkvp = 0; + + if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) + cur_mkvp = *((u64 *)cur_mkvp); + if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) + old_mkvp = *((u64 *)alt_mkvp); + rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, + ZCRYPT_CEX7, APKA_MK_SET, + cur_mkvp, old_mkvp, 1); + if (rc) + goto out; + + } else { + PKEY_DBF_ERR("%s unknown/unsupported key type %d", + __func__, (int)ktype); + return -EINVAL; + } + + if (apqns) { + if (*nr_apqns < _nr_apqns) + rc = -ENOSPC; + else + memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); + } + *nr_apqns = _nr_apqns; + +out: + kfree(_apqns); + pr_debug("rc=%d\n", rc); + return rc; +} + +static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns, + const u8 *key, u32 keylen, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) +{ + struct keytoken_header *hdr = (struct keytoken_header *)key; + struct pkey_apqn *local_apqns = NULL; + int i, rc; + + if (keylen < sizeof(*hdr)) + return -EINVAL; + if (hdr->type == TOKTYPE_CCA_INTERNAL && hdr->version == TOKVER_CCA_AES) { /* CCA AES data key */ @@ -70,8 +229,6 @@ int pkey_cca_key2protkey(u16 card, u16 dom, return -EINVAL; if (cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0)) return -EINVAL; - rc = cca_sec2protkey(card, dom, key, protkey, - protkeylen, protkeytype); } else if (hdr->type == TOKTYPE_CCA_INTERNAL && hdr->version == TOKVER_CCA_VLSC) { /* CCA AES cipher key */ @@ -80,23 +237,57 @@ int pkey_cca_key2protkey(u16 card, u16 dom, if (cca_check_secaescipherkey(pkey_dbf_info, 3, key, 0, 1)) return -EINVAL; - rc = cca_cipher2protkey(card, dom, key, protkey, - protkeylen, protkeytype); } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { /* CCA ECC (private) key */ if (keylen < sizeof(struct eccprivkeytoken)) return -EINVAL; if (cca_check_sececckeytoken(pkey_dbf_info, 3, key, keylen, 1)) return -EINVAL; - rc = cca_ecc2protkey(card, dom, key, protkey, - protkeylen, protkeytype); } else { PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n", __func__, hdr->type, hdr->version); - rc = -EINVAL; + return -EINVAL; } - pr_debug("card=%d dom=%d rc=%d\n", card, dom, rc); + zcrypt_wait_api_operational(); + + if (!apqns || (nr_apqns == 1 && + apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { + nr_apqns = MAXAPQNSINLIST; + local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), + GFP_KERNEL); + if (!local_apqns) + return -ENOMEM; + rc = cca_apqns4key(key, keylen, 0, local_apqns, &nr_apqns); + if (rc) + goto out; + apqns = local_apqns; + } + + for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { + if (hdr->type == TOKTYPE_CCA_INTERNAL && + hdr->version == TOKVER_CCA_AES) { + rc = cca_sec2protkey(apqns[i].card, apqns[i].domain, + key, protkey, + protkeylen, protkeytype); + } else if (hdr->type == TOKTYPE_CCA_INTERNAL && + hdr->version == TOKVER_CCA_VLSC) { + rc = cca_cipher2protkey(apqns[i].card, apqns[i].domain, + key, protkey, + protkeylen, protkeytype); + } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { + rc = cca_ecc2protkey(apqns[i].card, apqns[i].domain, + key, protkey, + protkeylen, protkeytype); + } else { + rc = -EINVAL; + break; + } + } + +out: + kfree(local_apqns); + pr_debug("rc=%d\n", rc); return rc; } @@ -109,12 +300,13 @@ int pkey_cca_key2protkey(u16 card, u16 dom, * keybitsize is the bit size of the key (may be 0 for * keytype PKEY_KEYTYPE_AES_*). */ -int pkey_cca_gen_key(u16 card, u16 dom, - u32 keytype, u32 subtype, - u32 keybitsize, u32 flags, - u8 *keybuf, u32 *keybuflen, u32 *_keyinfo) +static int cca_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns, + u32 keytype, u32 subtype, + u32 keybitsize, u32 flags, + u8 *keybuf, u32 *keybuflen, u32 *_keyinfo) { - int len, rc; + struct pkey_apqn *local_apqns = NULL; + int i, len, rc; /* check keytype, subtype, keybitsize */ switch (keytype) { @@ -129,7 +321,6 @@ int pkey_cca_gen_key(u16 card, u16 dom, } keybitsize = 8 * len; switch (subtype) { - case 0: case PKEY_TYPE_CCA_DATA: case PKEY_TYPE_CCA_CIPHER: break; @@ -147,16 +338,36 @@ int pkey_cca_gen_key(u16 card, u16 dom, zcrypt_wait_api_operational(); - if (subtype == PKEY_TYPE_CCA_CIPHER) { - rc = cca_gencipherkey(card, dom, keybitsize, flags, - keybuf, keybuflen); - } else { - /* 0 or PKEY_TYPE_CCA_DATA */ - rc = cca_genseckey(card, dom, keybitsize, keybuf); - *keybuflen = (rc ? 0 : SECKEYBLOBSIZE); + if (!apqns || (nr_apqns == 1 && + apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { + nr_apqns = MAXAPQNSINLIST; + local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), + GFP_KERNEL); + if (!local_apqns) + return -ENOMEM; + rc = cca_apqns4type(subtype, NULL, NULL, 0, + local_apqns, &nr_apqns); + if (rc) + goto out; + apqns = local_apqns; + } + + for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { + if (subtype == PKEY_TYPE_CCA_CIPHER) { + rc = cca_gencipherkey(apqns[i].card, apqns[i].domain, + keybitsize, flags, + keybuf, keybuflen); + } else { + /* PKEY_TYPE_CCA_DATA */ + rc = cca_genseckey(apqns[i].card, apqns[i].domain, + keybitsize, keybuf); + *keybuflen = (rc ? 0 : SECKEYBLOBSIZE); + } } - pr_debug("card=%d dom=%d rc=%d\n", card, dom, rc); +out: + kfree(local_apqns); + pr_debug("rc=%d\n", rc); return rc; } @@ -169,13 +380,14 @@ int pkey_cca_gen_key(u16 card, u16 dom, * keybitsize is the bit size of the key (may be 0 for * keytype PKEY_KEYTYPE_AES_*). */ -int pkey_cca_clr2key(u16 card, u16 dom, - u32 keytype, u32 subtype, - u32 keybitsize, u32 flags, - const u8 *clrkey, u32 clrkeylen, - u8 *keybuf, u32 *keybuflen, u32 *_keyinfo) +static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns, + u32 keytype, u32 subtype, + u32 keybitsize, u32 flags, + const u8 *clrkey, u32 clrkeylen, + u8 *keybuf, u32 *keybuflen, u32 *_keyinfo) { - int len, rc; + struct pkey_apqn *local_apqns = NULL; + int i, len, rc; /* check keytype, subtype, clrkeylen, keybitsize */ switch (keytype) { @@ -195,7 +407,6 @@ int pkey_cca_clr2key(u16 card, u16 dom, return -EINVAL; } switch (subtype) { - case 0: case PKEY_TYPE_CCA_DATA: case PKEY_TYPE_CCA_CIPHER: break; @@ -213,23 +424,42 @@ int pkey_cca_clr2key(u16 card, u16 dom, zcrypt_wait_api_operational(); - if (subtype == PKEY_TYPE_CCA_CIPHER) { - rc = cca_clr2cipherkey(card, dom, keybitsize, - flags, clrkey, keybuf, keybuflen); - } else { - /* 0 or PKEY_TYPE_CCA_DATA */ - rc = cca_clr2seckey(card, dom, keybitsize, - clrkey, keybuf); - *keybuflen = (rc ? 0 : SECKEYBLOBSIZE); + if (!apqns || (nr_apqns == 1 && + apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { + nr_apqns = MAXAPQNSINLIST; + local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), + GFP_KERNEL); + if (!local_apqns) + return -ENOMEM; + rc = cca_apqns4type(subtype, NULL, NULL, 0, + local_apqns, &nr_apqns); + if (rc) + goto out; + apqns = local_apqns; + } + + for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { + if (subtype == PKEY_TYPE_CCA_CIPHER) { + rc = cca_clr2cipherkey(apqns[i].card, apqns[i].domain, + keybitsize, flags, clrkey, + keybuf, keybuflen); + } else { + /* PKEY_TYPE_CCA_DATA */ + rc = cca_clr2seckey(apqns[i].card, apqns[i].domain, + keybitsize, clrkey, keybuf); + *keybuflen = (rc ? 0 : SECKEYBLOBSIZE); + } } - pr_debug("card=%d dom=%d rc=%d\n", card, dom, rc); +out: + kfree(local_apqns); + pr_debug("rc=%d\n", rc); return rc; } -int pkey_cca_verifykey(const u8 *key, u32 keylen, - u16 *card, u16 *dom, - u32 *keytype, u32 *keybitsize, u32 *flags) +static int cca_verifykey(const u8 *key, u32 keylen, + u16 *card, u16 *dom, + u32 *keytype, u32 *keybitsize, u32 *flags) { struct keytoken_header *hdr = (struct keytoken_header *)key; u32 nr_apqns, *apqns = NULL; @@ -311,143 +541,36 @@ out: return rc; } -int pkey_cca_apqns4key(const u8 *key, u32 keylen, u32 flags, - struct pkey_apqn *apqns, size_t *nr_apqns) -{ - struct keytoken_header *hdr = (struct keytoken_header *)key; - u32 _nr_apqns, *_apqns = NULL; - int rc; - - if (!flags) - flags = PKEY_FLAGS_MATCH_CUR_MKVP | PKEY_FLAGS_MATCH_ALT_MKVP; - - if (keylen < sizeof(struct keytoken_header)) - return -EINVAL; - - zcrypt_wait_api_operational(); - - if (hdr->type == TOKTYPE_CCA_INTERNAL) { - u64 cur_mkvp = 0, old_mkvp = 0; - int minhwtype = ZCRYPT_CEX3C; - - if (hdr->version == TOKVER_CCA_AES) { - struct secaeskeytoken *t = (struct secaeskeytoken *)key; - - if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) - cur_mkvp = t->mkvp; - if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) - old_mkvp = t->mkvp; - } else if (hdr->version == TOKVER_CCA_VLSC) { - struct cipherkeytoken *t = (struct cipherkeytoken *)key; - - minhwtype = ZCRYPT_CEX6; - if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) - cur_mkvp = t->mkvp0; - if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) - old_mkvp = t->mkvp0; - } else { - /* unknown CCA internal token type */ - return -EINVAL; - } - rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, - minhwtype, AES_MK_SET, - cur_mkvp, old_mkvp, 1); - if (rc) - goto out; - - } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { - struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; - u64 cur_mkvp = 0, old_mkvp = 0; - - if (t->secid == 0x20) { - if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) - cur_mkvp = t->mkvp; - if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) - old_mkvp = t->mkvp; - } else { - /* unknown CCA internal 2 token type */ - return -EINVAL; - } - rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, - ZCRYPT_CEX7, APKA_MK_SET, - cur_mkvp, old_mkvp, 1); - if (rc) - goto out; +static struct pkey_handler cca_handler = { + .module = THIS_MODULE, + .name = "PKEY CCA handler", + .is_supported_key = is_cca_key, + .is_supported_keytype = is_cca_keytype, + .key_to_protkey = cca_key2protkey, + .gen_key = cca_gen_key, + .clr_to_key = cca_clr2key, + .verify_key = cca_verifykey, + .apqns_for_key = cca_apqns4key, + .apqns_for_keytype = cca_apqns4type, +}; - } else { - PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n", - __func__, hdr->type, hdr->version); - return -EINVAL; - } - - if (apqns) { - if (*nr_apqns < _nr_apqns) - rc = -ENOSPC; - else - memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); - } - *nr_apqns = _nr_apqns; - -out: - kfree(_apqns); - pr_debug("rc=%d\n", rc); - return rc; +/* + * Module init + */ +static int __init pkey_cca_init(void) +{ + /* register this module as pkey handler for all the cca stuff */ + return pkey_handler_register(&cca_handler); } -int pkey_cca_apqns4type(enum pkey_key_type ktype, - u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, - struct pkey_apqn *apqns, size_t *nr_apqns) +/* + * Module exit + */ +static void __exit pkey_cca_exit(void) { - u32 _nr_apqns, *_apqns = NULL; - int rc; - - zcrypt_wait_api_operational(); - - if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { - u64 cur_mkvp = 0, old_mkvp = 0; - int minhwtype = ZCRYPT_CEX3C; - - if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) - cur_mkvp = *((u64 *)cur_mkvp); - if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) - old_mkvp = *((u64 *)alt_mkvp); - if (ktype == PKEY_TYPE_CCA_CIPHER) - minhwtype = ZCRYPT_CEX6; - rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, - minhwtype, AES_MK_SET, - cur_mkvp, old_mkvp, 1); - if (rc) - goto out; - - } else if (ktype == PKEY_TYPE_CCA_ECC) { - u64 cur_mkvp = 0, old_mkvp = 0; - - if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) - cur_mkvp = *((u64 *)cur_mkvp); - if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) - old_mkvp = *((u64 *)alt_mkvp); - rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, - ZCRYPT_CEX7, APKA_MK_SET, - cur_mkvp, old_mkvp, 1); - if (rc) - goto out; - - } else { - PKEY_DBF_ERR("%s unknown/unsupported key type %d", - __func__, (int)ktype); - return -EINVAL; - } - - if (apqns) { - if (*nr_apqns < _nr_apqns) - rc = -ENOSPC; - else - memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); - } - *nr_apqns = _nr_apqns; - -out: - kfree(_apqns); - pr_debug("rc=%d\n", rc); - return rc; + /* unregister this module as pkey handler */ + pkey_handler_unregister(&cca_handler); } + +module_init(pkey_cca_init); +module_exit(pkey_cca_exit); diff --git a/drivers/s390/crypto/pkey_ep11.c b/drivers/s390/crypto/pkey_ep11.c index 4c49e07ece74..624e55195d93 100644 --- a/drivers/s390/crypto/pkey_ep11.c +++ b/drivers/s390/crypto/pkey_ep11.c @@ -8,16 +8,35 @@ #define KMSG_COMPONENT "pkey" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt +#include <linux/init.h> +#include <linux/module.h> +#include <linux/cpufeature.h> + #include "zcrypt_api.h" #include "zcrypt_ccamisc.h" #include "zcrypt_ep11misc.h" - #include "pkey_base.h" +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("IBM Corporation"); +MODULE_DESCRIPTION("s390 protected key EP11 handler"); + +#if IS_MODULE(CONFIG_PKEY_EP11) +static struct ap_device_id pkey_ep11_card_ids[] = { + { .dev_type = AP_DEVICE_TYPE_CEX4 }, + { .dev_type = AP_DEVICE_TYPE_CEX5 }, + { .dev_type = AP_DEVICE_TYPE_CEX6 }, + { .dev_type = AP_DEVICE_TYPE_CEX7 }, + { .dev_type = AP_DEVICE_TYPE_CEX8 }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(ap, pkey_ep11_card_ids); +#endif + /* * Check key blob for known and supported EP11 key. */ -bool pkey_is_ep11_key(const u8 *key, u32 keylen) +static bool is_ep11_key(const u8 *key, u32 keylen) { struct keytoken_header *hdr = (struct keytoken_header *)key; @@ -39,7 +58,7 @@ bool pkey_is_ep11_key(const u8 *key, u32 keylen) } } -bool pkey_is_ep11_keytype(enum pkey_key_type key_type) +static bool is_ep11_keytype(enum pkey_key_type key_type) { switch (key_type) { case PKEY_TYPE_EP11: @@ -51,18 +70,131 @@ bool pkey_is_ep11_keytype(enum pkey_key_type key_type) } } -int pkey_ep11_key2protkey(u16 card, u16 dom, - const u8 *key, u32 keylen, - u8 *protkey, u32 *protkeylen, u32 *protkeytype) +static int ep11_apqns4key(const u8 *key, u32 keylen, u32 flags, + struct pkey_apqn *apqns, size_t *nr_apqns) { struct keytoken_header *hdr = (struct keytoken_header *)key; + u32 _nr_apqns, *_apqns = NULL; int rc; - if (keylen < sizeof(*hdr)) + if (!flags) + flags = PKEY_FLAGS_MATCH_CUR_MKVP; + + if (keylen < sizeof(struct keytoken_header) || flags == 0) + return -EINVAL; + + zcrypt_wait_api_operational(); + + if (hdr->type == TOKTYPE_NON_CCA && + (hdr->version == TOKVER_EP11_AES_WITH_HEADER || + hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && + is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { + struct ep11keyblob *kb = (struct ep11keyblob *) + (key + sizeof(struct ep11kblob_header)); + int minhwtype = 0, api = 0; + + if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) + return -EINVAL; + if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { + minhwtype = ZCRYPT_CEX7; + api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; + } + rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, + minhwtype, api, kb->wkvp); + if (rc) + goto out; + + } else if (hdr->type == TOKTYPE_NON_CCA && + hdr->version == TOKVER_EP11_AES && + is_ep11_keyblob(key)) { + struct ep11keyblob *kb = (struct ep11keyblob *)key; + int minhwtype = 0, api = 0; + + if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) + return -EINVAL; + if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { + minhwtype = ZCRYPT_CEX7; + api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; + } + rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, + minhwtype, api, kb->wkvp); + if (rc) + goto out; + + } else { + PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n", + __func__, hdr->type, hdr->version); return -EINVAL; + } + + if (apqns) { + if (*nr_apqns < _nr_apqns) + rc = -ENOSPC; + else + memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); + } + *nr_apqns = _nr_apqns; + +out: + kfree(_apqns); + pr_debug("rc=%d\n", rc); + return rc; +} + +static int ep11_apqns4type(enum pkey_key_type ktype, + u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, + struct pkey_apqn *apqns, size_t *nr_apqns) +{ + u32 _nr_apqns, *_apqns = NULL; + int rc; zcrypt_wait_api_operational(); + if (ktype == PKEY_TYPE_EP11 || + ktype == PKEY_TYPE_EP11_AES || + ktype == PKEY_TYPE_EP11_ECC) { + u8 *wkvp = NULL; + int api; + + if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) + wkvp = cur_mkvp; + api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; + rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, + ZCRYPT_CEX7, api, wkvp); + if (rc) + goto out; + + } else { + PKEY_DBF_ERR("%s unknown/unsupported key type %d\n", + __func__, (int)ktype); + return -EINVAL; + } + + if (apqns) { + if (*nr_apqns < _nr_apqns) + rc = -ENOSPC; + else + memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); + } + *nr_apqns = _nr_apqns; + +out: + kfree(_apqns); + pr_debug("rc=%d\n", rc); + return rc; +} + +static int ep11_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns, + const u8 *key, u32 keylen, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) +{ + struct keytoken_header *hdr = (struct keytoken_header *)key; + struct pkey_apqn *local_apqns = NULL; + int i, rc; + + if (keylen < sizeof(*hdr)) + return -EINVAL; + if (hdr->type == TOKTYPE_NON_CCA && hdr->version == TOKVER_EP11_AES_WITH_HEADER && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { @@ -70,8 +202,6 @@ int pkey_ep11_key2protkey(u16 card, u16 dom, if (ep11_check_aes_key_with_hdr(pkey_dbf_info, 3, key, keylen, 1)) return -EINVAL; - rc = ep11_kblob2protkey(card, dom, key, hdr->len, - protkey, protkeylen, protkeytype); } else if (hdr->type == TOKTYPE_NON_CCA && hdr->version == TOKVER_EP11_ECC_WITH_HEADER && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { @@ -79,23 +209,61 @@ int pkey_ep11_key2protkey(u16 card, u16 dom, if (ep11_check_ecc_key_with_hdr(pkey_dbf_info, 3, key, keylen, 1)) return -EINVAL; - rc = ep11_kblob2protkey(card, dom, key, hdr->len, - protkey, protkeylen, protkeytype); } else if (hdr->type == TOKTYPE_NON_CCA && hdr->version == TOKVER_EP11_AES && is_ep11_keyblob(key)) { /* EP11 AES key blob with header in session field */ if (ep11_check_aes_key(pkey_dbf_info, 3, key, keylen, 1)) return -EINVAL; - rc = ep11_kblob2protkey(card, dom, key, hdr->len, - protkey, protkeylen, protkeytype); } else { PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n", __func__, hdr->type, hdr->version); return -EINVAL; } - pr_debug("card=%d dom=%d rc=%d\n", card, dom, rc); + zcrypt_wait_api_operational(); + + if (!apqns || (nr_apqns == 1 && + apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { + nr_apqns = MAXAPQNSINLIST; + local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), + GFP_KERNEL); + if (!local_apqns) + return -ENOMEM; + rc = ep11_apqns4key(key, keylen, 0, local_apqns, &nr_apqns); + if (rc) + goto out; + apqns = local_apqns; + } + + for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { + if (hdr->type == TOKTYPE_NON_CCA && + hdr->version == TOKVER_EP11_AES_WITH_HEADER && + is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { + rc = ep11_kblob2protkey(apqns[i].card, apqns[i].domain, + key, hdr->len, protkey, + protkeylen, protkeytype); + } else if (hdr->type == TOKTYPE_NON_CCA && + hdr->version == TOKVER_EP11_ECC_WITH_HEADER && + is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { + rc = ep11_kblob2protkey(apqns[i].card, apqns[i].domain, + key, hdr->len, protkey, + protkeylen, protkeytype); + } else if (hdr->type == TOKTYPE_NON_CCA && + hdr->version == TOKVER_EP11_AES && + is_ep11_keyblob(key)) { + rc = ep11_kblob2protkey(apqns[i].card, apqns[i].domain, + key, hdr->len, protkey, + protkeylen, protkeytype); + } else { + rc = -EINVAL; + break; + } + } + +out: + kfree(local_apqns); + pr_debug("rc=%d\n", rc); return rc; } @@ -108,12 +276,13 @@ int pkey_ep11_key2protkey(u16 card, u16 dom, * keybitsize is the bit size of the key (may be 0 for * keytype PKEY_KEYTYPE_AES_*). */ -int pkey_ep11_gen_key(u16 card, u16 dom, - u32 keytype, u32 subtype, - u32 keybitsize, u32 flags, - u8 *keybuf, u32 *keybuflen, u32 *_keyinfo) +static int ep11_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns, + u32 keytype, u32 subtype, + u32 keybitsize, u32 flags, + u8 *keybuf, u32 *keybuflen, u32 *_keyinfo) { - int len, rc; + struct pkey_apqn *local_apqns = NULL; + int i, len, rc; /* check keytype, subtype, keybitsize */ switch (keytype) { @@ -128,9 +297,6 @@ int pkey_ep11_gen_key(u16 card, u16 dom, } keybitsize = 8 * len; switch (subtype) { - case 0: - subtype = PKEY_TYPE_EP11_AES; - break; case PKEY_TYPE_EP11: case PKEY_TYPE_EP11_AES: break; @@ -148,10 +314,29 @@ int pkey_ep11_gen_key(u16 card, u16 dom, zcrypt_wait_api_operational(); - rc = ep11_genaeskey(card, dom, keybitsize, flags, - keybuf, keybuflen, subtype); + if (!apqns || (nr_apqns == 1 && + apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { + nr_apqns = MAXAPQNSINLIST; + local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), + GFP_KERNEL); + if (!local_apqns) + return -ENOMEM; + rc = ep11_apqns4type(subtype, NULL, NULL, 0, + local_apqns, &nr_apqns); + if (rc) + goto out; + apqns = local_apqns; + } + + for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { + rc = ep11_genaeskey(apqns[i].card, apqns[i].domain, + keybitsize, flags, + keybuf, keybuflen, subtype); + } - pr_debug("card=%d dom=%d rc=%d\n", card, dom, rc); +out: + kfree(local_apqns); + pr_debug("rc=%d\n", rc); return rc; } @@ -164,13 +349,14 @@ int pkey_ep11_gen_key(u16 card, u16 dom, * keybitsize is the bit size of the key (may be 0 for * keytype PKEY_KEYTYPE_AES_*). */ -int pkey_ep11_clr2key(u16 card, u16 dom, - u32 keytype, u32 subtype, - u32 keybitsize, u32 flags, - const u8 *clrkey, u32 clrkeylen, - u8 *keybuf, u32 *keybuflen, u32 *_keyinfo) +static int ep11_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns, + u32 keytype, u32 subtype, + u32 keybitsize, u32 flags, + const u8 *clrkey, u32 clrkeylen, + u8 *keybuf, u32 *keybuflen, u32 *_keyinfo) { - int len, rc; + struct pkey_apqn *local_apqns = NULL; + int i, len, rc; /* check keytype, subtype, clrkeylen, keybitsize */ switch (keytype) { @@ -190,9 +376,6 @@ int pkey_ep11_clr2key(u16 card, u16 dom, return -EINVAL; } switch (subtype) { - case 0: - subtype = PKEY_TYPE_EP11_AES; - break; case PKEY_TYPE_EP11: case PKEY_TYPE_EP11_AES: break; @@ -210,16 +393,35 @@ int pkey_ep11_clr2key(u16 card, u16 dom, zcrypt_wait_api_operational(); - rc = ep11_clr2keyblob(card, dom, keybitsize, flags, - clrkey, keybuf, keybuflen, subtype); + if (!apqns || (nr_apqns == 1 && + apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { + nr_apqns = MAXAPQNSINLIST; + local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), + GFP_KERNEL); + if (!local_apqns) + return -ENOMEM; + rc = ep11_apqns4type(subtype, NULL, NULL, 0, + local_apqns, &nr_apqns); + if (rc) + goto out; + apqns = local_apqns; + } + + for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { + rc = ep11_clr2keyblob(apqns[i].card, apqns[i].domain, + keybitsize, flags, clrkey, + keybuf, keybuflen, subtype); + } - pr_debug("card=%d dom=%d rc=%d\n", card, dom, rc); +out: + kfree(local_apqns); + pr_debug("rc=%d\n", rc); return rc; } -int pkey_ep11_verifykey(const u8 *key, u32 keylen, - u16 *card, u16 *dom, - u32 *keytype, u32 *keybitsize, u32 *flags) +static int ep11_verifykey(const u8 *key, u32 keylen, + u16 *card, u16 *dom, + u32 *keytype, u32 *keybitsize, u32 *flags) { struct keytoken_header *hdr = (struct keytoken_header *)key; u32 nr_apqns, *apqns = NULL; @@ -288,116 +490,36 @@ out: return rc; } -int pkey_ep11_apqns4key(const u8 *key, u32 keylen, u32 flags, - struct pkey_apqn *apqns, size_t *nr_apqns) -{ - struct keytoken_header *hdr = (struct keytoken_header *)key; - u32 _nr_apqns, *_apqns = NULL; - int rc; - - if (!flags) - flags = PKEY_FLAGS_MATCH_CUR_MKVP; - - if (keylen < sizeof(struct keytoken_header) || flags == 0) - return -EINVAL; - - zcrypt_wait_api_operational(); - - if (hdr->type == TOKTYPE_NON_CCA && - (hdr->version == TOKVER_EP11_AES_WITH_HEADER || - hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && - is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { - struct ep11keyblob *kb = (struct ep11keyblob *) - (key + sizeof(struct ep11kblob_header)); - int minhwtype = 0, api = 0; - - if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) - return -EINVAL; - if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { - minhwtype = ZCRYPT_CEX7; - api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; - } - rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, - minhwtype, api, kb->wkvp); - if (rc) - goto out; - - } else if (hdr->type == TOKTYPE_NON_CCA && - hdr->version == TOKVER_EP11_AES && - is_ep11_keyblob(key)) { - struct ep11keyblob *kb = (struct ep11keyblob *)key; - int minhwtype = 0, api = 0; - - if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) - return -EINVAL; - if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { - minhwtype = ZCRYPT_CEX7; - api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; - } - rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, - minhwtype, api, kb->wkvp); - if (rc) - goto out; - - } else { - PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n", - __func__, hdr->type, hdr->version); - return -EINVAL; - } - - if (apqns) { - if (*nr_apqns < _nr_apqns) - rc = -ENOSPC; - else - memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); - } - *nr_apqns = _nr_apqns; +static struct pkey_handler ep11_handler = { + .module = THIS_MODULE, + .name = "PKEY EP11 handler", + .is_supported_key = is_ep11_key, + .is_supported_keytype = is_ep11_keytype, + .key_to_protkey = ep11_key2protkey, + .gen_key = ep11_gen_key, + .clr_to_key = ep11_clr2key, + .verify_key = ep11_verifykey, + .apqns_for_key = ep11_apqns4key, + .apqns_for_keytype = ep11_apqns4type, +}; -out: - kfree(_apqns); - pr_debug("rc=%d\n", rc); - return rc; +/* + * Module init + */ +static int __init pkey_ep11_init(void) +{ + /* register this module as pkey handler for all the ep11 stuff */ + return pkey_handler_register(&ep11_handler); } -int pkey_ep11_apqns4type(enum pkey_key_type ktype, - u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, - struct pkey_apqn *apqns, size_t *nr_apqns) +/* + * Module exit + */ +static void __exit pkey_ep11_exit(void) { - u32 _nr_apqns, *_apqns = NULL; - int rc; - - zcrypt_wait_api_operational(); - - if (ktype == PKEY_TYPE_EP11 || - ktype == PKEY_TYPE_EP11_AES || - ktype == PKEY_TYPE_EP11_ECC) { - u8 *wkvp = NULL; - int api; - - if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) - wkvp = cur_mkvp; - api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; - rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, - ZCRYPT_CEX7, api, wkvp); - if (rc) - goto out; - - } else { - PKEY_DBF_ERR("%s unknown/unsupported key type %d\n", - __func__, (int)ktype); - return -EINVAL; - } - - if (apqns) { - if (*nr_apqns < _nr_apqns) - rc = -ENOSPC; - else - memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); - } - *nr_apqns = _nr_apqns; - -out: - kfree(_apqns); - pr_debug("rc=%d\n", rc); - return rc; + /* unregister this module as pkey handler */ + pkey_handler_unregister(&ep11_handler); } + +module_init(pkey_ep11_init); +module_exit(pkey_ep11_exit); diff --git a/drivers/s390/crypto/pkey_pckmo.c b/drivers/s390/crypto/pkey_pckmo.c index d2c2c61f449b..0667e5510671 100644 --- a/drivers/s390/crypto/pkey_pckmo.c +++ b/drivers/s390/crypto/pkey_pckmo.c @@ -8,71 +8,20 @@ #define KMSG_COMPONENT "pkey" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt +#include <linux/init.h> +#include <linux/module.h> +#include <linux/cpufeature.h> #include <asm/cpacf.h> #include <crypto/aes.h> #include <linux/random.h> #include "zcrypt_api.h" #include "zcrypt_ccamisc.h" - #include "pkey_base.h" -/* - * Prototypes - */ - -static bool is_pckmo_key(const u8 *key, u32 keylen); -static int pckmo_key2protkey(const u8 *key, u32 keylen, - u8 *protkey, u32 *protkeylen, u32 *protkeytype); -static int pckmo_gen_protkey(u32 keytype, - u8 *protkey, u32 *protkeylen, u32 *protkeytype); -static int pckmo_clr2protkey(u32 keytype, const u8 *clrkey, u32 clrkeylen, - u8 *protkey, u32 *protkeylen, u32 *protkeytype); -static int pckmo_verify_protkey(const u8 *protkey, u32 protkeylen, - u32 protkeytype); - -/* - * Wrapper functions - */ - -bool pkey_is_pckmo_key(const u8 *key, u32 keylen) -{ - return is_pckmo_key(key, keylen); -} - -int pkey_pckmo_key2protkey(u16 _card, u16 _dom, - const u8 *key, u32 keylen, - u8 *protkey, u32 *protkeylen, u32 *keyinfo) -{ - return pckmo_key2protkey(key, keylen, - protkey, protkeylen, keyinfo); -} - -int pkey_pckmo_gen_key(u16 _card, u16 _dom, - u32 keytype, u32 _keysubtype, - u32 _keybitsize, u32 _flags, - u8 *keybuf, u32 *keybuflen, u32 *keyinfo) -{ - return pckmo_gen_protkey(keytype, - keybuf, keybuflen, keyinfo); -} - -int pkey_pckmo_clr2key(u16 _card, u16 _dom, - u32 keytype, u32 _keysubtype, - u32 _keybitsize, u32 _flags, - const u8 *clrkey, u32 clrkeylen, - u8 *keybuf, u32 *keybuflen, u32 *keyinfo) -{ - return pckmo_clr2protkey(keytype, clrkey, clrkeylen, - keybuf, keybuflen, keyinfo); -} - -int pkey_pckmo_verifykey(const u8 *key, u32 keylen, - u16 *_card, u16 *_dom, - u32 *keytype, u32 *_keybitsize, u32 *_flags) -{ - return pckmo_verify_protkey(key, keylen, *keytype); -} +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("IBM Corporation"); +MODULE_DESCRIPTION("s390 protected key PCKMO handler"); /* * Check key blob for known and supported here. @@ -112,122 +61,14 @@ static bool is_pckmo_key(const u8 *key, u32 keylen) } } -static int pckmo_key2protkey(const u8 *key, u32 keylen, - u8 *protkey, u32 *protkeylen, u32 *protkeytype) +static bool is_pckmo_keytype(enum pkey_key_type keytype) { - struct keytoken_header *hdr = (struct keytoken_header *)key; - int rc = -EINVAL; - - if (keylen < sizeof(*hdr)) - return -EINVAL; - if (hdr->type != TOKTYPE_NON_CCA) - return -EINVAL; - - switch (hdr->version) { - case TOKVER_PROTECTED_KEY: { - struct protaeskeytoken *t; - - if (keylen != sizeof(struct protaeskeytoken)) - goto out; - t = (struct protaeskeytoken *)key; - rc = pckmo_verify_protkey(t->protkey, t->len, t->keytype); - if (rc) - goto out; - memcpy(protkey, t->protkey, t->len); - *protkeylen = t->len; - *protkeytype = t->keytype; - break; - } - case TOKVER_CLEAR_KEY: { - struct clearkeytoken *t = (struct clearkeytoken *)key; - u32 keysize = 0; - - if (keylen < sizeof(struct clearkeytoken) || - keylen != sizeof(*t) + t->len) - goto out; - switch (t->keytype) { - case PKEY_KEYTYPE_AES_128: - case PKEY_KEYTYPE_AES_192: - case PKEY_KEYTYPE_AES_256: - keysize = pkey_keytype_aes_to_size(t->keytype); - break; - case PKEY_KEYTYPE_ECC_P256: - keysize = 32; - break; - case PKEY_KEYTYPE_ECC_P384: - keysize = 48; - break; - case PKEY_KEYTYPE_ECC_P521: - keysize = 80; - break; - case PKEY_KEYTYPE_ECC_ED25519: - keysize = 32; - break; - case PKEY_KEYTYPE_ECC_ED448: - keysize = 64; - break; - default: - break; - } - if (!keysize) { - PKEY_DBF_ERR("%s clear key token: unknown keytype %u\n", - __func__, t->keytype); - goto out; - } - if (t->len != keysize) { - PKEY_DBF_ERR("%s clear key token: invalid key len %u\n", - __func__, t->len); - goto out; - } - rc = pckmo_clr2protkey(t->keytype, t->clearkey, t->len, - protkey, protkeylen, protkeytype); - break; - } + switch (keytype) { + case PKEY_TYPE_PROTKEY: + return true; default: - PKEY_DBF_ERR("%s unknown non-CCA token version %d\n", - __func__, hdr->version); - break; - } - -out: - pr_debug("rc=%d\n", rc); - return rc; -} - -/* - * Generate a random protected key. - * Currently only the generation of AES protected keys - * is supported. - */ -static int pckmo_gen_protkey(u32 keytype, u8 *protkey, - u32 *protkeylen, u32 *protkeytype) -{ - u8 clrkey[32]; - int keysize; - int rc; - - keysize = pkey_keytype_aes_to_size(keytype); - if (!keysize) { - PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n", __func__, - keytype); - return -EINVAL; + return false; } - - /* generate a dummy random clear key */ - get_random_bytes(clrkey, keysize); - - /* convert it to a dummy protected key */ - rc = pckmo_clr2protkey(keytype, clrkey, keysize, - protkey, protkeylen, protkeytype); - if (rc) - goto out; - - /* replace the key part of the protected key with random bytes */ - get_random_bytes(protkey, keysize); - -out: - pr_debug("rc=%d\n", rc); - return rc; } /* @@ -346,7 +187,7 @@ out: } /* - * Verify a protected key blob. + * Verify a raw protected key blob. * Currently only AES protected keys are supported. */ static int pckmo_verify_protkey(const u8 *protkey, u32 protkeylen, @@ -405,3 +246,232 @@ out: pr_debug("rc=%d\n", rc); return rc; } + +static int pckmo_key2protkey(const u8 *key, u32 keylen, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) +{ + struct keytoken_header *hdr = (struct keytoken_header *)key; + int rc = -EINVAL; + + if (keylen < sizeof(*hdr)) + return -EINVAL; + if (hdr->type != TOKTYPE_NON_CCA) + return -EINVAL; + + switch (hdr->version) { + case TOKVER_PROTECTED_KEY: { + struct protaeskeytoken *t; + + if (keylen != sizeof(struct protaeskeytoken)) + goto out; + t = (struct protaeskeytoken *)key; + rc = pckmo_verify_protkey(t->protkey, t->len, t->keytype); + if (rc) + goto out; + memcpy(protkey, t->protkey, t->len); + *protkeylen = t->len; + *protkeytype = t->keytype; + break; + } + case TOKVER_CLEAR_KEY: { + struct clearkeytoken *t = (struct clearkeytoken *)key; + u32 keysize = 0; + + if (keylen < sizeof(struct clearkeytoken) || + keylen != sizeof(*t) + t->len) + goto out; + switch (t->keytype) { + case PKEY_KEYTYPE_AES_128: + case PKEY_KEYTYPE_AES_192: + case PKEY_KEYTYPE_AES_256: + keysize = pkey_keytype_aes_to_size(t->keytype); + break; + case PKEY_KEYTYPE_ECC_P256: + keysize = 32; + break; + case PKEY_KEYTYPE_ECC_P384: + keysize = 48; + break; + case PKEY_KEYTYPE_ECC_P521: + keysize = 80; + break; + case PKEY_KEYTYPE_ECC_ED25519: + keysize = 32; + break; + case PKEY_KEYTYPE_ECC_ED448: + keysize = 64; + break; + default: + break; + } + if (!keysize) { + PKEY_DBF_ERR("%s clear key token: unknown keytype %u\n", + __func__, t->keytype); + goto out; + } + if (t->len != keysize) { + PKEY_DBF_ERR("%s clear key token: invalid key len %u\n", + __func__, t->len); + goto out; + } + rc = pckmo_clr2protkey(t->keytype, t->clearkey, t->len, + protkey, protkeylen, protkeytype); + break; + } + default: + PKEY_DBF_ERR("%s unknown non-CCA token version %d\n", + __func__, hdr->version); + break; + } + +out: + pr_debug("rc=%d\n", rc); + return rc; +} + +/* + * Generate a random protected key. + * Currently only the generation of AES protected keys + * is supported. + */ +static int pckmo_gen_protkey(u32 keytype, u32 subtype, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) +{ + u8 clrkey[32]; + int keysize; + int rc; + + keysize = pkey_keytype_aes_to_size(keytype); + if (!keysize) { + PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n", __func__, + keytype); + return -EINVAL; + } + if (subtype != PKEY_TYPE_PROTKEY) { + PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n", + __func__, subtype); + return -EINVAL; + } + + /* generate a dummy random clear key */ + get_random_bytes(clrkey, keysize); + + /* convert it to a dummy protected key */ + rc = pckmo_clr2protkey(keytype, clrkey, keysize, + protkey, protkeylen, protkeytype); + if (rc) + goto out; + + /* replace the key part of the protected key with random bytes */ + get_random_bytes(protkey, keysize); + +out: + pr_debug("rc=%d\n", rc); + return rc; +} + +/* + * Verify a protected key token blob. + * Currently only AES protected keys are supported. + */ +static int pckmo_verify_key(const u8 *key, u32 keylen) +{ + struct keytoken_header *hdr = (struct keytoken_header *)key; + int rc = -EINVAL; + + if (keylen < sizeof(*hdr)) + return -EINVAL; + if (hdr->type != TOKTYPE_NON_CCA) + return -EINVAL; + + switch (hdr->version) { + case TOKVER_PROTECTED_KEY: { + struct protaeskeytoken *t; + + if (keylen != sizeof(struct protaeskeytoken)) + goto out; + t = (struct protaeskeytoken *)key; + rc = pckmo_verify_protkey(t->protkey, t->len, t->keytype); + break; + } + default: + PKEY_DBF_ERR("%s unknown non-CCA token version %d\n", + __func__, hdr->version); + break; + } + +out: + pr_debug("rc=%d\n", rc); + return rc; +} + +/* + * Wrapper functions used for the pkey handler struct + */ + +static int pkey_pckmo_key2protkey(const struct pkey_apqn *_apqns, + size_t _nr_apqns, + const u8 *key, u32 keylen, + u8 *protkey, u32 *protkeylen, u32 *keyinfo) +{ + return pckmo_key2protkey(key, keylen, + protkey, protkeylen, keyinfo); +} + +static int pkey_pckmo_gen_key(const struct pkey_apqn *_apqns, size_t _nr_apqns, + u32 keytype, u32 keysubtype, + u32 _keybitsize, u32 _flags, + u8 *keybuf, u32 *keybuflen, u32 *keyinfo) +{ + return pckmo_gen_protkey(keytype, keysubtype, + keybuf, keybuflen, keyinfo); +} + +static int pkey_pckmo_verifykey(const u8 *key, u32 keylen, + u16 *_card, u16 *_dom, + u32 *_keytype, u32 *_keybitsize, u32 *_flags) +{ + return pckmo_verify_key(key, keylen); +} + +static struct pkey_handler pckmo_handler = { + .module = THIS_MODULE, + .name = "PKEY PCKMO handler", + .is_supported_key = is_pckmo_key, + .is_supported_keytype = is_pckmo_keytype, + .key_to_protkey = pkey_pckmo_key2protkey, + .gen_key = pkey_pckmo_gen_key, + .verify_key = pkey_pckmo_verifykey, +}; + +/* + * Module init + */ +static int __init pkey_pckmo_init(void) +{ + cpacf_mask_t func_mask; + + /* + * The pckmo instruction should be available - even if we don't + * actually invoke it. This instruction comes with MSA 3 which + * is also the minimum level for the kmc instructions which + * are able to work with protected keys. + */ + if (!cpacf_query(CPACF_PCKMO, &func_mask)) + return -ENODEV; + + /* register this module as pkey handler for all the pckmo stuff */ + return pkey_handler_register(&pckmo_handler); +} + +/* + * Module exit + */ +static void __exit pkey_pckmo_exit(void) +{ + /* unregister this module as pkey handler */ + pkey_handler_unregister(&pckmo_handler); +} + +module_cpu_feature_match(S390_CPU_FEATURE_MSA, pkey_pckmo_init); +module_exit(pkey_pckmo_exit); diff --git a/drivers/s390/crypto/pkey_sysfs.c b/drivers/s390/crypto/pkey_sysfs.c index 684f87d6e9f1..242eb6b1a158 100644 --- a/drivers/s390/crypto/pkey_sysfs.c +++ b/drivers/s390/crypto/pkey_sysfs.c @@ -8,7 +8,6 @@ #define KMSG_COMPONENT "pkey" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt -#include <asm/pkey.h> #include <linux/sysfs.h> #include "zcrypt_api.h" @@ -42,10 +41,10 @@ static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, protkeytoken.keytype = keytype; protkey.len = sizeof(protkey.protkey); - rc = pkey_pckmo_gen_key(0, 0, - protkeytoken.keytype, 0, 0, 0, - protkey.protkey, &protkey.len, - &protkey.type); + rc = pkey_handler_gen_key(NULL, 0, keytype, + PKEY_TYPE_PROTKEY, 0, 0, + protkey.protkey, &protkey.len, + &protkey.type); if (rc) return rc; @@ -57,10 +56,10 @@ static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, if (is_xts) { /* xts needs a second protected key, reuse protkey struct */ protkey.len = sizeof(protkey.protkey); - rc = pkey_pckmo_gen_key(0, 0, - protkeytoken.keytype, 0, 0, 0, - protkey.protkey, &protkey.len, - &protkey.type); + rc = pkey_handler_gen_key(NULL, 0, keytype, + PKEY_TYPE_PROTKEY, 0, 0, + protkey.protkey, &protkey.len, + &protkey.type); if (rc) return rc; @@ -166,18 +165,18 @@ static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, return -EINVAL; buflen = sizeof(seckey->seckey); - rc = pkey_cca_gen_key(-1, -1, keytype, - PKEY_TYPE_CCA_DATA, 0, 0, - seckey->seckey, &buflen, NULL); + rc = pkey_handler_gen_key(NULL, 0, keytype, + PKEY_TYPE_CCA_DATA, 0, 0, + seckey->seckey, &buflen, NULL); if (rc) return rc; if (is_xts) { seckey++; buflen = sizeof(seckey->seckey); - rc = pkey_cca_gen_key(-1, -1, keytype, - PKEY_TYPE_CCA_DATA, 0, 0, - seckey->seckey, &buflen, NULL); + rc = pkey_handler_gen_key(NULL, 0, keytype, + PKEY_TYPE_CCA_DATA, 0, 0, + seckey->seckey, &buflen, NULL); if (rc) return rc; @@ -270,9 +269,7 @@ static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, size_t count) { u32 keysize = CCACIPHERTOKENSIZE; - struct pkey_apqn *apqns = NULL; - int i, rc, card, dom; - size_t nr_apqns; + int rc; if (off != 0 || count < CCACIPHERTOKENSIZE) return -EINVAL; @@ -280,51 +277,27 @@ static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, if (count < 2 * CCACIPHERTOKENSIZE) return -EINVAL; - nr_apqns = MAXAPQNSINLIST; - apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), GFP_KERNEL); - if (!apqns) - return -ENOMEM; - - /* build a list of apqns able to generate an cipher key */ - rc = pkey_cca_apqns4type(PKEY_TYPE_CCA_CIPHER, - NULL, NULL, 0, - apqns, &nr_apqns); - if (rc) { - kfree(apqns); - return rc; - } - memset(buf, 0, is_xts ? 2 * keysize : keysize); - /* simple try all apqns from the list */ - for (i = 0, rc = -ENODEV; rc && i < nr_apqns; i++) { - card = apqns[i].card; - dom = apqns[i].domain; - rc = pkey_cca_gen_key(card, dom, - pkey_aes_bitsize_to_keytype(keybits), - PKEY_TYPE_CCA_CIPHER, keybits, 0, - buf, &keysize, NULL); - } - if (rc) { - kfree(apqns); + rc = pkey_handler_gen_key(NULL, 0, + pkey_aes_bitsize_to_keytype(keybits), + PKEY_TYPE_CCA_CIPHER, keybits, 0, + buf, &keysize, NULL); + if (rc) return rc; - } if (is_xts) { keysize = CCACIPHERTOKENSIZE; buf += CCACIPHERTOKENSIZE; - rc = pkey_cca_gen_key(card, dom, - pkey_aes_bitsize_to_keytype(keybits), - PKEY_TYPE_CCA_CIPHER, keybits, 0, - buf, &keysize, NULL); - kfree(apqns); + rc = pkey_handler_gen_key(NULL, 0, + pkey_aes_bitsize_to_keytype(keybits), + PKEY_TYPE_CCA_CIPHER, keybits, 0, + buf, &keysize, NULL); if (rc) return rc; return 2 * CCACIPHERTOKENSIZE; } - kfree(apqns); - return CCACIPHERTOKENSIZE; } @@ -412,9 +385,7 @@ static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, size_t count) { u32 keysize = MAXEP11AESKEYBLOBSIZE; - struct pkey_apqn *apqns = NULL; - int i, rc, card, dom; - size_t nr_apqns; + int rc; if (off != 0 || count < MAXEP11AESKEYBLOBSIZE) return -EINVAL; @@ -422,51 +393,27 @@ static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, if (count < 2 * MAXEP11AESKEYBLOBSIZE) return -EINVAL; - nr_apqns = MAXAPQNSINLIST; - apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), GFP_KERNEL); - if (!apqns) - return -ENOMEM; - - /* build a list of apqns able to generate an EP11 AES key */ - rc = pkey_ep11_apqns4type(PKEY_TYPE_EP11_AES, - NULL, NULL, 0, - apqns, &nr_apqns); - if (rc) { - kfree(apqns); - return rc; - } - memset(buf, 0, is_xts ? 2 * keysize : keysize); - /* simple try all apqns from the list */ - for (i = 0, rc = -ENODEV; rc && i < nr_apqns; i++) { - card = apqns[i].card; - dom = apqns[i].domain; - rc = pkey_ep11_gen_key(card, dom, - pkey_aes_bitsize_to_keytype(keybits), - PKEY_TYPE_EP11_AES, keybits, 0, - buf, &keysize, NULL); - } - if (rc) { - kfree(apqns); + rc = pkey_handler_gen_key(NULL, 0, + pkey_aes_bitsize_to_keytype(keybits), + PKEY_TYPE_EP11_AES, keybits, 0, + buf, &keysize, NULL); + if (rc) return rc; - } if (is_xts) { keysize = MAXEP11AESKEYBLOBSIZE; buf += MAXEP11AESKEYBLOBSIZE; - rc = pkey_ep11_gen_key(card, dom, - pkey_aes_bitsize_to_keytype(keybits), - PKEY_TYPE_EP11_AES, keybits, 0, - buf, &keysize, NULL); - kfree(apqns); + rc = pkey_handler_gen_key(NULL, 0, + pkey_aes_bitsize_to_keytype(keybits), + PKEY_TYPE_EP11_AES, keybits, 0, + buf, &keysize, NULL); if (rc) return rc; return 2 * MAXEP11AESKEYBLOBSIZE; } - kfree(apqns); - return MAXEP11AESKEYBLOBSIZE; } |