Skip to content

Commit d3b6dd9

Browse files
committed
crypto: Add ML-DSA crypto_sig support
Add verify-only public key crypto support for ML-DSA so that the X.509/PKCS#7 signature verification code, as used by module signing, amongst other things, can make use of it through the common crypto_sig API. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> cc: Eric Biggers <ebiggers@kernel.org> cc: Lukas Wunner <lukas@wunner.de> cc: Ignat Korchagin <ignat@cloudflare.com> cc: Stephan Mueller <smueller@chronox.de> cc: Herbert Xu <herbert@gondor.apana.org.au> cc: keyrings@vger.kernel.org cc: linux-crypto@vger.kernel.org
1 parent 959a634 commit d3b6dd9

3 files changed

Lines changed: 212 additions & 0 deletions

File tree

crypto/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,15 @@ config CRYPTO_ECRDSA
344344
One of the Russian cryptographic standard algorithms (called GOST
345345
algorithms). Only signature verification is implemented.
346346

347+
config CRYPTO_MLDSA
348+
tristate "ML-DSA (Module-Lattice-Based Digital Signature Algorithm)"
349+
select CRYPTO_SIG
350+
select CRYPTO_LIB_MLDSA
351+
help
352+
ML-DSA (Module-Lattice-Based Digital Signature Algorithm) (FIPS-204).
353+
354+
Only signature verification is implemented.
355+
347356
endmenu
348357

349358
menu "Block ciphers"

crypto/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ ecdsa_generic-y += ecdsa-p1363.o
6060
ecdsa_generic-y += ecdsasignature.asn1.o
6161
obj-$(CONFIG_CRYPTO_ECDSA) += ecdsa_generic.o
6262

63+
obj-$(CONFIG_CRYPTO_MLDSA) += mldsa.o
64+
6365
crypto_acompress-y := acompress.o
6466
crypto_acompress-y += scompress.o
6567
obj-$(CONFIG_CRYPTO_ACOMP2) += crypto_acompress.o

