mirror of
https://github.com/torvalds/linux.git
synced 2026-03-07 23:04:33 +01:00
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
This commit is contained in:
parent
959a634ebc
commit
d3b6dd90e2
3 changed files with 212 additions and 0 deletions
|
|
@ -344,6 +344,15 @@ 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
|
||||
help
|
||||
ML-DSA (Module-Lattice-Based Digital Signature Algorithm) (FIPS-204).
|
||||
|
||||
Only signature verification is implemented.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Block ciphers"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
201
crypto/mldsa.c
Normal file
201
crypto/mldsa.c
Normal file
|
|
@ -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;
|
||||
bool 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");
|
||||
Loading…
Add table
Add a link
Reference in a new issue