Blame view

crypto/ecc.c 38.3 KB
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1
  /*
0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
2
3
   * Copyright (c) 2013, 2014 Kenneth MacKay. All rights reserved.
   * Copyright (c) 2019 Vitaly Chikunov <vt@altlinux.org>
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are
   * met:
   *  * Redistributions of source code must retain the above copyright
   *   notice, this list of conditions and the following disclaimer.
   *  * Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
26
  #include <linux/module.h>
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
27
28
29
30
31
  #include <linux/random.h>
  #include <linux/slab.h>
  #include <linux/swab.h>
  #include <linux/fips.h>
  #include <crypto/ecdh.h>
6755fd269   Tudor-Dan Ambarus   crypto: ecdh - ad...
32
  #include <crypto/rng.h>
0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
33
34
  #include <asm/unaligned.h>
  #include <linux/ratelimit.h>
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  
  #include "ecc.h"
  #include "ecc_curve_defs.h"
  
  typedef struct {
  	u64 m_low;
  	u64 m_high;
  } uint128_t;
  
  static inline const struct ecc_curve *ecc_get_curve(unsigned int curve_id)
  {
  	switch (curve_id) {
  	/* In FIPS mode only allow P256 and higher */
  	case ECC_CURVE_NIST_P192:
  		return fips_enabled ? NULL : &nist_p192;
  	case ECC_CURVE_NIST_P256:
  		return &nist_p256;
  	default:
  		return NULL;
  	}
  }
  
  static u64 *ecc_alloc_digits_space(unsigned int ndigits)
  {
  	size_t len = ndigits * sizeof(u64);
  
  	if (!len)
  		return NULL;
  
  	return kmalloc(len, GFP_KERNEL);
  }
  
  static void ecc_free_digits_space(u64 *space)
  {
  	kzfree(space);
  }
  
  static struct ecc_point *ecc_alloc_point(unsigned int ndigits)
  {
  	struct ecc_point *p = kmalloc(sizeof(*p), GFP_KERNEL);
  
  	if (!p)
  		return NULL;
  
  	p->x = ecc_alloc_digits_space(ndigits);
  	if (!p->x)
  		goto err_alloc_x;
  
  	p->y = ecc_alloc_digits_space(ndigits);
  	if (!p->y)
  		goto err_alloc_y;
  
  	p->ndigits = ndigits;
  
  	return p;
  
  err_alloc_y:
  	ecc_free_digits_space(p->x);
  err_alloc_x:
  	kfree(p);
  	return NULL;
  }
  
  static void ecc_free_point(struct ecc_point *p)
  {
  	if (!p)
  		return;
  
  	kzfree(p->x);
  	kzfree(p->y);
  	kzfree(p);
  }
  
  static void vli_clear(u64 *vli, unsigned int ndigits)
  {
  	int i;
  
  	for (i = 0; i < ndigits; i++)
  		vli[i] = 0;
  }
  
  /* Returns true if vli == 0, false otherwise. */
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
117
  bool vli_is_zero(const u64 *vli, unsigned int ndigits)
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
118
119
120
121
122
123
124
125
126
127
  {
  	int i;
  
  	for (i = 0; i < ndigits; i++) {
  		if (vli[i])
  			return false;
  	}
  
  	return true;
  }
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
128
  EXPORT_SYMBOL(vli_is_zero);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
129
130
131
132
133
134
  
  /* Returns nonzero if bit bit of vli is set. */
  static u64 vli_test_bit(const u64 *vli, unsigned int bit)
  {
  	return (vli[bit / 64] & ((u64)1 << (bit % 64)));
  }
0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
135
136
137
138
  static bool vli_is_negative(const u64 *vli, unsigned int ndigits)
  {
  	return vli_test_bit(vli, ndigits * 64 - 1);
  }
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  /* Counts the number of 64-bit "digits" in vli. */
  static unsigned int vli_num_digits(const u64 *vli, unsigned int ndigits)
  {
  	int i;
  
  	/* Search from the end until we find a non-zero digit.
  	 * We do it in reverse because we expect that most digits will
  	 * be nonzero.
  	 */
  	for (i = ndigits - 1; i >= 0 && vli[i] == 0; i--);
  
  	return (i + 1);
  }
  
  /* Counts the number of bits required for vli. */
  static unsigned int vli_num_bits(const u64 *vli, unsigned int ndigits)
  {
  	unsigned int i, num_digits;
  	u64 digit;
  
  	num_digits = vli_num_digits(vli, ndigits);
  	if (num_digits == 0)
  		return 0;
  
  	digit = vli[num_digits - 1];
  	for (i = 0; digit; i++)
  		digit >>= 1;
  
  	return ((num_digits - 1) * 64 + i);
  }
0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  /* Set dest from unaligned bit string src. */
  void vli_from_be64(u64 *dest, const void *src, unsigned int ndigits)
  {
  	int i;
  	const u64 *from = src;
  
  	for (i = 0; i < ndigits; i++)
  		dest[i] = get_unaligned_be64(&from[ndigits - 1 - i]);
  }
  EXPORT_SYMBOL(vli_from_be64);
  
  void vli_from_le64(u64 *dest, const void *src, unsigned int ndigits)
  {
  	int i;
  	const u64 *from = src;
  
  	for (i = 0; i < ndigits; i++)
  		dest[i] = get_unaligned_le64(&from[i]);
  }
  EXPORT_SYMBOL(vli_from_le64);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
189
190
191
192
193
194
195
196
197
198
  /* Sets dest = src. */
  static void vli_set(u64 *dest, const u64 *src, unsigned int ndigits)
  {
  	int i;
  
  	for (i = 0; i < ndigits; i++)
  		dest[i] = src[i];
  }
  
  /* Returns sign of left - right. */
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
199
  int vli_cmp(const u64 *left, const u64 *right, unsigned int ndigits)
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
200
201
202
203
204
205
206
207
208
209
210
211
  {
  	int i;
  
  	for (i = ndigits - 1; i >= 0; i--) {
  		if (left[i] > right[i])
  			return 1;
  		else if (left[i] < right[i])
  			return -1;
  	}
  
  	return 0;
  }
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
212
  EXPORT_SYMBOL(vli_cmp);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
  
  /* Computes result = in << c, returning carry. Can modify in place
   * (if result == in). 0 < shift < 64.
   */
  static u64 vli_lshift(u64 *result, const u64 *in, unsigned int shift,
  		      unsigned int ndigits)
  {
  	u64 carry = 0;
  	int i;
  
  	for (i = 0; i < ndigits; i++) {
  		u64 temp = in[i];
  
  		result[i] = (temp << shift) | carry;
  		carry = temp >> (64 - shift);
  	}
  
  	return carry;
  }
  
  /* Computes vli = vli >> 1. */
  static void vli_rshift1(u64 *vli, unsigned int ndigits)
  {
  	u64 *end = vli;
  	u64 carry = 0;
  
  	vli += ndigits;
  
  	while (vli-- > end) {
  		u64 temp = *vli;
  		*vli = (temp >> 1) | carry;
  		carry = temp << 63;
  	}
  }
  
  /* Computes result = left + right, returning carry. Can modify in place. */
  static u64 vli_add(u64 *result, const u64 *left, const u64 *right,
  		   unsigned int ndigits)
  {
  	u64 carry = 0;
  	int i;
  
  	for (i = 0; i < ndigits; i++) {
  		u64 sum;
  
  		sum = left[i] + right[i] + carry;
  		if (sum != left[i])
  			carry = (sum < left[i]);
  
  		result[i] = sum;
  	}
  
  	return carry;
  }
