654cbe77586edd7e74d2bab0a5907f84865b4c8e
[platform/kernel/linux-starfive.git] / dh.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*  Diffie-Hellman Key Agreement Method [RFC2631]
3  *
4  * Copyright (c) 2016, Intel Corporation
5  * Authors: Salvatore Benedetto <salvatore.benedetto@intel.com>
6  */
7
8 #include <linux/module.h>
9 #include <crypto/internal/kpp.h>
10 #include <crypto/kpp.h>
11 #include <crypto/dh.h>
12 #include <linux/fips.h>
13 #include <linux/mpi.h>
14
15 struct dh_ctx {
16         MPI p;  /* Value is guaranteed to be set. */
17         MPI q;  /* Value is optional. */
18         MPI g;  /* Value is guaranteed to be set. */
19         MPI xa; /* Value is guaranteed to be set. */
20 };
21
22 static inline void dh_clear_params(struct dh_ctx *ctx)
23 {
24         mpi_free(ctx->p);
25         mpi_free(ctx->q);
26         mpi_free(ctx->g);
27 }
28
29 static inline void dh_clear_key(struct dh_ctx *ctx)
30 {
31         mpi_free(ctx->xa);
32         memset(ctx, 0, sizeof(*ctx));
33 }
34
35 static void dh_clear_ctx(struct dh_ctx *ctx)
36 {
37         dh_clear_params(ctx);
38         dh_clear_key(ctx);
39 }
40
41 /*
42  * If base is g we compute the public key
43  *      ya = g^xa mod p; [RFC2631 sec 2.1.1]
44  * else if base if the counterpart public key we compute the shared secret
45  *      ZZ = yb^xa mod p; [RFC2631 sec 2.1.1]
46  */
47 static int _compute_val(const struct dh_ctx *ctx, MPI base, MPI val)
48 {
49         /* val = base^xa mod p */
50         return mpi_powm(val, base, ctx->xa, ctx->p);
51 }
52
53 static inline struct dh_ctx *dh_get_ctx(struct crypto_kpp *tfm)
54 {
55         return kpp_tfm_ctx(tfm);
56 }
57
58 static int dh_check_params_length(unsigned int p_len)
59 {
60         return (p_len < 1536) ? -EINVAL : 0;
61 }
62
63 static int dh_set_params(struct dh_ctx *ctx, struct dh *params)
64 {
65         /* If DH parameters are not given, do not check them. */
66         if (!params->p_size && !params->g_size)
67                 return 0;
68
69         if (dh_check_params_length(params->p_size << 3))
70                 return -EINVAL;
71
72         ctx->p = mpi_read_raw_data(params->p, params->p_size);
73         if (!ctx->p)
74                 return -EINVAL;
75
76         if (params->q && params->q_size) {
77                 ctx->q = mpi_read_raw_data(params->q, params->q_size);
78                 if (!ctx->q)
79                         return -EINVAL;
80         }
81
82         ctx->g = mpi_read_raw_data(params->g, params->g_size);
83         if (!ctx->g)
84                 return -EINVAL;
85
86         return 0;
87 }
88
89 static int dh_set_params_pkcs3(struct crypto_kpp *tfm, const void *param,
90                                unsigned int param_len)
91 {
92         struct dh_ctx *ctx = dh_get_ctx(tfm);
93         struct dh parsed_params;
94         int ret;
95
96         /* Free the old parameter if any */
97         dh_clear_params(ctx);
98
99         ret = dh_parse_params_pkcs3(&parsed_params, param, param_len);
100         if (ret)
101                 return ret;
102
103         return dh_set_params(ctx, &parsed_params);
104 }
105
106 static int dh_set_secret(struct crypto_kpp *tfm, const void *buf,
107                          unsigned int len)
108 {
109         struct dh_ctx *ctx = dh_get_ctx(tfm);
110         struct dh params;
111
112         /* Free the old MPI key if any */
113         dh_clear_key(ctx);
114
115         if (crypto_dh_decode_key(buf, len, &params) < 0)
116                 goto err_clear_ctx;
117
118         if (dh_set_params(ctx, &params) < 0)
119                 goto err_clear_ctx;
120
121         ctx->xa = mpi_read_raw_data(params.key, params.key_size);
122         if (!ctx->xa)
123                 goto err_clear_ctx;
124
125         return 0;
126
127 err_clear_ctx:
128         dh_clear_ctx(ctx);
129         return -EINVAL;
130 }
131
132 /*
133  * SP800-56A public key verification:
134  *
135  * * If Q is provided as part of the domain paramenters, a full validation
136  *   according to SP800-56A section 5.6.2.3.1 is performed.
137  *
138  * * If Q is not provided, a partial validation according to SP800-56A section
139  *   5.6.2.3.2 is performed.
140  */
141 static int dh_is_pubkey_valid(struct dh_ctx *ctx, MPI y)
142 {
143         if (unlikely(!ctx->p))
144                 return -EINVAL;
145
146         /*
147          * Step 1: Verify that 2 <= y <= p - 2.
148          *
149          * The upper limit check is actually y < p instead of y < p - 1
150          * as the mpi_sub_ui function is yet missing.
151          */
152         if (mpi_cmp_ui(y, 1) < 1 || mpi_cmp(y, ctx->p) >= 0)
153                 return -EINVAL;
154
155         /* Step 2: Verify that 1 = y^q mod p */
156         if (ctx->q) {
157                 MPI val = mpi_alloc(0);
158                 int ret;
159
160                 if (!val)
161                         return -ENOMEM;
162
163                 ret = mpi_powm(val, y, ctx->q, ctx->p);
164
165                 if (ret) {
166                         mpi_free(val);
167                         return ret;
168                 }
169
170                 ret = mpi_cmp_ui(val, 1);
171
172                 mpi_free(val);
173
174                 if (ret != 0)
175                         return -EINVAL;
176         }
177
178         return 0;
179 }
180
181 static int dh_compute_value(struct kpp_request *req)
182 {
183         struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
184         struct dh_ctx *ctx = dh_get_ctx(tfm);
185         MPI base, val = mpi_alloc(0);
186         int ret = 0;
187         int sign;
188
189         if (!val)
190                 return -ENOMEM;
191
192         if (unlikely(!ctx->xa || !ctx->p || !ctx->g)) {
193                 ret = -EINVAL;
194                 goto err_free_val;
195         }
196
197         if (req->src) {
198                 base = mpi_read_raw_from_sgl(req->src, req->src_len);
199                 if (!base) {
200                         ret = -EINVAL;
201                         goto err_free_val;
202                 }
203                 ret = dh_is_pubkey_valid(ctx, base);
204                 if (ret)
205                         goto err_free_base;
206         } else {
207                 base = ctx->g;
208         }
209
210         ret = _compute_val(ctx, base, val);
211         if (ret)
212                 goto err_free_base;
213
214         if (fips_enabled) {
215                 /* SP800-56A rev3 5.7.1.1 check: Validation of shared secret */
216                 if (req->src) {
217                         MPI pone;
218
219                         /* z <= 1 */
220                         if (mpi_cmp_ui(val, 1) < 1) {
221                                 ret = -EBADMSG;
222                                 goto err_free_base;
223                         }
224
225                         /* z == p - 1 */
226                         pone = mpi_alloc(0);
227
228                         if (!pone) {
229                                 ret = -ENOMEM;
230                                 goto err_free_base;
231                         }
232
233                         ret = mpi_sub_ui(pone, ctx->p, 1);
234                         if (!ret && !mpi_cmp(pone, val))
235                                 ret = -EBADMSG;
236
237                         mpi_free(pone);
238
239                         if (ret)
240                                 goto err_free_base;
241
242                 /* SP800-56A rev 3 5.6.2.1.3 key check */
243                 } else {
244                         if (dh_is_pubkey_valid(ctx, val)) {
245                                 ret = -EAGAIN;
246                                 goto err_free_val;
247                         }
248                 }
249         }
250
251         ret = mpi_write_to_sgl(val, req->dst, req->dst_len, &sign);
252         if (ret)
253                 goto err_free_base;
254
255         if (sign < 0)
256                 ret = -EBADMSG;
257 err_free_base:
258         if (req->src)
259                 mpi_free(base);
260 err_free_val:
261         mpi_free(val);
262         return ret;
263 }
264
265 static unsigned int dh_max_size(struct crypto_kpp *tfm)
266 {
267         struct dh_ctx *ctx = dh_get_ctx(tfm);
268
269         return mpi_get_size(ctx->p);
270 }
271
272 static void dh_exit_tfm(struct crypto_kpp *tfm)
273 {
274         struct dh_ctx *ctx = dh_get_ctx(tfm);
275
276         dh_clear_ctx(ctx);
277 }
278
279 static struct kpp_alg dh = {
280         .set_params = dh_set_params_pkcs3,
281         .set_secret = dh_set_secret,
282         .generate_public_key = dh_compute_value,
283         .compute_shared_secret = dh_compute_value,
284         .max_size = dh_max_size,
285         .exit = dh_exit_tfm,
286         .base = {
287                 .cra_name = "dh",
288                 .cra_driver_name = "dh-generic",
289                 .cra_priority = 100,
290                 .cra_module = THIS_MODULE,
291                 .cra_ctxsize = sizeof(struct dh_ctx),
292         },
293 };
294
295 static int dh_init(void)
296 {
297         return crypto_register_kpp(&dh);
298 }
299
300 static void dh_exit(void)
301 {
302         crypto_unregister_kpp(&dh);
303 }
304
305 subsys_initcall(dh_init);
306 module_exit(dh_exit);
307 MODULE_ALIAS_CRYPTO("dh");
308 MODULE_LICENSE("GPL");
309 MODULE_DESCRIPTION("DH generic algorithm");