Turris ECDSA signatures via keyctl()
Subsystems (2)
Marek Behún
maintainercover Turris ECDSA signatures via keyctl()
Hi Arnd et al.,
this series adds support for generating ECDSA signatures with hardware stored private key on Turris Omnia and Turris MOX.
This ability is exposed via the keyctl() syscall.
Patch 1 does a small refactor in the turris-omnia-mcu driver - a piece of code is moved to a separate function so that it can be reused in patch 3.
Patch 2 adds a new helper module turris-signing-key, which helps exposing the signing ability via the keyctl() syscall.
Patch 3 adds the functionality into the turris-omnia-mcu driver.
Patch 4 removes the old debugfs implementation of this functionality from turris-mox-rwtm driver. The debugfs implementation was intended to be temporary until a better userspace interface was introduced.
Patch 5 adds the functionality into the turris-mox-rwtm driver.
Marek
Marek Behún (5):
platform: cznic: turris-omnia-mcu: Refactor requesting MCU interrupt
platform: cznic: Add keyctl helpers for Turris platform
platform: cznic: turris-omnia-mcu: Add support for digital message
signing with HW private key
firmware: turris-mox-rwtm: Drop ECDSA signatures via debugfs
firmware: turris-mox-rwtm: Add support for ECDSA signatures with HW
private key
.../ABI/testing/debugfs-turris-mox-rwtm | 14 - .../testing/sysfs-firmware-turris-mox-rwtm | 9 - MAINTAINERS | 1 + drivers/firmware/Kconfig | 17 ++ drivers/firmware/turris-mox-rwtm.c | 260 +++++++++--------- drivers/platform/cznic/Kconfig | 17 ++ drivers/platform/cznic/Makefile | 3 + .../platform/cznic/turris-omnia-mcu-base.c | 4 + .../platform/cznic/turris-omnia-mcu-gpio.c | 21 +- .../platform/cznic/turris-omnia-mcu-keyctl.c | 162 +++++++++++ .../platform/cznic/turris-omnia-mcu-trng.c | 17 +- drivers/platform/cznic/turris-omnia-mcu.h | 33 ++- drivers/platform/cznic/turris-signing-key.c | 192 +++++++++++++ include/linux/turris-signing-key.h | 33 +++ 14 files changed, 608 insertions(+), 175 deletions(-) delete mode 100644 Documentation/ABI/testing/debugfs-turris-mox-rwtm create mode 100644 drivers/platform/cznic/turris-omnia-mcu-keyctl.c create mode 100644 drivers/platform/cznic/turris-signing-key.c create mode 100644 include/linux/turris-signing-key.h
Signature · 1 line
2.45.3
Marek Behún
maintainerPATCH 1/5 platform: cznic: turris-omnia-mcu: Refactor requesting MCU interrupt
Refactor the code that gets and requests the TRNG MCU interrupt in the TRNG part of the driver into a helper function and put it into the GPIO part of the driver.
--- .../platform/cznic/turris-omnia-mcu-gpio.c | 21 ++++++++++++++++++- .../platform/cznic/turris-omnia-mcu-trng.c | 17 ++++----------- drivers/platform/cznic/turris-omnia-mcu.h | 4 +++- 3 files changed, 27 insertions(+), 15 deletions(-)
drivers/platform/cznic/turris-omnia-mcu-gpio.c +20 -1
@@ -13,6 +13,7 @@#include <linux/device.h> #include <linux/devm-helpers.h> #include <linux/errno.h> +#include <linux/gpio/consumer.h> #include <linux/gpio/driver.h> #include <linux/i2c.h> #include <linux/interrupt.h>
@@ -195,7 +196,7 @@ static const struct omnia_gpio omnia_gpios[64] = { };/* mapping from interrupts to indexes of GPIOs in the omnia_gpios array */ -const u8 omnia_int_to_gpio_idx[32 ] = { +static const u8 omnia_int_to_gpio_idx[32 ] = { [__bf_shf (OMNIA_INT_CARD_DET )] =4 , [__bf_shf (OMNIA_INT_MSATA_IND )] =5 , [__bf_shf (OMNIA_INT_USB30_OVC )] =6 ,
@@ -1093,3 +1094,21 @@ int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu)return 0 ; } + +int omnia_mcu_request_irq (struct omnia_mcu *mcu,u32 spec, +irq_handler_t thread_fn,const char *devname) +{ +u8 irq_idx; +int irq; + +if (!spec) +return -EINVAL ; + + irq_idx = omnia_int_to_gpio_idx[__bf_shf (spec)]; + irq =gpiod_to_irq (gpio_device_get_desc (mcu->gc.gpiodev, irq_idx)); +if (irq <0 ) +return irq; + +return devm_request_threaded_irq (&mcu->client->dev, irq,NULL , + thread_fn,IRQF_ONESHOT , devname, mcu); +}
drivers/platform/cznic/turris-omnia-mcu-trng.c +4 -13
@@ -5,12 +5,9 @@* 2024 by Marek Behún <[email protected]> */ -#include <linux/bitfield.h> #include <linux/completion.h> #include <linux/container_of.h> #include <linux/errno.h> -#include <linux/gpio/consumer.h> -#include <linux/gpio/driver.h> #include <linux/hw_random.h> #include <linux/i2c.h> #include <linux/interrupt.h>
@@ -62,17 +59,12 @@ static int omnia_trng_read(struct hwrng *rng, void *data, size_t max, bool wait)int omnia_mcu_register_trng (struct omnia_mcu *mcu) {struct device *dev = &mcu->client->dev; -u8 irq_idx, dummy; -int irq, err; +u8 dummy; +int err;if (!(mcu->features &OMNIA_FEAT_TRNG ))return 0 ; - irq_idx = omnia_int_to_gpio_idx[__bf_shf (OMNIA_INT_TRNG )]; - irq =gpiod_to_irq (gpio_device_get_desc (mcu->gc.gpiodev, irq_idx)); -if (irq <0 ) -return dev_err_probe (dev, irq,"Cannot get TRNG IRQ\n" ); -/* * If someone else cleared the TRNG interrupt but did not read the * entropy, a new interrupt won't be generated, and entropy collection
@@ -86,9 +78,8 @@ int omnia_mcu_register_trng(struct omnia_mcu *mcu)init_completion (&mcu->trng_entropy_ready); - err =devm_request_threaded_irq (dev, irq,NULL , omnia_trng_irq_handler, -IRQF_ONESHOT ,"turris-omnia-mcu-trng" , - mcu); + err =omnia_mcu_request_irq (mcu,OMNIA_INT_TRNG , omnia_trng_irq_handler, +"turris-omnia-mcu-trng" );if (err)return dev_err_probe (dev, err,"Cannot request TRNG IRQ\n" );
drivers/platform/cznic/turris-omnia-mcu.h +3 -1
@@ -12,6 +12,7 @@#include <linux/gpio/driver.h> #include <linux/hw_random.h> #include <linux/if_ether.h> +#include <linux/interrupt.h> #include <linux/mutex.h> #include <linux/types.h> #include <linux/watchdog.h>
@@ -91,9 +92,10 @@ struct omnia_mcu { };#ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO -extern const u8 omnia_int_to_gpio_idx[32 ];extern const struct attribute_group omnia_mcu_gpio_group;int omnia_mcu_register_gpiochip (struct omnia_mcu *mcu); +int omnia_mcu_request_irq (struct omnia_mcu *mcu,u32 spec, +irq_handler_t thread_fn,const char *devname);#else static inline int omnia_mcu_register_gpiochip (struct omnia_mcu *mcu) {
Signature · 1 line
2.45.3
Marek Behún
maintainerPATCH 2/5 platform: cznic: Add keyctl helpers for Turris platform
In reply to Marek BehúnSome Turris devices support signing messages with a per-device unique asymmetric key that was created on the device at manufacture time.
Add helper module that helps to expose this ability via the keyctl() syscall.
A device-specific driver can register a signing key by calling devm_turris_signing_key_create().
Both the .turris-signing-keys keyring and the signing key are created with only the VIEW, READ and SEARCH permissions for userspace - it is impossible to link / unlink / move them, set their attributes, or unlink the keyring from userspace.
--- MAINTAINERS | 1 + drivers/platform/cznic/Kconfig | 5 + drivers/platform/cznic/Makefile | 2 + drivers/platform/cznic/turris-signing-key.c | 192 ++++++++++++++++++++ include/linux/turris-signing-key.h | 33 ++++ 5 files changed, 233 insertions(+) create mode 100644 drivers/platform/cznic/turris-signing-key.c create mode 100644 include/linux/turris-signing-key.h
MAINTAINERS +1 -0
@@ -2442,6 +2442,7 @@ F: include/dt-bindings/bus/moxtet.h F: include/linux/armada-37xx-rwtm-mailbox.h F: include/linux/moxtet.h F: include/linux/turris-omnia-mcu-interface.h +F: include/linux/turris-signing-key.h ARM/FARADAY FA526 PORT M: Hans Ulli Kroll <[email protected]>
drivers/platform/cznic/Kconfig +5 -0
@@ -77,4 +77,9 @@ config TURRIS_OMNIA_MCU_TRNG endif # TURRIS_OMNIA_MCU +config TURRIS_SIGNING_KEY + tristate + depends on KEYS + depends on ASYMMETRIC_KEY_TYPE + endif # CZNIC_PLATFORMS
drivers/platform/cznic/Makefile +2 -0
@@ -6,3 +6,5 @@ turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_GPIO) += turris-omnia-mcu-gpio.o turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP) += turris-omnia-mcu-sys-off-wakeup.o turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_TRNG) += turris-omnia-mcu-trng.o turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_WATCHDOG) += turris-omnia-mcu-watchdog.o + +obj-$(CONFIG_TURRIS_SIGNING_KEY) += turris-signing-key.o
drivers/platform/cznic/turris-signing-key.c new file +192 -0
192 lines not on this page · raw message
include/linux/turris-signing-key.h new file +33 -0
@@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* 2025 by Marek Behún <[email protected]> +*/ + +#ifndef __TURRIS_SIGNING_KEY_H +#define __TURRIS_SIGNING_KEY_H + +#include <linux/key.h> +#include <linux/types.h> + +struct device ; + +struct turris_signing_key_subtype { +u16 key_size; +u8 data_size; +u8 sig_size; +u8 public_key_size; +const char *hash_algo; +const void *(*get_public_key)(const struct key *key); +int (*sign)(const struct key *key,const void *msg,void *signature); +}; + +static inline struct device *turris_signing_key_get_dev (const struct key *key) +{ +return key->payload.data[1 ]; +} + +int +devm_turris_signing_key_create (struct device *dev,const struct turris_signing_key_subtype *subtype, +const char *desc); + +#endif /* __TURRIS_SIGNING_KEY_H */
Signature · 1 line
2.45.3
Marek Behún
maintainerPATCH 3/5 platform: cznic: turris-omnia-mcu: Add support for digital message signing with HW private key
In reply to Marek BehúnAdd support for digital message signing with the private key stored in the MCU. Turris Omnia boards with MKL MCUs have a NIST256p ECDSA private key generated and burned into MCU's flash when manufactured. The private key is not readable from the MCU, but MCU allows for signing messages with it and retrieving the public key.
This is exposed to userspace via the keyctl API.
In userspace, the user can look at /proc/keys or list the keyring:
$ cat /proc/keys 0a3b7cd3 ... keyring .turris-signing-keys: 1 3caf0b1a ... turris-om Turris Omnia SN 0000000A1000023 MCU ECDSA k...
$ keyctl rlist %:.turris-signing-keys 1018104602
To get the public key:
$ keyctl read 1018104602 33 bytes of data in key: 025d9108 1fb538ae 8435c88b b4379171 d6b158a9 55751b91 1d23e6a9 d017f4b2 1c
To sign a message:
$ dd if=/dev/urandom of=msg_to_sign bs=32 count=1 $ keyctl pkey_sign 1018104602 0 msg_to_sign >signature
--- drivers/platform/cznic/Kconfig | 12 ++ drivers/platform/cznic/Makefile | 1 + .../platform/cznic/turris-omnia-mcu-base.c | 4 + .../platform/cznic/turris-omnia-mcu-keyctl.c | 162 ++++++++++++++++++ drivers/platform/cznic/turris-omnia-mcu.h | 29 ++++ 5 files changed, 208 insertions(+) create mode 100644 drivers/platform/cznic/turris-omnia-mcu-keyctl.c
drivers/platform/cznic/Kconfig +12 -0
@@ -75,6 +75,18 @@ config TURRIS_OMNIA_MCU_TRNG Say Y here to add support for the true random number generator provided by CZ.NIC's Turris Omnia MCU. +config TURRIS_OMNIA_MCU_KEYCTL + bool "Turris Omnia MCU ECDSA message signing" + default y + depends on KEYS + depends on ASYMMETRIC_KEY_TYPE + depends on TURRIS_OMNIA_MCU_GPIO + select TURRIS_SIGNING_KEY + help + Say Y here to add support for ECDSA message signing with board private + key (if available on the MCU). This is exposed via the keyctl() + syscall. + endif # TURRIS_OMNIA_MCU config TURRIS_SIGNING_KEY
drivers/platform/cznic/Makefile +1 -0
@@ -3,6 +3,7 @@ obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris-omnia-mcu.o turris-omnia-mcu-y := turris-omnia-mcu-base.o turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_GPIO) += turris-omnia-mcu-gpio.o +turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_KEYCTL) += turris-omnia-mcu-keyctl.o turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP) += turris-omnia-mcu-sys-off-wakeup.o turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_TRNG) += turris-omnia-mcu-trng.o turris-omnia-mcu-$(CONFIG_TURRIS_OMNIA_MCU_WATCHDOG) += turris-omnia-mcu-watchdog.o
drivers/platform/cznic/turris-omnia-mcu-base.c +4 -0
@@ -392,6 +392,10 @@ static int omnia_mcu_probe(struct i2c_client *client)if (err)return err; + err =omnia_mcu_register_keyctl (mcu); +if (err) +return err; +return omnia_mcu_register_trng (mcu); }
drivers/platform/cznic/turris-omnia-mcu-keyctl.c new file +162 -0
162 lines not on this page · raw message
drivers/platform/cznic/turris-omnia-mcu.h +29 -0
@@ -18,6 +18,11 @@#include <linux/watchdog.h> #include <linux/workqueue.h> +enum { +OMNIA_MCU_CRYPTO_PUBLIC_KEY_LEN =1 +32 , +OMNIA_MCU_CRYPTO_SIGNATURE_LEN =64 , +}; +struct i2c_client ;struct rtc_device ;
@@ -56,6 +61,12 @@ struct rtc_device;* @wdt: watchdog driver structure * @trng: RNG driver structure * @trng_entropy_ready: RNG entropy ready completion +* @msg_signed: message signed completion +* @sign_lock: mutex to protect message signing state +* @sign_requested: flag indicating that message signing was requested but not completed +* @sign_err: message signing error number, filled in interrupt handler +* @signature: message signing signature, filled in interrupt handler +* @board_public_key: board public key, if stored in MCU */ struct omnia_mcu {struct i2c_client *client;
@@ -89,6 +100,15 @@ struct omnia_mcu {struct hwrng trng;struct completion trng_entropy_ready;#endif + +#ifdef CONFIG_TURRIS_OMNIA_MCU_KEYCTL +struct completion msg_signed; +struct mutex sign_lock; +bool sign_requested; +int sign_err; +u8 signature[OMNIA_MCU_CRYPTO_SIGNATURE_LEN ]; +u8 board_public_key[OMNIA_MCU_CRYPTO_PUBLIC_KEY_LEN ]; +#endif };#ifdef CONFIG_TURRIS_OMNIA_MCU_GPIO
@@ -103,6 +123,15 @@ static inline int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu) }#endif +#ifdef CONFIG_TURRIS_OMNIA_MCU_KEYCTL +int omnia_mcu_register_keyctl (struct omnia_mcu *mcu); +#else +static inline int omnia_mcu_register_keyctl (struct omnia_mcu *mcu) +{ +return 0 ; +} +#endif +#ifdef CONFIG_TURRIS_OMNIA_MCU_SYSOFF_WAKEUP extern const struct attribute_group omnia_mcu_poweroff_group;int omnia_mcu_register_sys_off_and_wakeup (struct omnia_mcu *mcu);
Signature · 1 line
2.45.3
Marek Behún
maintainerPATCH 4/5 firmware: turris-mox-rwtm: Drop ECDSA signatures via debugfs
In reply to Marek BehúnDrop the debugfs implementation of the ECDSA message signing, in preparation for a new implementation via the keyctl() syscall.
--- .../ABI/testing/debugfs-turris-mox-rwtm | 14 -- .../testing/sysfs-firmware-turris-mox-rwtm | 9 - drivers/firmware/turris-mox-rwtm.c | 184 +----------------- 3 files changed, 7 insertions(+), 200 deletions(-) delete mode 100644 Documentation/ABI/testing/debugfs-turris-mox-rwtm
Documentation/ABI/testing/debugfs-turris-mox-rwtm deleted +0 -14
@@ -1,14 +0,0 @@ -What: /sys/kernel/debug/turris-mox-rwtm/do_sign -Date: Jun 2020 -KernelVersion: 5.8 -Contact: Marek Behún <[email protected]> -Description: - - ======= =========================================================== - (Write) Message to sign with the ECDSA private key stored in - device's OTP. The message must be exactly 64 bytes - (since this is intended for SHA-512 hashes). - (Read) The resulting signature, 136 bytes. This contains the - R and S values of the ECDSA signature, both in - big-endian format. - ======= ===========================================================
Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm +0 -9
@@ -12,15 +12,6 @@ Contact: Marek Behún <[email protected]> Description: (Read) MAC addresses burned into eFuses of this Turris Mox board. Format: %pM -What: /sys/firmware/turris-mox-rwtm/pubkey -Date: August 2019 -KernelVersion: 5.4 -Contact: Marek Behún <[email protected]> -Description: (Read) ECDSA public key (in pubkey hex compressed form) computed - as pair to the ECDSA private key burned into eFuses of this - Turris Mox Board. - Format: string - What: /sys/firmware/turris-mox-rwtm/ram_size Date: August 2019 KernelVersion: 5.4
drivers/firmware/turris-mox-rwtm.c +7 -177
255 lines not on this page · raw message
Signature · 1 line
2.45.3
Marek Behún
maintainerPATCH 5/5 firmware: turris-mox-rwtm: Add support for ECDSA signatures with HW private key
In reply to Marek BehúnAdd support for digital message signing with the private key stored in the rWTM secure coprocessor. Turris Mox devices have an ECDSA private key generated and burned into rWTM eFuses when manufactured. This private key is not readable from the rWTM, but rWTM firmware allows for signing messages with it and retrieving the public key.
This is exposed to userspace via the keyctl API.
User can find the key by either looking at /proc/keys or listing the keyring:
$ cat /proc/keys 0240b221 ... keyring .turris-signing-keys: 1 34ff9ac9 ... turris-si Turris MOX SN 0000000D30000005 rWTM ECDSA ke...
$ keyctl rlist %:.turris-signing-keys 889166537
To get the public key:
$ keyctl read 889166537 67 bytes of data in key: 0201a05c 1a79242b 13f2fc02 b48ffdbb 6ee8d5ba 812d6784 5f04f302 c0894d3e b93474f9 46235777 5c926fb4 cce89b50 88cf5d10 c07fd9c5 fdcea257 3d8f1c33 1bf826
To sign a message:
$ dd if=/dev/urandom of=msg_to_sign bs=64 count=1 $ keyctl pkey_sign 889166537 0 msg_to_sign >signature
--- drivers/firmware/Kconfig | 17 ++++ drivers/firmware/turris-mox-rwtm.c | 158 ++++++++++++++++++++++++++++- 2 files changed, 174 insertions(+), 1 deletion(-)
drivers/firmware/Kconfig +17 -0
@@ -257,6 +257,23 @@ config TURRIS_MOX_RWTM other manufacturing data and also utilize the Entropy Bit Generator for hardware random number generation. +if TURRIS_MOX_RWTM + +config TURRIS_MOX_RWTM_KEYCTL + bool "Turris Mox rWTM ECDSA message signing" + default y + depends on KEYS + depends on ASYMMETRIC_KEY_TYPE + select CZNIC_PLATFORMS + select TURRIS_SIGNING_KEY + help + Say Y here to add support for ECDSA message signing with board private + key (each Turris Mox has an ECDSA private key generated in the secure + coprocessor when manufactured). This functionality is exposed via the + keyctl() syscall. + +endif # TURRIS_MOX_RWTM + source "drivers/firmware/arm_ffa/Kconfig" source "drivers/firmware/broadcom/Kconfig" source "drivers/firmware/cirrus/Kconfig"
drivers/firmware/turris-mox-rwtm.c +157 -1
212 lines not on this page · raw message
Signature · 1 line
2.45.3
Marek Behún
maintainerHi Arnd et al.,
any comments on this series?
Thanks,
Marek
This series was applied to soc/soc.git (for-next) by Arnd Bergmann <[email protected]>:
Hello:
This series was applied to soc/soc.git (for-next)
by Arnd Bergmann <[email protected]>:
Quoted 8 lines · On Tue, 4 Feb 2025 14:14:10 +0100 you wrote:
Hi Arnd et al.,
this series adds support for generating ECDSA signatures with hardware stored private key on Turris Omnia and Turris MOX.
This ability is exposed via the
keyctl()syscall.[...]
Here is the summary with links:
- [1/5] platform: cznic: turris-omnia-mcu: Refactor requesting MCU interrupt
https://git.kernel.org/soc/soc/c/ee7f8ed72990 - [2/5] platform: cznic: Add keyctl helpers for Turris platform https://git.kernel.org/soc/soc/c/0b28b7080ef5 - [3/5] platform: cznic: turris-omnia-mcu: Add support for digital message signing with HW private key https://git.kernel.org/soc/soc/c/df94a2f1eb45 - [4/5] firmware: turris-mox-rwtm: Drop ECDSA signatures via debugfs https://git.kernel.org/soc/soc/c/4110ad034fb7 - [5/5] firmware: turris-mox-rwtm: Add support for ECDSA signatures with HW private key https://git.kernel.org/soc/soc/c/ba8755ab541f
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html