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