xref: /linux/crypto/mldsa.c (revision 69050f8d6d075dc01af7a5f2f550a8067510366f)
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");
202