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