blob: e4e8e0db6dc56b5ec555a50cefab7c833f9f5aba [file] [log] [blame]
Jarno Lamsa18987a42019-04-24 15:40:43 +03001/* ecc.c - TinyCrypt implementation of common ECC functions */
2
3/*
Simon Butcher92c3d1f2019-09-09 17:25:08 +01004 * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved.
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8/*
Jarno Lamsa18987a42019-04-24 15:40:43 +03009 * Copyright (c) 2014, Kenneth MacKay
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 * * Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions are met:
35 *
36 * - Redistributions of source code must retain the above copyright notice,
37 * this list of conditions and the following disclaimer.
38 *
39 * - Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 *
43 * - Neither the name of Intel Corporation nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 * POSSIBILITY OF SUCH DAMAGE.
58 */
59
Hanno Becker36ae7582019-07-23 15:52:35 +010060#if !defined(MBEDTLS_CONFIG_FILE)
61#include "mbedtls/config.h"
62#else
63#include MBEDTLS_CONFIG_FILE
64#endif
65
Manuel Pégourié-Gonnardafdc1b52019-05-09 11:24:11 +020066#if defined(MBEDTLS_USE_TINYCRYPT)
Jarno Lamsa18987a42019-04-24 15:40:43 +030067#include <tinycrypt/ecc.h>
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +010068#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +010069#include "mbedtls/sha256.h"
Jarno Lamsa18987a42019-04-24 15:40:43 +030070#include <string.h>
71
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +010072/* Parameters for curve NIST P-256 aka secp256r1 */
73const uECC_word_t curve_p[NUM_ECC_WORDS] = {
74 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
75 BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
76 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
77 BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)
78};
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +010079const uECC_word_t curve_n[NUM_ECC_WORDS] = {
80 BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
81 BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
82 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
83 BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)
84};
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +010085const uECC_word_t curve_G[2 * NUM_ECC_WORDS] = {
86 BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
87 BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
88 BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
89 BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
90 BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
91 BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
92 BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
93 BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)
94};
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +010095const uECC_word_t curve_b[NUM_ECC_WORDS] = {
96 BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
97 BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
98 BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
99 BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)
100};
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100101
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100102static int uECC_update_param_sha256(mbedtls_sha256_context *ctx,
103 const uECC_word_t val[NUM_ECC_WORDS])
104{
105 uint8_t bytes[NUM_ECC_BYTES];
106
107 uECC_vli_nativeToBytes(bytes, NUM_ECC_BYTES, val);
108 return mbedtls_sha256_update_ret(ctx, bytes, NUM_ECC_BYTES);
109}
110
111static int uECC_compute_param_sha256(unsigned char output[32])
112{
113 int ret = UECC_FAILURE;
114 mbedtls_sha256_context ctx;
115
116 mbedtls_sha256_init( &ctx );
117
118 if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) {
119 goto exit;
120 }
121
122 if (uECC_update_param_sha256(&ctx, curve_p) != 0 ||
123 uECC_update_param_sha256(&ctx, curve_n) != 0 ||
124 uECC_update_param_sha256(&ctx, curve_G) != 0 ||
125 uECC_update_param_sha256(&ctx, curve_G + NUM_ECC_WORDS) != 0 ||
126 uECC_update_param_sha256(&ctx, curve_b) != 0)
127 {
128 goto exit;
129 }
130
131 if (mbedtls_sha256_finish_ret(&ctx, output) != 0) {
132 goto exit;
133 }
134
135 ret = UECC_SUCCESS;
136
137exit:
138 mbedtls_sha256_free( &ctx );
139
140 return ret;
141}
142
143/*
144 * Check integrity of curve parameters.
145 * Return 0 if everything's OK, non-zero otherwise.
146 */
147static int uECC_check_curve_integrity(void)
148{
149 unsigned char computed[32];
150 unsigned char reference[32] = {
151 0x2d, 0xa1, 0xa4, 0x64, 0x45, 0x28, 0x0d, 0xe1,
152 0x93, 0xf9, 0x29, 0x2f, 0xac, 0x3e, 0xe2, 0x92,
153 0x76, 0x0a, 0xe2, 0xbc, 0xce, 0x2a, 0xa2, 0xc6,
154 0x38, 0xf2, 0x19, 0x1d, 0x76, 0x72, 0x93, 0x49,
155 };
156 volatile unsigned char diff = 0;
157 unsigned char i;
158
159 if (uECC_compute_param_sha256(computed) != UECC_SUCCESS) {
160 return UECC_FAILURE;
161 }
162
163 for (i = 0; i < 32; i++)
164 diff |= computed[i] ^ reference[i];
165
166 return diff;
167}
168
Jarno Lamsa18987a42019-04-24 15:40:43 +0300169/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
170 * has access to enough entropy in order to feed the PRNG regularly. */
171#if default_RNG_defined
172static uECC_RNG_Function g_rng_function = &default_CSPRNG;
173#else
174static uECC_RNG_Function g_rng_function = 0;
175#endif
176
177void uECC_set_rng(uECC_RNG_Function rng_function)
178{
179 g_rng_function = rng_function;
180}
181
182uECC_RNG_Function uECC_get_rng(void)
183{
184 return g_rng_function;
185}
186
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +0100187int uECC_curve_private_key_size(void)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300188{
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +0100189 return BITS_TO_BYTES(NUM_ECC_BITS);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300190}
191
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +0100192int uECC_curve_public_key_size(void)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300193{
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +0100194 return 2 * NUM_ECC_BYTES;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300195}
196
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100197void uECC_vli_clear(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300198{
199 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100200 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300201 vli[i] = 0;
202 }
203}
204
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100205uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300206{
207 uECC_word_t bits = 0;
208 wordcount_t i;
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100209 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300210 bits |= vli[i];
211 }
212 return (bits == 0);
213}
214
215uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit)
216{
217 return (vli[bit >> uECC_WORD_BITS_SHIFT] &
218 ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
219}
220
221/* Counts the number of words in vli. */
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100222static wordcount_t vli_numDigits(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300223{
224
225 wordcount_t i;
226 /* Search from the end until we find a non-zero digit. We do it in reverse
227 * because we expect that most digits will be nonzero. */
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100228 for (i = NUM_ECC_WORDS - 1; i >= 0 && vli[i] == 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300229 }
230
231 return (i + 1);
232}
233
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100234bitcount_t uECC_vli_numBits(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300235{
236
237 uECC_word_t i;
238 uECC_word_t digit;
239
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100240 wordcount_t num_digits = vli_numDigits(vli);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300241 if (num_digits == 0) {
242 return 0;
243 }
244
245 digit = vli[num_digits - 1];
246 for (i = 0; digit; ++i) {
247 digit >>= 1;
248 }
249
250 return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
251}
252
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100253void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300254{
255 wordcount_t i;
256
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100257 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300258 dest[i] = src[i];
259 }
260}
261
262cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100263 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300264{
265 wordcount_t i;
266
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100267 for (i = NUM_ECC_WORDS - 1; i >= 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300268 if (left[i] > right[i]) {
269 return 1;
270 } else if (left[i] < right[i]) {
271 return -1;
272 }
273 }
274 return 0;
275}
276
Manuel Pégourié-Gonnard2eca3d32019-11-04 14:33:09 +0100277uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300278{
279
280 uECC_word_t diff = 0;
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100281 volatile int i;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300282
Manuel Pégourié-Gonnard2eca3d32019-11-04 14:33:09 +0100283 for (i = NUM_ECC_WORDS - 1; i >= 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300284 diff |= (left[i] ^ right[i]);
285 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100286
287 /* i should be -1 now */
288 mbedtls_platform_enforce_volatile_reads();
289 diff |= i ^ -1;
290
Manuel Pégourié-Gonnard2b6312b2019-11-06 10:42:02 +0100291 return diff;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300292}
293
294uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
295{
296 return (p_true*(cond)) | (p_false*(!cond));
297}
298
299/* Computes result = left - right, returning borrow, in constant time.
300 * Can modify in place. */
301uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100302 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300303{
304 uECC_word_t borrow = 0;
305 wordcount_t i;
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100306 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300307 uECC_word_t diff = left[i] - right[i] - borrow;
308 uECC_word_t val = (diff > left[i]);
309 borrow = cond_set(val, borrow, (diff != left[i]));
310
311 result[i] = diff;
312 }
313 return borrow;
314}
315
316/* Computes result = left + right, returning carry, in constant time.
317 * Can modify in place. */
318static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100319 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300320{
321 uECC_word_t carry = 0;
322 wordcount_t i;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100323 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300324 uECC_word_t sum = left[i] + right[i] + carry;
325 uECC_word_t val = (sum < left[i]);
326 carry = cond_set(val, carry, (sum != left[i]));
327 result[i] = sum;
328 }
329 return carry;
330}
331
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +0100332cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300333{
334 uECC_word_t tmp[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100335 uECC_word_t neg = !!uECC_vli_sub(tmp, left, right);
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100336 uECC_word_t equal = uECC_vli_isZero(tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300337 return (!equal - 2 * neg);
338}
339
340/* Computes vli = vli >> 1. */
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100341static void uECC_vli_rshift1(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300342{
343 uECC_word_t *end = vli;
344 uECC_word_t carry = 0;
345
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100346 vli += NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300347 while (vli-- > end) {
348 uECC_word_t temp = *vli;
349 *vli = (temp >> 1) | carry;
350 carry = temp << (uECC_WORD_BITS - 1);
351 }
352}
353
Manuel Pégourié-Gonnard86c4f812019-10-31 13:02:03 +0100354/* Compute a * b + r, where r is a double-word with high-order word r1 and
355 * low-order word r0, and store the result in the same double-word (r1, r0),
356 * with the carry bit stored in r2.
357 *
358 * (r2, r1, r0) = a * b + (r1, r0):
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200359 * [in] a, b: operands to be multiplied
360 * [in] r0, r1: low and high-order words of operand to add
361 * [out] r0, r1: low and high-order words of the result
362 * [out] r2: carry
363 */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300364static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0,
365 uECC_word_t *r1, uECC_word_t *r2)
366{
367
368 uECC_dword_t p = (uECC_dword_t)a * b;
369 uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0;
370 r01 += p;
371 *r2 += (r01 < p);
372 *r1 = r01 >> uECC_WORD_BITS;
373 *r0 = (uECC_word_t)r01;
374
375}
376
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200377/* State for implementing random delays in uECC_vli_mult_rnd().
378 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100379 * The state is initialized by randomizing delays and setting i = 0.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200380 * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i.
381 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100382 * Randomized vli multiplication is used only for point operations
383 * (XYcZ_add_rnd() * and XYcZ_addC_rnd()) in scalar multiplication
384 * (ECCPoint_mult()). Those go in pair, and each pair does 14 calls to
385 * uECC_vli_mult_rnd() (6 in XYcZ_add_rnd() and 8 in XYcZ_addC_rnd(),
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100386 * indirectly through uECC_vli_modMult_rnd().
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100387 *
388 * Considering this, in order to minimize the number of calls to the RNG
389 * (which impact performance) while keeping the size of the structure low,
390 * make room for 14 randomized vli mults, which corresponds to one step in the
391 * scalar multiplication routine.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200392 */
393typedef struct {
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100394 uint8_t i;
395 uint8_t delays[14];
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100396} ecc_wait_state_t;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200397
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100398/*
399 * Reset wait_state so that it's ready to be used.
400 */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100401void ecc_wait_state_reset(ecc_wait_state_t *ws)
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100402{
403 if (ws == NULL)
404 return;
405
406 ws->i = 0;
407 g_rng_function(ws->delays, sizeof(ws->delays));
408}
409
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200410/* Computes result = left * right. Result must be 2 * num_words long.
411 *
412 * As a counter-measure against horizontal attacks, add noise by performing
413 * a random number of extra computations performing random additional accesses
414 * to limbs of the input.
415 *
416 * Each of the two actual computation loops is surrounded by two
417 * similar-looking waiting loops, to make the beginning and end of the actual
418 * computation harder to spot.
419 *
420 * We add 4 waiting loops of between 0 and 3 calls to muladd() each. That
421 * makes an average of 6 extra calls. Compared to the main computation which
422 * makes 64 such calls, this represents an average performance degradation of
423 * less than 10%.
424 *
425 * Compared to the original uECC_vli_mult(), loose the num_words argument as we
426 * know it's always 8. This saves a bit of code size and execution speed.
427 */
428static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100429 const uECC_word_t *right, ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300430{
431
432 uECC_word_t r0 = 0;
433 uECC_word_t r1 = 0;
434 uECC_word_t r2 = 0;
435 wordcount_t i, k;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +0100436 const uint8_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200437
438 /* Fetch 8 bit worth of delay from the state; 0 if we have no state */
439 uint8_t delays = s ? s->delays[s->i++] : 0;
440 uECC_word_t rr0 = 0, rr1 = 0;
441 volatile uECC_word_t r;
442
443 /* Mimic start of next loop: k in [0, 3] */
444 k = 0 + (delays & 0x03);
445 delays >>= 2;
446 /* k = 0 -> i in [1, 0] -> 0 extra muladd;
447 * k = 3 -> i in [1, 3] -> 3 extra muladd */
Manuel Pégourié-Gonnardc8814862019-11-05 10:32:37 +0100448 for (i = 1; i <= k; ++i) {
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200449 muladd(left[i], right[k - i], &rr0, &rr1, &r2);
450 }
451 r = rr0;
452 rr0 = rr1;
453 rr1 = r2;
454 r2 = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300455
456 /* Compute each digit of result in sequence, maintaining the carries. */
457 for (k = 0; k < num_words; ++k) {
458
459 for (i = 0; i <= k; ++i) {
460 muladd(left[i], right[k - i], &r0, &r1, &r2);
461 }
462
463 result[k] = r0;
464 r0 = r1;
465 r1 = r2;
466 r2 = 0;
467 }
468
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200469 /* Mimic end of previous loop: k in [4, 7] */
470 k = 4 + (delays & 0x03);
471 delays >>= 2;
472 /* k = 4 -> i in [5, 4] -> 0 extra muladd;
473 * k = 7 -> i in [5, 7] -> 3 extra muladd */
474 for (i = 5; i <= k; ++i) {
475 muladd(left[i], right[k - i], &rr0, &rr1, &r2);
476 }
477 r = rr0;
478 rr0 = rr1;
479 rr1 = r2;
480 r2 = 0;
481
482 /* Mimic start of next loop: k in [8, 11] */
483 k = 11 - (delays & 0x03);
484 delays >>= 2;
485 /* k = 8 -> i in [5, 7] -> 3 extra muladd;
486 * k = 11 -> i in [8, 7] -> 0 extra muladd */
487 for (i = (k + 5) - num_words; i < num_words; ++i) {
488 muladd(left[i], right[k - i], &rr0, &rr1, &r2);
489 }
490 r = rr0;
491 rr0 = rr1;
492 rr1 = r2;
493 r2 = 0;
494
Jarno Lamsa18987a42019-04-24 15:40:43 +0300495 for (k = num_words; k < num_words * 2 - 1; ++k) {
496
497 for (i = (k + 1) - num_words; i < num_words; ++i) {
498 muladd(left[i], right[k - i], &r0, &r1, &r2);
499 }
500 result[k] = r0;
501 r0 = r1;
502 r1 = r2;
503 r2 = 0;
504 }
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200505
Jarno Lamsa18987a42019-04-24 15:40:43 +0300506 result[num_words * 2 - 1] = r0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200507
508 /* Mimic end of previous loop: k in [12, 15] */
509 k = 15 - (delays & 0x03);
510 delays >>= 2;
511 /* k = 12 -> i in [5, 7] -> 3 extra muladd;
512 * k = 15 -> i in [8, 7] -> 0 extra muladd */
513 for (i = (k + 1) - num_words; i < num_words; ++i) {
514 muladd(left[i], right[k - i], &rr0, &rr1, &r2);
515 }
516 r = rr0;
517 rr0 = rr1;
518 rr1 = r2;
519 r2 = 0;
520
521 /* avoid warning that r is set but not used */
522 (void) r;
523}
524
Jarno Lamsa18987a42019-04-24 15:40:43 +0300525void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard0779be72019-11-04 14:48:22 +0100526 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300527{
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100528 uECC_word_t carry = uECC_vli_add(result, left, right);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100529 if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300530 /* result > mod (result = mod + remainder), so subtract mod to get
531 * remainder. */
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100532 uECC_vli_sub(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300533 }
534}
535
536void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard1b0875d2019-11-04 14:50:54 +0100537 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300538{
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100539 uECC_word_t l_borrow = uECC_vli_sub(result, left, right);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300540 if (l_borrow) {
541 /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
542 * we can get the correct result from result + mod (with overflow). */
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100543 uECC_vli_add(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300544 }
545}
546
547/* Computes result = product % mod, where product is 2N words long. */
548/* Currently only designed to work for curve_p or curve_n. */
549void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +0100550 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300551{
552 uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
553 uECC_word_t tmp[2 * NUM_ECC_WORDS];
554 uECC_word_t *v[2] = {tmp, product};
555 uECC_word_t index;
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +0100556 const wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300557
558 /* Shift mod so its highest set bit is at the maximum position. */
559 bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100560 uECC_vli_numBits(mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300561 wordcount_t word_shift = shift / uECC_WORD_BITS;
562 wordcount_t bit_shift = shift % uECC_WORD_BITS;
563 uECC_word_t carry = 0;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100564 uECC_vli_clear(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300565 if (bit_shift > 0) {
566 for(index = 0; index < (uECC_word_t)num_words; ++index) {
567 mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
568 carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
569 }
570 } else {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100571 uECC_vli_set(mod_multiple + word_shift, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300572 }
573
574 for (index = 1; shift >= 0; --shift) {
575 uECC_word_t borrow = 0;
576 wordcount_t i;
577 for (i = 0; i < num_words * 2; ++i) {
578 uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
579 if (diff != v[index][i]) {
580 borrow = (diff > v[index][i]);
581 }
582 v[1 - index][i] = diff;
583 }
584 /* Swap the index if there was no borrow */
585 index = !(index ^ borrow);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100586 uECC_vli_rshift1(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300587 mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
588 (uECC_WORD_BITS - 1);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100589 uECC_vli_rshift1(mod_multiple + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300590 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100591 uECC_vli_set(result, v[index]);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300592}
593
594void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard3e20adf2019-11-04 15:00:43 +0100595 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300596{
597 uECC_word_t product[2 * NUM_ECC_WORDS];
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100598 uECC_vli_mult_rnd(product, left, right, NULL);
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +0100599 uECC_vli_mmod(result, product, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300600}
601
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100602static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100603 const uECC_word_t *right, ecc_wait_state_t *s)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100604{
605 uECC_word_t product[2 * NUM_ECC_WORDS];
606 uECC_vli_mult_rnd(product, left, right, s);
607
608 vli_mmod_fast_secp256r1(result, product);
609}
610
Jarno Lamsa18987a42019-04-24 15:40:43 +0300611void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100612 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300613{
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100614 uECC_vli_modMult_rnd(result, left, right, NULL);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300615}
616
Jarno Lamsa18987a42019-04-24 15:40:43 +0300617#define EVEN(vli) (!(vli[0] & 1))
618
619static void vli_modInv_update(uECC_word_t *uv,
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +0100620 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300621{
622
623 uECC_word_t carry = 0;
624
625 if (!EVEN(uv)) {
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100626 carry = uECC_vli_add(uv, uv, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300627 }
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100628 uECC_vli_rshift1(uv);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300629 if (carry) {
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +0100630 uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300631 }
632}
633
634void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +0100635 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300636{
637 uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
638 uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
639 cmpresult_t cmpResult;
640
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100641 if (uECC_vli_isZero(input)) {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100642 uECC_vli_clear(result);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300643 return;
644 }
645
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100646 uECC_vli_set(a, input);
647 uECC_vli_set(b, mod);
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100648 uECC_vli_clear(u);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300649 u[0] = 1;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100650 uECC_vli_clear(v);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100651 while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300652 if (EVEN(a)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100653 uECC_vli_rshift1(a);
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +0100654 vli_modInv_update(u, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300655 } else if (EVEN(b)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100656 uECC_vli_rshift1(b);
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +0100657 vli_modInv_update(v, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300658 } else if (cmpResult > 0) {
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100659 uECC_vli_sub(a, a, b);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100660 uECC_vli_rshift1(a);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100661 if (uECC_vli_cmp_unsafe(u, v) < 0) {
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100662 uECC_vli_add(u, u, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300663 }
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100664 uECC_vli_sub(u, u, v);
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +0100665 vli_modInv_update(u, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300666 } else {
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100667 uECC_vli_sub(b, b, a);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100668 uECC_vli_rshift1(b);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100669 if (uECC_vli_cmp_unsafe(v, u) < 0) {
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100670 uECC_vli_add(v, v, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300671 }
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100672 uECC_vli_sub(v, v, u);
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +0100673 vli_modInv_update(v, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300674 }
675 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100676 uECC_vli_set(result, u);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300677}
678
679/* ------ Point operations ------ */
680
681void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +0100682 uECC_word_t * Z1)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300683{
684 /* t1 = X, t2 = Y, t3 = Z */
685 uECC_word_t t4[NUM_ECC_WORDS];
686 uECC_word_t t5[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +0100687 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300688
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100689 if (uECC_vli_isZero(Z1)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300690 return;
691 }
692
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100693 uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */
694 uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */
695 uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */
696 uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */
697 uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300698
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100699 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = x1 + z1^2 */
700 uECC_vli_modAdd(Z1, Z1, Z1, curve_p); /* t3 = 2*z1^2 */
701 uECC_vli_modSub(Z1, X1, Z1, curve_p); /* t3 = x1 - z1^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100702 uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300703
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100704 uECC_vli_modAdd(Z1, X1, X1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
705 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300706 if (uECC_vli_testBit(X1, 0)) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100707 uECC_word_t l_carry = uECC_vli_add(X1, X1, curve_p);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100708 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300709 X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
710 } else {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100711 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300712 }
713
714 /* t1 = 3/2*(x1^2 - z1^4) = B */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100715 uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100716 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - A */
717 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
718 uECC_vli_modSub(t5, t5, Z1, curve_p); /* t5 = A - x3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100719 uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300720 /* t4 = B * (A - x3) - y1^4 = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100721 uECC_vli_modSub(t4, X1, t4, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300722
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100723 uECC_vli_set(X1, Z1);
724 uECC_vli_set(Z1, Y1);
725 uECC_vli_set(Y1, t4);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300726}
727
Manuel Pégourié-Gonnard1c6f7ea2019-11-21 09:18:29 +0100728/*
729 * @brief Computes x^3 + ax + b. result must not overlap x.
730 * @param result OUT -- x^3 + ax + b
731 * @param x IN -- value of x
732 * @param curve IN -- elliptic curve
733 */
734static void x_side_default(uECC_word_t *result,
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +0100735 const uECC_word_t *x)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300736{
737 uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300738
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100739 uECC_vli_modMult_fast(result, x, x); /* r = x^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100740 uECC_vli_modSub(result, result, _3, curve_p); /* r = x^2 - 3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100741 uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300742 /* r = x^3 - 3x + b: */
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +0100743 uECC_vli_modAdd(result, result, curve_b, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300744}
745
Jarno Lamsa18987a42019-04-24 15:40:43 +0300746void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
747{
748 unsigned int tmp[NUM_ECC_WORDS];
749 int carry;
750
751 /* t */
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100752 uECC_vli_set(result, product);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300753
754 /* s1 */
755 tmp[0] = tmp[1] = tmp[2] = 0;
756 tmp[3] = product[11];
757 tmp[4] = product[12];
758 tmp[5] = product[13];
759 tmp[6] = product[14];
760 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100761 carry = uECC_vli_add(tmp, tmp, tmp);
762 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300763
764 /* s2 */
765 tmp[3] = product[12];
766 tmp[4] = product[13];
767 tmp[5] = product[14];
768 tmp[6] = product[15];
769 tmp[7] = 0;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100770 carry += uECC_vli_add(tmp, tmp, tmp);
771 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300772
773 /* s3 */
774 tmp[0] = product[8];
775 tmp[1] = product[9];
776 tmp[2] = product[10];
777 tmp[3] = tmp[4] = tmp[5] = 0;
778 tmp[6] = product[14];
779 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100780 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300781
782 /* s4 */
783 tmp[0] = product[9];
784 tmp[1] = product[10];
785 tmp[2] = product[11];
786 tmp[3] = product[13];
787 tmp[4] = product[14];
788 tmp[5] = product[15];
789 tmp[6] = product[13];
790 tmp[7] = product[8];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100791 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300792
793 /* d1 */
794 tmp[0] = product[11];
795 tmp[1] = product[12];
796 tmp[2] = product[13];
797 tmp[3] = tmp[4] = tmp[5] = 0;
798 tmp[6] = product[8];
799 tmp[7] = product[10];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100800 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300801
802 /* d2 */
803 tmp[0] = product[12];
804 tmp[1] = product[13];
805 tmp[2] = product[14];
806 tmp[3] = product[15];
807 tmp[4] = tmp[5] = 0;
808 tmp[6] = product[9];
809 tmp[7] = product[11];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100810 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300811
812 /* d3 */
813 tmp[0] = product[13];
814 tmp[1] = product[14];
815 tmp[2] = product[15];
816 tmp[3] = product[8];
817 tmp[4] = product[9];
818 tmp[5] = product[10];
819 tmp[6] = 0;
820 tmp[7] = product[12];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100821 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300822
823 /* d4 */
824 tmp[0] = product[14];
825 tmp[1] = product[15];
826 tmp[2] = 0;
827 tmp[3] = product[9];
828 tmp[4] = product[10];
829 tmp[5] = product[11];
830 tmp[6] = 0;
831 tmp[7] = product[13];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100832 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300833
834 if (carry < 0) {
835 do {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100836 carry += uECC_vli_add(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300837 }
838 while (carry < 0);
839 } else {
840 while (carry ||
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100841 uECC_vli_cmp_unsafe(curve_p, result) != 1) {
842 carry -= uECC_vli_sub(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300843 }
844 }
845}
846
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +0100847uECC_word_t EccPoint_isZero(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300848{
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100849 return uECC_vli_isZero(point);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300850}
851
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100852void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300853{
854 uECC_word_t t1[NUM_ECC_WORDS];
855
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100856 uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */
857 uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */
858 uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */
859 uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300860}
861
862/* P = (x1, y1) => 2P, (x2, y2) => P' */
863static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
864 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +0100865 const uECC_word_t * const initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300866{
867 uECC_word_t z[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +0300868 if (initial_Z) {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100869 uECC_vli_set(z, initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300870 } else {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100871 uECC_vli_clear(z);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300872 z[0] = 1;
873 }
874
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100875 uECC_vli_set(X2, X1);
876 uECC_vli_set(Y2, Y1);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300877
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100878 apply_z(X1, Y1, z);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +0100879 double_jacobian_default(X1, Y1, z);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100880 apply_z(X2, Y2, z);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300881}
882
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100883static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1,
884 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100885 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300886{
887 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
888 uECC_word_t t5[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100889
890 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100891 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100892 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
893 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100894 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100895 uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300896
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100897 uECC_vli_modSub(t5, t5, X1, curve_p); /* t5 = D - B */
898 uECC_vli_modSub(t5, t5, X2, curve_p); /* t5 = D - B - C = x3 */
899 uECC_vli_modSub(X2, X2, X1, curve_p); /* t3 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100900 uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100901 uECC_vli_modSub(X2, X1, t5, curve_p); /* t3 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100902 uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100903 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300904
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100905 uECC_vli_set(X2, t5);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300906}
907
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100908void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +0100909 uECC_word_t * X2, uECC_word_t * Y2)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100910{
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100911 XYcZ_add_rnd(X1, Y1, X2, Y2, NULL);
912}
913
Jarno Lamsa18987a42019-04-24 15:40:43 +0300914/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
915 Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
916 or P => P - Q, Q => P + Q
917 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100918static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1,
919 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100920 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300921{
922 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
923 uECC_word_t t5[NUM_ECC_WORDS];
924 uECC_word_t t6[NUM_ECC_WORDS];
925 uECC_word_t t7[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100926
927 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100928 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100929 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
930 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100931 uECC_vli_modAdd(t5, Y2, Y1, curve_p); /* t5 = y2 + y1 */
932 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300933
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100934 uECC_vli_modSub(t6, X2, X1, curve_p); /* t6 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100935 uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100936 uECC_vli_modAdd(t6, X1, X2, curve_p); /* t6 = B + C */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100937 uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100938 uECC_vli_modSub(X2, X2, t6, curve_p); /* t3 = D - (B + C) = x3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300939
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100940 uECC_vli_modSub(t7, X1, X2, curve_p); /* t7 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100941 uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300942 /* t4 = (y2 - y1)*(B - x3) - E = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100943 uECC_vli_modSub(Y2, Y2, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300944
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100945 uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100946 uECC_vli_modSub(t7, t7, t6, curve_p); /* t7 = F - (B + C) = x3' */
947 uECC_vli_modSub(t6, t7, X1, curve_p); /* t6 = x3' - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100948 uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300949 /* t2 = (y2+y1)*(x3' - B) - E = y3': */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100950 uECC_vli_modSub(Y1, t6, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300951
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100952 uECC_vli_set(X1, t7);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300953}
954
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +0100955static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
Jarno Lamsa18987a42019-04-24 15:40:43 +0300956 const uECC_word_t * scalar,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +0100957 const uECC_word_t * initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300958{
959 /* R0 and R1 */
960 uECC_word_t Rx[2][NUM_ECC_WORDS];
961 uECC_word_t Ry[2][NUM_ECC_WORDS];
962 uECC_word_t z[NUM_ECC_WORDS];
963 bitcount_t i;
964 uECC_word_t nb;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +0100965 const wordcount_t num_words = NUM_ECC_WORDS;
966 const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100967 ecc_wait_state_t wait_state;
968 ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300969
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100970 uECC_vli_set(Rx[1], point);
971 uECC_vli_set(Ry[1], point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300972
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +0100973 XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300974
975 for (i = num_bits - 2; i > 0; --i) {
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100976 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300977 nb = !uECC_vli_testBit(scalar, i);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100978 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
979 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300980 }
981
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100982 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300983 nb = !uECC_vli_testBit(scalar, 0);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100984 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300985
986 /* Find final 1/Z value. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100987 uECC_vli_modSub(z, Rx[1], Rx[0], curve_p); /* X1 - X0 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100988 uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */
989 uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100990 uECC_vli_modInv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0))*/
Jarno Lamsa18987a42019-04-24 15:40:43 +0300991 /* yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100992 uECC_vli_modMult_fast(z, z, point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300993 /* Xb * yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100994 uECC_vli_modMult_fast(z, z, Rx[1 - nb]);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300995 /* End 1/Z calculation */
996
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100997 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100998 apply_z(Rx[0], Ry[0], z);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300999
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001000 uECC_vli_set(result, Rx[0]);
1001 uECC_vli_set(result + num_words, Ry[0]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001002}
1003
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001004static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001005 uECC_word_t *k1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001006{
1007
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001008 wordcount_t num_n_words = NUM_ECC_WORDS;
1009 bitcount_t num_n_bits = NUM_ECC_BITS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001010
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001011 uECC_word_t carry = uECC_vli_add(k0, k, curve_n) ||
Jarno Lamsa18987a42019-04-24 15:40:43 +03001012 (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
1013 uECC_vli_testBit(k0, num_n_bits));
1014
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001015 uECC_vli_add(k1, k0, curve_n);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001016
1017 return carry;
1018}
1019
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001020int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001021 const uECC_word_t * scalar)
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001022{
1023 uECC_word_t tmp[NUM_ECC_WORDS];
1024 uECC_word_t s[NUM_ECC_WORDS];
1025 uECC_word_t *k2[2] = {tmp, s};
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001026 wordcount_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001027 uECC_word_t carry;
1028 uECC_word_t *initial_Z = 0;
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001029 int r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001030 volatile int problem;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001031
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001032 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001033 problem = -1;
1034 problem = uECC_check_curve_integrity();
1035 if (problem != 0) {
1036 return UECC_FAULT_DETECTED;
1037 }
1038 mbedtls_platform_enforce_volatile_reads();
1039 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001040 return UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001041 }
1042
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001043 /* Protects against invalid curve attacks */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001044 problem = -1;
1045 problem = uECC_valid_point(point);
1046 if (problem != 0) {
1047 /* invalid input, can happen without fault */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001048 return UECC_FAILURE;
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001049 }
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001050 mbedtls_platform_enforce_volatile_reads();
1051 if (problem != 0) {
1052 /* failure on second check means fault, though */
1053 return UECC_FAULT_DETECTED;
1054 }
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001055
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001056 /* Regularize the bitcount for the private key so that attackers cannot use a
1057 * side channel attack to learn the number of leading zeros. */
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001058 carry = regularize_k(scalar, tmp, s);
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001059
1060 /* If an RNG function was specified, get a random initial Z value to
1061 * protect against side-channel attacks such as Template SPA */
1062 if (g_rng_function) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001063 if (!uECC_generate_random_int(k2[carry], curve_p, num_words)) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001064 r = UECC_FAILURE;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001065 goto clear_and_out;
1066 }
1067 initial_Z = k2[carry];
1068 }
1069
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001070 EccPoint_mult(result, point, k2[!carry], initial_Z);
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001071
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001072 /* Protect against fault injections that would make the resulting
1073 * point not lie on the intended curve */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001074 problem = -1;
1075 problem = uECC_valid_point(result);
1076 if (problem != 0) {
1077 r = UECC_FAULT_DETECTED;
1078 goto clear_and_out;
1079 }
1080 mbedtls_platform_enforce_volatile_reads();
1081 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001082 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001083 goto clear_and_out;
1084 }
1085
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001086 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001087 problem = -1;
1088 problem = uECC_check_curve_integrity();
1089 if (problem != 0) {
1090 r = UECC_FAULT_DETECTED;
1091 goto clear_and_out;
1092 }
1093 mbedtls_platform_enforce_volatile_reads();
1094 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001095 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001096 goto clear_and_out;
1097 }
1098
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001099 r = UECC_SUCCESS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001100
1101clear_and_out:
1102 /* erasing temporary buffer used to store secret: */
1103 mbedtls_platform_zeroize(k2, sizeof(k2));
1104 mbedtls_platform_zeroize(tmp, sizeof(tmp));
1105 mbedtls_platform_zeroize(s, sizeof(s));
1106
1107 return r;
1108}
1109
Jarno Lamsa18987a42019-04-24 15:40:43 +03001110uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001111 uECC_word_t *private_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001112{
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001113 return EccPoint_mult_safer(result, curve_G, private_key);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001114}
1115
1116/* Converts an integer in uECC native format to big-endian bytes. */
1117void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
1118 const unsigned int *native)
1119{
1120 wordcount_t i;
1121 for (i = 0; i < num_bytes; ++i) {
1122 unsigned b = num_bytes - 1 - i;
1123 bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
1124 }
1125}
1126
1127/* Converts big-endian bytes to an integer in uECC native format. */
1128void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
1129 int num_bytes)
1130{
1131 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001132 uECC_vli_clear(native);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001133 for (i = 0; i < num_bytes; ++i) {
1134 unsigned b = num_bytes - 1 - i;
1135 native[b / uECC_WORD_SIZE] |=
1136 (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
1137 }
1138}
1139
1140int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
1141 wordcount_t num_words)
1142{
1143 uECC_word_t mask = (uECC_word_t)-1;
1144 uECC_word_t tries;
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001145 bitcount_t num_bits = uECC_vli_numBits(top);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001146
1147 if (!g_rng_function) {
1148 return 0;
1149 }
1150
1151 for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
1152 if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
1153 return 0;
1154 }
1155 random[num_words - 1] &=
1156 mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001157 if (!uECC_vli_isZero(random) &&
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +01001158 uECC_vli_cmp(top, random) == 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001159 return 1;
1160 }
1161 }
1162 return 0;
1163}
1164
1165
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001166int uECC_valid_point(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001167{
1168 uECC_word_t tmp1[NUM_ECC_WORDS];
1169 uECC_word_t tmp2[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001170 wordcount_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001171 volatile uECC_word_t diff = -1u;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001172
1173 /* The point at infinity is invalid. */
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001174 if (EccPoint_isZero(point)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001175 return -1;
1176 }
1177
1178 /* x and y must be smaller than p. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001179 if (uECC_vli_cmp_unsafe(curve_p, point) != 1 ||
1180 uECC_vli_cmp_unsafe(curve_p, point + num_words) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001181 return -2;
1182 }
1183
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001184 uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001185 x_side_default(tmp2, point); /* tmp2 = x^3 + ax + b */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001186
1187 /* Make sure that y^2 == x^3 + ax + b */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001188 diff = uECC_vli_equal(tmp1, tmp2);
1189 if (diff == 0) {
1190 mbedtls_platform_enforce_volatile_reads();
1191 if (diff == 0) {
1192 return 0;
1193 }
1194 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001195
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001196 return -3;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001197}
1198
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001199int uECC_valid_public_key(const uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001200{
1201
1202 uECC_word_t _public[NUM_ECC_WORDS * 2];
1203
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001204 uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001205 uECC_vli_bytesToNative(
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001206 _public + NUM_ECC_WORDS,
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001207 public_key + NUM_ECC_BYTES,
1208 NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001209
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +01001210 if (memcmp(_public, curve_G, NUM_ECC_WORDS * 2) == 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001211 return -4;
1212 }
1213
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001214 return uECC_valid_point(_public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001215}
1216
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001217int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001218{
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001219 int ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001220 uECC_word_t _private[NUM_ECC_WORDS];
1221 uECC_word_t _public[NUM_ECC_WORDS * 2];
1222
1223 uECC_vli_bytesToNative(
1224 _private,
1225 private_key,
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +01001226 BITS_TO_BYTES(NUM_ECC_BITS));
Jarno Lamsa18987a42019-04-24 15:40:43 +03001227
1228 /* Make sure the private key is in the range [1, n-1]. */
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001229 if (uECC_vli_isZero(_private)) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001230 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001231 }
1232
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001233 if (uECC_vli_cmp(curve_n, _private) != 1) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001234 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001235 }
1236
1237 /* Compute public key. */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001238 ret = EccPoint_compute_public_key(_public, _private);
1239 if (ret != UECC_SUCCESS) {
1240 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001241 }
1242
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001243 uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001244 uECC_vli_nativeToBytes(
1245 public_key +
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001246 NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS);
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001247 return UECC_SUCCESS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001248}
Jarno Lamsa46132202019-04-29 14:29:52 +03001249#else
Manuel Pégourié-Gonnardafdc1b52019-05-09 11:24:11 +02001250typedef int mbedtls_dummy_tinycrypt_def;
1251#endif /* MBEDTLS_USE_TINYCRYPT */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001252