1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2021 IBM Corporation
6 #include <linux/module.h>
7 #include <crypto/internal/akcipher.h>
8 #include <crypto/internal/ecc.h>
9 #include <crypto/akcipher.h>
10 #include <crypto/ecdh.h>
11 #include <linux/asn1_decoder.h>
12 #include <linux/scatterlist.h>
14 #include "ecdsasignature.asn1.h"
17 unsigned int curve_id
;
18 const struct ecc_curve
*curve
;
21 u64 x
[ECC_MAX_DIGITS
]; /* pub key x and y coordinates */
22 u64 y
[ECC_MAX_DIGITS
];
23 struct ecc_point pub_key
;
26 struct ecdsa_signature_ctx
{
27 const struct ecc_curve
*curve
;
28 u64 r
[ECC_MAX_DIGITS
];
29 u64 s
[ECC_MAX_DIGITS
];
33 * Get the r and s components of a signature from the X509 certificate.
35 static int ecdsa_get_signature_rs(u64
*dest
, size_t hdrlen
, unsigned char tag
,
36 const void *value
, size_t vlen
, unsigned int ndigits
)
38 size_t bufsize
= ndigits
* sizeof(u64
);
39 ssize_t diff
= vlen
- bufsize
;
40 const char *d
= value
;
45 /* diff = 0: 'value' has exacly the right size
46 * diff > 0: 'value' has too many bytes; one leading zero is allowed that
47 * makes the value a positive integer; error on more
48 * diff < 0: 'value' is missing leading zeros
51 /* skip over leading zeros that make 'value' a positive int */
63 ecc_digits_from_bytes(d
, vlen
, dest
, ndigits
);
68 int ecdsa_get_signature_r(void *context
, size_t hdrlen
, unsigned char tag
,
69 const void *value
, size_t vlen
)
71 struct ecdsa_signature_ctx
*sig
= context
;
73 return ecdsa_get_signature_rs(sig
->r
, hdrlen
, tag
, value
, vlen
,
74 sig
->curve
->g
.ndigits
);
77 int ecdsa_get_signature_s(void *context
, size_t hdrlen
, unsigned char tag
,
78 const void *value
, size_t vlen
)
80 struct ecdsa_signature_ctx
*sig
= context
;
82 return ecdsa_get_signature_rs(sig
->s
, hdrlen
, tag
, value
, vlen
,
83 sig
->curve
->g
.ndigits
);
86 static int _ecdsa_verify(struct ecc_ctx
*ctx
, const u64
*hash
, const u64
*r
, const u64
*s
)
88 const struct ecc_curve
*curve
= ctx
->curve
;
89 unsigned int ndigits
= curve
->g
.ndigits
;
90 u64 s1
[ECC_MAX_DIGITS
];
91 u64 u1
[ECC_MAX_DIGITS
];
92 u64 u2
[ECC_MAX_DIGITS
];
93 u64 x1
[ECC_MAX_DIGITS
];
94 u64 y1
[ECC_MAX_DIGITS
];
95 struct ecc_point res
= ECC_POINT_INIT(x1
, y1
, ndigits
);
97 /* 0 < r < n and 0 < s < n */
98 if (vli_is_zero(r
, ndigits
) || vli_cmp(r
, curve
->n
, ndigits
) >= 0 ||
99 vli_is_zero(s
, ndigits
) || vli_cmp(s
, curve
->n
, ndigits
) >= 0)
103 pr_devel("hash : %016llx %016llx ... %016llx\n",
104 hash
[ndigits
- 1], hash
[ndigits
- 2], hash
[0]);
106 /* s1 = (s^-1) mod n */
107 vli_mod_inv(s1
, s
, curve
->n
, ndigits
);
108 /* u1 = (hash * s1) mod n */
109 vli_mod_mult_slow(u1
, hash
, s1
, curve
->n
, ndigits
);
110 /* u2 = (r * s1) mod n */
111 vli_mod_mult_slow(u2
, r
, s1
, curve
->n
, ndigits
);
112 /* res = u1*G + u2 * pub_key */
113 ecc_point_mult_shamir(&res
, u1
, &curve
->g
, u2
, &ctx
->pub_key
, curve
);
115 /* res.x = res.x mod n (if res.x > order) */
116 if (unlikely(vli_cmp(res
.x
, curve
->n
, ndigits
) == 1))
117 /* faster alternative for NIST p521, p384, p256 & p192 */
118 vli_sub(res
.x
, res
.x
, curve
->n
, ndigits
);
120 if (!vli_cmp(res
.x
, r
, ndigits
))
123 return -EKEYREJECTED
;
127 * Verify an ECDSA signature.
129 static int ecdsa_verify(struct akcipher_request
*req
)
131 struct crypto_akcipher
*tfm
= crypto_akcipher_reqtfm(req
);
132 struct ecc_ctx
*ctx
= akcipher_tfm_ctx(tfm
);
133 size_t bufsize
= ctx
->curve
->g
.ndigits
* sizeof(u64
);
134 struct ecdsa_signature_ctx sig_ctx
= {
137 u64 hash
[ECC_MAX_DIGITS
];
138 unsigned char *buffer
;
141 if (unlikely(!ctx
->pub_key_set
))
144 buffer
= kmalloc(req
->src_len
+ req
->dst_len
, GFP_KERNEL
);
148 sg_pcopy_to_buffer(req
->src
,
149 sg_nents_for_len(req
->src
, req
->src_len
+ req
->dst_len
),
150 buffer
, req
->src_len
+ req
->dst_len
, 0);
152 ret
= asn1_ber_decoder(&ecdsasignature_decoder
, &sig_ctx
,
153 buffer
, req
->src_len
);
157 if (bufsize
> req
->dst_len
)
158 bufsize
= req
->dst_len
;
160 ecc_digits_from_bytes(buffer
+ req
->src_len
, bufsize
,
161 hash
, ctx
->curve
->g
.ndigits
);
163 ret
= _ecdsa_verify(ctx
, hash
, sig_ctx
.r
, sig_ctx
.s
);
171 static int ecdsa_ecc_ctx_init(struct ecc_ctx
*ctx
, unsigned int curve_id
)
173 ctx
->curve_id
= curve_id
;
174 ctx
->curve
= ecc_get_curve(curve_id
);
182 static void ecdsa_ecc_ctx_deinit(struct ecc_ctx
*ctx
)
184 ctx
->pub_key_set
= false;
187 static int ecdsa_ecc_ctx_reset(struct ecc_ctx
*ctx
)
189 unsigned int curve_id
= ctx
->curve_id
;
192 ecdsa_ecc_ctx_deinit(ctx
);
193 ret
= ecdsa_ecc_ctx_init(ctx
, curve_id
);
195 ctx
->pub_key
= ECC_POINT_INIT(ctx
->x
, ctx
->y
,
196 ctx
->curve
->g
.ndigits
);
201 * Set the public ECC key as defined by RFC5480 section 2.2 "Subject Public
202 * Key". Only the uncompressed format is supported.
204 static int ecdsa_set_pub_key(struct crypto_akcipher
*tfm
, const void *key
, unsigned int keylen
)
206 struct ecc_ctx
*ctx
= akcipher_tfm_ctx(tfm
);
207 unsigned int digitlen
, ndigits
;
208 const unsigned char *d
= key
;
211 ret
= ecdsa_ecc_ctx_reset(ctx
);
215 if (keylen
< 1 || ((keylen
- 1) & 1) != 0)
217 /* we only accept uncompressed format indicated by '4' */
222 digitlen
= keylen
>> 1;
224 ndigits
= DIV_ROUND_UP(digitlen
, sizeof(u64
));
225 if (ndigits
!= ctx
->curve
->g
.ndigits
)
230 ecc_digits_from_bytes(d
, digitlen
, ctx
->pub_key
.x
, ndigits
);
231 ecc_digits_from_bytes(&d
[digitlen
], digitlen
, ctx
->pub_key
.y
, ndigits
);
233 ret
= ecc_is_pubkey_valid_full(ctx
->curve
, &ctx
->pub_key
);
235 ctx
->pub_key_set
= ret
== 0;
240 static void ecdsa_exit_tfm(struct crypto_akcipher
*tfm
)
242 struct ecc_ctx
*ctx
= akcipher_tfm_ctx(tfm
);
244 ecdsa_ecc_ctx_deinit(ctx
);
247 static unsigned int ecdsa_max_size(struct crypto_akcipher
*tfm
)
249 struct ecc_ctx
*ctx
= akcipher_tfm_ctx(tfm
);
251 return DIV_ROUND_UP(ctx
->curve
->nbits
, 8);
254 static int ecdsa_nist_p521_init_tfm(struct crypto_akcipher
*tfm
)
256 struct ecc_ctx
*ctx
= akcipher_tfm_ctx(tfm
);
258 return ecdsa_ecc_ctx_init(ctx
, ECC_CURVE_NIST_P521
);
261 static struct akcipher_alg ecdsa_nist_p521
= {
262 .verify
= ecdsa_verify
,
263 .set_pub_key
= ecdsa_set_pub_key
,
264 .max_size
= ecdsa_max_size
,
265 .init
= ecdsa_nist_p521_init_tfm
,
266 .exit
= ecdsa_exit_tfm
,
268 .cra_name
= "ecdsa-nist-p521",
269 .cra_driver_name
= "ecdsa-nist-p521-generic",
271 .cra_module
= THIS_MODULE
,
272 .cra_ctxsize
= sizeof(struct ecc_ctx
),
276 static int ecdsa_nist_p384_init_tfm(struct crypto_akcipher
*tfm
)
278 struct ecc_ctx
*ctx
= akcipher_tfm_ctx(tfm
);
280 return ecdsa_ecc_ctx_init(ctx
, ECC_CURVE_NIST_P384
);
283 static struct akcipher_alg ecdsa_nist_p384
= {
284 .verify
= ecdsa_verify
,
285 .set_pub_key
= ecdsa_set_pub_key
,
286 .max_size
= ecdsa_max_size
,
287 .init
= ecdsa_nist_p384_init_tfm
,
288 .exit
= ecdsa_exit_tfm
,
290 .cra_name
= "ecdsa-nist-p384",
291 .cra_driver_name
= "ecdsa-nist-p384-generic",
293 .cra_module
= THIS_MODULE
,
294 .cra_ctxsize
= sizeof(struct ecc_ctx
),
298 static int ecdsa_nist_p256_init_tfm(struct crypto_akcipher
*tfm
)
300 struct ecc_ctx
*ctx
= akcipher_tfm_ctx(tfm
);
302 return ecdsa_ecc_ctx_init(ctx
, ECC_CURVE_NIST_P256
);
305 static struct akcipher_alg ecdsa_nist_p256
= {
306 .verify
= ecdsa_verify
,
307 .set_pub_key
= ecdsa_set_pub_key
,
308 .max_size
= ecdsa_max_size
,
309 .init
= ecdsa_nist_p256_init_tfm
,
310 .exit
= ecdsa_exit_tfm
,
312 .cra_name
= "ecdsa-nist-p256",
313 .cra_driver_name
= "ecdsa-nist-p256-generic",
315 .cra_module
= THIS_MODULE
,
316 .cra_ctxsize
= sizeof(struct ecc_ctx
),
320 static int ecdsa_nist_p192_init_tfm(struct crypto_akcipher
*tfm
)
322 struct ecc_ctx
*ctx
= akcipher_tfm_ctx(tfm
);
324 return ecdsa_ecc_ctx_init(ctx
, ECC_CURVE_NIST_P192
);
327 static struct akcipher_alg ecdsa_nist_p192
= {
328 .verify
= ecdsa_verify
,
329 .set_pub_key
= ecdsa_set_pub_key
,
330 .max_size
= ecdsa_max_size
,
331 .init
= ecdsa_nist_p192_init_tfm
,
332 .exit
= ecdsa_exit_tfm
,
334 .cra_name
= "ecdsa-nist-p192",
335 .cra_driver_name
= "ecdsa-nist-p192-generic",
337 .cra_module
= THIS_MODULE
,
338 .cra_ctxsize
= sizeof(struct ecc_ctx
),
341 static bool ecdsa_nist_p192_registered
;
343 static int __init
ecdsa_init(void)
347 /* NIST p192 may not be available in FIPS mode */
348 ret
= crypto_register_akcipher(&ecdsa_nist_p192
);
349 ecdsa_nist_p192_registered
= ret
== 0;
351 ret
= crypto_register_akcipher(&ecdsa_nist_p256
);
353 goto nist_p256_error
;
355 ret
= crypto_register_akcipher(&ecdsa_nist_p384
);
357 goto nist_p384_error
;
359 ret
= crypto_register_akcipher(&ecdsa_nist_p521
);
361 goto nist_p521_error
;
366 crypto_unregister_akcipher(&ecdsa_nist_p384
);
369 crypto_unregister_akcipher(&ecdsa_nist_p256
);
372 if (ecdsa_nist_p192_registered
)
373 crypto_unregister_akcipher(&ecdsa_nist_p192
);
377 static void __exit
ecdsa_exit(void)
379 if (ecdsa_nist_p192_registered
)
380 crypto_unregister_akcipher(&ecdsa_nist_p192
);
381 crypto_unregister_akcipher(&ecdsa_nist_p256
);
382 crypto_unregister_akcipher(&ecdsa_nist_p384
);
383 crypto_unregister_akcipher(&ecdsa_nist_p521
);
386 subsys_initcall(ecdsa_init
);
387 module_exit(ecdsa_exit
);
389 MODULE_LICENSE("GPL");
390 MODULE_AUTHOR("Stefan Berger <stefanb@linux.ibm.com>");
391 MODULE_DESCRIPTION("ECDSA generic algorithm");
392 MODULE_ALIAS_CRYPTO("ecdsa-nist-p192");
393 MODULE_ALIAS_CRYPTO("ecdsa-nist-p256");
394 MODULE_ALIAS_CRYPTO("ecdsa-nist-p384");
395 MODULE_ALIAS_CRYPTO("ecdsa-nist-p521");
396 MODULE_ALIAS_CRYPTO("ecdsa-generic");