xref: /openbmc/linux/crypto/curve25519-generic.c (revision 33837be3)
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