diff options
-rw-r--r-- | drivers/s390/crypto/pkey_api.c | 13 | ||||
-rw-r--r-- | drivers/s390/crypto/pkey_base.c | 29 | ||||
-rw-r--r-- | drivers/s390/crypto/pkey_base.h | 5 | ||||
-rw-r--r-- | drivers/s390/crypto/pkey_sysfs.c | 80 |
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; |