0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
  /* Computes result = left + right, returning carry. Can modify in place. */
  static u64 vli_uadd(u64 *result, const u64 *left, u64 right,
  		    unsigned int ndigits)
  {
  	u64 carry = right;
  	int i;
  
  	for (i = 0; i < ndigits; i++) {
  		u64 sum;
  
  		sum = left[i] + carry;
  		if (sum != left[i])
  			carry = (sum < left[i]);
  		else
  			carry = !!carry;
  
  		result[i] = sum;
  	}
  
  	return carry;
  }
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
288
  /* Computes result = left - right, returning borrow. Can modify in place. */
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
289
  u64 vli_sub(u64 *result, const u64 *left, const u64 *right,
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  		   unsigned int ndigits)
  {
  	u64 borrow = 0;
  	int i;
  
  	for (i = 0; i < ndigits; i++) {
  		u64 diff;
  
  		diff = left[i] - right[i] - borrow;
  		if (diff != left[i])
  			borrow = (diff > left[i]);
  
  		result[i] = diff;
  	}
  
  	return borrow;
  }
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
307
  EXPORT_SYMBOL(vli_sub);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
308

0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
  /* Computes result = left - right, returning borrow. Can modify in place. */
  static u64 vli_usub(u64 *result, const u64 *left, u64 right,
  	     unsigned int ndigits)
  {
  	u64 borrow = right;
  	int i;
  
  	for (i = 0; i < ndigits; i++) {
  		u64 diff;
  
  		diff = left[i] - borrow;
  		if (diff != left[i])
  			borrow = (diff > left[i]);
  
  		result[i] = diff;
  	}
  
  	return borrow;
  }
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
328
329
  static uint128_t mul_64_64(u64 left, u64 right)
  {
0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
330
331
332
333
334
335
336
  	uint128_t result;
  #if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
  	unsigned __int128 m = (unsigned __int128)left * right;
  
  	result.m_low  = m;
  	result.m_high = m >> 64;
  #else
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
337
338
339
340
341
342
343
344
  	u64 a0 = left & 0xffffffffull;
  	u64 a1 = left >> 32;
  	u64 b0 = right & 0xffffffffull;
  	u64 b1 = right >> 32;
  	u64 m0 = a0 * b0;
  	u64 m1 = a0 * b1;
  	u64 m2 = a1 * b0;
  	u64 m3 = a1 * b1;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
345
346
347
348
349
350
351
352
353
354
  
  	m2 += (m0 >> 32);
  	m2 += m1;
  
  	/* Overflow */
  	if (m2 < m1)
  		m3 += 0x100000000ull;
  
  	result.m_low = (m0 & 0xffffffffull) | (m2 << 32);
  	result.m_high = m3 + (m2 >> 32);
0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
355
  #endif
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  	return result;
  }
  
  static uint128_t add_128_128(uint128_t a, uint128_t b)
  {
  	uint128_t result;
  
  	result.m_low = a.m_low + b.m_low;
  	result.m_high = a.m_high + b.m_high + (result.m_low < a.m_low);
  
  	return result;
  }
  
  static void vli_mult(u64 *result, const u64 *left, const u64 *right,
  		     unsigned int ndigits)
  {
  	uint128_t r01 = { 0, 0 };
  	u64 r2 = 0;
  	unsigned int i, k;
  
  	/* Compute each digit of result in sequence, maintaining the
  	 * carries.
  	 */
  	for (k = 0; k < ndigits * 2 - 1; k++) {
  		unsigned int min;
  
  		if (k < ndigits)
  			min = 0;
  		else
  			min = (k + 1) - ndigits;
  
  		for (i = min; i <= k && i < ndigits; i++) {
  			uint128_t product;
  
  			product = mul_64_64(left[i], right[k - i]);
  
  			r01 = add_128_128(r01, product);
  			r2 += (r01.m_high < product.m_high);
  		}
  
  		result[k] = r01.m_low;
  		r01.m_low = r01.m_high;
  		r01.m_high = r2;
  		r2 = 0;
  	}
  
  	result[ndigits * 2 - 1] = r01.m_low;
  }
0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
  /* Compute product = left * right, for a small right value. */
  static void vli_umult(u64 *result, const u64 *left, u32 right,
  		      unsigned int ndigits)
  {
  	uint128_t r01 = { 0 };
  	unsigned int k;
  
  	for (k = 0; k < ndigits; k++) {
  		uint128_t product;
  
  		product = mul_64_64(left[k], right);
  		r01 = add_128_128(r01, product);
  		/* no carry */
  		result[k] = r01.m_low;
  		r01.m_low = r01.m_high;
  		r01.m_high = 0;
  	}
  	result[k] = r01.m_low;
  	for (++k; k < ndigits * 2; k++)
  		result[k] = 0;
  }
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
  static void vli_square(u64 *result, const u64 *left, unsigned int ndigits)
  {
  	uint128_t r01 = { 0, 0 };
  	u64 r2 = 0;
  	int i, k;
  
  	for (k = 0; k < ndigits * 2 - 1; k++) {
  		unsigned int min;
  
  		if (k < ndigits)
  			min = 0;
  		else
  			min = (k + 1) - ndigits;
  
  		for (i = min; i <= k && i <= k - i; i++) {
  			uint128_t product;
  
  			product = mul_64_64(left[i], left[k - i]);
  
  			if (i < k - i) {
  				r2 += product.m_high >> 63;
  				product.m_high = (product.m_high << 1) |
  						 (product.m_low >> 63);
  				product.m_low <<= 1;
  			}
  
  			r01 = add_128_128(r01, product);
  			r2 += (r01.m_high < product.m_high);
  		}
  
  		result[k] = r01.m_low;
  		r01.m_low = r01.m_high;
  		r01.m_high = r2;
  		r2 = 0;
  	}
  
  	result[ndigits * 2 - 1] = r01.m_low;
  }
  
  /* Computes result = (left + right) % mod.
   * Assumes that left < mod and right < mod, result != mod.
   */
  static void vli_mod_add(u64 *result, const u64 *left, const u64 *right,
  			const u64 *mod, unsigned int ndigits)
  {
  	u64 carry;
  
  	carry = vli_add(result, left, right, ndigits);
  
  	/* result > mod (result = mod + remainder), so subtract mod to
  	 * get remainder.
  	 */
  	if (carry || vli_cmp(result, mod, ndigits) >= 0)
  		vli_sub(result, result, mod, ndigits);
  }
  
  /* Computes result = (left - right) % mod.
   * Assumes that left < mod and right < mod, result != mod.
   */
  static void vli_mod_sub(u64 *result, const u64 *left, const u64 *right,
  			const u64 *mod, unsigned int ndigits)
  {
  	u64 borrow = vli_sub(result, left, right, ndigits);
  
  	/* In this case, p_result == -diff == (max int) - diff.
  	 * Since -x % d == d - x, we can get the correct result from
  	 * result + mod (with overflow).
  	 */
  	if (borrow)
  		vli_add(result, result, mod, ndigits);
  }
