blob: ab1956a5036ab4965d804b8ff1aecb3e2e4bab35 [file] [log] [blame]
Jarno Lamsa18987a42019-04-24 15:40:43 +03001/* ecc.c - TinyCrypt implementation of common ECC functions */
2
3/*
4 * Copyright (c) 2014, Kenneth MacKay
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions are met:
30 *
31 * - Redistributions of source code must retain the above copyright notice,
32 * this list of conditions and the following disclaimer.
33 *
34 * - Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 *
38 * - Neither the name of Intel Corporation nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
46 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
47 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
48 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
49 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
50 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
52 * POSSIBILITY OF SUCH DAMAGE.
53 */
54
Hanno Becker36ae7582019-07-23 15:52:35 +010055#if !defined(MBEDTLS_CONFIG_FILE)
56#include "mbedtls/config.h"
57#else
58#include MBEDTLS_CONFIG_FILE
59#endif
60
Manuel Pégourié-Gonnardafdc1b52019-05-09 11:24:11 +020061#if defined(MBEDTLS_USE_TINYCRYPT)
Jarno Lamsa18987a42019-04-24 15:40:43 +030062#include <tinycrypt/ecc.h>
Jarno Lamsa18987a42019-04-24 15:40:43 +030063#include <string.h>
64
65/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
66 * has access to enough entropy in order to feed the PRNG regularly. */
67#if default_RNG_defined
68static uECC_RNG_Function g_rng_function = &default_CSPRNG;
69#else
70static uECC_RNG_Function g_rng_function = 0;
71#endif
72
73void uECC_set_rng(uECC_RNG_Function rng_function)
74{
75 g_rng_function = rng_function;
76}
77
78uECC_RNG_Function uECC_get_rng(void)
79{
80 return g_rng_function;
81}
82
83int uECC_curve_private_key_size(uECC_Curve curve)
84{
85 return BITS_TO_BYTES(curve->num_n_bits);
86}
87
88int uECC_curve_public_key_size(uECC_Curve curve)
89{
90 return 2 * curve->num_bytes;
91}
92
93void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words)
94{
95 wordcount_t i;
96 for (i = 0; i < num_words; ++i) {
97 vli[i] = 0;
98 }
99}
100
101uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words)
102{
103 uECC_word_t bits = 0;
104 wordcount_t i;
105 for (i = 0; i < num_words; ++i) {
106 bits |= vli[i];
107 }
108 return (bits == 0);
109}
110
111uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit)
112{
113 return (vli[bit >> uECC_WORD_BITS_SHIFT] &
114 ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
115}
116
117/* Counts the number of words in vli. */
118static wordcount_t vli_numDigits(const uECC_word_t *vli,
119 const wordcount_t max_words)
120{
121
122 wordcount_t i;
123 /* Search from the end until we find a non-zero digit. We do it in reverse
124 * because we expect that most digits will be nonzero. */
125 for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) {
126 }
127
128 return (i + 1);
129}
130
131bitcount_t uECC_vli_numBits(const uECC_word_t *vli,
132 const wordcount_t max_words)
133{
134
135 uECC_word_t i;
136 uECC_word_t digit;
137
138 wordcount_t num_digits = vli_numDigits(vli, max_words);
139 if (num_digits == 0) {
140 return 0;
141 }
142
143 digit = vli[num_digits - 1];
144 for (i = 0; digit; ++i) {
145 digit >>= 1;
146 }
147
148 return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
149}
150
151void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
152 wordcount_t num_words)
153{
154 wordcount_t i;
155
156 for (i = 0; i < num_words; ++i) {
157 dest[i] = src[i];
158 }
159}
160
161cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
162 const uECC_word_t *right,
163 wordcount_t num_words)
164{
165 wordcount_t i;
166
167 for (i = num_words - 1; i >= 0; --i) {
168 if (left[i] > right[i]) {
169 return 1;
170 } else if (left[i] < right[i]) {
171 return -1;
172 }
173 }
174 return 0;
175}
176
177uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
178 wordcount_t num_words)
179{
180
181 uECC_word_t diff = 0;
182 wordcount_t i;
183
184 for (i = num_words - 1; i >= 0; --i) {
185 diff |= (left[i] ^ right[i]);
186 }
187 return !(diff == 0);
188}
189
190uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
191{
192 return (p_true*(cond)) | (p_false*(!cond));
193}
194
195/* Computes result = left - right, returning borrow, in constant time.
196 * Can modify in place. */
197uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
198 const uECC_word_t *right, wordcount_t num_words)
199{
200 uECC_word_t borrow = 0;
201 wordcount_t i;
202 for (i = 0; i < num_words; ++i) {
203 uECC_word_t diff = left[i] - right[i] - borrow;
204 uECC_word_t val = (diff > left[i]);
205 borrow = cond_set(val, borrow, (diff != left[i]));
206
207 result[i] = diff;
208 }
209 return borrow;
210}
211
212/* Computes result = left + right, returning carry, in constant time.
213 * Can modify in place. */
214static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
215 const uECC_word_t *right, wordcount_t num_words)
216{
217 uECC_word_t carry = 0;
218 wordcount_t i;
219 for (i = 0; i < num_words; ++i) {
220 uECC_word_t sum = left[i] + right[i] + carry;
221 uECC_word_t val = (sum < left[i]);
222 carry = cond_set(val, carry, (sum != left[i]));
223 result[i] = sum;
224 }
225 return carry;
226}
227
228cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
229 wordcount_t num_words)
230{
231 uECC_word_t tmp[NUM_ECC_WORDS];
232 uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words);
233 uECC_word_t equal = uECC_vli_isZero(tmp, num_words);
234 return (!equal - 2 * neg);
235}
236
237/* Computes vli = vli >> 1. */
238static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words)
239{
240 uECC_word_t *end = vli;
241 uECC_word_t carry = 0;
242
243 vli += num_words;
244 while (vli-- > end) {
245 uECC_word_t temp = *vli;
246 *vli = (temp >> 1) | carry;
247 carry = temp << (uECC_WORD_BITS - 1);
248 }
249}
250
251static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0,
252 uECC_word_t *r1, uECC_word_t *r2)
253{
254
255 uECC_dword_t p = (uECC_dword_t)a * b;
256 uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0;
257 r01 += p;
258 *r2 += (r01 < p);
259 *r1 = r01 >> uECC_WORD_BITS;
260 *r0 = (uECC_word_t)r01;
261
262}
263
264/* Computes result = left * right. Result must be 2 * num_words long. */
265static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left,
266 const uECC_word_t *right, wordcount_t num_words)
267{
268
269 uECC_word_t r0 = 0;
270 uECC_word_t r1 = 0;
271 uECC_word_t r2 = 0;
272 wordcount_t i, k;
273
274 /* Compute each digit of result in sequence, maintaining the carries. */
275 for (k = 0; k < num_words; ++k) {
276
277 for (i = 0; i <= k; ++i) {
278 muladd(left[i], right[k - i], &r0, &r1, &r2);
279 }
280
281 result[k] = r0;
282 r0 = r1;
283 r1 = r2;
284 r2 = 0;
285 }
286
287 for (k = num_words; k < num_words * 2 - 1; ++k) {
288
289 for (i = (k + 1) - num_words; i < num_words; ++i) {
290 muladd(left[i], right[k - i], &r0, &r1, &r2);
291 }
292 result[k] = r0;
293 r0 = r1;
294 r1 = r2;
295 r2 = 0;
296 }
297 result[num_words * 2 - 1] = r0;
298}
299
300void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
301 const uECC_word_t *right, const uECC_word_t *mod,
302 wordcount_t num_words)
303{
304 uECC_word_t carry = uECC_vli_add(result, left, right, num_words);
305 if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) {
306 /* result > mod (result = mod + remainder), so subtract mod to get
307 * remainder. */
308 uECC_vli_sub(result, result, mod, num_words);
309 }
310}
311
312void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
313 const uECC_word_t *right, const uECC_word_t *mod,
314 wordcount_t num_words)
315{
316 uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words);
317 if (l_borrow) {
318 /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
319 * we can get the correct result from result + mod (with overflow). */
320 uECC_vli_add(result, result, mod, num_words);
321 }
322}
323
324/* Computes result = product % mod, where product is 2N words long. */
325/* Currently only designed to work for curve_p or curve_n. */
326void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
327 const uECC_word_t *mod, wordcount_t num_words)
328{
329 uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
330 uECC_word_t tmp[2 * NUM_ECC_WORDS];
331 uECC_word_t *v[2] = {tmp, product};
332 uECC_word_t index;
333
334 /* Shift mod so its highest set bit is at the maximum position. */
335 bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
336 uECC_vli_numBits(mod, num_words);
337 wordcount_t word_shift = shift / uECC_WORD_BITS;
338 wordcount_t bit_shift = shift % uECC_WORD_BITS;
339 uECC_word_t carry = 0;
340 uECC_vli_clear(mod_multiple, word_shift);
341 if (bit_shift > 0) {
342 for(index = 0; index < (uECC_word_t)num_words; ++index) {
343 mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
344 carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
345 }
346 } else {
347 uECC_vli_set(mod_multiple + word_shift, mod, num_words);
348 }
349
350 for (index = 1; shift >= 0; --shift) {
351 uECC_word_t borrow = 0;
352 wordcount_t i;
353 for (i = 0; i < num_words * 2; ++i) {
354 uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
355 if (diff != v[index][i]) {
356 borrow = (diff > v[index][i]);
357 }
358 v[1 - index][i] = diff;
359 }
360 /* Swap the index if there was no borrow */
361 index = !(index ^ borrow);
362 uECC_vli_rshift1(mod_multiple, num_words);
363 mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
364 (uECC_WORD_BITS - 1);
365 uECC_vli_rshift1(mod_multiple + num_words, num_words);
366 }
367 uECC_vli_set(result, v[index], num_words);
368}
369
370void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
371 const uECC_word_t *right, const uECC_word_t *mod,
372 wordcount_t num_words)
373{
374 uECC_word_t product[2 * NUM_ECC_WORDS];
375 uECC_vli_mult(product, left, right, num_words);
376 uECC_vli_mmod(result, product, mod, num_words);
377}
378
379void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
380 const uECC_word_t *right, uECC_Curve curve)
381{
382 uECC_word_t product[2 * NUM_ECC_WORDS];
383 uECC_vli_mult(product, left, right, curve->num_words);
384
385 curve->mmod_fast(result, product);
386}
387
388static void uECC_vli_modSquare_fast(uECC_word_t *result,
389 const uECC_word_t *left,
390 uECC_Curve curve)
391{
392 uECC_vli_modMult_fast(result, left, left, curve);
393}
394
395
396#define EVEN(vli) (!(vli[0] & 1))
397
398static void vli_modInv_update(uECC_word_t *uv,
399 const uECC_word_t *mod,
400 wordcount_t num_words)
401{
402
403 uECC_word_t carry = 0;
404
405 if (!EVEN(uv)) {
406 carry = uECC_vli_add(uv, uv, mod, num_words);
407 }
408 uECC_vli_rshift1(uv, num_words);
409 if (carry) {
410 uv[num_words - 1] |= HIGH_BIT_SET;
411 }
412}
413
414void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
415 const uECC_word_t *mod, wordcount_t num_words)
416{
417 uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
418 uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
419 cmpresult_t cmpResult;
420
421 if (uECC_vli_isZero(input, num_words)) {
422 uECC_vli_clear(result, num_words);
423 return;
424 }
425
426 uECC_vli_set(a, input, num_words);
427 uECC_vli_set(b, mod, num_words);
428 uECC_vli_clear(u, num_words);
429 u[0] = 1;
430 uECC_vli_clear(v, num_words);
431 while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) {
432 if (EVEN(a)) {
433 uECC_vli_rshift1(a, num_words);
434 vli_modInv_update(u, mod, num_words);
435 } else if (EVEN(b)) {
436 uECC_vli_rshift1(b, num_words);
437 vli_modInv_update(v, mod, num_words);
438 } else if (cmpResult > 0) {
439 uECC_vli_sub(a, a, b, num_words);
440 uECC_vli_rshift1(a, num_words);
441 if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) {
442 uECC_vli_add(u, u, mod, num_words);
443 }
444 uECC_vli_sub(u, u, v, num_words);
445 vli_modInv_update(u, mod, num_words);
446 } else {
447 uECC_vli_sub(b, b, a, num_words);
448 uECC_vli_rshift1(b, num_words);
449 if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) {
450 uECC_vli_add(v, v, mod, num_words);
451 }
452 uECC_vli_sub(v, v, u, num_words);
453 vli_modInv_update(v, mod, num_words);
454 }
455 }
456 uECC_vli_set(result, u, num_words);
457}
458
459/* ------ Point operations ------ */
460
461void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
462 uECC_word_t * Z1, uECC_Curve curve)
463{
464 /* t1 = X, t2 = Y, t3 = Z */
465 uECC_word_t t4[NUM_ECC_WORDS];
466 uECC_word_t t5[NUM_ECC_WORDS];
467 wordcount_t num_words = curve->num_words;
468
469 if (uECC_vli_isZero(Z1, num_words)) {
470 return;
471 }
472
473 uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */
474 uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */
475 uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */
476 uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */
477 uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */
478
479 uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */
480 uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */
481 uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */
482 uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */
483
484 uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */
485 uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */
486 if (uECC_vli_testBit(X1, 0)) {
487 uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words);
488 uECC_vli_rshift1(X1, num_words);
489 X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
490 } else {
491 uECC_vli_rshift1(X1, num_words);
492 }
493
494 /* t1 = 3/2*(x1^2 - z1^4) = B */
495 uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */
496 uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */
497 uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */
498 uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */
499 uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */
500 /* t4 = B * (A - x3) - y1^4 = y3: */
501 uECC_vli_modSub(t4, X1, t4, curve->p, num_words);
502
503 uECC_vli_set(X1, Z1, num_words);
504 uECC_vli_set(Z1, Y1, num_words);
505 uECC_vli_set(Y1, t4, num_words);
506}
507
508void x_side_default(uECC_word_t *result,
509 const uECC_word_t *x,
510 uECC_Curve curve)
511{
512 uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
513 wordcount_t num_words = curve->num_words;
514
515 uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */
516 uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */
517 uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */
518 /* r = x^3 - 3x + b: */
519 uECC_vli_modAdd(result, result, curve->b, curve->p, num_words);
520}
521
522uECC_Curve uECC_secp256r1(void)
523{
524 return &curve_secp256r1;
525}
526
527void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
528{
529 unsigned int tmp[NUM_ECC_WORDS];
530 int carry;
531
532 /* t */
533 uECC_vli_set(result, product, NUM_ECC_WORDS);
534
535 /* s1 */
536 tmp[0] = tmp[1] = tmp[2] = 0;
537 tmp[3] = product[11];
538 tmp[4] = product[12];
539 tmp[5] = product[13];
540 tmp[6] = product[14];
541 tmp[7] = product[15];
542 carry = uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS);
543 carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
544
545 /* s2 */
546 tmp[3] = product[12];
547 tmp[4] = product[13];
548 tmp[5] = product[14];
549 tmp[6] = product[15];
550 tmp[7] = 0;
551 carry += uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS);
552 carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
553
554 /* s3 */
555 tmp[0] = product[8];
556 tmp[1] = product[9];
557 tmp[2] = product[10];
558 tmp[3] = tmp[4] = tmp[5] = 0;
559 tmp[6] = product[14];
560 tmp[7] = product[15];
561 carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
562
563 /* s4 */
564 tmp[0] = product[9];
565 tmp[1] = product[10];
566 tmp[2] = product[11];
567 tmp[3] = product[13];
568 tmp[4] = product[14];
569 tmp[5] = product[15];
570 tmp[6] = product[13];
571 tmp[7] = product[8];
572 carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
573
574 /* d1 */
575 tmp[0] = product[11];
576 tmp[1] = product[12];
577 tmp[2] = product[13];
578 tmp[3] = tmp[4] = tmp[5] = 0;
579 tmp[6] = product[8];
580 tmp[7] = product[10];
581 carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
582
583 /* d2 */
584 tmp[0] = product[12];
585 tmp[1] = product[13];
586 tmp[2] = product[14];
587 tmp[3] = product[15];
588 tmp[4] = tmp[5] = 0;
589 tmp[6] = product[9];
590 tmp[7] = product[11];
591 carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
592
593 /* d3 */
594 tmp[0] = product[13];
595 tmp[1] = product[14];
596 tmp[2] = product[15];
597 tmp[3] = product[8];
598 tmp[4] = product[9];
599 tmp[5] = product[10];
600 tmp[6] = 0;
601 tmp[7] = product[12];
602 carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
603
604 /* d4 */
605 tmp[0] = product[14];
606 tmp[1] = product[15];
607 tmp[2] = 0;
608 tmp[3] = product[9];
609 tmp[4] = product[10];
610 tmp[5] = product[11];
611 tmp[6] = 0;
612 tmp[7] = product[13];
613 carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
614
615 if (carry < 0) {
616 do {
617 carry += uECC_vli_add(result, result, curve_secp256r1.p, NUM_ECC_WORDS);
618 }
619 while (carry < 0);
620 } else {
621 while (carry ||
622 uECC_vli_cmp_unsafe(curve_secp256r1.p, result, NUM_ECC_WORDS) != 1) {
623 carry -= uECC_vli_sub(result, result, curve_secp256r1.p, NUM_ECC_WORDS);
624 }
625 }
626}
627
628uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve)
629{
630 return uECC_vli_isZero(point, curve->num_words * 2);
631}
632
633void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
634 uECC_Curve curve)
635{
636 uECC_word_t t1[NUM_ECC_WORDS];
637
638 uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */
639 uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */
640 uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */
641 uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */
642}
643
644/* P = (x1, y1) => 2P, (x2, y2) => P' */
645static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
646 uECC_word_t * X2, uECC_word_t * Y2,
647 const uECC_word_t * const initial_Z,
648 uECC_Curve curve)
649{
650 uECC_word_t z[NUM_ECC_WORDS];
651 wordcount_t num_words = curve->num_words;
652 if (initial_Z) {
653 uECC_vli_set(z, initial_Z, num_words);
654 } else {
655 uECC_vli_clear(z, num_words);
656 z[0] = 1;
657 }
658
659 uECC_vli_set(X2, X1, num_words);
660 uECC_vli_set(Y2, Y1, num_words);
661
662 apply_z(X1, Y1, z, curve);
663 curve->double_jacobian(X1, Y1, z, curve);
664 apply_z(X2, Y2, z, curve);
665}
666
667void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
668 uECC_word_t * X2, uECC_word_t * Y2,
669 uECC_Curve curve)
670{
671 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
672 uECC_word_t t5[NUM_ECC_WORDS];
673 wordcount_t num_words = curve->num_words;
674
675 uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
676 uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
677 uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
678 uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
679 uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
680 uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */
681
682 uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */
683 uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */
684 uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */
685 uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */
686 uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */
687 uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */
688 uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */
689
690 uECC_vli_set(X2, t5, num_words);
691}
692
693/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
694 Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
695 or P => P - Q, Q => P + Q
696 */
697static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1,
698 uECC_word_t * X2, uECC_word_t * Y2,
699 uECC_Curve curve)
700{
701 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
702 uECC_word_t t5[NUM_ECC_WORDS];
703 uECC_word_t t6[NUM_ECC_WORDS];
704 uECC_word_t t7[NUM_ECC_WORDS];
705 wordcount_t num_words = curve->num_words;
706
707 uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
708 uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
709 uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
710 uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
711 uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */
712 uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
713
714 uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */
715 uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */
716 uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */
717 uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */
718 uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */
719
720 uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */
721 uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */
722 /* t4 = (y2 - y1)*(B - x3) - E = y3: */
723 uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words);
724
725 uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */
726 uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */
727 uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */
728 uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */
729 /* t2 = (y2+y1)*(x3' - B) - E = y3': */
730 uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words);
731
732 uECC_vli_set(X1, t7, num_words);
733}
734
735void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
736 const uECC_word_t * scalar,
737 const uECC_word_t * initial_Z,
738 bitcount_t num_bits, uECC_Curve curve)
739{
740 /* R0 and R1 */
741 uECC_word_t Rx[2][NUM_ECC_WORDS];
742 uECC_word_t Ry[2][NUM_ECC_WORDS];
743 uECC_word_t z[NUM_ECC_WORDS];
744 bitcount_t i;
745 uECC_word_t nb;
746 wordcount_t num_words = curve->num_words;
747
748 uECC_vli_set(Rx[1], point, num_words);
749 uECC_vli_set(Ry[1], point + num_words, num_words);
750
751 XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve);
752
753 for (i = num_bits - 2; i > 0; --i) {
754 nb = !uECC_vli_testBit(scalar, i);
755 XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
756 XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
757 }
758
759 nb = !uECC_vli_testBit(scalar, 0);
760 XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
761
762 /* Find final 1/Z value. */
763 uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */
764 uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */
765 uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */
766 uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0))*/
767 /* yP / (xP * Yb * (X1 - X0)) */
768 uECC_vli_modMult_fast(z, z, point + num_words, curve);
769 /* Xb * yP / (xP * Yb * (X1 - X0)) */
770 uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve);
771 /* End 1/Z calculation */
772
773 XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
774 apply_z(Rx[0], Ry[0], z, curve);
775
776 uECC_vli_set(result, Rx[0], num_words);
777 uECC_vli_set(result + num_words, Ry[0], num_words);
778}
779
780uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
781 uECC_word_t *k1, uECC_Curve curve)
782{
783
784 wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
785
786 bitcount_t num_n_bits = curve->num_n_bits;
787
788 uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
789 (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
790 uECC_vli_testBit(k0, num_n_bits));
791
792 uECC_vli_add(k1, k0, curve->n, num_n_words);
793
794 return carry;
795}
796
797uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
798 uECC_word_t *private_key,
799 uECC_Curve curve)
800{
801
802 uECC_word_t tmp1[NUM_ECC_WORDS];
803 uECC_word_t tmp2[NUM_ECC_WORDS];
804 uECC_word_t *p2[2] = {tmp1, tmp2};
805 uECC_word_t carry;
806
807 /* Regularize the bitcount for the private key so that attackers cannot
808 * use a side channel attack to learn the number of leading zeros. */
809 carry = regularize_k(private_key, tmp1, tmp2, curve);
810
811 EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve);
812
813 if (EccPoint_isZero(result, curve)) {
814 return 0;
815 }
816 return 1;
817}
818
819/* Converts an integer in uECC native format to big-endian bytes. */
820void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
821 const unsigned int *native)
822{
823 wordcount_t i;
824 for (i = 0; i < num_bytes; ++i) {
825 unsigned b = num_bytes - 1 - i;
826 bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
827 }
828}
829
830/* Converts big-endian bytes to an integer in uECC native format. */
831void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
832 int num_bytes)
833{
834 wordcount_t i;
835 uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
836 for (i = 0; i < num_bytes; ++i) {
837 unsigned b = num_bytes - 1 - i;
838 native[b / uECC_WORD_SIZE] |=
839 (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
840 }
841}
842
843int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
844 wordcount_t num_words)
845{
846 uECC_word_t mask = (uECC_word_t)-1;
847 uECC_word_t tries;
848 bitcount_t num_bits = uECC_vli_numBits(top, num_words);
849
850 if (!g_rng_function) {
851 return 0;
852 }
853
854 for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
855 if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
856 return 0;
857 }
858 random[num_words - 1] &=
859 mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
860 if (!uECC_vli_isZero(random, num_words) &&
861 uECC_vli_cmp(top, random, num_words) == 1) {
862 return 1;
863 }
864 }
865 return 0;
866}
867
868
869int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve)
870{
871 uECC_word_t tmp1[NUM_ECC_WORDS];
872 uECC_word_t tmp2[NUM_ECC_WORDS];
873 wordcount_t num_words = curve->num_words;
874
875 /* The point at infinity is invalid. */
876 if (EccPoint_isZero(point, curve)) {
877 return -1;
878 }
879
880 /* x and y must be smaller than p. */
881 if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 ||
882 uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) {
883 return -2;
884 }
885
886 uECC_vli_modSquare_fast(tmp1, point + num_words, curve);
887 curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
888
889 /* Make sure that y^2 == x^3 + ax + b */
890 if (uECC_vli_equal(tmp1, tmp2, num_words) != 0)
891 return -3;
892
893 return 0;
894}
895
896int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve)
897{
898
899 uECC_word_t _public[NUM_ECC_WORDS * 2];
900
901 uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
902 uECC_vli_bytesToNative(
903 _public + curve->num_words,
904 public_key + curve->num_bytes,
905 curve->num_bytes);
906
907 if (uECC_vli_cmp_unsafe(_public, curve->G, NUM_ECC_WORDS * 2) == 0) {
908 return -4;
909 }
910
911 return uECC_valid_point(_public, curve);
912}
913
914int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key,
915 uECC_Curve curve)
916{
917
918 uECC_word_t _private[NUM_ECC_WORDS];
919 uECC_word_t _public[NUM_ECC_WORDS * 2];
920
921 uECC_vli_bytesToNative(
922 _private,
923 private_key,
924 BITS_TO_BYTES(curve->num_n_bits));
925
926 /* Make sure the private key is in the range [1, n-1]. */
927 if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) {
928 return 0;
929 }
930
931 if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) {
932 return 0;
933 }
934
935 /* Compute public key. */
936 if (!EccPoint_compute_public_key(_public, _private, curve)) {
937 return 0;
938 }
939
940 uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public);
941 uECC_vli_nativeToBytes(
942 public_key +
943 curve->num_bytes, curve->num_bytes, _public + curve->num_words);
944 return 1;
945}
Jarno Lamsa46132202019-04-29 14:29:52 +0300946#else
Manuel Pégourié-Gonnardafdc1b52019-05-09 11:24:11 +0200947typedef int mbedtls_dummy_tinycrypt_def;
948#endif /* MBEDTLS_USE_TINYCRYPT */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300949