[PATCH v10 5/8] crypto: Add ML-DSA crypto_sig support

David Howells posted 8 patches 2 months, 2 weeks ago
[PATCH v10 5/8] crypto: Add ML-DSA crypto_sig support
Posted by David Howells 2 months, 2 weeks ago
---
 crypto/Kconfig  | 10 ++++++++++
 crypto/Makefile |  2 ++
 2 files changed, 12 insertions(+)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index bf8b8a60a0c0..45e376af02dc 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -344,6 +344,16 @@ config CRYPTO_ECRDSA
 	  One of the Russian cryptographic standard algorithms (called GOST
 	  algorithms). Only signature verification is implemented.
 
+config CRYPTO_MLDSA
+	tristate "ML-DSA (Module-Lattice-Based Digital Signature Algorithm)"
+	select CRYPTO_SIG
+	select CRYPTO_LIB_MLDSA
+	select CRYPTO_LIB_SHA3
+	help
+	  ML-DSA (Module-Lattice-Based Digital Signature Algorithm) (FIPS-204).
+
+	  Only signature verification is implemented.
+
 endmenu
 
 menu "Block ciphers"
diff --git a/crypto/Makefile b/crypto/Makefile
index 093c56a45d3f..b181f8a54099 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -60,6 +60,8 @@ ecdsa_generic-y += ecdsa-p1363.o
 ecdsa_generic-y += ecdsasignature.asn1.o
 obj-$(CONFIG_CRYPTO_ECDSA) += ecdsa_generic.o
 
+obj-$(CONFIG_CRYPTO_MLDSA) += mldsa.o
+
 crypto_acompress-y := acompress.o
 crypto_acompress-y += scompress.o
 obj-$(CONFIG_CRYPTO_ACOMP2) += crypto_acompress.o
Re: [PATCH v10 5/8] crypto: Add ML-DSA crypto_sig support
Posted by David Howells 2 months, 2 weeks ago
Meh.  I forgot to git add crypto/mldsa.c.

David
---
diff --git a/crypto/Kconfig b/crypto/Kconfig
index bf8b8a60a0c0..45e376af02dc 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -344,6 +344,16 @@ config CRYPTO_ECRDSA
 	  One of the Russian cryptographic standard algorithms (called GOST
 	  algorithms). Only signature verification is implemented.
 
+config CRYPTO_MLDSA
+	tristate "ML-DSA (Module-Lattice-Based Digital Signature Algorithm)"
+	select CRYPTO_SIG
+	select CRYPTO_LIB_MLDSA
+	select CRYPTO_LIB_SHA3
+	help
+	  ML-DSA (Module-Lattice-Based Digital Signature Algorithm) (FIPS-204).
+
+	  Only signature verification is implemented.
+
 endmenu
 
 menu "Block ciphers"
diff --git a/crypto/Makefile b/crypto/Makefile
index 093c56a45d3f..b181f8a54099 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -60,6 +60,8 @@ ecdsa_generic-y += ecdsa-p1363.o
 ecdsa_generic-y += ecdsasignature.asn1.o
 obj-$(CONFIG_CRYPTO_ECDSA) += ecdsa_generic.o
 
+obj-$(CONFIG_CRYPTO_MLDSA) += mldsa.o
+
 crypto_acompress-y := acompress.o
 crypto_acompress-y += scompress.o
 obj-$(CONFIG_CRYPTO_ACOMP2) += crypto_acompress.o