0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
  /*
   * Computes result = product % mod
   * for special form moduli: p = 2^k-c, for small c (note the minus sign)
   *
   * References:
   * R. Crandall, C. Pomerance. Prime Numbers: A Computational Perspective.
   * 9 Fast Algorithms for Large-Integer Arithmetic. 9.2.3 Moduli of special form
   * Algorithm 9.2.13 (Fast mod operation for special-form moduli).
   */
  static void vli_mmod_special(u64 *result, const u64 *product,
  			      const u64 *mod, unsigned int ndigits)
  {
  	u64 c = -mod[0];
  	u64 t[ECC_MAX_DIGITS * 2];
  	u64 r[ECC_MAX_DIGITS * 2];
  
  	vli_set(r, product, ndigits * 2);
  	while (!vli_is_zero(r + ndigits, ndigits)) {
  		vli_umult(t, r + ndigits, c, ndigits);
  		vli_clear(r + ndigits, ndigits);
  		vli_add(r, r, t, ndigits * 2);
  	}
  	vli_set(t, mod, ndigits);
  	vli_clear(t + ndigits, ndigits);
  	while (vli_cmp(r, t, ndigits * 2) >= 0)
  		vli_sub(r, r, t, ndigits * 2);
  	vli_set(result, r, ndigits);
  }
  
  /*
   * Computes result = product % mod
   * for special form moduli: p = 2^{k-1}+c, for small c (note the plus sign)
   * where k-1 does not fit into qword boundary by -1 bit (such as 255).
  
   * References (loosely based on):
   * A. Menezes, P. van Oorschot, S. Vanstone. Handbook of Applied Cryptography.
   * 14.3.4 Reduction methods for moduli of special form. Algorithm 14.47.
   * URL: http://cacr.uwaterloo.ca/hac/about/chap14.pdf
   *
   * H. Cohen, G. Frey, R. Avanzi, C. Doche, T. Lange, K. Nguyen, F. Vercauteren.
   * Handbook of Elliptic and Hyperelliptic Curve Cryptography.
   * Algorithm 10.25 Fast reduction for special form moduli
   */
  static void vli_mmod_special2(u64 *result, const u64 *product,
  			       const u64 *mod, unsigned int ndigits)
  {
  	u64 c2 = mod[0] * 2;
  	u64 q[ECC_MAX_DIGITS];
  	u64 r[ECC_MAX_DIGITS * 2];
  	u64 m[ECC_MAX_DIGITS * 2]; /* expanded mod */
  	int carry; /* last bit that doesn't fit into q */
  	int i;
  
  	vli_set(m, mod, ndigits);
  	vli_clear(m + ndigits, ndigits);
  
  	vli_set(r, product, ndigits);
  	/* q and carry are top bits */
  	vli_set(q, product + ndigits, ndigits);
  	vli_clear(r + ndigits, ndigits);
  	carry = vli_is_negative(r, ndigits);
  	if (carry)
  		r[ndigits - 1] &= (1ull << 63) - 1;
  	for (i = 1; carry || !vli_is_zero(q, ndigits); i++) {
  		u64 qc[ECC_MAX_DIGITS * 2];
  
  		vli_umult(qc, q, c2, ndigits);
  		if (carry)
  			vli_uadd(qc, qc, mod[0], ndigits * 2);
  		vli_set(q, qc + ndigits, ndigits);
  		vli_clear(qc + ndigits, ndigits);
  		carry = vli_is_negative(qc, ndigits);
  		if (carry)
  			qc[ndigits - 1] &= (1ull << 63) - 1;
  		if (i & 1)
  			vli_sub(r, r, qc, ndigits * 2);
  		else
  			vli_add(r, r, qc, ndigits * 2);
  	}
  	while (vli_is_negative(r, ndigits * 2))
  		vli_add(r, r, m, ndigits * 2);
  	while (vli_cmp(r, m, ndigits * 2) >= 0)
  		vli_sub(r, r, m, ndigits * 2);
  
  	vli_set(result, r, ndigits);
  }
  
  /*
   * Computes result = product % mod, where product is 2N words long.
   * Reference: Ken MacKay's micro-ecc.
   * Currently only designed to work for curve_p or curve_n.
   */
  static void vli_mmod_slow(u64 *result, u64 *product, const u64 *mod,
  			  unsigned int ndigits)
  {
  	u64 mod_m[2 * ECC_MAX_DIGITS];
  	u64 tmp[2 * ECC_MAX_DIGITS];
  	u64 *v[2] = { tmp, product };
  	u64 carry = 0;
  	unsigned int i;
  	/* Shift mod so its highest set bit is at the maximum position. */
  	int shift = (ndigits * 2 * 64) - vli_num_bits(mod, ndigits);
  	int word_shift = shift / 64;
  	int bit_shift = shift % 64;
  
  	vli_clear(mod_m, word_shift);
  	if (bit_shift > 0) {
  		for (i = 0; i < ndigits; ++i) {
  			mod_m[word_shift + i] = (mod[i] << bit_shift) | carry;
  			carry = mod[i] >> (64 - bit_shift);
  		}
  	} else
  		vli_set(mod_m + word_shift, mod, ndigits);
  
  	for (i = 1; shift >= 0; --shift) {
  		u64 borrow = 0;
  		unsigned int j;
  
  		for (j = 0; j < ndigits * 2; ++j) {
  			u64 diff = v[i][j] - mod_m[j] - borrow;
  
  			if (diff != v[i][j])
  				borrow = (diff > v[i][j]);
  			v[1 - i][j] = diff;
  		}
  		i = !(i ^ borrow); /* Swap the index if there was no borrow */
  		vli_rshift1(mod_m, ndigits);
  		mod_m[ndigits - 1] |= mod_m[ndigits] << (64 - 1);
  		vli_rshift1(mod_m + ndigits, ndigits);
  	}
  	vli_set(result, v[i], ndigits);
  }
  
  /* Computes result = product % mod using Barrett's reduction with precomputed
   * value mu appended to the mod after ndigits, mu = (2^{2w} / mod) and have
   * length ndigits + 1, where mu * (2^w - 1) should not overflow ndigits
   * boundary.
   *
   * Reference:
   * R. Brent, P. Zimmermann. Modern Computer Arithmetic. 2010.
   * 2.4.1 Barrett's algorithm. Algorithm 2.5.
   */
  static void vli_mmod_barrett(u64 *result, u64 *product, const u64 *mod,
  			     unsigned int ndigits)
  {
  	u64 q[ECC_MAX_DIGITS * 2];
  	u64 r[ECC_MAX_DIGITS * 2];
  	const u64 *mu = mod + ndigits;
  
  	vli_mult(q, product + ndigits, mu, ndigits);
  	if (mu[ndigits])
  		vli_add(q + ndigits, q + ndigits, product + ndigits, ndigits);
  	vli_mult(r, mod, q + ndigits, ndigits);
  	vli_sub(r, product, r, ndigits * 2);
  	while (!vli_is_zero(r + ndigits, ndigits) ||
  	       vli_cmp(r, mod, ndigits) != -1) {
  		u64 carry;
  
  		carry = vli_sub(r, r, mod, ndigits);
  		vli_usub(r + ndigits, r + ndigits, carry, ndigits);
  	}
  	vli_set(result, r, ndigits);
  }
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
  /* Computes p_result = p_product % curve_p.
   * See algorithm 5 and 6 from
   * http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf
   */
  static void vli_mmod_fast_192(u64 *result, const u64 *product,
  			      const u64 *curve_prime, u64 *tmp)
  {
  	const unsigned int ndigits = 3;
  	int carry;
  
  	vli_set(result, product, ndigits);
  
  	vli_set(tmp, &product[3], ndigits);
  	carry = vli_add(result, result, tmp, ndigits);
  
  	tmp[0] = 0;
  	tmp[1] = product[3];
  	tmp[2] = product[4];
  	carry += vli_add(result, result, tmp, ndigits);
  
  	tmp[0] = tmp[1] = product[5];
  	tmp[2] = 0;
  	carry += vli_add(result, result, tmp, ndigits);
  
  	while (carry || vli_cmp(curve_prime, result, ndigits) != 1)
  		carry -= vli_sub(result, result, curve_prime, ndigits);
  }
  
  /* Computes result = product % curve_prime
   * from http://www.nsa.gov/ia/_files/nist-routines.pdf
   */
  static void vli_mmod_fast_256(u64 *result, const u64 *product,
  			      const u64 *curve_prime, u64 *tmp)
  {
  	int carry;
  	const unsigned int ndigits = 4;
  
  	/* t */
  	vli_set(result, product, ndigits);
  
  	/* s1 */
  	tmp[0] = 0;
  	tmp[1] = product[5] & 0xffffffff00000000ull;
  	tmp[2] = product[6];
  	tmp[3] = product[7];
  	carry = vli_lshift(tmp, tmp, 1, ndigits);
  	carry += vli_add(result, result, tmp, ndigits);
  
  	/* s2 */
  	tmp[1] = product[6] << 32;
  	tmp[2] = (product[6] >> 32) | (product[7] << 32);
  	tmp[3] = product[7] >> 32;
  	carry += vli_lshift(tmp, tmp, 1, ndigits);
  	carry += vli_add(result, result, tmp, ndigits);
  
  	/* s3 */
  	tmp[0] = product[4];
  	tmp[1] = product[5] & 0xffffffff;
  	tmp[2] = 0;
  	tmp[3] = product[7];
  	carry += vli_add(result, result, tmp, ndigits);
  
  	/* s4 */
  	tmp[0] = (product[4] >> 32) | (product[5] << 32);
  	tmp[1] = (product[5] >> 32) | (product[6] & 0xffffffff00000000ull);
  	tmp[2] = product[7];
  	tmp[3] = (product[6] >> 32) | (product[4] << 32);
  	carry += vli_add(result, result, tmp, ndigits);
  
  	/* d1 */
  	tmp[0] = (product[5] >> 32) | (product[6] << 32);
  	tmp[1] = (product[6] >> 32);
  	tmp[2] = 0;
  	tmp[3] = (product[4] & 0xffffffff) | (product[5] << 32);
  	carry -= vli_sub(result, result, tmp, ndigits);
  
  	/* d2 */
  	tmp[0] = product[6];
  	tmp[1] = product[7];
  	tmp[2] = 0;
  	tmp[3] = (product[4] >> 32) | (product[5] & 0xffffffff00000000ull);
  	carry -= vli_sub(result, result, tmp, ndigits);
  
  	/* d3 */
  	tmp[0] = (product[6] >> 32) | (product[7] << 32);
  	tmp[1] = (product[7] >> 32) | (product[4] << 32);
  	tmp[2] = (product[4] >> 32) | (product[5] << 32);
  	tmp[3] = (product[6] << 32);
  	carry -= vli_sub(result, result, tmp, ndigits);
  
  	/* d4 */
  	tmp[0] = product[7];
  	tmp[1] = product[4] & 0xffffffff00000000ull;
  	tmp[2] = product[5];
  	tmp[3] = product[6] & 0xffffffff00000000ull;
  	carry -= vli_sub(result, result, tmp, ndigits);
  
  	if (carry < 0) {
  		do {
  			carry += vli_add(result, result, curve_prime, ndigits);
  		} while (carry < 0);
  	} else {
  		while (carry || vli_cmp(curve_prime, result, ndigits) != 1)
  			carry -= vli_sub(result, result, curve_prime, ndigits);
  	}
  }
