]> Git Repo - J-linux.git/blob - crypto/ecdsa.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / crypto / ecdsa.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2021 IBM Corporation
4  */
5
6 #include <linux/module.h>
7 #include <crypto/internal/ecc.h>
8 #include <crypto/internal/sig.h>
9 #include <crypto/ecdh.h>
10 #include <crypto/sha2.h>
11 #include <crypto/sig.h>
12
13 struct ecc_ctx {
14         unsigned int curve_id;
15         const struct ecc_curve *curve;
16
17         bool pub_key_set;
18         u64 x[ECC_MAX_DIGITS]; /* pub key x and y coordinates */
19         u64 y[ECC_MAX_DIGITS];
20         struct ecc_point pub_key;
21 };
22
23 static int _ecdsa_verify(struct ecc_ctx *ctx, const u64 *hash, const u64 *r, const u64 *s)
24 {
25         const struct ecc_curve *curve = ctx->curve;
26         unsigned int ndigits = curve->g.ndigits;
27         u64 s1[ECC_MAX_DIGITS];
28         u64 u1[ECC_MAX_DIGITS];
29         u64 u2[ECC_MAX_DIGITS];
30         u64 x1[ECC_MAX_DIGITS];
31         u64 y1[ECC_MAX_DIGITS];
32         struct ecc_point res = ECC_POINT_INIT(x1, y1, ndigits);
33
34         /* 0 < r < n  and 0 < s < n */
35         if (vli_is_zero(r, ndigits) || vli_cmp(r, curve->n, ndigits) >= 0 ||
36             vli_is_zero(s, ndigits) || vli_cmp(s, curve->n, ndigits) >= 0)
37                 return -EBADMSG;
38
39         /* hash is given */
40         pr_devel("hash : %016llx %016llx ... %016llx\n",
41                  hash[ndigits - 1], hash[ndigits - 2], hash[0]);
42
43         /* s1 = (s^-1) mod n */
44         vli_mod_inv(s1, s, curve->n, ndigits);
45         /* u1 = (hash * s1) mod n */
46         vli_mod_mult_slow(u1, hash, s1, curve->n, ndigits);
47         /* u2 = (r * s1) mod n */
48         vli_mod_mult_slow(u2, r, s1, curve->n, ndigits);
49         /* res = u1*G + u2 * pub_key */
50         ecc_point_mult_shamir(&res, u1, &curve->g, u2, &ctx->pub_key, curve);
51
52         /* res.x = res.x mod n (if res.x > order) */
53         if (unlikely(vli_cmp(res.x, curve->n, ndigits) == 1))
54                 /* faster alternative for NIST p521, p384, p256 & p192 */
55                 vli_sub(res.x, res.x, curve->n, ndigits);
56
57         if (!vli_cmp(res.x, r, ndigits))
58                 return 0;
59
60         return -EKEYREJECTED;
61 }
62
63 /*
64  * Verify an ECDSA signature.
65  */
66 static int ecdsa_verify(struct crypto_sig *tfm,
67                         const void *src, unsigned int slen,
68                         const void *digest, unsigned int dlen)
69 {
70         struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
71         size_t bufsize = ctx->curve->g.ndigits * sizeof(u64);
72         const struct ecdsa_raw_sig *sig = src;
73         u64 hash[ECC_MAX_DIGITS];
74
75         if (unlikely(!ctx->pub_key_set))
76                 return -EINVAL;
77
78         if (slen != sizeof(*sig))
79                 return -EINVAL;
80
81         if (bufsize > dlen)
82                 bufsize = dlen;
83
84         ecc_digits_from_bytes(digest, bufsize, hash, ctx->curve->g.ndigits);
85
86         return _ecdsa_verify(ctx, hash, sig->r, sig->s);
87 }
88
89 static int ecdsa_ecc_ctx_init(struct ecc_ctx *ctx, unsigned int curve_id)
90 {
91         ctx->curve_id = curve_id;
92         ctx->curve = ecc_get_curve(curve_id);
93         if (!ctx->curve)
94                 return -EINVAL;
95
96         return 0;
97 }
98
99
100 static void ecdsa_ecc_ctx_deinit(struct ecc_ctx *ctx)
101 {
102         ctx->pub_key_set = false;
103 }
104
105 static int ecdsa_ecc_ctx_reset(struct ecc_ctx *ctx)
106 {
107         unsigned int curve_id = ctx->curve_id;
108         int ret;
109
110         ecdsa_ecc_ctx_deinit(ctx);
111         ret = ecdsa_ecc_ctx_init(ctx, curve_id);
112         if (ret == 0)
113                 ctx->pub_key = ECC_POINT_INIT(ctx->x, ctx->y,
114                                               ctx->curve->g.ndigits);
115         return ret;
116 }
117
118 /*
119  * Set the public ECC key as defined by RFC5480 section 2.2 "Subject Public
120  * Key". Only the uncompressed format is supported.
121  */
122 static int ecdsa_set_pub_key(struct crypto_sig *tfm, const void *key,
123                              unsigned int keylen)
124 {
125         struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
126         unsigned int digitlen, ndigits;
127         const unsigned char *d = key;
128         int ret;
129
130         ret = ecdsa_ecc_ctx_reset(ctx);
131         if (ret < 0)
132                 return ret;
133
134         if (keylen < 1 || ((keylen - 1) & 1) != 0)
135                 return -EINVAL;
136         /* we only accept uncompressed format indicated by '4' */
137         if (d[0] != 4)
138                 return -EINVAL;
139
140         keylen--;
141         digitlen = keylen >> 1;
142
143         ndigits = DIV_ROUND_UP(digitlen, sizeof(u64));
144         if (ndigits != ctx->curve->g.ndigits)
145                 return -EINVAL;
146
147         d++;
148
149         ecc_digits_from_bytes(d, digitlen, ctx->pub_key.x, ndigits);
150         ecc_digits_from_bytes(&d[digitlen], digitlen, ctx->pub_key.y, ndigits);
151
152         ret = ecc_is_pubkey_valid_full(ctx->curve, &ctx->pub_key);
153
154         ctx->pub_key_set = ret == 0;
155
156         return ret;
157 }
158
159 static void ecdsa_exit_tfm(struct crypto_sig *tfm)
160 {
161         struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
162
163         ecdsa_ecc_ctx_deinit(ctx);
164 }
165
166 static unsigned int ecdsa_key_size(struct crypto_sig *tfm)
167 {
168         struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
169
170         return DIV_ROUND_UP(ctx->curve->nbits, 8);
171 }
172
173 static unsigned int ecdsa_digest_size(struct crypto_sig *tfm)
174 {
175         /*
176          * ECDSA key sizes are much smaller than RSA, and thus could
177          * operate on (hashed) inputs that are larger than the key size.
178          * E.g. SHA384-hashed input used with secp256r1 based keys.
179          * Return the largest supported hash size (SHA512).
180          */
181         return SHA512_DIGEST_SIZE;
182 }
183
184 static int ecdsa_nist_p521_init_tfm(struct crypto_sig *tfm)
185 {
186         struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
187
188         return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P521);
189 }
190
191 static struct sig_alg ecdsa_nist_p521 = {
192         .verify = ecdsa_verify,
193         .set_pub_key = ecdsa_set_pub_key,
194         .key_size = ecdsa_key_size,
195         .digest_size = ecdsa_digest_size,
196         .init = ecdsa_nist_p521_init_tfm,
197         .exit = ecdsa_exit_tfm,
198         .base = {
199                 .cra_name = "ecdsa-nist-p521",
200                 .cra_driver_name = "ecdsa-nist-p521-generic",
201                 .cra_priority = 100,
202                 .cra_module = THIS_MODULE,
203                 .cra_ctxsize = sizeof(struct ecc_ctx),
204         },
205 };
206
207 static int ecdsa_nist_p384_init_tfm(struct crypto_sig *tfm)
208 {
209         struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
210
211         return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P384);
212 }
213
214 static struct sig_alg ecdsa_nist_p384 = {
215         .verify = ecdsa_verify,
216         .set_pub_key = ecdsa_set_pub_key,
217         .key_size = ecdsa_key_size,
218         .digest_size = ecdsa_digest_size,
219         .init = ecdsa_nist_p384_init_tfm,
220         .exit = ecdsa_exit_tfm,
221         .base = {
222                 .cra_name = "ecdsa-nist-p384",
223                 .cra_driver_name = "ecdsa-nist-p384-generic",
224                 .cra_priority = 100,
225                 .cra_module = THIS_MODULE,
226                 .cra_ctxsize = sizeof(struct ecc_ctx),
227         },
228 };
229
230 static int ecdsa_nist_p256_init_tfm(struct crypto_sig *tfm)
231 {
232         struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
233
234         return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P256);
235 }
236
237 static struct sig_alg ecdsa_nist_p256 = {
238         .verify = ecdsa_verify,
239         .set_pub_key = ecdsa_set_pub_key,
240         .key_size = ecdsa_key_size,
241         .digest_size = ecdsa_digest_size,
242         .init = ecdsa_nist_p256_init_tfm,
243         .exit = ecdsa_exit_tfm,
244         .base = {
245                 .cra_name = "ecdsa-nist-p256",
246                 .cra_driver_name = "ecdsa-nist-p256-generic",
247                 .cra_priority = 100,
248                 .cra_module = THIS_MODULE,
249                 .cra_ctxsize = sizeof(struct ecc_ctx),
250         },
251 };
252
253 static int ecdsa_nist_p192_init_tfm(struct crypto_sig *tfm)
254 {
255         struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
256
257         return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P192);
258 }
259
260 static struct sig_alg ecdsa_nist_p192 = {
261         .verify = ecdsa_verify,
262         .set_pub_key = ecdsa_set_pub_key,
263         .key_size = ecdsa_key_size,
264         .digest_size = ecdsa_digest_size,
265         .init = ecdsa_nist_p192_init_tfm,
266         .exit = ecdsa_exit_tfm,
267         .base = {
268                 .cra_name = "ecdsa-nist-p192",
269                 .cra_driver_name = "ecdsa-nist-p192-generic",
270                 .cra_priority = 100,
271                 .cra_module = THIS_MODULE,
272                 .cra_ctxsize = sizeof(struct ecc_ctx),
273         },
274 };
275 static bool ecdsa_nist_p192_registered;
276
277 static int __init ecdsa_init(void)
278 {
279         int ret;
280
281         /* NIST p192 may not be available in FIPS mode */
282         ret = crypto_register_sig(&ecdsa_nist_p192);
283         ecdsa_nist_p192_registered = ret == 0;
284
285         ret = crypto_register_sig(&ecdsa_nist_p256);
286         if (ret)
287                 goto nist_p256_error;
288
289         ret = crypto_register_sig(&ecdsa_nist_p384);
290         if (ret)
291                 goto nist_p384_error;
292
293         ret = crypto_register_sig(&ecdsa_nist_p521);
294         if (ret)
295                 goto nist_p521_error;
296
297         ret = crypto_register_template(&ecdsa_x962_tmpl);
298         if (ret)
299                 goto x962_tmpl_error;
300
301         ret = crypto_register_template(&ecdsa_p1363_tmpl);
302         if (ret)
303                 goto p1363_tmpl_error;
304
305         return 0;
306
307 p1363_tmpl_error:
308         crypto_unregister_template(&ecdsa_x962_tmpl);
309
310 x962_tmpl_error:
311         crypto_unregister_sig(&ecdsa_nist_p521);
312
313 nist_p521_error:
314         crypto_unregister_sig(&ecdsa_nist_p384);
315
316 nist_p384_error:
317         crypto_unregister_sig(&ecdsa_nist_p256);
318
319 nist_p256_error:
320         if (ecdsa_nist_p192_registered)
321                 crypto_unregister_sig(&ecdsa_nist_p192);
322         return ret;
323 }
324
325 static void __exit ecdsa_exit(void)
326 {
327         crypto_unregister_template(&ecdsa_x962_tmpl);
328         crypto_unregister_template(&ecdsa_p1363_tmpl);
329
330         if (ecdsa_nist_p192_registered)
331                 crypto_unregister_sig(&ecdsa_nist_p192);
332         crypto_unregister_sig(&ecdsa_nist_p256);
333         crypto_unregister_sig(&ecdsa_nist_p384);
334         crypto_unregister_sig(&ecdsa_nist_p521);
335 }
336
337 subsys_initcall(ecdsa_init);
338 module_exit(ecdsa_exit);
339
340 MODULE_LICENSE("GPL");
341 MODULE_AUTHOR("Stefan Berger <[email protected]>");
342 MODULE_DESCRIPTION("ECDSA generic algorithm");
343 MODULE_ALIAS_CRYPTO("ecdsa-nist-p192");
344 MODULE_ALIAS_CRYPTO("ecdsa-nist-p256");
345 MODULE_ALIAS_CRYPTO("ecdsa-nist-p384");
346 MODULE_ALIAS_CRYPTO("ecdsa-nist-p521");
347 MODULE_ALIAS_CRYPTO("ecdsa-generic");
This page took 0.047538 seconds and 4 git commands to generate.