2d6de581ee43fdfdadbabab4c11ee442f22d1c1c
[openwrt/openwrt.git] /
1 From 54bdc995d525de6ae20f74af36d079f8b79e52fa Mon Sep 17 00:00:00 2001
2 From: Ard Biesheuvel <ardb@kernel.org>
3 Date: Fri, 8 Nov 2019 13:22:34 +0100
4 Subject: [PATCH 027/124] crypto: curve25519 - implement generic KPP driver
5
6 commit ee772cb641135739c1530647391d5a04c39db192 upstream.
7
8 Expose the generic Curve25519 library via the crypto API KPP interface.
9
10 Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
11 Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
12 Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
13 ---
14 crypto/Kconfig | 5 +++
15 crypto/Makefile | 1 +
16 crypto/curve25519-generic.c | 90 +++++++++++++++++++++++++++++++++++++
17 3 files changed, 96 insertions(+)
18 create mode 100644 crypto/curve25519-generic.c
19
20 --- a/crypto/Kconfig
21 +++ b/crypto/Kconfig
22 @@ -264,6 +264,11 @@ config CRYPTO_ECRDSA
23 standard algorithms (called GOST algorithms). Only signature verification
24 is implemented.
25
26 +config CRYPTO_CURVE25519
27 + tristate "Curve25519 algorithm"
28 + select CRYPTO_KPP
29 + select CRYPTO_LIB_CURVE25519_GENERIC
30 +
31 comment "Authenticated Encryption with Associated Data"
32
33 config CRYPTO_CCM
34 --- a/crypto/Makefile
35 +++ b/crypto/Makefile
36 @@ -167,6 +167,7 @@ obj-$(CONFIG_CRYPTO_ZSTD) += zstd.o
37 obj-$(CONFIG_CRYPTO_OFB) += ofb.o
38 obj-$(CONFIG_CRYPTO_ECC) += ecc.o
39 obj-$(CONFIG_CRYPTO_ESSIV) += essiv.o
40 +obj-$(CONFIG_CRYPTO_CURVE25519) += curve25519-generic.o
41
42 ecdh_generic-y += ecdh.o
43 ecdh_generic-y += ecdh_helper.o
44 --- /dev/null
45 +++ b/crypto/curve25519-generic.c
46 @@ -0,0 +1,90 @@
47 +// SPDX-License-Identifier: GPL-2.0-or-later
48 +
49 +#include <crypto/curve25519.h>
50 +#include <crypto/internal/kpp.h>
51 +#include <crypto/kpp.h>
52 +#include <linux/module.h>
53 +#include <linux/scatterlist.h>
54 +
55 +static int curve25519_set_secret(struct crypto_kpp *tfm, const void *buf,
56 + unsigned int len)
57 +{
58 + u8 *secret = kpp_tfm_ctx(tfm);
59 +
60 + if (!len)
61 + curve25519_generate_secret(secret);
62 + else if (len == CURVE25519_KEY_SIZE &&
63 + crypto_memneq(buf, curve25519_null_point, CURVE25519_KEY_SIZE))
64 + memcpy(secret, buf, CURVE25519_KEY_SIZE);
65 + else
66 + return -EINVAL;
67 + return 0;
68 +}
69 +
70 +static int curve25519_compute_value(struct kpp_request *req)
71 +{
72 + struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
73 + const u8 *secret = kpp_tfm_ctx(tfm);
74 + u8 public_key[CURVE25519_KEY_SIZE];
75 + u8 buf[CURVE25519_KEY_SIZE];
76 + int copied, nbytes;
77 + u8 const *bp;
78 +
79 + if (req->src) {
80 + copied = sg_copy_to_buffer(req->src,
81 + sg_nents_for_len(req->src,
82 + CURVE25519_KEY_SIZE),
83 + public_key, CURVE25519_KEY_SIZE);
84 + if (copied != CURVE25519_KEY_SIZE)
85 + return -EINVAL;
86 + bp = public_key;
87 + } else {
88 + bp = curve25519_base_point;
89 + }
90 +
91 + curve25519_generic(buf, secret, bp);
92 +
93 + /* might want less than we've got */
94 + nbytes = min_t(size_t, CURVE25519_KEY_SIZE, req->dst_len);
95 + copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst,
96 + nbytes),
97 + buf, nbytes);
98 + if (copied != nbytes)
99 + return -EINVAL;
100 + return 0;
101 +}
102 +
103 +static unsigned int curve25519_max_size(struct crypto_kpp *tfm)
104 +{
105 + return CURVE25519_KEY_SIZE;
106 +}
107 +
108 +static struct kpp_alg curve25519_alg = {
109 + .base.cra_name = "curve25519",
110 + .base.cra_driver_name = "curve25519-generic",
111 + .base.cra_priority = 100,
112 + .base.cra_module = THIS_MODULE,
113 + .base.cra_ctxsize = CURVE25519_KEY_SIZE,
114 +
115 + .set_secret = curve25519_set_secret,
116 + .generate_public_key = curve25519_compute_value,
117 + .compute_shared_secret = curve25519_compute_value,
118 + .max_size = curve25519_max_size,
119 +};
120 +
121 +static int curve25519_init(void)
122 +{
123 + return crypto_register_kpp(&curve25519_alg);
124 +}
125 +
126 +static void curve25519_exit(void)
127 +{
128 + crypto_unregister_kpp(&curve25519_alg);
129 +}
130 +
131 +subsys_initcall(curve25519_init);
132 +module_exit(curve25519_exit);
133 +
134 +MODULE_ALIAS_CRYPTO("curve25519");
135 +MODULE_ALIAS_CRYPTO("curve25519-generic");
136 +MODULE_LICENSE("GPL");