0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
765
766
767
768
769
  /* Computes result = product % curve_prime for different curve_primes.
   *
   * Note that curve_primes are distinguished just by heuristic check and
   * not by complete conformance check.
   */
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
770
771
772
  static bool vli_mmod_fast(u64 *result, u64 *product,
  			  const u64 *curve_prime, unsigned int ndigits)
  {
d5c3b1789   Kees Cook   crypto: ecc - Act...
773
  	u64 tmp[2 * ECC_MAX_DIGITS];
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
774

0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
  	/* Currently, both NIST primes have -1 in lowest qword. */
  	if (curve_prime[0] != -1ull) {
  		/* Try to handle Pseudo-Marsenne primes. */
  		if (curve_prime[ndigits - 1] == -1ull) {
  			vli_mmod_special(result, product, curve_prime,
  					 ndigits);
  			return true;
  		} else if (curve_prime[ndigits - 1] == 1ull << 63 &&
  			   curve_prime[ndigits - 2] == 0) {
  			vli_mmod_special2(result, product, curve_prime,
  					  ndigits);
  			return true;
  		}
  		vli_mmod_barrett(result, product, curve_prime, ndigits);
  		return true;
  	}
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
791
792
793
794
795
796
797
798
  	switch (ndigits) {
  	case 3:
  		vli_mmod_fast_192(result, product, curve_prime, tmp);
  		break;
  	case 4:
  		vli_mmod_fast_256(result, product, curve_prime, tmp);
  		break;
  	default:
0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
799
800
  		pr_err_ratelimited("ecc: unsupported digits size!
  ");
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
801
802
803
804
805
  		return false;
  	}
  
  	return true;
  }
0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
806
807
808
809
810
811
812
813
814
815
816
817
  /* Computes result = (left * right) % mod.
   * Assumes that mod is big enough curve order.
   */
  void vli_mod_mult_slow(u64 *result, const u64 *left, const u64 *right,
  		       const u64 *mod, unsigned int ndigits)
  {
  	u64 product[ECC_MAX_DIGITS * 2];
  
  	vli_mult(product, left, right, ndigits);
  	vli_mmod_slow(result, product, mod, ndigits);
  }
  EXPORT_SYMBOL(vli_mod_mult_slow);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
818
819
820
821
  /* Computes result = (left * right) % curve_prime. */
  static void vli_mod_mult_fast(u64 *result, const u64 *left, const u64 *right,
  			      const u64 *curve_prime, unsigned int ndigits)
  {
d5c3b1789   Kees Cook   crypto: ecc - Act...
822
  	u64 product[2 * ECC_MAX_DIGITS];
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
823
824
825
826
827
828
829
830
831
  
  	vli_mult(product, left, right, ndigits);
  	vli_mmod_fast(result, product, curve_prime, ndigits);
  }
  
  /* Computes result = left^2 % curve_prime. */
  static void vli_mod_square_fast(u64 *result, const u64 *left,
  				const u64 *curve_prime, unsigned int ndigits)
  {
d5c3b1789   Kees Cook   crypto: ecc - Act...
832
  	u64 product[2 * ECC_MAX_DIGITS];
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
833
834
835
836
837
838
839
840
841
842
  
  	vli_square(product, left, ndigits);
  	vli_mmod_fast(result, product, curve_prime, ndigits);
  }
  
  #define EVEN(vli) (!(vli[0] & 1))
  /* Computes result = (1 / p_input) % mod. All VLIs are the same size.
   * See "From Euclid's GCD to Montgomery Multiplication to the Great Divide"
   * https://labs.oracle.com/techrep/2001/smli_tr-2001-95.pdf
   */
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
843
  void vli_mod_inv(u64 *result, const u64 *input, const u64 *mod,
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
844
845
  			unsigned int ndigits)
  {
d5c3b1789   Kees Cook   crypto: ecc - Act...
846
847
  	u64 a[ECC_MAX_DIGITS], b[ECC_MAX_DIGITS];
  	u64 u[ECC_MAX_DIGITS], v[ECC_MAX_DIGITS];
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
  	u64 carry;
  	int cmp_result;
  
  	if (vli_is_zero(input, ndigits)) {
  		vli_clear(result, ndigits);
  		return;
  	}
  
  	vli_set(a, input, ndigits);
  	vli_set(b, mod, ndigits);
  	vli_clear(u, ndigits);
  	u[0] = 1;
  	vli_clear(v, ndigits);
  
  	while ((cmp_result = vli_cmp(a, b, ndigits)) != 0) {
  		carry = 0;
  
  		if (EVEN(a)) {
  			vli_rshift1(a, ndigits);
  
  			if (!EVEN(u))
  				carry = vli_add(u, u, mod, ndigits);
  
  			vli_rshift1(u, ndigits);
  			if (carry)
  				u[ndigits - 1] |= 0x8000000000000000ull;
  		} else if (EVEN(b)) {
  			vli_rshift1(b, ndigits);
  
  			if (!EVEN(v))
  				carry = vli_add(v, v, mod, ndigits);
  
  			vli_rshift1(v, ndigits);
  			if (carry)
  				v[ndigits - 1] |= 0x8000000000000000ull;
  		} else if (cmp_result > 0) {
  			vli_sub(a, a, b, ndigits);
  			vli_rshift1(a, ndigits);
  
  			if (vli_cmp(u, v, ndigits) < 0)
  				vli_add(u, u, mod, ndigits);
  
  			vli_sub(u, u, v, ndigits);
  			if (!EVEN(u))
  				carry = vli_add(u, u, mod, ndigits);
  
  			vli_rshift1(u, ndigits);
  			if (carry)
  				u[ndigits - 1] |= 0x8000000000000000ull;
  		} else {
  			vli_sub(b, b, a, ndigits);
  			vli_rshift1(b, ndigits);
  
  			if (vli_cmp(v, u, ndigits) < 0)
  				vli_add(v, v, mod, ndigits);
  
  			vli_sub(v, v, u, ndigits);
  			if (!EVEN(v))
  				carry = vli_add(v, v, mod, ndigits);
  
  			vli_rshift1(v, ndigits);
  			if (carry)
  				v[ndigits - 1] |= 0x8000000000000000ull;
  		}
  	}
  
  	vli_set(result, u, ndigits);
  }
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
916
  EXPORT_SYMBOL(vli_mod_inv);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
  
  /* ------ Point operations ------ */
  
  /* Returns true if p_point is the point at infinity, false otherwise. */
  static bool ecc_point_is_zero(const struct ecc_point *point)
  {
  	return (vli_is_zero(point->x, point->ndigits) &&
  		vli_is_zero(point->y, point->ndigits));
  }
  
  /* Point multiplication algorithm using Montgomery's ladder with co-Z
   * coordinates. From http://eprint.iacr.org/2011/338.pdf
   */
  
  /* Double in place */
  static void ecc_point_double_jacobian(u64 *x1, u64 *y1, u64 *z1,
  				      u64 *curve_prime, unsigned int ndigits)
  {
  	/* t1 = x, t2 = y, t3 = z */
d5c3b1789   Kees Cook   crypto: ecc - Act...
936
937
  	u64 t4[ECC_MAX_DIGITS];
  	u64 t5[ECC_MAX_DIGITS];
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
  
  	if (vli_is_zero(z1, ndigits))
  		return;
  
  	/* t4 = y1^2 */
  	vli_mod_square_fast(t4, y1, curve_prime, ndigits);
  	/* t5 = x1*y1^2 = A */
  	vli_mod_mult_fast(t5, x1, t4, curve_prime, ndigits);
  	/* t4 = y1^4 */
  	vli_mod_square_fast(t4, t4, curve_prime, ndigits);
  	/* t2 = y1*z1 = z3 */
  	vli_mod_mult_fast(y1, y1, z1, curve_prime, ndigits);
  	/* t3 = z1^2 */
  	vli_mod_square_fast(z1, z1, curve_prime, ndigits);
  
  	/* t1 = x1 + z1^2 */
  	vli_mod_add(x1, x1, z1, curve_prime, ndigits);
  	/* t3 = 2*z1^2 */
  	vli_mod_add(z1, z1, z1, curve_prime, ndigits);
  	/* t3 = x1 - z1^2 */
  	vli_mod_sub(z1, x1, z1, curve_prime, ndigits);
  	/* t1 = x1^2 - z1^4 */
  	vli_mod_mult_fast(x1, x1, z1, curve_prime, ndigits);
  
  	/* t3 = 2*(x1^2 - z1^4) */
  	vli_mod_add(z1, x1, x1, curve_prime, ndigits);
  	/* t1 = 3*(x1^2 - z1^4) */
  	vli_mod_add(x1, x1, z1, curve_prime, ndigits);
  	if (vli_test_bit(x1, 0)) {
  		u64 carry = vli_add(x1, x1, curve_prime, ndigits);
  
  		vli_rshift1(x1, ndigits);
  		x1[ndigits - 1] |= carry << 63;
  	} else {
  		vli_rshift1(x1, ndigits);
  	}
  	/* t1 = 3/2*(x1^2 - z1^4) = B */
  
  	/* t3 = B^2 */
  	vli_mod_square_fast(z1, x1, curve_prime, ndigits);
  	/* t3 = B^2 - A */
  	vli_mod_sub(z1, z1, t5, curve_prime, ndigits);
  	/* t3 = B^2 - 2A = x3 */
  	vli_mod_sub(z1, z1, t5, curve_prime, ndigits);
  	/* t5 = A - x3 */
  	vli_mod_sub(t5, t5, z1, curve_prime, ndigits);
  	/* t1 = B * (A - x3) */
  	vli_mod_mult_fast(x1, x1, t5, curve_prime, ndigits);
  	/* t4 = B * (A - x3) - y1^4 = y3 */
  	vli_mod_sub(t4, x1, t4, curve_prime, ndigits);
  
  	vli_set(x1, z1, ndigits);
  	vli_set(z1, y1, ndigits);
  	vli_set(y1, t4, ndigits);
  }
  
  /* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */
  static void apply_z(u64 *x1, u64 *y1, u64 *z, u64 *curve_prime,
  		    unsigned int ndigits)
  {
d5c3b1789   Kees Cook   crypto: ecc - Act...
998
  	u64 t1[ECC_MAX_DIGITS];
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
  
  	vli_mod_square_fast(t1, z, curve_prime, ndigits);    /* z^2 */
  	vli_mod_mult_fast(x1, x1, t1, curve_prime, ndigits); /* x1 * z^2 */
  	vli_mod_mult_fast(t1, t1, z, curve_prime, ndigits);  /* z^3 */
  	vli_mod_mult_fast(y1, y1, t1, curve_prime, ndigits); /* y1 * z^3 */
  }
  
  /* P = (x1, y1) => 2P, (x2, y2) => P' */
  static void xycz_initial_double(u64 *x1, u64 *y1, u64 *x2, u64 *y2,
  				u64 *p_initial_z, u64 *curve_prime,
  				unsigned int ndigits)
  {
d5c3b1789   Kees Cook   crypto: ecc - Act...
1011
  	u64 z[ECC_MAX_DIGITS];
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
  
  	vli_set(x2, x1, ndigits);
  	vli_set(y2, y1, ndigits);
  
  	vli_clear(z, ndigits);
  	z[0] = 1;
  
  	if (p_initial_z)
  		vli_set(z, p_initial_z, ndigits);
  
  	apply_z(x1, y1, z, curve_prime, ndigits);
  
  	ecc_point_double_jacobian(x1, y1, z, curve_prime, ndigits);
  
  	apply_z(x2, y2, z, curve_prime, ndigits);
  }
  
  /* Input P = (x1, y1, Z), Q = (x2, y2, Z)
   * Output P' = (x1', y1', Z3), P + Q = (x3, y3, Z3)
   * or P => P', Q => P + Q
   */
  static void xycz_add(u64 *x1, u64 *y1, u64 *x2, u64 *y2, u64 *curve_prime,
  		     unsigned int ndigits)
  {
  	/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
d5c3b1789   Kees Cook   crypto: ecc - Act...
1037
  	u64 t5[ECC_MAX_DIGITS];
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
  
  	/* t5 = x2 - x1 */
  	vli_mod_sub(t5, x2, x1, curve_prime, ndigits);
  	/* t5 = (x2 - x1)^2 = A */
  	vli_mod_square_fast(t5, t5, curve_prime, ndigits);
  	/* t1 = x1*A = B */
  	vli_mod_mult_fast(x1, x1, t5, curve_prime, ndigits);
  	/* t3 = x2*A = C */
  	vli_mod_mult_fast(x2, x2, t5, curve_prime, ndigits);
  	/* t4 = y2 - y1 */
  	vli_mod_sub(y2, y2, y1, curve_prime, ndigits);
  	/* t5 = (y2 - y1)^2 = D */
  	vli_mod_square_fast(t5, y2, curve_prime, ndigits);
  
  	/* t5 = D - B */
  	vli_mod_sub(t5, t5, x1, curve_prime, ndigits);
  	/* t5 = D - B - C = x3 */
  	vli_mod_sub(t5, t5, x2, curve_prime, ndigits);
  	/* t3 = C - B */
  	vli_mod_sub(x2, x2, x1, curve_prime, ndigits);
  	/* t2 = y1*(C - B) */
  	vli_mod_mult_fast(y1, y1, x2, curve_prime, ndigits);
  	/* t3 = B - x3 */
  	vli_mod_sub(x2, x1, t5, curve_prime, ndigits);
  	/* t4 = (y2 - y1)*(B - x3) */
  	vli_mod_mult_fast(y2, y2, x2, curve_prime, ndigits);
  	/* t4 = y3 */
  	vli_mod_sub(y2, y2, y1, curve_prime, ndigits);
  
  	vli_set(x2, t5, ndigits);
  }
  
  /* Input P = (x1, y1, Z), Q = (x2, y2, Z)
   * Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
   * or P => P - Q, Q => P + Q
   */
  static void xycz_add_c(u64 *x1, u64 *y1, u64 *x2, u64 *y2, u64 *curve_prime,
  		       unsigned int ndigits)
  {
  	/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
d5c3b1789   Kees Cook   crypto: ecc - Act...
1078
1079
1080
  	u64 t5[ECC_MAX_DIGITS];
  	u64 t6[ECC_MAX_DIGITS];
  	u64 t7[ECC_MAX_DIGITS];
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
  
  	/* t5 = x2 - x1 */
  	vli_mod_sub(t5, x2, x1, curve_prime, ndigits);
  	/* t5 = (x2 - x1)^2 = A */
  	vli_mod_square_fast(t5, t5, curve_prime, ndigits);
  	/* t1 = x1*A = B */
  	vli_mod_mult_fast(x1, x1, t5, curve_prime, ndigits);
  	/* t3 = x2*A = C */
  	vli_mod_mult_fast(x2, x2, t5, curve_prime, ndigits);
  	/* t4 = y2 + y1 */
  	vli_mod_add(t5, y2, y1, curve_prime, ndigits);
  	/* t4 = y2 - y1 */
  	vli_mod_sub(y2, y2, y1, curve_prime, ndigits);
  
  	/* t6 = C - B */
  	vli_mod_sub(t6, x2, x1, curve_prime, ndigits);
  	/* t2 = y1 * (C - B) */
  	vli_mod_mult_fast(y1, y1, t6, curve_prime, ndigits);
  	/* t6 = B + C */
  	vli_mod_add(t6, x1, x2, curve_prime, ndigits);
  	/* t3 = (y2 - y1)^2 */
  	vli_mod_square_fast(x2, y2, curve_prime, ndigits);
  	/* t3 = x3 */
  	vli_mod_sub(x2, x2, t6, curve_prime, ndigits);
  
  	/* t7 = B - x3 */
  	vli_mod_sub(t7, x1, x2, curve_prime, ndigits);
  	/* t4 = (y2 - y1)*(B - x3) */
  	vli_mod_mult_fast(y2, y2, t7, curve_prime, ndigits);
  	/* t4 = y3 */
  	vli_mod_sub(y2, y2, y1, curve_prime, ndigits);
  
  	/* t7 = (y2 + y1)^2 = F */
  	vli_mod_square_fast(t7, t5, curve_prime, ndigits);
  	/* t7 = x3' */
  	vli_mod_sub(t7, t7, t6, curve_prime, ndigits);
  	/* t6 = x3' - B */
  	vli_mod_sub(t6, t7, x1, curve_prime, ndigits);
  	/* t6 = (y2 + y1)*(x3' - B) */
  	vli_mod_mult_fast(t6, t6, t5, curve_prime, ndigits);
  	/* t2 = y3' */
  	vli_mod_sub(y1, t6, y1, curve_prime, ndigits);
  
  	vli_set(x1, t7, ndigits);
  }
  
  static void ecc_point_mult(struct ecc_point *result,
  			   const struct ecc_point *point, const u64 *scalar,
3da2c1dfd   Vitaly Chikunov   crypto: ecc - reg...
1129
  			   u64 *initial_z, const struct ecc_curve *curve,
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1130
1131
1132
  			   unsigned int ndigits)
  {
  	/* R0 and R1 */
d5c3b1789   Kees Cook   crypto: ecc - Act...
1133
1134
1135
  	u64 rx[2][ECC_MAX_DIGITS];
  	u64 ry[2][ECC_MAX_DIGITS];
  	u64 z[ECC_MAX_DIGITS];
3da2c1dfd   Vitaly Chikunov   crypto: ecc - reg...
1136
1137
  	u64 sk[2][ECC_MAX_DIGITS];
  	u64 *curve_prime = curve->p;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1138
  	int i, nb;
3da2c1dfd   Vitaly Chikunov   crypto: ecc - reg...
1139
1140
1141
1142
1143
1144
1145
  	int num_bits;
  	int carry;
  
  	carry = vli_add(sk[0], scalar, curve->n, ndigits);
  	vli_add(sk[1], sk[0], curve->n, ndigits);
  	scalar = sk[!carry];
  	num_bits = sizeof(u64) * ndigits * 8 + 1;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
  
  	vli_set(rx[1], point->x, ndigits);
  	vli_set(ry[1], point->y, ndigits);
  
  	xycz_initial_double(rx[1], ry[1], rx[0], ry[0], initial_z, curve_prime,
  			    ndigits);
  
  	for (i = num_bits - 2; i > 0; i--) {
  		nb = !vli_test_bit(scalar, i);
  		xycz_add_c(rx[1 - nb], ry[1 - nb], rx[nb], ry[nb], curve_prime,
  			   ndigits);
  		xycz_add(rx[nb], ry[nb], rx[1 - nb], ry[1 - nb], curve_prime,
  			 ndigits);
  	}
  
  	nb = !vli_test_bit(scalar, 0);
  	xycz_add_c(rx[1 - nb], ry[1 - nb], rx[nb], ry[nb], curve_prime,
  		   ndigits);
  
  	/* Find final 1/Z value. */
  	/* X1 - X0 */
  	vli_mod_sub(z, rx[1], rx[0], curve_prime, ndigits);
  	/* Yb * (X1 - X0) */
  	vli_mod_mult_fast(z, z, ry[1 - nb], curve_prime, ndigits);
  	/* xP * Yb * (X1 - X0) */
  	vli_mod_mult_fast(z, z, point->x, curve_prime, ndigits);
  
  	/* 1 / (xP * Yb * (X1 - X0)) */
  	vli_mod_inv(z, z, curve_prime, point->ndigits);
  
  	/* yP / (xP * Yb * (X1 - X0)) */
  	vli_mod_mult_fast(z, z, point->y, curve_prime, ndigits);
  	/* Xb * yP / (xP * Yb * (X1 - X0)) */
  	vli_mod_mult_fast(z, z, rx[1 - nb], curve_prime, ndigits);
  	/* End 1/Z calculation */
  
  	xycz_add(rx[nb], ry[nb], rx[1 - nb], ry[1 - nb], curve_prime, ndigits);
  
  	apply_z(rx[0], ry[0], z, curve_prime, ndigits);
  
  	vli_set(result->x, rx[0], ndigits);
  	vli_set(result->y, ry[0], ndigits);
  }
0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
  /* Computes R = P + Q mod p */
  static void ecc_point_add(const struct ecc_point *result,
  		   const struct ecc_point *p, const struct ecc_point *q,
  		   const struct ecc_curve *curve)
  {
  	u64 z[ECC_MAX_DIGITS];
  	u64 px[ECC_MAX_DIGITS];
  	u64 py[ECC_MAX_DIGITS];
  	unsigned int ndigits = curve->g.ndigits;
  
  	vli_set(result->x, q->x, ndigits);
  	vli_set(result->y, q->y, ndigits);
  	vli_mod_sub(z, result->x, p->x, curve->p, ndigits);
  	vli_set(px, p->x, ndigits);
  	vli_set(py, p->y, ndigits);
  	xycz_add(px, py, result->x, result->y, curve->p, ndigits);
  	vli_mod_inv(z, z, curve->p, ndigits);
  	apply_z(result->x, result->y, z, curve->p, ndigits);
  }
  
  /* Computes R = u1P + u2Q mod p using Shamir's trick.
   * Based on: Kenneth MacKay's micro-ecc (2014).
   */
  void ecc_point_mult_shamir(const struct ecc_point *result,
  			   const u64 *u1, const struct ecc_point *p,
  			   const u64 *u2, const struct ecc_point *q,
  			   const struct ecc_curve *curve)
  {
  	u64 z[ECC_MAX_DIGITS];
  	u64 sump[2][ECC_MAX_DIGITS];
  	u64 *rx = result->x;
  	u64 *ry = result->y;
  	unsigned int ndigits = curve->g.ndigits;
  	unsigned int num_bits;
  	struct ecc_point sum = ECC_POINT_INIT(sump[0], sump[1], ndigits);
  	const struct ecc_point *points[4];
  	const struct ecc_point *point;
  	unsigned int idx;
  	int i;
  
  	ecc_point_add(&sum, p, q, curve);
  	points[0] = NULL;
  	points[1] = p;
  	points[2] = q;
  	points[3] = &sum;
  
  	num_bits = max(vli_num_bits(u1, ndigits),
  		       vli_num_bits(u2, ndigits));
  	i = num_bits - 1;
  	idx = (!!vli_test_bit(u1, i)) | ((!!vli_test_bit(u2, i)) << 1);
  	point = points[idx];
  
  	vli_set(rx, point->x, ndigits);
  	vli_set(ry, point->y, ndigits);
  	vli_clear(z + 1, ndigits - 1);
  	z[0] = 1;
  
  	for (--i; i >= 0; i--) {
  		ecc_point_double_jacobian(rx, ry, z, curve->p, ndigits);
  		idx = (!!vli_test_bit(u1, i)) | ((!!vli_test_bit(u2, i)) << 1);
  		point = points[idx];
  		if (point) {
  			u64 tx[ECC_MAX_DIGITS];
  			u64 ty[ECC_MAX_DIGITS];
  			u64 tz[ECC_MAX_DIGITS];
  
  			vli_set(tx, point->x, ndigits);
  			vli_set(ty, point->y, ndigits);
  			apply_z(tx, ty, z, curve->p, ndigits);
  			vli_mod_sub(tz, rx, tx, curve->p, ndigits);
  			xycz_add(tx, ty, rx, ry, curve->p, ndigits);
  			vli_mod_mult_fast(z, z, tz, curve->p, ndigits);
  		}
  	}
  	vli_mod_inv(z, z, curve->p, ndigits);
  	apply_z(rx, ry, z, curve->p, ndigits);
  }
  EXPORT_SYMBOL(ecc_point_mult_shamir);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1267
1268
1269
  static inline void ecc_swap_digits(const u64 *in, u64 *out,
  				   unsigned int ndigits)
  {
8e6d97c5b   Ard Biesheuvel   crypto: ecdh - fi...
1270
  	const __be64 *src = (__force __be64 *)in;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1271
1272
1273
  	int i;
  
  	for (i = 0; i < ndigits; i++)
8e6d97c5b   Ard Biesheuvel   crypto: ecdh - fi...
1274
  		out[i] = be64_to_cpu(src[ndigits - 1 - i]);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1275
  }
2eb4942b6   Vitaly Chikunov   crypto: ecc - che...
1276
1277
  static int __ecc_is_key_valid(const struct ecc_curve *curve,
  			      const u64 *private_key, unsigned int ndigits)
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1278
  {
2eb4942b6   Vitaly Chikunov   crypto: ecc - che...
1279
1280
  	u64 one[ECC_MAX_DIGITS] = { 1, };
  	u64 res[ECC_MAX_DIGITS];
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1281
1282
1283
  
  	if (!private_key)
  		return -EINVAL;
2eb4942b6   Vitaly Chikunov   crypto: ecc - che...
1284
  	if (curve->g.ndigits != ndigits)
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1285
  		return -EINVAL;
2eb4942b6   Vitaly Chikunov   crypto: ecc - che...
1286
1287
  	/* Make sure the private key is in the range [2, n-3]. */
  	if (vli_cmp(one, private_key, ndigits) != -1)
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1288
  		return -EINVAL;
2eb4942b6   Vitaly Chikunov   crypto: ecc - che...
1289
1290
1291
  	vli_sub(res, curve->n, one, ndigits);
  	vli_sub(res, res, one, ndigits);
  	if (vli_cmp(res, private_key, ndigits) != 1)
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1292
1293
1294
1295
  		return -EINVAL;
  
  	return 0;
  }
2eb4942b6   Vitaly Chikunov   crypto: ecc - che...
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
  int ecc_is_key_valid(unsigned int curve_id, unsigned int ndigits,
  		     const u64 *private_key, unsigned int private_key_len)
  {
  	int nbytes;
  	const struct ecc_curve *curve = ecc_get_curve(curve_id);
  
  	nbytes = ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
  
  	if (private_key_len != nbytes)
  		return -EINVAL;
  
  	return __ecc_is_key_valid(curve, private_key, ndigits);
  }
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
1309
  EXPORT_SYMBOL(ecc_is_key_valid);
2eb4942b6   Vitaly Chikunov   crypto: ecc - che...
1310

6755fd269   Tudor-Dan Ambarus   crypto: ecdh - ad...
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
  /*
   * ECC private keys are generated using the method of extra random bits,
   * equivalent to that described in FIPS 186-4, Appendix B.4.1.
   *
   * d = (c mod(n–1)) + 1    where c is a string of random bits, 64 bits longer
   *                         than requested
   * 0 <= c mod(n-1) <= n-2  and implies that
   * 1 <= d <= n-1
   *
   * This method generates a private key uniformly distributed in the range
   * [1, n-1].
   */
  int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits, u64 *privkey)
  {
  	const struct ecc_curve *curve = ecc_get_curve(curve_id);
d5c3b1789   Kees Cook   crypto: ecc - Act...
1326
  	u64 priv[ECC_MAX_DIGITS];
6755fd269   Tudor-Dan Ambarus   crypto: ecdh - ad...
1327
1328
1329
1330
1331
  	unsigned int nbytes = ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
  	unsigned int nbits = vli_num_bits(curve->n, ndigits);
  	int err;
  
  	/* Check that N is included in Table 1 of FIPS 186-4, section 6.1.1 */
d5c3b1789   Kees Cook   crypto: ecc - Act...
1332
  	if (nbits < 160 || ndigits > ARRAY_SIZE(priv))
6755fd269   Tudor-Dan Ambarus   crypto: ecdh - ad...
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
  		return -EINVAL;
  
  	/*
  	 * FIPS 186-4 recommends that the private key should be obtained from a
  	 * RBG with a security strength equal to or greater than the security
  	 * strength associated with N.
  	 *
  	 * The maximum security strength identified by NIST SP800-57pt1r4 for
  	 * ECC is 256 (N >= 512).
  	 *
  	 * This condition is met by the default RNG because it selects a favored
  	 * DRBG with a security strength of 256.
  	 */
  	if (crypto_get_default_rng())
4c0e22c90   Pierre   crypto: ecc - Fix...
1347
  		return -EFAULT;
6755fd269   Tudor-Dan Ambarus   crypto: ecdh - ad...
1348
1349
1350
1351
1352
  
  	err = crypto_rng_get_bytes(crypto_default_rng, (u8 *)priv, nbytes);
  	crypto_put_default_rng();
  	if (err)
  		return err;
2eb4942b6   Vitaly Chikunov   crypto: ecc - che...
1353
1354
  	/* Make sure the private key is in the valid range. */
  	if (__ecc_is_key_valid(curve, priv, ndigits))
6755fd269   Tudor-Dan Ambarus   crypto: ecdh - ad...
1355
1356
1357
1358
1359
1360
  		return -EINVAL;
  
  	ecc_swap_digits(priv, privkey, ndigits);
  
  	return 0;
  }
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
1361
  EXPORT_SYMBOL(ecc_gen_privkey);
