mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:24:47 +01:00
powerpc updates for 7.0
- Implement masked user access - Add support for internal only per-CPU instructions and inline the bpf_get_smp_processor_id() and bpf_get_current_task() - Fix pSeries MSI-X allocation failure when quota is exceeded - Fix recursive pci_lock_rescan_remove locking in EEH event handling - Support tailcalls with subprogs & BPF exceptions on 64bit - Extend "trusted" keys to support the PowerVM Key Wrapping Module (PKWM) Thanks to: Abhishek Dubey, Christophe Leroy, Gaurav Batra, Guangshuo Li, Jarkko Sakkinen, Mahesh Salgaonkar, Mimi Zohar, Miquel Sabaté Solà, Nam Cao, Narayana Murty N, Nayna Jain, Nilay Shroff, Puranjay Mohan, Saket Kumar Bhaskar, Sourabh Jain, Srish Srinivasan, Venkat Rao Bagalkote, -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEqX2DNAOgU8sBX3pRpnEsdPSHZJQFAmmL7S0ACgkQpnEsdPSH ZJR2xA/9G+tZp9+2TidbLSyPT5o063uC5H5+j5QcvvHWi/ImGUNtixlDm5HcZLCR yKywE1piKYBU8HoISjzAt0+JCVd3ZjJ8chTpKgCHLXPRSBTgdR1MG+SXQysDJSWb yA4pwDikmwoLlfi+pf500F0nX2DRCRdU2Yi28ZFeaF/khJ7ebwj41QJ7LjN22+Q1 G8Kq543obZluzSoVvfG4xUK4ByWER+Zdd2F6699iMP68yw5PJ8PPc0SUGt8nuD4i FUs0Lw7XV7i/K3+zm/ZgH5+Cvn7wOIcMNkXgFlxJXkFit97KXUDijifYPoXQyKLL ksD7SPFdV0++Sc+3mWcgW4j+hQZC0Pn864unmh8C6ug3SagQ+3pE1JYWKwCmoyXd 49ROH0y+npArJ4NAc79eweunhafGcRYTSG+zV7swQvpRocMujEqa4CDz4uk1ll5W 1yAac08AN6PnfcXl2VMrcDboziTlQVFcnNQbK/ieYMC7KpgA+udw1hd2rOWNZCPd u0byXxR1ak5YaAEuyMztd/39hrExx8306Jtkh5FIRZKWGAO+3np5bi3vxk11rDni c9BGh2JIMtuPUGys3wcFPGMRTKwF2bDFW/pB+5hMHeLUdlkni9WGCX8eLe2klYsy T7fBVb4d99IVrJGYv3J1lwELgjrgXvv35XOaUiyJyZhcbng15cc= =zJoL -----END PGP SIGNATURE----- Merge tag 'powerpc-7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux Pull powerpc updates for 7.0 - Implement masked user access - Add bpf support for internal only per-CPU instructions and inline the bpf_get_smp_processor_id() and bpf_get_current_task() functions - Fix pSeries MSI-X allocation failure when quota is exceeded - Fix recursive pci_lock_rescan_remove locking in EEH event handling - Support tailcalls with subprogs & BPF exceptions on 64bit - Extend "trusted" keys to support the PowerVM Key Wrapping Module (PKWM) Thanks to Abhishek Dubey, Christophe Leroy, Gaurav Batra, Guangshuo Li, Jarkko Sakkinen, Mahesh Salgaonkar, Mimi Zohar, Miquel Sabaté Solà, Nam Cao, Narayana Murty N, Nayna Jain, Nilay Shroff, Puranjay Mohan, Saket Kumar Bhaskar, Sourabh Jain, Srish Srinivasan, and Venkat Rao Bagalkote. * tag 'powerpc-7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (27 commits) powerpc/pseries: plpks: export plpks_wrapping_is_supported docs: trusted-encryped: add PKWM as a new trust source keys/trusted_keys: establish PKWM as a trusted source pseries/plpks: add HCALLs for PowerVM Key Wrapping Module pseries/plpks: expose PowerVM wrapping features via the sysfs powerpc/pseries: move the PLPKS config inside its own sysfs directory pseries/plpks: fix kernel-doc comment inconsistencies powerpc/smp: Add check for kcalloc() failure in parse_thread_groups() powerpc: kgdb: Remove OUTBUFMAX constant powerpc64/bpf: Additional NVR handling for bpf_throw powerpc64/bpf: Support exceptions powerpc64/bpf: Add arch_bpf_stack_walk() for BPF JIT powerpc64/bpf: Avoid tailcall restore from trampoline powerpc64/bpf: Support tailcalls with subprogs powerpc64/bpf: Moving tail_call_cnt to bottom of frame powerpc/eeh: fix recursive pci_lock_rescan_remove locking in EEH event handling powerpc/pseries: Fix MSI-X allocation failure when quota is exceeded powerpc/iommu: bypass DMA APIs for coherent allocations for pre-mapped memory powerpc64/bpf: Inline bpf_get_smp_processor_id() and bpf_get_current_task/_btf() powerpc64/bpf: Support internal-only MOV instruction to resolve per-CPU addrs ...
This commit is contained in:
commit
192c015940
51 changed files with 1857 additions and 421 deletions
|
|
@ -46,6 +46,14 @@ config TRUSTED_KEYS_DCP
|
|||
help
|
||||
Enable use of NXP's DCP (Data Co-Processor) as trusted key backend.
|
||||
|
||||
config TRUSTED_KEYS_PKWM
|
||||
bool "PKWM-based trusted keys"
|
||||
depends on PSERIES_PLPKS >= TRUSTED_KEYS
|
||||
default y
|
||||
select HAVE_TRUSTED_KEYS
|
||||
help
|
||||
Enable use of IBM PowerVM Key Wrapping Module (PKWM) as a trusted key backend.
|
||||
|
||||
if !HAVE_TRUSTED_KEYS
|
||||
comment "No trust source selected!"
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -16,3 +16,5 @@ trusted-$(CONFIG_TRUSTED_KEYS_TEE) += trusted_tee.o
|
|||
trusted-$(CONFIG_TRUSTED_KEYS_CAAM) += trusted_caam.o
|
||||
|
||||
trusted-$(CONFIG_TRUSTED_KEYS_DCP) += trusted_dcp.o
|
||||
|
||||
trusted-$(CONFIG_TRUSTED_KEYS_PKWM) += trusted_pkwm.o
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <keys/trusted_caam.h>
|
||||
#include <keys/trusted_dcp.h>
|
||||
#include <keys/trusted_tpm.h>
|
||||
#include <keys/trusted_pkwm.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
@ -31,7 +32,7 @@ MODULE_PARM_DESC(rng, "Select trusted key RNG");
|
|||
|
||||
static char *trusted_key_source;
|
||||
module_param_named(source, trusted_key_source, charp, 0);
|
||||
MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee, caam or dcp)");
|
||||
MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee, caam, dcp or pkwm)");
|
||||
|
||||
static const struct trusted_key_source trusted_key_sources[] = {
|
||||
#if defined(CONFIG_TRUSTED_KEYS_TPM)
|
||||
|
|
@ -46,6 +47,9 @@ static const struct trusted_key_source trusted_key_sources[] = {
|
|||
#if defined(CONFIG_TRUSTED_KEYS_DCP)
|
||||
{ "dcp", &dcp_trusted_key_ops },
|
||||
#endif
|
||||
#if defined(CONFIG_TRUSTED_KEYS_PKWM)
|
||||
{ "pkwm", &pkwm_trusted_key_ops },
|
||||
#endif
|
||||
};
|
||||
|
||||
DEFINE_STATIC_CALL_NULL(trusted_key_seal, *trusted_key_sources[0].ops->seal);
|
||||
|
|
|
|||
190
security/keys/trusted-keys/trusted_pkwm.c
Normal file
190
security/keys/trusted-keys/trusted_pkwm.c
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2025 IBM Corporation, Srish Srinivasan <ssrish@linux.ibm.com>
|
||||
*/
|
||||
|
||||
#include <keys/trusted_pkwm.h>
|
||||
#include <keys/trusted-type.h>
|
||||
#include <linux/build_bug.h>
|
||||
#include <linux/key-type.h>
|
||||
#include <linux/parser.h>
|
||||
#include <asm/plpks.h>
|
||||
|
||||
enum {
|
||||
Opt_err,
|
||||
Opt_wrap_flags,
|
||||
};
|
||||
|
||||
static const match_table_t key_tokens = {
|
||||
{Opt_wrap_flags, "wrap_flags=%s"},
|
||||
{Opt_err, NULL}
|
||||
};
|
||||
|
||||
static int getoptions(char *datablob, struct trusted_key_options *opt)
|
||||
{
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
char *p = datablob;
|
||||
int token;
|
||||
int res;
|
||||
u16 wrap_flags;
|
||||
unsigned long token_mask = 0;
|
||||
struct trusted_pkwm_options *pkwm;
|
||||
|
||||
if (!datablob)
|
||||
return 0;
|
||||
|
||||
pkwm = opt->private;
|
||||
|
||||
while ((p = strsep(&datablob, " \t"))) {
|
||||
if (*p == '\0' || *p == ' ' || *p == '\t')
|
||||
continue;
|
||||
|
||||
token = match_token(p, key_tokens, args);
|
||||
if (test_and_set_bit(token, &token_mask))
|
||||
return -EINVAL;
|
||||
|
||||
switch (token) {
|
||||
case Opt_wrap_flags:
|
||||
res = kstrtou16(args[0].from, 16, &wrap_flags);
|
||||
if (res < 0 || wrap_flags > 2)
|
||||
return -EINVAL;
|
||||
pkwm->wrap_flags = wrap_flags;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct trusted_key_options *trusted_options_alloc(void)
|
||||
{
|
||||
struct trusted_key_options *options;
|
||||
struct trusted_pkwm_options *pkwm;
|
||||
|
||||
options = kzalloc(sizeof(*options), GFP_KERNEL);
|
||||
|
||||
if (options) {
|
||||
pkwm = kzalloc(sizeof(*pkwm), GFP_KERNEL);
|
||||
|
||||
if (!pkwm) {
|
||||
kfree_sensitive(options);
|
||||
options = NULL;
|
||||
} else {
|
||||
options->private = pkwm;
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
static int trusted_pkwm_seal(struct trusted_key_payload *p, char *datablob)
|
||||
{
|
||||
struct trusted_key_options *options = NULL;
|
||||
struct trusted_pkwm_options *pkwm = NULL;
|
||||
u8 *input_buf, *output_buf;
|
||||
u32 output_len, input_len;
|
||||
int rc;
|
||||
|
||||
options = trusted_options_alloc();
|
||||
|
||||
if (!options)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = getoptions(datablob, options);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
dump_options(options);
|
||||
|
||||
input_len = p->key_len;
|
||||
input_buf = kmalloc(ALIGN(input_len, 4096), GFP_KERNEL);
|
||||
if (!input_buf) {
|
||||
pr_err("Input buffer allocation failed. Returning -ENOMEM.");
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(input_buf, p->key, p->key_len);
|
||||
|
||||
pkwm = options->private;
|
||||
|
||||
rc = plpks_wrap_object(&input_buf, input_len, pkwm->wrap_flags,
|
||||
&output_buf, &output_len);
|
||||
if (!rc) {
|
||||
memcpy(p->blob, output_buf, output_len);
|
||||
p->blob_len = output_len;
|
||||
dump_payload(p);
|
||||
} else {
|
||||
pr_err("Wrapping of payload key failed: %d\n", rc);
|
||||
}
|
||||
|
||||
kfree(input_buf);
|
||||
kfree(output_buf);
|
||||
|
||||
out:
|
||||
kfree_sensitive(options->private);
|
||||
kfree_sensitive(options);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int trusted_pkwm_unseal(struct trusted_key_payload *p, char *datablob)
|
||||
{
|
||||
u8 *input_buf, *output_buf;
|
||||
u32 input_len, output_len;
|
||||
int rc;
|
||||
|
||||
input_len = p->blob_len;
|
||||
input_buf = kmalloc(ALIGN(input_len, 4096), GFP_KERNEL);
|
||||
if (!input_buf) {
|
||||
pr_err("Input buffer allocation failed. Returning -ENOMEM.");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(input_buf, p->blob, p->blob_len);
|
||||
|
||||
rc = plpks_unwrap_object(&input_buf, input_len, &output_buf,
|
||||
&output_len);
|
||||
if (!rc) {
|
||||
memcpy(p->key, output_buf, output_len);
|
||||
p->key_len = output_len;
|
||||
dump_payload(p);
|
||||
} else {
|
||||
pr_err("Unwrapping of payload failed: %d\n", rc);
|
||||
}
|
||||
|
||||
kfree(input_buf);
|
||||
kfree(output_buf);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int trusted_pkwm_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!plpks_wrapping_is_supported()) {
|
||||
pr_err("H_PKS_WRAP_OBJECT interface not supported\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = plpks_gen_wrapping_key();
|
||||
if (ret) {
|
||||
pr_err("Failed to generate default wrapping key\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return register_key_type(&key_type_trusted);
|
||||
}
|
||||
|
||||
static void trusted_pkwm_exit(void)
|
||||
{
|
||||
unregister_key_type(&key_type_trusted);
|
||||
}
|
||||
|
||||
struct trusted_key_ops pkwm_trusted_key_ops = {
|
||||
.migratable = 0, /* non-migratable */
|
||||
.init = trusted_pkwm_init,
|
||||
.seal = trusted_pkwm_seal,
|
||||
.unseal = trusted_pkwm_unseal,
|
||||
.exit = trusted_pkwm_exit,
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue