mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
s390/pkey: Add function to enforce pkey handler modules load
There is a use case during early boot with an secure key encrypted root file system where the paes cipher may try to derive a protected key from secure key while the AP bus is still in the process of scanning the bus and building up the zcrypt device drivers. As the detection of CEX cards also triggers the modprobe of the pkey handler modules, these modules may come into existence too late. Yet another use case happening during early boot is for use of an protected key encrypted swap file(system). There is an ephemeral protected key read via sysfs to set up the swap file. But this only works when the pkey_pckmo module is already in - which may happen at a later time as the load is triggered via CPU feature. This patch introduces a new function pkey_handler_request_modules() and invokes it which unconditional tries to load in the pkey handler modules. This function is called for the in-kernel API to derive a protected key from whatever and in the sysfs API when the first attempt to simple invoke the handler function failed. Signed-off-by: Harald Freudenberger <freude@linux.ibm.com> Reviewed-by: Holger Dengler <dengler@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
2fc401b944
commit
177b621bf0
@ -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);
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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_ */
|
||||
|
@ -16,6 +16,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
|
||||
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user