6755fd269   Tudor-Dan Ambarus   crypto: ecdh - ad...
1362

7380c56d2   Tudor-Dan Ambarus   crypto: ecc - ren...
1363
1364
  int ecc_make_pub_key(unsigned int curve_id, unsigned int ndigits,
  		     const u64 *private_key, u64 *public_key)
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1365
1366
1367
  {
  	int ret = 0;
  	struct ecc_point *pk;
d5c3b1789   Kees Cook   crypto: ecc - Act...
1368
  	u64 priv[ECC_MAX_DIGITS];
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1369
  	const struct ecc_curve *curve = ecc_get_curve(curve_id);
d5c3b1789   Kees Cook   crypto: ecc - Act...
1370
  	if (!private_key || !curve || ndigits > ARRAY_SIZE(priv)) {
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1371
1372
1373
  		ret = -EINVAL;
  		goto out;
  	}
ad2695971   Tudor-Dan Ambarus   crypto: ecc - rem...
1374
  	ecc_swap_digits(private_key, priv, ndigits);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1375
1376
1377
1378
1379
1380
  
  	pk = ecc_alloc_point(ndigits);
  	if (!pk) {
  		ret = -ENOMEM;
  		goto out;
  	}
3da2c1dfd   Vitaly Chikunov   crypto: ecc - reg...
1381
  	ecc_point_mult(pk, &curve->g, priv, NULL, curve, ndigits);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1382
1383
1384
1385
  	if (ecc_point_is_zero(pk)) {
  		ret = -EAGAIN;
  		goto err_free_point;
  	}
ad2695971   Tudor-Dan Ambarus   crypto: ecc - rem...
1386
1387
  	ecc_swap_digits(pk->x, public_key, ndigits);
  	ecc_swap_digits(pk->y, &public_key[ndigits], ndigits);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1388
1389
1390
1391
1392
1393
  
  err_free_point:
  	ecc_free_point(pk);
  out:
  	return ret;
  }
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
1394
  EXPORT_SYMBOL(ecc_make_pub_key);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1395

ea169a30a   Stephan Mueller   crypto: ecdh - ad...
1396
  /* SP800-56A section 5.6.2.3.4 partial verification: ephemeral keys only */
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
1397
1398
  int ecc_is_pubkey_valid_partial(const struct ecc_curve *curve,
  				struct ecc_point *pk)
ea169a30a   Stephan Mueller   crypto: ecdh - ad...
1399
1400
  {
  	u64 yy[ECC_MAX_DIGITS], xxx[ECC_MAX_DIGITS], w[ECC_MAX_DIGITS];
0d7a78643   Vitaly Chikunov   crypto: ecrdsa - ...
1401
1402
  	if (WARN_ON(pk->ndigits != curve->g.ndigits))
  		return -EINVAL;
ea169a30a   Stephan Mueller   crypto: ecdh - ad...
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
  	/* Check 1: Verify key is not the zero point. */
  	if (ecc_point_is_zero(pk))
  		return -EINVAL;
  
  	/* Check 2: Verify key is in the range [1, p-1]. */
  	if (vli_cmp(curve->p, pk->x, pk->ndigits) != 1)
  		return -EINVAL;
  	if (vli_cmp(curve->p, pk->y, pk->ndigits) != 1)
  		return -EINVAL;
  
  	/* Check 3: Verify that y^2 == (x^3 + a·x + b) mod p */
  	vli_mod_square_fast(yy, pk->y, curve->p, pk->ndigits); /* y^2 */
  	vli_mod_square_fast(xxx, pk->x, curve->p, pk->ndigits); /* x^2 */
  	vli_mod_mult_fast(xxx, xxx, pk->x, curve->p, pk->ndigits); /* x^3 */
  	vli_mod_mult_fast(w, curve->a, pk->x, curve->p, pk->ndigits); /* a·x */
  	vli_mod_add(w, w, curve->b, curve->p, pk->ndigits); /* a·x + b */
  	vli_mod_add(w, w, xxx, curve->p, pk->ndigits); /* x^3 + a·x + b */
  	if (vli_cmp(yy, w, pk->ndigits) != 0) /* Equation */
  		return -EINVAL;
  
  	return 0;
ea169a30a   Stephan Mueller   crypto: ecdh - ad...
1424
  }
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
1425
  EXPORT_SYMBOL(ecc_is_pubkey_valid_partial);
ea169a30a   Stephan Mueller   crypto: ecdh - ad...
1426

8f44df154   Stephen Rothwell   crypto: ecdh - ma...
1427
  int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
ad2695971   Tudor-Dan Ambarus   crypto: ecc - rem...
1428
1429
  			      const u64 *private_key, const u64 *public_key,
  			      u64 *secret)
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1430
1431
1432
  {
  	int ret = 0;
  	struct ecc_point *product, *pk;
d5c3b1789   Kees Cook   crypto: ecc - Act...
1433
1434
1435
  	u64 priv[ECC_MAX_DIGITS];
  	u64 rand_z[ECC_MAX_DIGITS];
  	unsigned int nbytes;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1436
  	const struct ecc_curve *curve = ecc_get_curve(curve_id);
d5c3b1789   Kees Cook   crypto: ecc - Act...
1437
1438
  	if (!private_key || !public_key || !curve ||
  	    ndigits > ARRAY_SIZE(priv) || ndigits > ARRAY_SIZE(rand_z)) {
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1439
1440
1441
  		ret = -EINVAL;
  		goto out;
  	}
d5c3b1789   Kees Cook   crypto: ecc - Act...
1442
  	nbytes = ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1443

d5c3b1789   Kees Cook   crypto: ecc - Act...
1444
  	get_random_bytes(rand_z, nbytes);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1445
1446
1447
1448
  
  	pk = ecc_alloc_point(ndigits);
  	if (!pk) {
  		ret = -ENOMEM;
d5c3b1789   Kees Cook   crypto: ecc - Act...
1449
  		goto out;
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1450
  	}
ea169a30a   Stephan Mueller   crypto: ecdh - ad...
1451
1452
1453
1454
1455
1456
1457
  	ecc_swap_digits(public_key, pk->x, ndigits);
  	ecc_swap_digits(&public_key[ndigits], pk->y, ndigits);
  	ret = ecc_is_pubkey_valid_partial(curve, pk);
  	if (ret)
  		goto err_alloc_product;
  
  	ecc_swap_digits(private_key, priv, ndigits);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1458
1459
1460
1461
1462
  	product = ecc_alloc_point(ndigits);
  	if (!product) {
  		ret = -ENOMEM;
  		goto err_alloc_product;
  	}
3da2c1dfd   Vitaly Chikunov   crypto: ecc - reg...
1463
  	ecc_point_mult(product, pk, priv, rand_z, curve, ndigits);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1464

ad2695971   Tudor-Dan Ambarus   crypto: ecc - rem...
1465
  	ecc_swap_digits(product->x, secret, ndigits);
3c4b23901   Salvatore Benedetto   crypto: ecdh - Ad...
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
  
  	if (ecc_point_is_zero(product))
  		ret = -EFAULT;
  
  	ecc_free_point(product);
  err_alloc_product:
  	ecc_free_point(pk);
  out:
  	return ret;
  }
4a2289dae   Vitaly Chikunov   crypto: ecc - mak...
1476
1477
1478
  EXPORT_SYMBOL(crypto_ecdh_shared_secret);
  
  MODULE_LICENSE("Dual BSD/GPL");