1ee772cb6SArd Biesheuvel // SPDX-License-Identifier: GPL-2.0-or-later
2ee772cb6SArd Biesheuvel
3ee772cb6SArd Biesheuvel #include <crypto/curve25519.h>
4ee772cb6SArd Biesheuvel #include <crypto/internal/kpp.h>
5ee772cb6SArd Biesheuvel #include <crypto/kpp.h>
6ee772cb6SArd Biesheuvel #include <linux/module.h>
7ee772cb6SArd Biesheuvel #include <linux/scatterlist.h>
8ee772cb6SArd Biesheuvel
curve25519_set_secret(struct crypto_kpp * tfm,const void * buf,unsigned int len)9ee772cb6SArd Biesheuvel static int curve25519_set_secret(struct crypto_kpp *tfm, const void *buf,
10ee772cb6SArd Biesheuvel unsigned int len)
11ee772cb6SArd Biesheuvel {
12ee772cb6SArd Biesheuvel u8 *secret = kpp_tfm_ctx(tfm);
13ee772cb6SArd Biesheuvel
14ee772cb6SArd Biesheuvel if (!len)
15ee772cb6SArd Biesheuvel curve25519_generate_secret(secret);
16ee772cb6SArd Biesheuvel else if (len == CURVE25519_KEY_SIZE &&
17ee772cb6SArd Biesheuvel crypto_memneq(buf, curve25519_null_point, CURVE25519_KEY_SIZE))
18ee772cb6SArd Biesheuvel memcpy(secret, buf, CURVE25519_KEY_SIZE);
19ee772cb6SArd Biesheuvel else
20ee772cb6SArd Biesheuvel return -EINVAL;
21ee772cb6SArd Biesheuvel return 0;
22ee772cb6SArd Biesheuvel }
23ee772cb6SArd Biesheuvel
curve25519_compute_value(struct kpp_request * req)24ee772cb6SArd Biesheuvel static int curve25519_compute_value(struct kpp_request *req)
25ee772cb6SArd Biesheuvel {
26ee772cb6SArd Biesheuvel struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
27ee772cb6SArd Biesheuvel const u8 *secret = kpp_tfm_ctx(tfm);
28ee772cb6SArd Biesheuvel u8 public_key[CURVE25519_KEY_SIZE];
29ee772cb6SArd Biesheuvel u8 buf[CURVE25519_KEY_SIZE];
30ee772cb6SArd Biesheuvel int copied, nbytes;
31ee772cb6SArd Biesheuvel u8 const *bp;
32ee772cb6SArd Biesheuvel
33ee772cb6SArd Biesheuvel if (req->src) {
34ee772cb6SArd Biesheuvel copied = sg_copy_to_buffer(req->src,
35ee772cb6SArd Biesheuvel sg_nents_for_len(req->src,
36ee772cb6SArd Biesheuvel CURVE25519_KEY_SIZE),
37ee772cb6SArd Biesheuvel public_key, CURVE25519_KEY_SIZE);
38ee772cb6SArd Biesheuvel if (copied != CURVE25519_KEY_SIZE)
39ee772cb6SArd Biesheuvel return -EINVAL;
40ee772cb6SArd Biesheuvel bp = public_key;
41ee772cb6SArd Biesheuvel } else {
42ee772cb6SArd Biesheuvel bp = curve25519_base_point;
43ee772cb6SArd Biesheuvel }
44ee772cb6SArd Biesheuvel
45ee772cb6SArd Biesheuvel curve25519_generic(buf, secret, bp);
46ee772cb6SArd Biesheuvel
47ee772cb6SArd Biesheuvel /* might want less than we've got */
48ee772cb6SArd Biesheuvel nbytes = min_t(size_t, CURVE25519_KEY_SIZE, req->dst_len);
49ee772cb6SArd Biesheuvel copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst,
50ee772cb6SArd Biesheuvel nbytes),
51ee772cb6SArd Biesheuvel buf, nbytes);
52ee772cb6SArd Biesheuvel if (copied != nbytes)
53ee772cb6SArd Biesheuvel return -EINVAL;
54ee772cb6SArd Biesheuvel return 0;
55ee772cb6SArd Biesheuvel }
56ee772cb6SArd Biesheuvel
curve25519_max_size(struct crypto_kpp * tfm)57ee772cb6SArd Biesheuvel static unsigned int curve25519_max_size(struct crypto_kpp *tfm)
58ee772cb6SArd Biesheuvel {
59ee772cb6SArd Biesheuvel return CURVE25519_KEY_SIZE;
60ee772cb6SArd Biesheuvel }
61ee772cb6SArd Biesheuvel
62ee772cb6SArd Biesheuvel static struct kpp_alg curve25519_alg = {
63ee772cb6SArd Biesheuvel .base.cra_name = "curve25519",
64ee772cb6SArd Biesheuvel .base.cra_driver_name = "curve25519-generic",
65ee772cb6SArd Biesheuvel .base.cra_priority = 100,
66ee772cb6SArd Biesheuvel .base.cra_module = THIS_MODULE,
67ee772cb6SArd Biesheuvel .base.cra_ctxsize = CURVE25519_KEY_SIZE,
68ee772cb6SArd Biesheuvel
69ee772cb6SArd Biesheuvel .set_secret = curve25519_set_secret,
70ee772cb6SArd Biesheuvel .generate_public_key = curve25519_compute_value,
71ee772cb6SArd Biesheuvel .compute_shared_secret = curve25519_compute_value,
72ee772cb6SArd Biesheuvel .max_size = curve25519_max_size,
73ee772cb6SArd Biesheuvel };
74ee772cb6SArd Biesheuvel
curve25519_init(void)75*33837be3SXiu Jianfeng static int __init curve25519_init(void)
76ee772cb6SArd Biesheuvel {
77ee772cb6SArd Biesheuvel return crypto_register_kpp(&curve25519_alg);
78ee772cb6SArd Biesheuvel }
79ee772cb6SArd Biesheuvel
curve25519_exit(void)80*33837be3SXiu Jianfeng static void __exit curve25519_exit(void)
81ee772cb6SArd Biesheuvel {
82ee772cb6SArd Biesheuvel crypto_unregister_kpp(&curve25519_alg);
83ee772cb6SArd Biesheuvel }
84ee772cb6SArd Biesheuvel
85ee772cb6SArd Biesheuvel subsys_initcall(curve25519_init);
86ee772cb6SArd Biesheuvel module_exit(curve25519_exit);
87ee772cb6SArd Biesheuvel
88ee772cb6SArd Biesheuvel MODULE_ALIAS_CRYPTO("curve25519");
89ee772cb6SArd Biesheuvel MODULE_ALIAS_CRYPTO("curve25519-generic");
90ee772cb6SArd Biesheuvel MODULE_LICENSE("GPL");
91