crypto/mldsa.c

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* crypto_sig wrapper around ML-DSA library.
4+
*/
5+
#include <linux/init.h>
6+
#include <linux/module.h>
7+
#include <crypto/internal/sig.h>
8+
#include <crypto/mldsa.h>
9+
10+
struct crypto_mldsa_ctx {
11+
u8 pk[MAX(MAX(MLDSA44_PUBLIC_KEY_SIZE,
12+
MLDSA65_PUBLIC_KEY_SIZE),
13+
MLDSA87_PUBLIC_KEY_SIZE)];
14+
unsigned int pk_len;
15+
enum mldsa_alg strength;
16+
bool key_set;
17+
};
18+
19+
static int crypto_mldsa_sign(struct crypto_sig *tfm,
20+
const void *msg, unsigned int msg_len,
21+
void *sig, unsigned int sig_len)
22+
{
23+
return -EOPNOTSUPP;
24+
}
25+
26+
static int crypto_mldsa_verify(struct crypto_sig *tfm,
27+
const void *sig, unsigned int sig_len,
28+
const void *msg, unsigned int msg_len)
29+
{
30+
const struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
31+
32+
if (unlikely(!ctx->key_set))
33+
return -EINVAL;
34+
35+
return mldsa_verify(ctx->strength, sig, sig_len, msg, msg_len,
36+
ctx->pk, ctx->pk_len);
37+
}
38+
39+
static unsigned int crypto_mldsa_key_size(struct crypto_sig *tfm)
40+
{
41+
struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
42+
43+
switch (ctx->strength) {
44+
case MLDSA44:
45+
return MLDSA44_PUBLIC_KEY_SIZE;
46+
case MLDSA65:
47+
return MLDSA65_PUBLIC_KEY_SIZE;
48+
case MLDSA87:
49+
return MLDSA87_PUBLIC_KEY_SIZE;
50+
default:
51+
WARN_ON_ONCE(1);
52+
return 0;
53+
}
54+
}
55+
56+
static int crypto_mldsa_set_pub_key(struct crypto_sig *tfm,
57+
const void *key, unsigned int keylen)
58+
{
59+
struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
60+
unsigned int expected_len = crypto_mldsa_key_size(tfm);
61+
62+
if (keylen != expected_len)
63+
return -EINVAL;
64+
65+
ctx->pk_len = keylen;
66+
memcpy(ctx->pk, key, keylen);
67+
ctx->key_set = true;
68+
return 0;
69+
}
70+
71+
static int crypto_mldsa_set_priv_key(struct crypto_sig *tfm,
72+
const void *key, unsigned int keylen)
73+
{
74+
return -EOPNOTSUPP;
75+
}
76+
77+
static unsigned int crypto_mldsa_max_size(struct crypto_sig *tfm)
78+
{
79+
struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
80+
81+
switch (ctx->strength) {
82+
case MLDSA44:
83+
return MLDSA44_SIGNATURE_SIZE;
84+
case MLDSA65:
85+
return MLDSA65_SIGNATURE_SIZE;
86+
case MLDSA87:
87+
return MLDSA87_SIGNATURE_SIZE;
88+
default:
89+
WARN_ON_ONCE(1);
90+
return 0;
91+
}
92+
}
93+
94+
static int crypto_mldsa44_alg_init(struct crypto_sig *tfm)
95+
{
96+
struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
97+
98+
ctx->strength = MLDSA44;
99+
ctx->key_set = false;
100+
return 0;
101+
}
102+
103+
static int crypto_mldsa65_alg_init(struct crypto_sig *tfm)
104+
{
105+
struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
106+
107+
ctx->strength = MLDSA65;
108+
ctx->key_set = false;
109+
return 0;
110+
}
111+
112+
static int crypto_mldsa87_alg_init(struct crypto_sig *tfm)
113+
{
114+
struct crypto_mldsa_ctx *ctx = crypto_sig_ctx(tfm);
115+
116+
ctx->strength = MLDSA87;
117+
ctx->key_set = false;
118+
return 0;
119+
}
120+
121+
static void crypto_mldsa_alg_exit(struct crypto_sig *tfm)
122+
{
123+
}
124+
125+
static struct sig_alg crypto_mldsa_algs[] = {
126+
{
127+
.sign = crypto_mldsa_sign,
128+
.verify = crypto_mldsa_verify,
129+
.set_pub_key = crypto_mldsa_set_pub_key,
130+
.set_priv_key = crypto_mldsa_set_priv_key,
131+
.key_size = crypto_mldsa_key_size,
132+
.max_size = crypto_mldsa_max_size,
133+
.init = crypto_mldsa44_alg_init,
134+
.exit = crypto_mldsa_alg_exit,
135+
.base.cra_name = "mldsa44",
136+
.base.cra_driver_name = "mldsa44-lib",
137+
.base.cra_ctxsize = sizeof(struct crypto_mldsa_ctx),
138+
.base.cra_module = THIS_MODULE,
139+
.base.cra_priority = 5000,
140+
}, {
141+
.sign = crypto_mldsa_sign,
142+
.verify = crypto_mldsa_verify,
143+
.set_pub_key = crypto_mldsa_set_pub_key,
144+
.set_priv_key = crypto_mldsa_set_priv_key,
145+
.key_size = crypto_mldsa_key_size,
146+
.max_size = crypto_mldsa_max_size,
147+
.init = crypto_mldsa65_alg_init,
148+
.exit = crypto_mldsa_alg_exit,
149+
.base.cra_name = "mldsa65",
150+
.base.cra_driver_name = "mldsa65-lib",
151+
.base.cra_ctxsize = sizeof(struct crypto_mldsa_ctx),
152+
.base.cra_module = THIS_MODULE,
153+
.base.cra_priority = 5000,
154+
}, {
155+
.sign = crypto_mldsa_sign,
156+
.verify = crypto_mldsa_verify,
157+
.set_pub_key = crypto_mldsa_set_pub_key,
158+
.set_priv_key = crypto_mldsa_set_priv_key,
159+
.key_size = crypto_mldsa_key_size,
160+
.max_size = crypto_mldsa_max_size,
161+
.init = crypto_mldsa87_alg_init,
162+
.exit = crypto_mldsa_alg_exit,
163+
.base.cra_name = "mldsa87",
164+
.base.cra_driver_name = "mldsa87-lib",
165+
.base.cra_ctxsize = sizeof(struct crypto_mldsa_ctx),
166+
.base.cra_module = THIS_MODULE,
167+
.base.cra_priority = 5000,
168+
},
169+
};
170+
171+
static int __init mldsa_init(void)
172+
{
173+
int ret, i;
174+
175+
for (i = 0; i < ARRAY_SIZE(crypto_mldsa_algs); i++) {
176+
ret = crypto_register_sig(&crypto_mldsa_algs[i]);
177+
if (ret < 0)
178+
goto error;
179+
}
180+
return 0;
181+
182+
error:
183+
pr_err("Failed to register (%d)\n", ret);
184+
for (i--; i >= 0; i--)
185+
crypto_unregister_sig(&crypto_mldsa_algs[i]);
186+
return ret;
187+
}
188+
module_init(mldsa_init);
189+
190+
static void mldsa_exit(void)
191+
{
192+
for (int i = 0; i < ARRAY_SIZE(crypto_mldsa_algs); i++)
193+
crypto_unregister_sig(&crypto_mldsa_algs[i]);
194+
}
195+
module_exit(mldsa_exit);
196+
197+
MODULE_LICENSE("GPL");
198+
MODULE_DESCRIPTION("Crypto API support for ML-DSA signature verification");
199+
MODULE_ALIAS_CRYPTO("mldsa44");
200+
MODULE_ALIAS_CRYPTO("mldsa65");
201+
MODULE_ALIAS_CRYPTO("mldsa87");

0 commit comments

Comments
 (0)