summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/crypto/pkey_api.c13
-rw-r--r--drivers/s390/crypto/pkey_base.c29
-rw-r--r--drivers/s390/crypto/pkey_base.h5
-rw-r--r--drivers/s390/crypto/pkey_sysfs.c80
4 files changed, 95 insertions, 32 deletions
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c
index d6c5e5ae915b..c20251e00cf9 100644
--- a/drivers/s390/crypto/pkey_api.c
+++ b/drivers/s390/crypto/pkey_api.c
@@ -54,8 +54,17 @@ static int key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
int pkey_key2protkey(const u8 *key, u32 keylen,
u8 *protkey, u32 *protkeylen, u32 *protkeytype)
{
- return key2protkey(NULL, 0, key, keylen,
- protkey, protkeylen, protkeytype);
+ int rc;
+
+ rc = key2protkey(NULL, 0, key, keylen,
+ protkey, protkeylen, protkeytype);
+ if (rc == -ENODEV) {
+ pkey_handler_request_modules();
+ rc = key2protkey(NULL, 0, key, keylen,
+ protkey, protkeylen, protkeytype);
+ }
+
+ return rc;
}
EXPORT_SYMBOL(pkey_key2protkey);
diff --git a/drivers/s390/crypto/pkey_base.c b/drivers/s390/crypto/pkey_base.c
index 976b9ddfbe15..fea243322838 100644
--- a/drivers/s390/crypto/pkey_base.c
+++ b/drivers/s390/crypto/pkey_base.c
@@ -300,6 +300,35 @@ int pkey_handler_apqns_for_keytype(enum pkey_key_type keysubtype,
}
EXPORT_SYMBOL(pkey_handler_apqns_for_keytype);
+void pkey_handler_request_modules(void)
+{
+#ifdef CONFIG_MODULES
+ static const char * const pkey_handler_modules[] = {
+ "pkey_cca", "pkey_ep11", "pkey_pckmo" };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pkey_handler_modules); i++) {
+ const struct pkey_handler *h;
+ bool found = false;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(h, &handler_list, list) {
+ if (h->module &&
+ !strcmp(h->module->name, pkey_handler_modules[i])) {
+ found = true;
+ break;
+ }
+ }
+ rcu_read_unlock();
+ if (!found) {
+ pr_debug("request_module(%s)\n", pkey_handler_modules[i]);
+ request_module(pkey_handler_modules[i]);
+ }
+ }
+#endif
+}
+EXPORT_SYMBOL(pkey_handler_request_modules);
+
/*
* Module init
*/
diff --git a/drivers/s390/crypto/pkey_base.h b/drivers/s390/crypto/pkey_base.h
index 41fd69e7c66e..fd151903fd06 100644
--- a/drivers/s390/crypto/pkey_base.h
+++ b/drivers/s390/crypto/pkey_base.h
@@ -176,4 +176,9 @@ 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);
+/*
+ * Unconditional try to load all handler modules
+ */
+void pkey_handler_request_modules(void);
+
#endif /* _PKEY_BASE_H_ */
diff --git a/drivers/s390/crypto/pkey_sysfs.c b/drivers/s390/crypto/pkey_sysfs.c
index 242eb6b1a158..56205f53f77b 100644
--- a/drivers/s390/crypto/pkey_sysfs.c
+++ b/drivers/s390/crypto/pkey_sysfs.c
@@ -17,6 +17,32 @@
#include "pkey_base.h"
/*
+ * Wrapper around pkey_handler_gen_key() which deals with the
+ * ENODEV return code and then tries to enforce a pkey handler
+ * module load.
+ */
+static int sys_pkey_handler_gen_key(u32 keytype, u32 keysubtype,
+ u32 keybitsize, u32 flags,
+ u8 *keybuf, u32 *keybuflen, u32 *keyinfo)
+{
+ int rc;
+
+ rc = pkey_handler_gen_key(NULL, 0,
+ keytype, keysubtype,
+ keybitsize, flags,
+ keybuf, keybuflen, keyinfo);
+ if (rc == -ENODEV) {
+ pkey_handler_request_modules();
+ rc = pkey_handler_gen_key(NULL, 0,
+ keytype, keysubtype,
+ keybitsize, flags,
+ keybuf, keybuflen, keyinfo);
+ }
+
+ return rc;
+}
+
+/*
* Sysfs attribute read function for all protected key binary attributes.
* The implementation can not deal with partial reads, because a new random
* protected key blob is generated with each read. In case of partial reads
@@ -41,10 +67,9 @@ 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_handler_gen_key(NULL, 0, keytype,
- PKEY_TYPE_PROTKEY, 0, 0,
- protkey.protkey, &protkey.len,
- &protkey.type);
+ rc = sys_pkey_handler_gen_key(keytype, PKEY_TYPE_PROTKEY, 0, 0,
+ protkey.protkey, &protkey.len,
+ &protkey.type);
if (rc)
return rc;
@@ -56,10 +81,9 @@ 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_handler_gen_key(NULL, 0, keytype,
- PKEY_TYPE_PROTKEY, 0, 0,
- protkey.protkey, &protkey.len,
- &protkey.type);
+ rc = sys_pkey_handler_gen_key(keytype, PKEY_TYPE_PROTKEY, 0, 0,
+ protkey.protkey, &protkey.len,
+ &protkey.type);
if (rc)
return rc;
@@ -165,18 +189,16 @@ static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf,
return -EINVAL;
buflen = sizeof(seckey->seckey);
- rc = pkey_handler_gen_key(NULL, 0, keytype,
- PKEY_TYPE_CCA_DATA, 0, 0,
- seckey->seckey, &buflen, NULL);
+ rc = sys_pkey_handler_gen_key(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_handler_gen_key(NULL, 0, keytype,
- PKEY_TYPE_CCA_DATA, 0, 0,
- seckey->seckey, &buflen, NULL);
+ rc = sys_pkey_handler_gen_key(keytype, PKEY_TYPE_CCA_DATA, 0, 0,
+ seckey->seckey, &buflen, NULL);
if (rc)
return rc;
@@ -279,20 +301,19 @@ static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits,
memset(buf, 0, is_xts ? 2 * keysize : keysize);
- rc = pkey_handler_gen_key(NULL, 0,
- pkey_aes_bitsize_to_keytype(keybits),
- PKEY_TYPE_CCA_CIPHER, keybits, 0,
- buf, &keysize, NULL);
+ rc = sys_pkey_handler_gen_key(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_handler_gen_key(NULL, 0,
- pkey_aes_bitsize_to_keytype(keybits),
- PKEY_TYPE_CCA_CIPHER, keybits, 0,
- buf, &keysize, NULL);
+ rc = sys_pkey_handler_gen_key(
+ pkey_aes_bitsize_to_keytype(keybits),
+ PKEY_TYPE_CCA_CIPHER, keybits, 0,
+ buf, &keysize, NULL);
if (rc)
return rc;
return 2 * CCACIPHERTOKENSIZE;
@@ -395,20 +416,19 @@ static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits,
memset(buf, 0, is_xts ? 2 * keysize : keysize);
- rc = pkey_handler_gen_key(NULL, 0,
- pkey_aes_bitsize_to_keytype(keybits),
- PKEY_TYPE_EP11_AES, keybits, 0,
- buf, &keysize, NULL);
+ rc = sys_pkey_handler_gen_key(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_handler_gen_key(NULL, 0,
- pkey_aes_bitsize_to_keytype(keybits),
- PKEY_TYPE_EP11_AES, keybits, 0,
- buf, &keysize, NULL);
+ rc = sys_pkey_handler_gen_key(
+ pkey_aes_bitsize_to_keytype(keybits),
+ PKEY_TYPE_EP11_AES, keybits, 0,
+ buf, &keysize, NULL);
if (rc)
return rc;
return 2 * MAXEP11AESKEYBLOBSIZE;