diff --git a/crypto/mldsa.c b/crypto/mldsa.c
new file mode 100644
index 000000000000..2146c774b5ca
--- /dev/null
+++ b/crypto/mldsa.c
@@ -0,0 +1,201 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * crypto_sig wrapper around ML-DSA library.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <crypto/internal/sig.h>
+#include <crypto/mldsa.h>
+
+struct crypto_mldsa_ctx {
+	u8 pk[MAX(MAX(MLDSA44_PUBLIC_KEY_SIZE,
+		      MLDSA65_PUBLIC_KEY_SIZE),
+		  MLDSA87_PUBLIC_KEY_SIZE)];
+	unsigned int pk_len;
+	enum mldsa_alg strength;
+	u8 key_set;
+};
+
+static int crypto_mldsa_sign(struct crypto_sig *tfm,
+			     const void *msg, unsigned int msg_len,
+			     void *sig, unsigned int sig_len)
+{
+	return -EOPNOTSUPP;
+}
+
+static int crypto_mldsa_verify(struct crypto_sig *tfm,
+			       const void *sig, unsigned int sig_len,
+			       const void *msg, unsigned int msg_len)
+{
+	const struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
+
+	if (unlikely(!ctx->key_set))
+		return -EINVAL;
+
+	return mldsa_verify(ctx->strength, sig, sig_len, msg, msg_len,
+			    ctx->pk, ctx->pk_len);
+}
+
+static unsigned int crypto_mldsa_key_size(struct crypto_sig *tfm)
+{
+	struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
+
+	switch (ctx->strength) {
+	case MLDSA44:
+		return MLDSA44_PUBLIC_KEY_SIZE;
+	case MLDSA65:
+		return MLDSA65_PUBLIC_KEY_SIZE;
+	case MLDSA87:
+		return MLDSA87_PUBLIC_KEY_SIZE;
+	default:
+		WARN_ON_ONCE(1);
+		return 0;
+	}
+}
+
+static int crypto_mldsa_set_pub_key(struct crypto_sig *tfm,
+				    const void *key, unsigned int keylen)
+{
+	struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
+	unsigned int expected_len = crypto_mldsa_key_size(tfm);
+
+	if (keylen != expected_len)
+		return -EINVAL;
+
+	ctx->pk_len = keylen;
+	memcpy(ctx->pk, key, keylen);
+	ctx->key_set = true;
+	return 0;
+}
+
+static int crypto_mldsa_set_priv_key(struct crypto_sig *tfm,
+				     const void *key, unsigned int keylen)
+{
+	return -EOPNOTSUPP;
+}
+
+static unsigned int crypto_mldsa_max_size(struct crypto_sig *tfm)
+{
+	struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
+
+	switch (ctx->strength) {
+	case MLDSA44:
+		return MLDSA44_SIGNATURE_SIZE;
+	case MLDSA65:
+		return MLDSA65_SIGNATURE_SIZE;
+	case MLDSA87:
+		return MLDSA87_SIGNATURE_SIZE;
+	default:
+		WARN_ON_ONCE(1);
+		return 0;
+	}
+}
+
+static int crypto_mldsa44_alg_init(struct crypto_sig *tfm)
+{
+	struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
+
+	ctx->strength = MLDSA44;
+	ctx->key_set = false;
+	return 0;
+}
+
+static int crypto_mldsa65_alg_init(struct crypto_sig *tfm)
+{
+	struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
+
+	ctx->strength = MLDSA65;
+	ctx->key_set = false;
+	return 0;
+}
+
+static int crypto_mldsa87_alg_init(struct crypto_sig *tfm)
+{
+	struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
+
+	ctx->strength = MLDSA87;
+	ctx->key_set = false;
+	return 0;
+}
+
+static void crypto_mldsa_alg_exit(struct crypto_sig *tfm)
+{
+}
+
+static struct sig_alg crypto_mldsa_algs[] = {
+	{
+		.sign			= crypto_mldsa_sign,
+		.verify			= crypto_mldsa_verify,
+		.set_pub_key		= crypto_mldsa_set_pub_key,
+		.set_priv_key		= crypto_mldsa_set_priv_key,
+		.key_size		= crypto_mldsa_key_size,
+		.max_size		= crypto_mldsa_max_size,
+		.init			= crypto_mldsa44_alg_init,
+		.exit			= crypto_mldsa_alg_exit,
+		.base.cra_name		= "mldsa44",
+		.base.cra_driver_name	= "mldsa44-lib",
+		.base.cra_ctxsize	= sizeof(struct crypto_mldsa_ctx),
+		.base.cra_module	= THIS_MODULE,
+		.base.cra_priority	= 5000,
+	}, {
+		.sign			= crypto_mldsa_sign,
+		.verify			= crypto_mldsa_verify,
+		.set_pub_key		= crypto_mldsa_set_pub_key,
+		.set_priv_key		= crypto_mldsa_set_priv_key,
+		.key_size		= crypto_mldsa_key_size,
+		.max_size		= crypto_mldsa_max_size,
+		.init			= crypto_mldsa65_alg_init,
+		.exit			= crypto_mldsa_alg_exit,
+		.base.cra_name		= "mldsa65",
+		.base.cra_driver_name	= "mldsa65-lib",
+		.base.cra_ctxsize	= sizeof(struct crypto_mldsa_ctx),
+		.base.cra_module	= THIS_MODULE,
+		.base.cra_priority	= 5000,
+	}, {
+		.sign			= crypto_mldsa_sign,
+		.verify			= crypto_mldsa_verify,
+		.set_pub_key		= crypto_mldsa_set_pub_key,
+		.set_priv_key		= crypto_mldsa_set_priv_key,
+		.key_size		= crypto_mldsa_key_size,
+		.max_size		= crypto_mldsa_max_size,
+		.init			= crypto_mldsa87_alg_init,
+		.exit			= crypto_mldsa_alg_exit,
+		.base.cra_name		= "mldsa87",
+		.base.cra_driver_name	= "mldsa87-lib",
+		.base.cra_ctxsize	= sizeof(struct crypto_mldsa_ctx),
+		.base.cra_module	= THIS_MODULE,
+		.base.cra_priority	= 5000,
+	},
+};
+
+static int __init mldsa_init(void)
+{
+	int ret, i;
+
+	for (i = 0; i < ARRAY_SIZE(crypto_mldsa_algs); i++) {
+		ret = crypto_register_sig(&crypto_mldsa_algs[i]);
+		if (ret < 0)
+			goto error;
+	}
+	return 0;
+
+error:
+	pr_err("Failed to register (%d)\n", ret);
+	for (i--; i >= 0; i--)
+		crypto_unregister_sig(&crypto_mldsa_algs[i]);
+	return ret;
+}
+module_init(mldsa_init);
+
+static void mldsa_exit(void)
+{
+	for (int i = 0; i < ARRAY_SIZE(crypto_mldsa_algs); i++)
+		crypto_unregister_sig(&crypto_mldsa_algs[i]);
+}
+module_exit(mldsa_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Crypto API support for ML-DSA signature verification");
+MODULE_ALIAS_CRYPTO("mldsa44");
+MODULE_ALIAS_CRYPTO("mldsa65");
+MODULE_ALIAS_CRYPTO("mldsa87");
RE: [PATCH v10 5/8] crypto: Add ML-DSA crypto_sig support
Posted by Elliott, Robert (Servers) 2 months, 2 weeks ago
> -----Original Message-----
> From: David Howells <dhowells@redhat.com>
> Sent: Monday, November 24, 2025 3:13 AM
> Subject: Re: [PATCH v10 5/8] crypto: Add ML-DSA crypto_sig support
...
> +++ b/crypto/mldsa.c
...
> +static unsigned int crypto_mldsa_key_size(struct crypto_sig *tfm)
> +{
> +	struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
> +
> +	switch (ctx->strength) {
> +	case MLDSA44:
> +		return MLDSA44_PUBLIC_KEY_SIZE;
> +	case MLDSA65:
> +		return MLDSA65_PUBLIC_KEY_SIZE;
> +	case MLDSA87:
> +		return MLDSA87_PUBLIC_KEY_SIZE;
> +	default:
> +		WARN_ON_ONCE(1);
> +		return 0;
> +	}
> +}
...
> +static unsigned int crypto_mldsa_max_size(struct crypto_sig *tfm)
> +{
> +	struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
> +
> +	switch (ctx->strength) {
> +	case MLDSA44:
> +		return MLDSA44_SIGNATURE_SIZE;
> +	case MLDSA65:
> +		return MLDSA65_SIGNATURE_SIZE;
> +	case MLDSA87:
> +		return MLDSA87_SIGNATURE_SIZE;
> +	default:
> +		WARN_ON_ONCE(1);
> +		return 0;
> +	}

In case there's any way userspace can trigger those, I'd rather
not have any WARN stack dumps.
Re: [PATCH v10 5/8] crypto: Add ML-DSA crypto_sig support
Posted by Eric Biggers 2 months, 2 weeks ago
On Mon, Nov 24, 2025 at 09:12:57AM +0000, David Howells wrote:
> diff --git a/crypto/mldsa.c b/crypto/mldsa.c
> new file mode 100644
> index 000000000000..2146c774b5ca
> --- /dev/null
> +++ b/crypto/mldsa.c
> @@ -0,0 +1,201 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * crypto_sig wrapper around ML-DSA library.
> + */

Still not really sure what the point is.  There's only one user of
crypto_sig, and it could just call the ML-DSA functions directly.

- Eric
Re: [PATCH v10 5/8] crypto: Add ML-DSA crypto_sig support
Posted by David Howells 2 months, 2 weeks ago
Eric Biggers <ebiggers@kernel.org> wrote:

> Still not really sure what the point is.  There's only one user of
> crypto_sig, and it could just call the ML-DSA functions directly.

Is it your aim to kill off the crypto/ dir and all the (old) crypto API?

Someone (not me) thought it worthwhile removing the akcipher algorithms out of
crypto/asymmetric_keys/ and interfacing to them inside crypto_akcipher and
crypto_sig.

Anyway, I'll continue using crypto_sig as that provides module autoload
capabilities - meaning we don't have to build all the algorithms into the base
kernel.

David
Re: [PATCH v10 5/8] crypto: Add ML-DSA crypto_sig support
Posted by Jason A. Donenfeld 2 months, 2 weeks ago
On Mon, Nov 24, 2025 at 6:25 PM David Howells <dhowells@redhat.com> wrote:
>
> Eric Biggers <ebiggers@kernel.org> wrote:
>
> > Still not really sure what the point is.  There's only one user of
> > crypto_sig, and it could just call the ML-DSA functions directly.
>
> Is it your aim to kill off the crypto/ dir and all the (old) crypto API?

Probably entirely killing off the old API is going to be fraught
because its abstraction has leaked out to userspace. But to the extent
we can minimize its use over time, I think that's a good thing. Even
for crypto usages that generalize to a few different ciphers of one
variety or another, I think being explicit about which ciphers and
having purpose-built dispatchers is usually a better route.

Jason
Re: [PATCH v10 5/8] crypto: Add ML-DSA crypto_sig support
Posted by David Howells 2 months, 2 weeks ago
Jason A. Donenfeld <Jason@zx2c4.com> wrote:

> > > Still not really sure what the point is.  There's only one user of
> > > crypto_sig, and it could just call the ML-DSA functions directly.
> >
> > Is it your aim to kill off the crypto/ dir and all the (old) crypto API?
> 
> Probably entirely killing off the old API is going to be fraught
> because its abstraction has leaked out to userspace. But to the extent
> we can minimize its use over time, I think that's a good thing. Even
> for crypto usages that generalize to a few different ciphers of one
> variety or another, I think being explicit about which ciphers and
> having purpose-built dispatchers is usually a better route.

How are you proposing handling the autoloading feature of the old API?

David
Re: [PATCH v10 5/8] crypto: Add ML-DSA crypto_sig support
Posted by Jason A. Donenfeld 2 months, 2 weeks ago
On Mon, Nov 24, 2025 at 8:54 PM David Howells <dhowells@redhat.com> wrote:
> > > > Still not really sure what the point is.  There's only one user of
> > > > crypto_sig, and it could just call the ML-DSA functions directly.
> > >
> > > Is it your aim to kill off the crypto/ dir and all the (old) crypto API?
> >
> > Probably entirely killing off the old API is going to be fraught
> > because its abstraction has leaked out to userspace. But to the extent
> > we can minimize its use over time, I think that's a good thing. Even
> > for crypto usages that generalize to a few different ciphers of one
> > variety or another, I think being explicit about which ciphers and
> > having purpose-built dispatchers is usually a better route.
>
> How are you proposing handling the autoloading feature of the old API?

I don't know. Not all features will have direct replacements. Not all
usages will be replaced. Not all use cases benefit from being
replaced. You asked if it was an "aim." I replied by telling you that
I think killing it is going to be difficult, but that over time, usage
will decline. I think that'll be a natural thing. For now, when
something uses the library API, there's a pretty easy and obvious case
to be made for it, as there are still such obvious low hanging use
cases. I suppose in a while, we might run out of those perhaps. But
that hasn't happened yet, I guess.

Jason
Re: [PATCH v10 5/8] crypto: Add ML-DSA crypto_sig support
Posted by Eric Biggers 2 months, 2 weeks ago
On Mon, Nov 24, 2025 at 09:10:33PM +0100, Jason A. Donenfeld wrote:
> On Mon, Nov 24, 2025 at 8:54 PM David Howells <dhowells@redhat.com> wrote:
> > > > > Still not really sure what the point is.  There's only one user of
> > > > > crypto_sig, and it could just call the ML-DSA functions directly.
> > > >
> > > > Is it your aim to kill off the crypto/ dir and all the (old) crypto API?
> > >
> > > Probably entirely killing off the old API is going to be fraught
> > > because its abstraction has leaked out to userspace. But to the extent
> > > we can minimize its use over time, I think that's a good thing. Even
> > > for crypto usages that generalize to a few different ciphers of one
> > > variety or another, I think being explicit about which ciphers and
> > > having purpose-built dispatchers is usually a better route.
> >
> > How are you proposing handling the autoloading feature of the old API?
> 
> I don't know. Not all features will have direct replacements. Not all
> usages will be replaced. Not all use cases benefit from being
> replaced. You asked if it was an "aim." I replied by telling you that
> I think killing it is going to be difficult, but that over time, usage
> will decline. I think that'll be a natural thing. For now, when
> something uses the library API, there's a pretty easy and obvious case
> to be made for it, as there are still such obvious low hanging use
> cases. I suppose in a while, we might run out of those perhaps. But
> that hasn't happened yet, I guess.
> 
> Jason

+1 to what Jason said.  The traditional API generally isn't going away.
However, there's no need to add new functionality to it when the library
is a better fit.  The crypto_sig abstraction doesn't seem very helpful,
since it was added only recently and has only one user (public_key).

The traditional crypto API's dynamic loading by name also tends to be
more harmful than helpful.  Linux users and distros keep running into
problems where algorithms aren't available in the initramfs when they
should be, or where the slow generic code is used instead of the
optimized code.  The direct linking finally just fixes that.

You may also still be thinking of the ML-DSA code as something
heavyweight.  I reduced it to under 4 KB of object code.

It should also become the recommended algorithm anyway, right?

Either way, 4 KB seems awfully small to be wanting to be dynamically
loaded.  Last year I shrunk the x86_64 AES-GCM code (which most Linux
distros build in to avoid the dynamic loading issues) by over 200 KB.
No one even seemed to care that much...  We can add a lot of stuff
before we're even back to where we were before that.

- Eric
Re: [PATCH v10 5/8] crypto: Add ML-DSA crypto_sig support
Posted by David Howells 2 months, 2 weeks ago
Eric Biggers <ebiggers@kernel.org> wrote:

> It should also become the recommended algorithm anyway, right?

It's used for more than just module signing.  IMA, for example.

David