.../admin-guide/kernel-parameters.txt | 14 +++++ drivers/char/tpm/tpm_vtpm_proxy.c | 51 +++++++++++++++++++ 2 files changed, 65 insertions(+)
From: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
Provide a kernel command-line parameter named as `supplicant`, which
contains a path to an TPM emulator binary. When defind, the kernel will
launch the program during boot-time.
This feature is most useful in feature testing e.g., in environments
where other means are not possible, such as CI runners. Its original use
case highlights also quite well of its applicability for pre-production
hardware: it was used to provide a TPM implemnentation for a RISC-V SoC
running on FPGA with no TPM HW implementation at the time.
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
---
Bumped into this in my archives so thought to make it available just in
case anyone is interested.
---
.../admin-guide/kernel-parameters.txt | 14 +++++
drivers/char/tpm/tpm_vtpm_proxy.c | 51 +++++++++++++++++++
2 files changed, 65 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index f1f2c0874da9..e062de99480e 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -7230,6 +7230,20 @@
defined by Trusted Computing Group (TCG) see
https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
+ tpm_vtpm_proxy.supplicant= [TPM]
+ When defined, this field must contain a legit path to a
+ program emulating a TPM chip, which will be started
+ during the driver initialization, thus providing a
+ mechanism for the user space have an emulated TPM from
+ the get go. Kernel prepares the process with a file
+ pre-opened file descriptor in the index 3 for
+ /dev/vtpmx.
+
+ An emulator can optionally provide support for
+ localities by reacting to the vendor command defined
+ by the driver: 0x20001000. Its payload is a single
+ byte containing the new locality.
+
tp_printk [FTRACE]
Have the tracepoints sent to printk as well as the
tracing ring buffer. This is useful for early boot up
diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c
index 0818bb517805..612f5251fdc0 100644
--- a/drivers/char/tpm/tpm_vtpm_proxy.c
+++ b/drivers/char/tpm/tpm_vtpm_proxy.c
@@ -51,6 +51,8 @@ struct proxy_dev {
#define VTPM_PROXY_FLAGS_ALL (VTPM_PROXY_FLAG_TPM2)
static struct workqueue_struct *workqueue;
+static char *supplicant;
+module_param(supplicant, charp, 0);
static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev);
@@ -678,6 +680,55 @@ static const struct file_operations vtpmx_fops = {
.llseek = noop_llseek,
};
+static int vtpmx_supplicant_setup(struct subprocess_info *info, struct cred *new)
+{
+ struct vtpm_proxy_new_dev dev = { .flags = VTPM_PROXY_FLAG_TPM2 };
+ struct file *file = vtpm_proxy_create_device(&dev);
+
+ if (IS_ERR(file))
+ return PTR_ERR(file);
+
+ fd_install(dev.fd, file);
+ return 0;
+}
+
+static void vtpmx_supplicant_cleanup(struct subprocess_info *info)
+{
+}
+
+static int vtpmx_supplicant_init(void)
+{
+ static const char * const argv[] = { supplicant, NULL };
+ struct subprocess_info *info;
+ int ret;
+
+ if (!supplicant)
+ return 0;
+
+ info = call_usermodehelper_setup(argv[0], (char **)argv, NULL,
+ GFP_KERNEL, vtpmx_supplicant_setup,
+ vtpmx_supplicant_cleanup, NULL);
+ if (!info)
+ return -ENOMEM;
+
+ ret = call_usermodehelper_exec(info, UMH_KILLABLE | UMH_NO_WAIT);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int vtpmx_init(void)
+{
+ int ret;
+
+ ret = vtpmx_supplicant_init();
+ if (ret)
+ return ret;
+
+ return misc_register(&vtpmx_miscdev);
+}
+
static struct miscdevice vtpmx_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "vtpmx",
--
2.39.5
(mostly nits, along with Paul's comments) On 7/16/25 5:18 AM, Jarkko Sakkinen wrote: > From: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com> > > Provide a kernel command-line parameter named as `supplicant`, which > contains a path to an TPM emulator binary. When defind, the kernel will to a TPM > launch the program during boot-time. > > This feature is most useful in feature testing e.g., in environments testing, e.g., > where other means are not possible, such as CI runners. Its original use > case highlights also quite well of its applicability for pre-production > hardware: it was used to provide a TPM implemnentation for a RISC-V SoC > running on FPGA with no TPM HW implementation at the time. > > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com> > --- > Bumped into this in my archives so thought to make it available just in > case anyone is interested. > --- > .../admin-guide/kernel-parameters.txt | 14 +++++ > drivers/char/tpm/tpm_vtpm_proxy.c | 51 +++++++++++++++++++ > 2 files changed, 65 insertions(+) > > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt > index f1f2c0874da9..e062de99480e 100644 > --- a/Documentation/admin-guide/kernel-parameters.txt > +++ b/Documentation/admin-guide/kernel-parameters.txt > @@ -7230,6 +7230,20 @@ > defined by Trusted Computing Group (TCG) see > https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/ > > + tpm_vtpm_proxy.supplicant= [TPM] > + When defined, this field must contain a legit path to a legitimate or valid > + program emulating a TPM chip, which will be started > + during the driver initialization, thus providing a > + mechanism for the user space have an emulated TPM from > + the get go. Kernel prepares the process with a file get-go. or just don't use slang terms. > + pre-opened file descriptor in the index 3 for > + /dev/vtpmx. > + > + An emulator can optionally provide support for > + localities by reacting to the vendor command defined > + by the driver: 0x20001000. Its payload is a single > + byte containing the new locality. > + > tp_printk [FTRACE] > Have the tracepoints sent to printk as well as the > tracing ring buffer. This is useful for early boot up thanks. -- ~Randy
On Wed, Jul 16, 2025 at 11:44:02AM -0700, Randy Dunlap wrote: > (mostly nits, along with Paul's comments) > > > On 7/16/25 5:18 AM, Jarkko Sakkinen wrote: > > From: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com> > > > > Provide a kernel command-line parameter named as `supplicant`, which > > contains a path to an TPM emulator binary. When defind, the kernel will > > to a TPM > > > launch the program during boot-time. > > > > This feature is most useful in feature testing e.g., in environments > > testing, e.g., > > > where other means are not possible, such as CI runners. Its original use > > case highlights also quite well of its applicability for pre-production > > hardware: it was used to provide a TPM implemnentation for a RISC-V SoC > > running on FPGA with no TPM HW implementation at the time. > > > > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com> > > --- > > Bumped into this in my archives so thought to make it available just in > > case anyone is interested. > > --- > > .../admin-guide/kernel-parameters.txt | 14 +++++ > > drivers/char/tpm/tpm_vtpm_proxy.c | 51 +++++++++++++++++++ > > 2 files changed, 65 insertions(+) > > > > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt > > index f1f2c0874da9..e062de99480e 100644 > > --- a/Documentation/admin-guide/kernel-parameters.txt > > +++ b/Documentation/admin-guide/kernel-parameters.txt > > @@ -7230,6 +7230,20 @@ > > defined by Trusted Computing Group (TCG) see > > https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/ > > > > + tpm_vtpm_proxy.supplicant= [TPM] > > + When defined, this field must contain a legit path to a > > legitimate > or valid > > > + program emulating a TPM chip, which will be started > > + during the driver initialization, thus providing a > > + mechanism for the user space have an emulated TPM from > > + the get go. Kernel prepares the process with a file > > get-go. > or just don't use slang terms. > > > + pre-opened file descriptor in the index 3 for > > + /dev/vtpmx. > > + > > + An emulator can optionally provide support for > > + localities by reacting to the vendor command defined > > + by the driver: 0x20001000. Its payload is a single > > + byte containing the new locality. > > + > > tp_printk [FTRACE] > > Have the tracepoints sent to printk as well as the > > tracing ring buffer. This is useful for early boot up > > thanks. > -- > ~Randy > Thank you for reviewing this (especially given how bad shape it was)! BR, Jarkko
Dear Jarkko, Am 16.07.25 um 14:18 schrieb Jarkko Sakkinen: > From: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com> Congratulations on the new(?) job! Big thanks to that company to do upstream Linux kernel work. > Provide a kernel command-line parameter named as `supplicant`, which > contains a path to an TPM emulator binary. When defind, the kernel will defin*e*d > launch the program during boot-time. > > This feature is most useful in feature testing e.g., in environments > where other means are not possible, such as CI runners. Its original use > case highlights also quite well of its applicability for pre-production > hardware: it was used to provide a TPM implemnentation for a RISC-V SoC implementation > running on FPGA with no TPM HW implementation at the time. > > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com> > --- > Bumped into this in my archives so thought to make it available just in > case anyone is interested. Do you have such a TPM emulator binary? Thank you for upstreaming this. > --- > .../admin-guide/kernel-parameters.txt | 14 +++++ > drivers/char/tpm/tpm_vtpm_proxy.c | 51 +++++++++++++++++++ > 2 files changed, 65 insertions(+) > > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt > index f1f2c0874da9..e062de99480e 100644 > --- a/Documentation/admin-guide/kernel-parameters.txt > +++ b/Documentation/admin-guide/kernel-parameters.txt > @@ -7230,6 +7230,20 @@ > defined by Trusted Computing Group (TCG) see > https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/ > > + tpm_vtpm_proxy.supplicant= [TPM] > + When defined, this field must contain a legit path to a > + program emulating a TPM chip, which will be started > + during the driver initialization, thus providing a > + mechanism for the user space have an emulated TPM from > + the get go. Kernel prepares the process with a file > + pre-opened file descriptor in the index 3 for > + /dev/vtpmx. > + > + An emulator can optionally provide support for > + localities by reacting to the vendor command defined > + by the driver: 0x20001000. Its payload is a single > + byte containing the new locality. > + > tp_printk [FTRACE] > Have the tracepoints sent to printk as well as the > tracing ring buffer. This is useful for early boot up > diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c > index 0818bb517805..612f5251fdc0 100644 > --- a/drivers/char/tpm/tpm_vtpm_proxy.c > +++ b/drivers/char/tpm/tpm_vtpm_proxy.c > @@ -51,6 +51,8 @@ struct proxy_dev { > #define VTPM_PROXY_FLAGS_ALL (VTPM_PROXY_FLAG_TPM2) > > static struct workqueue_struct *workqueue; > +static char *supplicant; > +module_param(supplicant, charp, 0); > > static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev); > > @@ -678,6 +680,55 @@ static const struct file_operations vtpmx_fops = { > .llseek = noop_llseek, > }; > > +static int vtpmx_supplicant_setup(struct subprocess_info *info, struct cred *new) > +{ > + struct vtpm_proxy_new_dev dev = { .flags = VTPM_PROXY_FLAG_TPM2 }; > + struct file *file = vtpm_proxy_create_device(&dev); > + > + if (IS_ERR(file)) > + return PTR_ERR(file); > + > + fd_install(dev.fd, file); > + return 0; > +} > + > +static void vtpmx_supplicant_cleanup(struct subprocess_info *info) > +{ > +} > + > +static int vtpmx_supplicant_init(void) > +{ > + static const char * const argv[] = { supplicant, NULL }; > + struct subprocess_info *info; > + int ret; > + > + if (!supplicant) > + return 0; > + > + info = call_usermodehelper_setup(argv[0], (char **)argv, NULL, > + GFP_KERNEL, vtpmx_supplicant_setup, > + vtpmx_supplicant_cleanup, NULL); > + if (!info) > + return -ENOMEM; > + > + ret = call_usermodehelper_exec(info, UMH_KILLABLE | UMH_NO_WAIT); > + if (ret) > + return ret; > + > + return 0; > +} > + > +static int vtpmx_init(void) > +{ > + int ret; > + > + ret = vtpmx_supplicant_init(); > + if (ret) > + return ret; > + > + return misc_register(&vtpmx_miscdev); > +} > + > static struct miscdevice vtpmx_miscdev = { > .minor = MISC_DYNAMIC_MINOR, > .name = "vtpmx", Kind regards, Paul
On Wed, Jul 16, 2025 at 02:23:04PM +0200, Paul Menzel wrote: > Dear Jarkko, > > > Am 16.07.25 um 14:18 schrieb Jarkko Sakkinen: > > From: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com> > > Congratulations on the new(?) job! Big thanks to that company to do upstream > Linux kernel work. > > > Provide a kernel command-line parameter named as `supplicant`, which > > contains a path to an TPM emulator binary. When defind, the kernel will > > defin*e*d > > > launch the program during boot-time. > > > > This feature is most useful in feature testing e.g., in environments > > where other means are not possible, such as CI runners. Its original use > > case highlights also quite well of its applicability for pre-production > > hardware: it was used to provide a TPM implemnentation for a RISC-V SoC > > implementation Thanks for the corrections! I think also the code changes are actually half-broken or missing some of the stuff. I'm glad that I remebered to use RFC tag ;-) > > > running on FPGA with no TPM HW implementation at the time. > > > > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com> > > --- > > Bumped into this in my archives so thought to make it available just in > > case anyone is interested. > > Do you have such a TPM emulator binary? > > Thank you for upstreaming this. It was like internal project within research group but e.g, MS TPM emulator [1] is pretty easy to wrap and wire with a program that does three functions: 1. Feeds the emulator with incoming data coming from the client through socket provided by vtpmx. 2. Writes the data coming from the emulator back to the client. 3. Handles TPM2_CC_LOCALITY. MS TPM 2.0 emulator is quite generic and abstracted out code, so you can almost just take the source files, ignore the build files, and meld it into your own thing and it will envetually work, if you spend a few afternoons on it :-) [1] https://github.com/microsoft/ms-tpm-20-ref BR, Jarkko
© 2016 - 2025 Red Hat, Inc.