summaryrefslogtreecommitdiffstats
path: root/crypto/ecc.c
diff options
context:
space:
mode:
authorVitaly Chikunov <vt@altlinux.org>2019-04-11 11:51:20 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2019-04-18 10:15:02 -0400
commit0d7a78643f6972214e99205b364e508f8ea9598e (patch)
tree52c767540817a76e45a0dedd785ee97f7beda100 /crypto/ecc.c
parent4a2289dae0cdecd70d93dda610d059bec67551d3 (diff)
crypto: ecrdsa - add EC-RDSA (GOST 34.10) algorithm
Add Elliptic Curve Russian Digital Signature Algorithm (GOST R 34.10-2012, RFC 7091, ISO/IEC 14888-3) is one of the Russian (and since 2018 the CIS countries) cryptographic standard algorithms (called GOST algorithms). Only signature verification is supported, with intent to be used in the IMA. Summary of the changes: * crypto/Kconfig: - EC-RDSA is added into Public-key cryptography section. * crypto/Makefile: - ecrdsa objects are added. * crypto/asymmetric_keys/x509_cert_parser.c: - Recognize EC-RDSA and Streebog OIDs. * include/linux/oid_registry.h: - EC-RDSA OIDs are added to the enum. Also, a two currently not implemented curve OIDs are added for possible extension later (to not change numbering and grouping). * crypto/ecc.c: - Kenneth MacKay copyright date is updated to 2014, because vli_mmod_slow, ecc_point_add, ecc_point_mult_shamir are based on his code from micro-ecc. - Functions needed for ecrdsa are EXPORT_SYMBOL'ed. - New functions: vli_is_negative - helper to determine sign of vli; vli_from_be64 - unpack big-endian array into vli (used for a signature); vli_from_le64 - unpack little-endian array into vli (used for a public key); vli_uadd, vli_usub - add/sub u64 value to/from vli (used for increment/decrement); mul_64_64 - optimized to use __int128 where appropriate, this speeds up point multiplication (and as a consequence signature verification) by the factor of 1.5-2; vli_umult - multiply vli by a small value (speeds up point multiplication by another factor of 1.5-2, depending on vli sizes); vli_mmod_special - module reduction for some form of Pseudo-Mersenne primes (used for the curves A); vli_mmod_special2 - module reduction for another form of Pseudo-Mersenne primes (used for the curves B); vli_mmod_barrett - module reduction using pre-computed value (used for the curve C); vli_mmod_slow - more general module reduction which is much slower (used when the modulus is subgroup order); vli_mod_mult_slow - modular multiplication; ecc_point_add - add two points; ecc_point_mult_shamir - add two points multiplied by scalars in one combined multiplication (this gives speed up by another factor 2 in compare to two separate multiplications). ecc_is_pubkey_valid_partial - additional samity check is added. - Updated vli_mmod_fast with non-strict heuristic to call optimal module reduction function depending on the prime value; - All computations for the previously defined (two NIST) curves should not unaffected. * crypto/ecc.h: - Newly exported functions are documented. * crypto/ecrdsa_defs.h - Five curves are defined. * crypto/ecrdsa.c: - Signature verification is implemented. * crypto/ecrdsa_params.asn1, crypto/ecrdsa_pub_key.asn1: - Templates for BER decoder for EC-RDSA parameters and public key. Cc: linux-integrity@vger.kernel.org Signed-off-by: Vitaly Chikunov <vt@altlinux.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/ecc.c')
-rw-r--r--crypto/ecc.c392
1 files changed, 384 insertions, 8 deletions
diff --git a/crypto/ecc.c b/crypto/ecc.c
index 5f36792d143d..dfe114bc0c4a 100644
--- a/crypto/ecc.c
+++ b/crypto/ecc.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (c) 2013, Kenneth MacKay 2 * Copyright (c) 2013, 2014 Kenneth MacKay. All rights reserved.
3 * All rights reserved. 3 * Copyright (c) 2019 Vitaly Chikunov <vt@altlinux.org>
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
@@ -31,6 +31,8 @@
31#include <linux/fips.h> 31#include <linux/fips.h>
32#include <crypto/ecdh.h> 32#include <crypto/ecdh.h>
33#include <crypto/rng.h> 33#include <crypto/rng.h>
34#include <asm/unaligned.h>
35#include <linux/ratelimit.h>
34 36
35#include "ecc.h" 37#include "ecc.h"
36#include "ecc_curve_defs.h" 38#include "ecc_curve_defs.h"
@@ -132,6 +134,11 @@ static u64 vli_test_bit(const u64 *vli, unsigned int bit)
132 return (vli[bit / 64] & ((u64)1 << (bit % 64))); 134 return (vli[bit / 64] & ((u64)1 << (bit % 64)));
133} 135}
134 136
137static bool vli_is_negative(const u64 *vli, unsigned int ndigits)
138{
139 return vli_test_bit(vli, ndigits * 64 - 1);
140}
141
135/* Counts the number of 64-bit "digits" in vli. */ 142/* Counts the number of 64-bit "digits" in vli. */
136static unsigned int vli_num_digits(const u64 *vli, unsigned int ndigits) 143static unsigned int vli_num_digits(const u64 *vli, unsigned int ndigits)
137{ 144{
@@ -163,6 +170,27 @@ static unsigned int vli_num_bits(const u64 *vli, unsigned int ndigits)
163 return ((num_digits - 1) * 64 + i); 170 return ((num_digits - 1) * 64 + i);
164} 171}
165 172
173/* Set dest from unaligned bit string src. */
174void vli_from_be64(u64 *dest, const void *src, unsigned int ndigits)
175{
176 int i;
177 const u64 *from = src;
178
179 for (i = 0; i < ndigits; i++)
180 dest[i] = get_unaligned_be64(&from[ndigits - 1 - i]);
181}
182EXPORT_SYMBOL(vli_from_be64);
183
184void vli_from_le64(u64 *dest, const void *src, unsigned int ndigits)
185{
186 int i;
187 const u64 *from = src;
188
189 for (i = 0; i < ndigits; i++)
190 dest[i] = get_unaligned_le64(&from[i]);
191}
192EXPORT_SYMBOL(vli_from_le64);
193
166/* Sets dest = src. */ 194/* Sets dest = src. */
167static void vli_set(u64 *dest, const u64 *src, unsigned int ndigits) 195static void vli_set(u64 *dest, const u64 *src, unsigned int ndigits)
168{ 196{
@@ -242,6 +270,28 @@ static u64 vli_add(u64 *result, const u64 *left, const u64 *right,
242 return carry; 270 return carry;
243} 271}
244 272
273/* Computes result = left + right, returning carry. Can modify in place. */
274static u64 vli_uadd(u64 *result, const u64 *left, u64 right,
275 unsigned int ndigits)
276{
277 u64 carry = right;
278 int i;
279
280 for (i = 0; i < ndigits; i++) {
281 u64 sum;
282
283 sum = left[i] + carry;
284 if (sum != left[i])
285 carry = (sum < left[i]);
286 else
287 carry = !!carry;
288
289 result[i] = sum;
290 }
291
292 return carry;
293}
294
245/* Computes result = left - right, returning borrow. Can modify in place. */ 295/* Computes result = left - right, returning borrow. Can modify in place. */
246u64 vli_sub(u64 *result, const u64 *left, const u64 *right, 296u64 vli_sub(u64 *result, const u64 *left, const u64 *right,
247 unsigned int ndigits) 297 unsigned int ndigits)
@@ -263,8 +313,35 @@ u64 vli_sub(u64 *result, const u64 *left, const u64 *right,
263} 313}
264EXPORT_SYMBOL(vli_sub); 314EXPORT_SYMBOL(vli_sub);
265 315
316/* Computes result = left - right, returning borrow. Can modify in place. */
317static u64 vli_usub(u64 *result, const u64 *left, u64 right,
318 unsigned int ndigits)
319{
320 u64 borrow = right;
321 int i;
322
323 for (i = 0; i < ndigits; i++) {
324 u64 diff;
325
326 diff = left[i] - borrow;
327 if (diff != left[i])
328 borrow = (diff > left[i]);
329
330 result[i] = diff;
331 }
332
333 return borrow;
334}
335
266static uint128_t mul_64_64(u64 left, u64 right) 336static uint128_t mul_64_64(u64 left, u64 right)
267{ 337{
338 uint128_t result;
339#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
340 unsigned __int128 m = (unsigned __int128)left * right;
341
342 result.m_low = m;
343 result.m_high = m >> 64;
344#else
268 u64 a0 = left & 0xffffffffull; 345 u64 a0 = left & 0xffffffffull;
269 u64 a1 = left >> 32; 346 u64 a1 = left >> 32;
270 u64 b0 = right & 0xffffffffull; 347 u64 b0 = right & 0xffffffffull;
@@ -273,7 +350,6 @@ static uint128_t mul_64_64(u64 left, u64 right)
273 u64 m1 = a0 * b1; 350 u64 m1 = a0 * b1;
274 u64 m2 = a1 * b0; 351 u64 m2 = a1 * b0;
275 u64 m3 = a1 * b1; 352 u64 m3 = a1 * b1;
276 uint128_t result;
277 353
278 m2 += (m0 >> 32); 354 m2 += (m0 >> 32);
279 m2 += m1; 355 m2 += m1;
@@ -284,7 +360,7 @@ static uint128_t mul_64_64(u64 left, u64 right)
284 360
285 result.m_low = (m0 & 0xffffffffull) | (m2 << 32); 361 result.m_low = (m0 & 0xffffffffull) | (m2 << 32);
286 result.m_high = m3 + (m2 >> 32); 362 result.m_high = m3 + (m2 >> 32);
287 363#endif
288 return result; 364 return result;
289} 365}
290 366
@@ -334,6 +410,28 @@ static void vli_mult(u64 *result, const u64 *left, const u64 *right,
334 result[ndigits * 2 - 1] = r01.m_low; 410 result[ndigits * 2 - 1] = r01.m_low;
335} 411}
336 412
413/* Compute product = left * right, for a small right value. */
414static void vli_umult(u64 *result, const u64 *left, u32 right,
415 unsigned int ndigits)
416{
417 uint128_t r01 = { 0 };
418 unsigned int k;
419
420 for (k = 0; k < ndigits; k++) {
421 uint128_t product;
422
423 product = mul_64_64(left[k], right);
424 r01 = add_128_128(r01, product);
425 /* no carry */
426 result[k] = r01.m_low;
427 r01.m_low = r01.m_high;
428 r01.m_high = 0;
429 }
430 result[k] = r01.m_low;
431 for (++k; k < ndigits * 2; k++)
432 result[k] = 0;
433}
434
337static void vli_square(u64 *result, const u64 *left, unsigned int ndigits) 435static void vli_square(u64 *result, const u64 *left, unsigned int ndigits)
338{ 436{
339 uint128_t r01 = { 0, 0 }; 437 uint128_t r01 = { 0, 0 };
@@ -406,6 +504,170 @@ static void vli_mod_sub(u64 *result, const u64 *left, const u64 *right,
406 vli_add(result, result, mod, ndigits); 504 vli_add(result, result, mod, ndigits);
407} 505}
408 506
507/*
508 * Computes result = product % mod
509 * for special form moduli: p = 2^k-c, for small c (note the minus sign)
510 *
511 * References:
512 * R. Crandall, C. Pomerance. Prime Numbers: A Computational Perspective.
513 * 9 Fast Algorithms for Large-Integer Arithmetic. 9.2.3 Moduli of special form
514 * Algorithm 9.2.13 (Fast mod operation for special-form moduli).
515 */
516static void vli_mmod_special(u64 *result, const u64 *product,
517 const u64 *mod, unsigned int ndigits)
518{
519 u64 c = -mod[0];
520 u64 t[ECC_MAX_DIGITS * 2];
521 u64 r[ECC_MAX_DIGITS * 2];
522
523 vli_set(r, product, ndigits * 2);
524 while (!vli_is_zero(r + ndigits, ndigits)) {
525 vli_umult(t, r + ndigits, c, ndigits);
526 vli_clear(r + ndigits, ndigits);
527 vli_add(r, r, t, ndigits * 2);
528 }
529 vli_set(t, mod, ndigits);
530 vli_clear(t + ndigits, ndigits);
531 while (vli_cmp(r, t, ndigits * 2) >= 0)
532 vli_sub(r, r, t, ndigits * 2);
533 vli_set(result, r, ndigits);
534}
535
536/*
537 * Computes result = product % mod
538 * for special form moduli: p = 2^{k-1}+c, for small c (note the plus sign)
539 * where k-1 does not fit into qword boundary by -1 bit (such as 255).
540
541 * References (loosely based on):
542 * A. Menezes, P. van Oorschot, S. Vanstone. Handbook of Applied Cryptography.
543 * 14.3.4 Reduction methods for moduli of special form. Algorithm 14.47.
544 * URL: http://cacr.uwaterloo.ca/hac/about/chap14.pdf
545 *
546 * H. Cohen, G. Frey, R. Avanzi, C. Doche, T. Lange, K. Nguyen, F. Vercauteren.
547 * Handbook of Elliptic and Hyperelliptic Curve Cryptography.
548 * Algorithm 10.25 Fast reduction for special form moduli
549 */
550static void vli_mmod_special2(u64 *result, const u64 *product,
551 const u64 *mod, unsigned int ndigits)
552{
553 u64 c2 = mod[0] * 2;
554 u64 q[ECC_MAX_DIGITS];
555 u64 r[ECC_MAX_DIGITS * 2];
556 u64 m[ECC_MAX_DIGITS * 2]; /* expanded mod */
557 int carry; /* last bit that doesn't fit into q */
558 int i;
559
560 vli_set(m, mod, ndigits);
561 vli_clear(m + ndigits, ndigits);
562
563 vli_set(r, product, ndigits);
564 /* q and carry are top bits */
565 vli_set(q, product + ndigits, ndigits);
566 vli_clear(r + ndigits, ndigits);
567 carry = vli_is_negative(r, ndigits);
568 if (carry)
569 r[ndigits - 1] &= (1ull << 63) - 1;
570 for (i = 1; carry || !vli_is_zero(q, ndigits); i++) {
571 u64 qc[ECC_MAX_DIGITS * 2];
572
573 vli_umult(qc, q, c2, ndigits);
574 if (carry)
575 vli_uadd(qc, qc, mod[0], ndigits * 2);
576 vli_set(q, qc + ndigits, ndigits);
577 vli_clear(qc + ndigits, ndigits);
578 carry = vli_is_negative(qc, ndigits);
579 if (carry)
580 qc[ndigits - 1] &= (1ull << 63) - 1;
581 if (i & 1)
582 vli_sub(r, r, qc, ndigits * 2);
583 else
584 vli_add(r, r, qc, ndigits * 2);
585 }
586 while (vli_is_negative(r, ndigits * 2))
587 vli_add(r, r, m, ndigits * 2);
588 while (vli_cmp(r, m, ndigits * 2) >= 0)
589 vli_sub(r, r, m, ndigits * 2);
590
591 vli_set(result, r, ndigits);
592}
593
594/*
595 * Computes result = product % mod, where product is 2N words long.
596 * Reference: Ken MacKay's micro-ecc.
597 * Currently only designed to work for curve_p or curve_n.
598 */
599static void vli_mmod_slow(u64 *result, u64 *product, const u64 *mod,
600 unsigned int ndigits)
601{
602 u64 mod_m[2 * ECC_MAX_DIGITS];
603 u64 tmp[2 * ECC_MAX_DIGITS];
604 u64 *v[2] = { tmp, product };
605 u64 carry = 0;
606 unsigned int i;
607 /* Shift mod so its highest set bit is at the maximum position. */
608 int shift = (ndigits * 2 * 64) - vli_num_bits(mod, ndigits);
609 int word_shift = shift / 64;
610 int bit_shift = shift % 64;
611
612 vli_clear(mod_m, word_shift);
613 if (bit_shift > 0) {
614 for (i = 0; i < ndigits; ++i) {
615 mod_m[word_shift + i] = (mod[i] << bit_shift) | carry;
616 carry = mod[i] >> (64 - bit_shift);
617 }
618 } else
619 vli_set(mod_m + word_shift, mod, ndigits);
620
621 for (i = 1; shift >= 0; --shift) {
622 u64 borrow = 0;
623 unsigned int j;
624
625 for (j = 0; j < ndigits * 2; ++j) {
626 u64 diff = v[i][j] - mod_m[j] - borrow;
627
628 if (diff != v[i][j])
629 borrow = (diff > v[i][j]);
630 v[1 - i][j] = diff;
631 }
632 i = !(i ^ borrow); /* Swap the index if there was no borrow */
633 vli_rshift1(mod_m, ndigits);
634 mod_m[ndigits - 1] |= mod_m[ndigits] << (64 - 1);
635 vli_rshift1(mod_m + ndigits, ndigits);
636 }
637 vli_set(result, v[i], ndigits);
638}
639
640/* Computes result = product % mod using Barrett's reduction with precomputed
641 * value mu appended to the mod after ndigits, mu = (2^{2w} / mod) and have
642 * length ndigits + 1, where mu * (2^w - 1) should not overflow ndigits
643 * boundary.
644 *
645 * Reference:
646 * R. Brent, P. Zimmermann. Modern Computer Arithmetic. 2010.
647 * 2.4.1 Barrett's algorithm. Algorithm 2.5.
648 */
649static void vli_mmod_barrett(u64 *result, u64 *product, const u64 *mod,
650 unsigned int ndigits)
651{
652 u64 q[ECC_MAX_DIGITS * 2];
653 u64 r[ECC_MAX_DIGITS * 2];
654 const u64 *mu = mod + ndigits;
655
656 vli_mult(q, product + ndigits, mu, ndigits);
657 if (mu[ndigits])
658 vli_add(q + ndigits, q + ndigits, product + ndigits, ndigits);
659 vli_mult(r, mod, q + ndigits, ndigits);
660 vli_sub(r, product, r, ndigits * 2);
661 while (!vli_is_zero(r + ndigits, ndigits) ||
662 vli_cmp(r, mod, ndigits) != -1) {
663 u64 carry;
664
665 carry = vli_sub(r, r, mod, ndigits);
666 vli_usub(r + ndigits, r + ndigits, carry, ndigits);
667 }
668 vli_set(result, r, ndigits);
669}
670
409/* Computes p_result = p_product % curve_p. 671/* Computes p_result = p_product % curve_p.
410 * See algorithm 5 and 6 from 672 * See algorithm 5 and 6 from
411 * http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf 673 * http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf
@@ -513,14 +775,33 @@ static void vli_mmod_fast_256(u64 *result, const u64 *product,
513 } 775 }
514} 776}
515 777
516/* Computes result = product % curve_prime 778/* Computes result = product % curve_prime for different curve_primes.
517 * from http://www.nsa.gov/ia/_files/nist-routines.pdf 779 *
518*/ 780 * Note that curve_primes are distinguished just by heuristic check and
781 * not by complete conformance check.
782 */
519static bool vli_mmod_fast(u64 *result, u64 *product, 783static bool vli_mmod_fast(u64 *result, u64 *product,
520 const u64 *curve_prime, unsigned int ndigits) 784 const u64 *curve_prime, unsigned int ndigits)
521{ 785{
522 u64 tmp[2 * ECC_MAX_DIGITS]; 786 u64 tmp[2 * ECC_MAX_DIGITS];
523 787
788 /* Currently, both NIST primes have -1 in lowest qword. */
789 if (curve_prime[0] != -1ull) {
790 /* Try to handle Pseudo-Marsenne primes. */
791 if (curve_prime[ndigits - 1] == -1ull) {
792 vli_mmod_special(result, product, curve_prime,
793 ndigits);
794 return true;
795 } else if (curve_prime[ndigits - 1] == 1ull << 63 &&
796 curve_prime[ndigits - 2] == 0) {
797 vli_mmod_special2(result, product, curve_prime,
798 ndigits);
799 return true;
800 }
801 vli_mmod_barrett(result, product, curve_prime, ndigits);
802 return true;
803 }
804
524 switch (ndigits) { 805 switch (ndigits) {
525 case 3: 806 case 3:
526 vli_mmod_fast_192(result, product, curve_prime, tmp); 807 vli_mmod_fast_192(result, product, curve_prime, tmp);
@@ -529,13 +810,26 @@ static bool vli_mmod_fast(u64 *result, u64 *product,
529 vli_mmod_fast_256(result, product, curve_prime, tmp); 810 vli_mmod_fast_256(result, product, curve_prime, tmp);
530 break; 811 break;
531 default: 812 default:
532 pr_err("unsupports digits size!\n"); 813 pr_err_ratelimited("ecc: unsupported digits size!\n");
533 return false; 814 return false;
534 } 815 }
535 816
536 return true; 817 return true;
537} 818}
538 819
820/* Computes result = (left * right) % mod.
821 * Assumes that mod is big enough curve order.
822 */
823void vli_mod_mult_slow(u64 *result, const u64 *left, const u64 *right,
824 const u64 *mod, unsigned int ndigits)
825{
826 u64 product[ECC_MAX_DIGITS * 2];
827
828 vli_mult(product, left, right, ndigits);
829 vli_mmod_slow(result, product, mod, ndigits);
830}
831EXPORT_SYMBOL(vli_mod_mult_slow);
832
539/* Computes result = (left * right) % curve_prime. */ 833/* Computes result = (left * right) % curve_prime. */
540static void vli_mod_mult_fast(u64 *result, const u64 *left, const u64 *right, 834static void vli_mod_mult_fast(u64 *result, const u64 *left, const u64 *right,
541 const u64 *curve_prime, unsigned int ndigits) 835 const u64 *curve_prime, unsigned int ndigits)
@@ -908,6 +1202,85 @@ static void ecc_point_mult(struct ecc_point *result,
908 vli_set(result->y, ry[0], ndigits); 1202 vli_set(result->y, ry[0], ndigits);
909} 1203}
910 1204
1205/* Computes R = P + Q mod p */
1206static void ecc_point_add(const struct ecc_point *result,
1207 const struct ecc_point *p, const struct ecc_point *q,
1208 const struct ecc_curve *curve)
1209{
1210 u64 z[ECC_MAX_DIGITS];
1211 u64 px[ECC_MAX_DIGITS];
1212 u64 py[ECC_MAX_DIGITS];
1213 unsigned int ndigits = curve->g.ndigits;
1214
1215 vli_set(result->x, q->x, ndigits);
1216 vli_set(result->y, q->y, ndigits);
1217 vli_mod_sub(z, result->x, p->x, curve->p, ndigits);
1218 vli_set(px, p->x, ndigits);
1219 vli_set(py, p->y, ndigits);
1220 xycz_add(px, py, result->x, result->y, curve->p, ndigits);
1221 vli_mod_inv(z, z, curve->p, ndigits);
1222 apply_z(result->x, result->y, z, curve->p, ndigits);
1223}
1224
1225/* Computes R = u1P + u2Q mod p using Shamir's trick.
1226 * Based on: Kenneth MacKay's micro-ecc (2014).
1227 */
1228void ecc_point_mult_shamir(const struct ecc_point *result,
1229 const u64 *u1, const struct ecc_point *p,
1230 const u64 *u2, const struct ecc_point *q,
1231 const struct ecc_curve *curve)
1232{
1233 u64 z[ECC_MAX_DIGITS];
1234 u64 sump[2][ECC_MAX_DIGITS];
1235 u64 *rx = result->x;
1236 u64 *ry = result->y;
1237 unsigned int ndigits = curve->g.ndigits;
1238 unsigned int num_bits;
1239 struct ecc_point sum = ECC_POINT_INIT(sump[0], sump[1], ndigits);
1240 const struct ecc_point *points[4];
1241 const struct ecc_point *point;
1242 unsigned int idx;
1243 int i;
1244
1245 ecc_point_add(&sum, p, q, curve);
1246 points[0] = NULL;
1247 points[1] = p;
1248 points[2] = q;
1249 points[3] = &sum;
1250
1251 num_bits = max(vli_num_bits(u1, ndigits),
1252 vli_num_bits(u2, ndigits));
1253 i = num_bits - 1;
1254 idx = (!!vli_test_bit(u1, i)) | ((!!vli_test_bit(u2, i)) << 1);
1255 point = points[idx];
1256
1257 vli_set(rx, point->x, ndigits);
1258 vli_set(ry, point->y, ndigits);
1259 vli_clear(z + 1, ndigits - 1);
1260 z[0] = 1;
1261
1262 for (--i; i >= 0; i--) {
1263 ecc_point_double_jacobian(rx, ry, z, curve->p, ndigits);
1264 idx = (!!vli_test_bit(u1, i)) | ((!!vli_test_bit(u2, i)) << 1);
1265 point = points[idx];
1266 if (point) {
1267 u64 tx[ECC_MAX_DIGITS];
1268 u64 ty[ECC_MAX_DIGITS];
1269 u64 tz[ECC_MAX_DIGITS];
1270
1271 vli_set(tx, point->x, ndigits);
1272 vli_set(ty, point->y, ndigits);
1273 apply_z(tx, ty, z, curve->p, ndigits);
1274 vli_mod_sub(tz, rx, tx, curve->p, ndigits);
1275 xycz_add(tx, ty, rx, ry, curve->p, ndigits);
1276 vli_mod_mult_fast(z, z, tz, curve->p, ndigits);
1277 }
1278 }
1279 vli_mod_inv(z, z, curve->p, ndigits);
1280 apply_z(rx, ry, z, curve->p, ndigits);
1281}
1282EXPORT_SYMBOL(ecc_point_mult_shamir);
1283
911static inline void ecc_swap_digits(const u64 *in, u64 *out, 1284static inline void ecc_swap_digits(const u64 *in, u64 *out,
912 unsigned int ndigits) 1285 unsigned int ndigits)
913{ 1286{
@@ -1051,6 +1424,9 @@ int ecc_is_pubkey_valid_partial(const struct ecc_curve *curve,
1051{ 1424{
1052 u64 yy[ECC_MAX_DIGITS], xxx[ECC_MAX_DIGITS], w[ECC_MAX_DIGITS]; 1425 u64 yy[ECC_MAX_DIGITS], xxx[ECC_MAX_DIGITS], w[ECC_MAX_DIGITS];
1053 1426
1427 if (WARN_ON(pk->ndigits != curve->g.ndigits))
1428 return -EINVAL;
1429
1054 /* Check 1: Verify key is not the zero point. */ 1430 /* Check 1: Verify key is not the zero point. */
1055 if (ecc_point_is_zero(pk)) 1431 if (ecc_point_is_zero(pk))
1056 return -EINVAL; 1432 return -EINVAL;