// 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");
// 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");