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