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