blob: ee91957182af287574be00c4d65c48b4712c14e4 [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 *
Andrzej Kurek0919b142020-07-06 15:28:59 -040036 * - Redistributions of source code must retain the above copyright notice,
37 * this list of conditions and the following disclaimer.
Jarno Lamsa18987a42019-04-24 15:40:43 +030038 *
Andrzej Kurek0919b142020-07-06 15:28:59 -040039 * - 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.
Jarno Lamsa18987a42019-04-24 15:40:43 +030042 *
Andrzej Kurek0919b142020-07-06 15:28:59 -040043 * - 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.
Jarno Lamsa18987a42019-04-24 15:40:43 +030046 *
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
Jarno Lamsa18987a42019-04-24 15:40:43 +030066#include <tinycrypt/ecc.h>
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +010067#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +010068#include "mbedtls/sha256.h"
Jarno Lamsa18987a42019-04-24 15:40:43 +030069#include <string.h>
Shelly Liberman05beb9a2020-09-13 15:23:56 +030070#include "mbedtls/platform_util.h"
Jarno Lamsa18987a42019-04-24 15:40:43 +030071
Kevin Bracey1959c182020-07-16 21:03:19 +030072#ifdef __CC_ARM
73#pragma diag_suppress 667 // strict diagnostic: "asm" function is nonstandard
74#endif
75
76#if defined MBEDTLS_HAVE_ASM
77#ifndef asm
78#define asm __asm
79#endif
80#endif
81
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +010082/* Parameters for curve NIST P-256 aka secp256r1 */
83const uECC_word_t curve_p[NUM_ECC_WORDS] = {
84 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
85 BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
86 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
87 BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)
88};
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +010089const uECC_word_t curve_n[NUM_ECC_WORDS] = {
90 BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
91 BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
92 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
93 BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)
94};
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +010095const uECC_word_t curve_G[2 * NUM_ECC_WORDS] = {
96 BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
97 BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
98 BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
99 BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
100 BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
101 BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
102 BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
103 BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)
104};
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +0100105const uECC_word_t curve_b[NUM_ECC_WORDS] = {
106 BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
107 BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
108 BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
109 BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)
110};
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100111
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100112static int uECC_update_param_sha256(mbedtls_sha256_context *ctx,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400113 const uECC_word_t val[NUM_ECC_WORDS])
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100114{
115 uint8_t bytes[NUM_ECC_BYTES];
116
117 uECC_vli_nativeToBytes(bytes, NUM_ECC_BYTES, val);
118 return mbedtls_sha256_update_ret(ctx, bytes, NUM_ECC_BYTES);
119}
120
121static int uECC_compute_param_sha256(unsigned char output[32])
122{
123 int ret = UECC_FAILURE;
124 mbedtls_sha256_context ctx;
125
126 mbedtls_sha256_init( &ctx );
127
128 if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) {
129 goto exit;
130 }
131
132 if (uECC_update_param_sha256(&ctx, curve_p) != 0 ||
Andrzej Kurek0919b142020-07-06 15:28:59 -0400133 uECC_update_param_sha256(&ctx, curve_n) != 0 ||
134 uECC_update_param_sha256(&ctx, curve_G) != 0 ||
135 uECC_update_param_sha256(&ctx, curve_G + NUM_ECC_WORDS) != 0 ||
136 uECC_update_param_sha256(&ctx, curve_b) != 0)
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100137 {
138 goto exit;
139 }
140
141 if (mbedtls_sha256_finish_ret(&ctx, output) != 0) {
142 goto exit;
143 }
144
145 ret = UECC_SUCCESS;
146
147exit:
148 mbedtls_sha256_free( &ctx );
149
150 return ret;
151}
152
153/*
154 * Check integrity of curve parameters.
155 * Return 0 if everything's OK, non-zero otherwise.
156 */
157static int uECC_check_curve_integrity(void)
158{
159 unsigned char computed[32];
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100160 static const unsigned char reference[32] = {
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100161 0x2d, 0xa1, 0xa4, 0x64, 0x45, 0x28, 0x0d, 0xe1,
162 0x93, 0xf9, 0x29, 0x2f, 0xac, 0x3e, 0xe2, 0x92,
163 0x76, 0x0a, 0xe2, 0xbc, 0xce, 0x2a, 0xa2, 0xc6,
164 0x38, 0xf2, 0x19, 0x1d, 0x76, 0x72, 0x93, 0x49,
165 };
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100166 unsigned char diff = 0;
167 unsigned char tmp1, tmp2;
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100168 volatile unsigned i;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100169
170 if (uECC_compute_param_sha256(computed) != UECC_SUCCESS) {
171 return UECC_FAILURE;
172 }
173
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100174 for (i = 0; i < 32; i++) {
175 /* make sure the order of volatile accesses is well-defined */
176 tmp1 = computed[i];
177 tmp2 = reference[i];
178 diff |= tmp1 ^ tmp2;
179 }
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100180
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100181 /* i should be 32 */
Arto Kinnunenac6d2262020-01-09 10:11:20 +0200182 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100183 diff |= (unsigned char) i ^ 32;
184
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100185 return diff;
186}
187
Jarno Lamsa18987a42019-04-24 15:40:43 +0300188/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
189 * has access to enough entropy in order to feed the PRNG regularly. */
190#if default_RNG_defined
191static uECC_RNG_Function g_rng_function = &default_CSPRNG;
192#else
193static uECC_RNG_Function g_rng_function = 0;
194#endif
195
196void uECC_set_rng(uECC_RNG_Function rng_function)
197{
198 g_rng_function = rng_function;
199}
200
201uECC_RNG_Function uECC_get_rng(void)
202{
203 return g_rng_function;
204}
205
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +0100206int uECC_curve_private_key_size(void)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300207{
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +0100208 return BITS_TO_BYTES(NUM_ECC_BITS);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300209}
210
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +0100211int uECC_curve_public_key_size(void)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300212{
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +0100213 return 2 * NUM_ECC_BYTES;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300214}
215
Kevin Bracey3be252e2020-10-09 12:54:48 +0300216#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
217__asm void uECC_vli_clear(uECC_word_t *vli)
218{
219#if NUM_ECC_WORDS != 8
220#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
221#endif
222#if !defined __thumb__ || __TARGET_ARCH_THUMB < 4
223 MOVS r1,#0
224 MOVS r2,#0
225 STMIA r0!,{r1,r2}
226 STMIA r0!,{r1,r2}
227 STMIA r0!,{r1,r2}
228 STMIA r0!,{r1,r2}
229 BX lr
230#else
231 MOVS r1,#0
232 STRD r1,r1,[r0,#0] // Only Thumb2 STRD can store same reg twice, not ARM
233 STRD r1,r1,[r0,#8]
234 STRD r1,r1,[r0,#16]
235 STRD r1,r1,[r0,#24]
236 BX lr
237#endif
238}
239#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
240void uECC_vli_clear(uECC_word_t *vli)
241{
242#if NUM_ECC_WORDS != 8
243#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
244#endif
245#if !defined __thumb__ || !defined __thumb2__
246 register uECC_word_t *r0 asm("r0") = vli;
247 register uECC_word_t r1 asm("r1") = 0;
248 register uECC_word_t r2 asm("r2") = 0;
249 asm volatile (
250 ".syntax unified \n\t"
251 "STMIA r0!,{r1,r2} \n\t"
252 "STMIA r0!,{r1,r2} \n\t"
253 "STMIA r0!,{r1,r2} \n\t"
254 "STMIA r0!,{r1,r2} \n\t"
255 : "+r" (r0)
256 : "r" (r1), "r" (r2)
257 : "memory"
258#else
259 register uECC_word_t *r0 asm("r0") = vli;
260 register uECC_word_t r1 asm("r1") = 0;
261 asm volatile (
262 "STRD r1,r1,[r0,#0] \n\t" // Only Thumb2 STRD can store same reg twice, not ARM
263 "STRD r1,r1,[r0,#8] \n\t"
264 "STRD r1,r1,[r0,#16] \n\t"
265 "STRD r1,r1,[r0,#24] \n\t"
266 :
267 : "r" (r0), "r" (r1)
268 : "memory"
269#endif
270 );
271}
272#else
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100273void uECC_vli_clear(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300274{
275 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100276 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300277 vli[i] = 0;
278 }
279}
Kevin Bracey3be252e2020-10-09 12:54:48 +0300280#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300281
Kevin Bracey3be252e2020-10-09 12:54:48 +0300282#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
283__asm uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
284{
285#if NUM_ECC_WORDS != 8
286#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
287#endif
288#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
289 LDMIA r0!,{r1,r2,r3}
290 ORRS r1,r2
291 ORRS r1,r3
292 LDMIA r0!,{r2,r3}
293 ORRS r1,r2
294 ORRS r1,r3
295 LDMIA r0,{r0,r2,r3}
296 ORRS r1,r0
297 ORRS r1,r2
298 ORRS r1,r3
299 RSBS r1,r1,#0 // C set if zero
300 MOVS r0,#0
301 ADCS r0,r0
302 BX lr
303#else
304 LDMIA r0!,{r1,r2,r3,ip}
305 ORRS r1,r2
306 ORRS r1,r3
307 ORRS r1,ip
308 LDMIA r0,{r0,r2,r3,ip}
309 ORRS r1,r0
310 ORRS r1,r2
311 ORRS r1,r3
312 ORRS r1,ip
313#ifdef __ARM_FEATURE_CLZ
314 CLZ r0,r1 // 32 if zero
315 LSRS r0,r0,#5
316#else
317 RSBS r1,r1,#0 // C set if zero
318 MOVS r0,#0
319 ADCS r0,r0
320#endif
321 BX lr
322#endif
323}
324#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
325uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
326{
327 uECC_word_t ret;
328#if NUM_ECC_WORDS != 8
329#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
330#endif
331#if defined __thumb__ && !defined __thumb2__
332 register uECC_word_t r1 asm ("r1");
333 register uECC_word_t r2 asm ("r2");
334 register uECC_word_t r3 asm ("r3");
335 asm volatile (
336 ".syntax unified \n\t"
337 "LDMIA %[vli]!,{%[r1],%[r2],%[r3]} \n\t"
338 "ORRS %[r1],%[r2] \n\t"
339 "ORRS %[r1],%[r3] \n\t"
340 "LDMIA %[vli]!,{%[r2],%[r3]} \n\t"
341 "ORRS %[r1],%[r2] \n\t"
342 "ORRS %[r1],%[r3] \n\t"
343 "LDMIA %[vli],{%[vli],%[r2],%[r3]} \n\t"
344 "ORRS %[r1],%[vli] \n\t"
345 "ORRS %[r1],%[r2] \n\t"
346 "ORRS %[r1],%[r3] \n\t"
347 "RSBS %[r1],%[r1],#0 \n\t" // C set if zero
348 "MOVS %[ret],#0 \n\t"
349 "ADCS %[ret],r0 \n\t"
350 : [ret]"=r" (ret), [r1]"=r" (r1), [r2]"=r" (r2), [r3]"=r" (r3)
351 : [vli]"[ret]" (vli)
352 : "cc", "memory"
353 );
354#else
355 register uECC_word_t r1 asm ("r1");
356 register uECC_word_t r2 asm ("r2");
357 register uECC_word_t r3 asm ("r3");
358 register uECC_word_t ip asm ("ip");
359 asm volatile (
360 "LDMIA %[vli]!,{%[r1],%[r2],%[r3],%[ip]}\n\t"
361 "ORRS %[r1],%[r2] \n\t"
362 "ORRS %[r1],%[r3] \n\t"
363 "ORRS %[r1],%[ip] \n\t"
364 "LDMIA %[vli],{%[vli],%[r2],%[r3],%[ip]}\n\t"
365 "ORRS %[r1],%[vli] \n\t"
366 "ORRS %[r1],%[r2] \n\t"
367 "ORRS %[r1],%[r3] \n\t"
368 "ORRS %[r1],%[ip] \n\t"
369#if __ARM_ARCH >= 5
370 "CLZ %[ret],%[r1] \n\t" // r0 = 32 if zero
371 "LSRS %[ret],%[ret],#5 \n\t"
372#else
373 "RSBS %[r1],%[r1],#0 \n\t" // C set if zero
374 "MOVS %[ret],#0 \n\t"
375 "ADCS %[ret],r0 \n\t"
376#endif
377 : [ret]"=r" (ret), [r1]"=r" (r1), [r2]"=r" (r2), [r3]"=r" (r3), [ip]"=r" (ip)
378 : [vli]"[ret]" (vli)
379 : "cc", "memory"
380 );
381#endif
382 return ret;
383}
384#else
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100385uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300386{
387 uECC_word_t bits = 0;
388 wordcount_t i;
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100389 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300390 bits |= vli[i];
391 }
392 return (bits == 0);
393}
Kevin Bracey3be252e2020-10-09 12:54:48 +0300394#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300395
396uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit)
397{
398 return (vli[bit >> uECC_WORD_BITS_SHIFT] &
399 ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
400}
401
402/* Counts the number of words in vli. */
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100403static wordcount_t vli_numDigits(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300404{
405
406 wordcount_t i;
407 /* Search from the end until we find a non-zero digit. We do it in reverse
408 * because we expect that most digits will be nonzero. */
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100409 for (i = NUM_ECC_WORDS - 1; i >= 0 && vli[i] == 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300410 }
411
412 return (i + 1);
413}
414
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100415bitcount_t uECC_vli_numBits(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300416{
417
418 uECC_word_t i;
419 uECC_word_t digit;
420
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100421 wordcount_t num_digits = vli_numDigits(vli);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300422 if (num_digits == 0) {
423 return 0;
424 }
425
426 digit = vli[num_digits - 1];
427 for (i = 0; digit; ++i) {
428 digit >>= 1;
429 }
430
431 return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
432}
433
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100434void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300435{
436 wordcount_t i;
437
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100438 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300439 dest[i] = src[i];
440 }
441}
442
443cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100444 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300445{
446 wordcount_t i;
447
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100448 for (i = NUM_ECC_WORDS - 1; i >= 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300449 if (left[i] > right[i]) {
450 return 1;
451 } else if (left[i] < right[i]) {
452 return -1;
453 }
454 }
455 return 0;
456}
457
Manuel Pégourié-Gonnard2eca3d32019-11-04 14:33:09 +0100458uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300459{
460
461 uECC_word_t diff = 0;
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200462 uECC_word_t flow_monitor = 0;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100463 uECC_word_t tmp1, tmp2;
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100464 volatile int i;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300465
Piotr Nowickif0ab6d62020-05-25 12:48:30 +0200466 /* Start from a random location and check the correct number of iterations */
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200467 int start_offset = mbedtls_platform_random_in_range(NUM_ECC_WORDS);
468
469 for (i = start_offset; i < NUM_ECC_WORDS; ++i) {
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100470 tmp1 = left[i];
471 tmp2 = right[i];
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200472 flow_monitor++;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100473 diff |= (tmp1 ^ tmp2);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300474 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100475
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200476 for (i = 0; i < start_offset; ++i) {
477 tmp1 = left[i];
478 tmp2 = right[i];
479 flow_monitor++;
480 diff |= (tmp1 ^ tmp2);
481 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100482
Piotr Nowickif0ab6d62020-05-25 12:48:30 +0200483 /* Random delay to increase security */
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200484 mbedtls_platform_random_delay();
485
486 /* Return 0 only when diff is 0 and flow_counter is equal to NUM_ECC_WORDS */
487 return (diff | (flow_monitor ^ NUM_ECC_WORDS));
Jarno Lamsa18987a42019-04-24 15:40:43 +0300488}
489
490uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
491{
492 return (p_true*(cond)) | (p_false*(!cond));
493}
494
495/* Computes result = left - right, returning borrow, in constant time.
496 * Can modify in place. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300497#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
498__asm uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
499 const uECC_word_t *right)
500{
501#if NUM_ECC_WORDS != 8
502#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
503#endif
504#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
505 PUSH {r4-r6,lr}
506 FRAME PUSH {r4-r6,lr}
507 LDMIA r1!,{r3,r4}
508 LDMIA r2!,{r5,r6}
509 SUBS r3,r5
510 SBCS r4,r6
511 STMIA r0!,{r3,r4}
512 LDMIA r1!,{r3,r4}
513 LDMIA r2!,{r5,r6}
514 SBCS r3,r5
515 SBCS r4,r6
516 STMIA r0!,{r3,r4}
517 LDMIA r1!,{r3,r4}
518 LDMIA r2!,{r5,r6}
519 SBCS r3,r5
520 SBCS r4,r6
521 STMIA r0!,{r3,r4}
522 LDMIA r1!,{r3,r4}
523 LDMIA r2!,{r5,r6}
524 SBCS r3,r5
525 SBCS r4,r6
526 STMIA r0!,{r3,r4}
527 SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow
528 RSBS r0,r0,#0 // r0 := borrow
529 POP {r4-r6,pc}
530#else
531 PUSH {r4-r8,lr}
532 FRAME PUSH {r4-r8,lr}
533 LDMIA r1!,{r3-r6}
534 LDMIA r2!,{r7,r8,r12,lr}
535 SUBS r3,r7
536 SBCS r4,r8
537 SBCS r5,r12
538 SBCS r6,lr
539 STMIA r0!,{r3-r6}
540 LDMIA r1!,{r3-r6}
541 LDMIA r2!,{r7,r8,r12,lr}
542 SBCS r3,r7
543 SBCS r4,r8
544 SBCS r5,r12
545 SBCS r6,lr
546 STMIA r0!,{r3-r6}
547 SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow
548 RSBS r0,r0,#0 // r0 := borrow
549 POP {r4-r8,pc}
550#endif
551}
Kevin Bracey4aea6252020-10-09 12:54:28 +0300552#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
553uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
554 const uECC_word_t *right)
555{
556#if NUM_ECC_WORDS != 8
557#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
558#endif
559 register uECC_word_t *r0 asm ("r0") = result;
560 register const uECC_word_t *r1 asm ("r1") = left;
561 register const uECC_word_t *r2 asm ("r2") = right;
562 asm volatile (
563#if defined __thumb__ && !defined __thumb2__
564 ".syntax unified \n\t"
565 "LDMIA r1!,{r3,r4} \n\t"
566 "LDMIA r2!,{r5,r6} \n\t"
567 "SUBS r3,r5 \n\t"
568 "SBCS r4,r6 \n\t"
569 "STMIA r0!,{r3,r4} \n\t"
570 "LDMIA r1!,{r3,r4} \n\t"
571 "LDMIA r2!,{r5,r6} \n\t"
572 "SBCS r3,r5 \n\t"
573 "SBCS r4,r6 \n\t"
574 "STMIA r0!,{r3,r4} \n\t"
575 "LDMIA r1!,{r3,r4} \n\t"
576 "LDMIA r2!,{r5,r6} \n\t"
577 "SBCS r3,r5 \n\t"
578 "SBCS r4,r6 \n\t"
579 "STMIA r0!,{r3,r4} \n\t"
580 "LDMIA r1!,{r3,r4} \n\t"
581 "LDMIA r2!,{r5,r6} \n\t"
582 "SBCS r3,r5 \n\t"
583 "SBCS r4,r6 \n\t"
584 "STMIA r0!,{r3,r4} \n\t"
585 "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow
586 "RSBS r0,r0,#0 \n\t" // r0 := borrow
587 : "+r" (r0), "+r" (r1), "+r" (r2)
588 :
589 : "r3", "r4", "r5", "r6", "cc", "memory"
590#else
591 "LDMIA r1!,{r3-r6} \n\t"
592 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
593 "SUBS r3,r7 \n\t"
594 "SBCS r4,r8 \n\t"
595 "SBCS r5,r12 \n\t"
596 "SBCS r6,lr \n\t"
597 "STMIA r0!,{r3-r6} \n\t"
598 "LDMIA r1!,{r3-r6} \n\t"
599 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
600 "SBCS r3,r7 \n\t"
601 "SBCS r4,r8 \n\t"
602 "SBCS r5,r12 \n\t"
603 "SBCS r6,lr \n\t"
604 "STMIA r0!,{r3-r6} \n\t"
605 "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow
606 "RSBS r0,r0,#0 \n\t" // r0 := borrow
607 : "+r" (r0), "+r" (r1), "+r" (r2)
608 :
609 : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory"
610#endif
611 );
612 return (uECC_word_t) r0;
613}
Kevin Bracey1959c182020-07-16 21:03:19 +0300614#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300615uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100616 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300617{
618 uECC_word_t borrow = 0;
619 wordcount_t i;
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100620 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300621 uECC_word_t diff = left[i] - right[i] - borrow;
622 uECC_word_t val = (diff > left[i]);
623 borrow = cond_set(val, borrow, (diff != left[i]));
624
625 result[i] = diff;
626 }
627 return borrow;
628}
Kevin Bracey1959c182020-07-16 21:03:19 +0300629#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300630
631/* Computes result = left + right, returning carry, in constant time.
632 * Can modify in place. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300633#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
634static __asm uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
635 const uECC_word_t *right)
636{
637#if NUM_ECC_WORDS != 8
638#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
639#endif
640#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
641 PUSH {r4-r6,lr}
642 FRAME PUSH {r4-r6,lr}
643 LDMIA r1!,{r3,r4}
644 LDMIA r2!,{r5,r6}
645 ADDS r3,r5
646 ADCS r4,r6
647 STMIA r0!,{r3,r4}
648 LDMIA r1!,{r3,r4}
649 LDMIA r2!,{r5,r6}
650 ADCS r3,r5
651 ADCS r4,r6
652 STMIA r0!,{r3,r4}
653 LDMIA r1!,{r3,r4}
654 LDMIA r2!,{r5,r6}
655 ADCS r3,r5
656 ADCS r4,r6
657 STMIA r0!,{r3,r4}
658 LDMIA r1!,{r3,r4}
659 LDMIA r2!,{r5,r6}
660 ADCS r3,r5
661 ADCS r4,r6
662 STMIA r0!,{r3,r4}
663 MOVS r0,#0 // does not affect C flag
664 ADCS r0,r0 // r0 := 0 + 0 + C = carry
665 POP {r4-r6,pc}
666#else
667 PUSH {r4-r8,lr}
668 FRAME PUSH {r4-r8,lr}
669 LDMIA r1!,{r3-r6}
670 LDMIA r2!,{r7,r8,r12,lr}
671 ADDS r3,r7
672 ADCS r4,r8
673 ADCS r5,r12
674 ADCS r6,lr
675 STMIA r0!,{r3-r6}
676 LDMIA r1!,{r3-r6}
677 LDMIA r2!,{r7,r8,r12,lr}
678 ADCS r3,r7
679 ADCS r4,r8
680 ADCS r5,r12
681 ADCS r6,lr
682 STMIA r0!,{r3-r6}
683 MOVS r0,#0 // does not affect C flag
684 ADCS r0,r0 // r0 := 0 + 0 + C = carry
685 POP {r4-r8,pc}
686#endif
687}
Kevin Bracey4aea6252020-10-09 12:54:28 +0300688#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
689static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
690 const uECC_word_t *right)
691{
692 register uECC_word_t *r0 asm ("r0") = result;
693 register const uECC_word_t *r1 asm ("r1") = left;
694 register const uECC_word_t *r2 asm ("r2") = right;
695
696 asm volatile (
697#if defined __thumb__ && !defined __thumb2__
698 ".syntax unified \n\t"
699 "LDMIA r1!,{r3,r4} \n\t"
700 "LDMIA r2!,{r5,r6} \n\t"
701 "ADDS r3,r5 \n\t"
702 "ADCS r4,r6 \n\t"
703 "STMIA r0!,{r3,r4} \n\t"
704 "LDMIA r1!,{r3,r4} \n\t"
705 "LDMIA r2!,{r5,r6} \n\t"
706 "ADCS r3,r5 \n\t"
707 "ADCS r4,r6 \n\t"
708 "STMIA r0!,{r3,r4} \n\t"
709 "LDMIA r1!,{r3,r4} \n\t"
710 "LDMIA r2!,{r5,r6} \n\t"
711 "ADCS r3,r5 \n\t"
712 "ADCS r4,r6 \n\t"
713 "STMIA r0!,{r3,r4} \n\t"
714 "LDMIA r1!,{r3,r4} \n\t"
715 "LDMIA r2!,{r5,r6} \n\t"
716 "ADCS r3,r5 \n\t"
717 "ADCS r4,r6 \n\t"
718 "STMIA r0!,{r3,r4} \n\t"
719 "MOVS r0,#0 \n\t" // does not affect C flag
720 "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry
721 : "+r" (r0), "+r" (r1), "+r" (r2)
722 :
723 : "r3", "r4", "r5", "r6", "cc", "memory"
724#else
725 "LDMIA r1!,{r3-r6} \n\t"
726 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
727 "ADDS r3,r7 \n\t"
728 "ADCS r4,r8 \n\t"
729 "ADCS r5,r12 \n\t"
730 "ADCS r6,lr \n\t"
731 "STMIA r0!,{r3-r6} \n\t"
732 "LDMIA r1!,{r3-r6} \n\t"
733 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
734 "ADCS r3,r7 \n\t"
735 "ADCS r4,r8 \n\t"
736 "ADCS r5,r12 \n\t"
737 "ADCS r6,lr \n\t"
738 "STMIA r0!,{r3-r6} \n\t"
739 "MOVS r0,#0 \n\t" // does not affect C flag
740 "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry
741 : "+r" (r0), "+r" (r1), "+r" (r2)
742 :
743 : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory"
744#endif
745 );
746 return (uECC_word_t) r0;
747}
Kevin Bracey1959c182020-07-16 21:03:19 +0300748#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300749static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100750 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300751{
752 uECC_word_t carry = 0;
753 wordcount_t i;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100754 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300755 uECC_word_t sum = left[i] + right[i] + carry;
756 uECC_word_t val = (sum < left[i]);
757 carry = cond_set(val, carry, (sum != left[i]));
758 result[i] = sum;
759 }
760 return carry;
761}
Kevin Bracey1959c182020-07-16 21:03:19 +0300762#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300763
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +0100764cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300765{
766 uECC_word_t tmp[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100767 uECC_word_t neg = !!uECC_vli_sub(tmp, left, right);
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100768 uECC_word_t equal = uECC_vli_isZero(tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300769 return (!equal - 2 * neg);
770}
771
772/* Computes vli = vli >> 1. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300773#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
774static __asm void uECC_vli_rshift1(uECC_word_t *vli)
775{
776#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
777// RRX instruction is not available, so although we
778// can use C flag, it's not that effective. Does at
779// least save one working register, meaning we don't need stack
780 MOVS r3,#0 // initial carry = 0
781 MOVS r2,#__cpp(4 * (NUM_ECC_WORDS - 1))
78201 LDR r1,[r0,r2]
783 LSRS r1,r1,#1 // r2 = word >> 1
784 ORRS r1,r3 // merge in the previous carry
785 STR r1,[r0,r2]
786 ADCS r3,r3 // put C into bottom bit of r3
787 LSLS r3,r3,#31 // shift it up to the top ready for next word
788 SUBS r2,r2,#4
789 BPL %B01
790 BX lr
791#else
792#if NUM_ECC_WORDS != 8
793#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
794#endif
795// Smooth multiword operation, lots of 32-bit instructions
796 ADDS r0,#32
797 LDMDB r0,{r1-r3,ip}
798 LSRS ip,ip,#1
799 RRXS r3,r3
800 RRXS r2,r2
801 RRXS r1,r1
802 STMDB r0!,{r1-r3,ip}
803 LDMDB r0,{r1-r3,ip}
804 RRXS ip,ip
805 RRXS r3,r3
806 RRXS r2,r2
807 RRX r1,r1
808 STMDB r0!,{r1-r3,ip}
809 BX lr
810#endif
811}
Kevin Bracey06060332020-10-02 17:43:12 +0300812#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__ && defined __thumb2__
813static void uECC_vli_rshift1(uECC_word_t *vli)
814{
815 register uECC_word_t *r0 asm ("r0") = vli;
816#if NUM_ECC_WORDS != 8
817#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
818#endif
819 asm volatile (
820 "ADDS r0,#32 \n\t"
821 "LDMDB r0,{r1-r3,ip} \n\t"
822 "LSRS ip,ip,#1 \n\t"
823 "RRXS r3,r3 \n\t"
824 "RRXS r2,r2 \n\t"
825 "RRXS r1,r1 \n\t"
826 "STMDB r0!,{r1-r3,ip} \n\t"
827 "LDMDB r0,{r1-r3,ip} \n\t"
828 "RRXS ip,ip \n\t"
829 "RRXS r3,r3 \n\t"
830 "RRXS r2,r2 \n\t"
831 "RRX r1,r1 \n\t"
832 "STMDB r0!,{r1-r3,ip} \n\t"
833 : "+r" (r0)
834 :
835 : "r1", "r2", "r3", "ip", "cc", "memory"
836 );
837}
Kevin Bracey1959c182020-07-16 21:03:19 +0300838#else
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100839static void uECC_vli_rshift1(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300840{
841 uECC_word_t *end = vli;
842 uECC_word_t carry = 0;
843
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100844 vli += NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300845 while (vli-- > end) {
846 uECC_word_t temp = *vli;
847 *vli = (temp >> 1) | carry;
848 carry = temp << (uECC_WORD_BITS - 1);
849 }
850}
Kevin Bracey1959c182020-07-16 21:03:19 +0300851#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300852
Kevin Bracey84f31d32020-09-29 17:51:04 +0300853/* Compute a * b + r, where r is a triple-word with high-order word r[2] and
854 * low-order word r[0], and store the result in the same triple-word.
Manuel Pégourié-Gonnard86c4f812019-10-31 13:02:03 +0100855 *
Kevin Bracey84f31d32020-09-29 17:51:04 +0300856 * r[2..0] = a * b + r[2..0]:
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200857 * [in] a, b: operands to be multiplied
Kevin Bracey84f31d32020-09-29 17:51:04 +0300858 * [in] r: 3 words of operand to add
859 * [out] r: 3 words of result
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200860 */
Kevin Bracey1959c182020-07-16 21:03:19 +0300861#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
Kevin Bracey84f31d32020-09-29 17:51:04 +0300862static __asm void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Bracey1959c182020-07-16 21:03:19 +0300863{
864#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
Kevin Bracey84f31d32020-09-29 17:51:04 +0300865 PUSH {r4-r5}
866 FRAME PUSH {r4-r5}
867 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
868 // Separate operands into halfwords
869 UXTH r3,r0 // r3 := a.lo
870 LSRS r4,r0,#16 // r4 := a.hi
871 UXTH r5,r1 // r5 := b.lo
872 LSRS r1,r1,#16 // r1 := b.hi
873 // Multiply halfword pairs
874 MOVS r0,r3
875 MULS r0,r5,r0 // r0 := a.lo * b.lo
876 MULS r3,r1,r3 // r3 := a.lo * b.hi
877 MULS r5,r4,r5 // r5 := a.hi * b.lo
878 MULS r1,r4,r1 // r1 := a.hi * b.hi
879 // Split, shift and add a.lo * b.hi
880 LSRS r4,r3,#16 // r4 := (a.lo * b.hi).hi
881 LSLS r3,r3,#16 // r3 := (a.lo * b.hi).lo
882 ADDS r0,r0,r3 // r0 := a.lo * b.lo + (a.lo * b.hi).lo
883 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
884 // Split, shift and add a.hi * b.lo
885 LSRS r4,r5,#16 // r4 := (a.hi * b.lo).hi
886 LSLS r5,r5,#16 // r5 := (a.hi * b.lo).lo
887 ADDS r0,r0,r5 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
888 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
889 // Finally add r[]
890 LDMIA r2!,{r3,r4,r5}
891 ADDS r3,r3,r0
Kevin Bracey1959c182020-07-16 21:03:19 +0300892 ADCS r4,r1
Kevin Bracey1959c182020-07-16 21:03:19 +0300893 MOVS r0,#0
Kevin Bracey84f31d32020-09-29 17:51:04 +0300894 ADCS r5,r0
895 SUBS r2,#12
896 STMIA r2!,{r3,r4,r5}
897 POP {r4-r5}
898 FRAME POP {r4-r5}
899 BX lr
Kevin Bracey1959c182020-07-16 21:03:19 +0300900#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300901 UMULL r3,ip,r0,r1 // pre-ARMv6 requires Rd[Lo|Hi] != Rn
902 LDMIA r2,{r0,r1}
903 ADDS r0,r0,r3
904 LDR r3,[r2,#8]
905 ADCS r1,r1,ip
906 ADC r3,r3,#0
907 STMIA r2!,{r0,r1,r3}
Kevin Bracey1959c182020-07-16 21:03:19 +0300908 BX lr
909#endif
Kevin Braceye0f88d52020-09-30 12:52:15 +0300910}
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300911#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
912static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Braceye0f88d52020-09-30 12:52:15 +0300913{
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300914 register uECC_word_t r0 asm ("r0") = a;
915 register uECC_word_t r1 asm ("r1") = b;
916 register uECC_word_t *r2 asm ("r2") = r;
917 asm volatile (
Kevin Braceye0f88d52020-09-30 12:52:15 +0300918#if defined __thumb__ && !defined(__thumb2__)
919 ".syntax unified \n\t"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300920 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
921 // Separate operands into halfwords
922 "UXTH r3,r0 \n\t" // r3 := a.lo
923 "LSRS r4,r0,#16 \n\t" // r4 := a.hi
924 "UXTH r5,r1 \n\t" // r5 := b.lo
925 "LSRS r1,r1,#16 \n\t" // r1 := b.hi
926 // Multiply halfword pairs
927 "MOVS r0,r3 \n\t"
928 "MULS r0,r5,r0 \n\t" // r0 := a.lo * b.lo
929 "MULS r3,r1,r3 \n\t" // r3 := a.lo * b.hi
930 "MULS r5,r4,r5 \n\t" // r5 := a.hi * b.lo
931 "MULS r1,r4,r1 \n\t" // r1 := a.hi * b.hi
932 // Split, shift and add a.lo * b.hi
933 "LSRS r4,r3,#16 \n\t" // r4 := (a.lo * b.hi).hi
934 "LSLS r3,r3,#16 \n\t" // r3 := (a.lo * b.hi).lo
935 "ADDS r0,r0,r3 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo
936 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
937 // Split, shift and add a.hi * b.lo
938 "LSRS r4,r5,#16 \n\t" // r4 := (a.hi * b.lo).hi
939 "LSLS r5,r5,#16 \n\t" // r5 := (a.hi * b.lo).lo
940 "ADDS r0,r0,r5 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
941 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
942 // Finally add r[]
943 "LDMIA r2!,{r3,r4,r5} \n\t"
944 "ADDS r3,r3,r0 \n\t"
945 "ADCS r4,r1 \n\t"
946 "MOVS r0,#0 \n\t"
947 "ADCS r5,r0 \n\t"
948 "SUBS r2,#12 \n\t"
949 "STMIA r2!,{r3,r4,r5} \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300950 : "+r" (r0), "+r" (r1), "+r" (r2)
951 :
952 : "r3", "r4", "r5", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300953#else
954 "UMULL r3,ip,r0,r1 \n\t" // pre-ARMv6 requires Rd[Lo|Hi] != Rn
955 "LDMIA r2,{r0,r1} \n\t"
956 "ADDS r0,r0,r3 \n\t"
957 "LDR r3,[r2,#8] \n\t"
958 "ADCS r1,r1,ip \n\t"
959 "ADC r3,r3,#0 \n\t"
960 "STMIA r2!,{r0,r1,r3} \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300961 : "+r" (r0), "+r" (r1), "+r" (r2)
962 :
963 : "r3", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300964#endif
965 );
Kevin Bracey1959c182020-07-16 21:03:19 +0300966}
967#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300968static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Jarno Lamsa18987a42019-04-24 15:40:43 +0300969{
970
971 uECC_dword_t p = (uECC_dword_t)a * b;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300972 uECC_dword_t r01 = ((uECC_dword_t)(r[1]) << uECC_WORD_BITS) | r[0];
Jarno Lamsa18987a42019-04-24 15:40:43 +0300973 r01 += p;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300974 r[2] += (r01 < p);
975 r[1] = r01 >> uECC_WORD_BITS;
976 r[0] = (uECC_word_t)r01;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300977}
Kevin Bracey1959c182020-07-16 21:03:19 +0300978#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300979
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200980/* State for implementing random delays in uECC_vli_mult_rnd().
981 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100982 * The state is initialized by randomizing delays and setting i = 0.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200983 * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i.
984 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100985 * Randomized vli multiplication is used only for point operations
986 * (XYcZ_add_rnd() * and XYcZ_addC_rnd()) in scalar multiplication
987 * (ECCPoint_mult()). Those go in pair, and each pair does 14 calls to
988 * uECC_vli_mult_rnd() (6 in XYcZ_add_rnd() and 8 in XYcZ_addC_rnd(),
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100989 * indirectly through uECC_vli_modMult_rnd().
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100990 *
991 * Considering this, in order to minimize the number of calls to the RNG
992 * (which impact performance) while keeping the size of the structure low,
993 * make room for 14 randomized vli mults, which corresponds to one step in the
994 * scalar multiplication routine.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200995 */
996typedef struct {
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100997 uint8_t i;
998 uint8_t delays[14];
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100999} ecc_wait_state_t;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001000
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001001/*
1002 * Reset wait_state so that it's ready to be used.
1003 */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001004void ecc_wait_state_reset(ecc_wait_state_t *ws)
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001005{
1006 if (ws == NULL)
1007 return;
1008
1009 ws->i = 0;
Shelly Liberman05beb9a2020-09-13 15:23:56 +03001010 mbedtls_platform_random_buf(ws->delays, sizeof(ws->delays));
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001011}
1012
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001013/* Computes result = left * right. Result must be 2 * num_words long.
1014 *
1015 * As a counter-measure against horizontal attacks, add noise by performing
1016 * a random number of extra computations performing random additional accesses
1017 * to limbs of the input.
1018 *
1019 * Each of the two actual computation loops is surrounded by two
1020 * similar-looking waiting loops, to make the beginning and end of the actual
1021 * computation harder to spot.
1022 *
1023 * We add 4 waiting loops of between 0 and 3 calls to muladd() each. That
1024 * makes an average of 6 extra calls. Compared to the main computation which
1025 * makes 64 such calls, this represents an average performance degradation of
1026 * less than 10%.
1027 *
1028 * Compared to the original uECC_vli_mult(), loose the num_words argument as we
1029 * know it's always 8. This saves a bit of code size and execution speed.
1030 */
1031static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001032 const uECC_word_t *right, ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001033{
1034
Kevin Bracey84f31d32020-09-29 17:51:04 +03001035 uECC_word_t r[3] = { 0, 0, 0 };
Jarno Lamsa18987a42019-04-24 15:40:43 +03001036 wordcount_t i, k;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001037 const uint8_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001038
1039 /* Fetch 8 bit worth of delay from the state; 0 if we have no state */
1040 uint8_t delays = s ? s->delays[s->i++] : 0;
Kevin Bracey84f31d32020-09-29 17:51:04 +03001041 uECC_word_t rr[3] = { 0, 0, 0 };
1042 volatile uECC_word_t rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001043
1044 /* Mimic start of next loop: k in [0, 3] */
1045 k = 0 + (delays & 0x03);
1046 delays >>= 2;
1047 /* k = 0 -> i in [1, 0] -> 0 extra muladd;
1048 * k = 3 -> i in [1, 3] -> 3 extra muladd */
Manuel Pégourié-Gonnardc8814862019-11-05 10:32:37 +01001049 for (i = 1; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001050 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001051 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001052 rdummy = rr[0];
1053 rr[0] = rr[1];
1054 rr[1] = rr[2];
1055 rr[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001056
1057 /* Compute each digit of result in sequence, maintaining the carries. */
1058 for (k = 0; k < num_words; ++k) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001059 for (i = 0; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001060 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001061 }
1062
Kevin Bracey84f31d32020-09-29 17:51:04 +03001063 result[k] = r[0];
1064 r[0] = r[1];
1065 r[1] = r[2];
1066 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001067 }
1068
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001069 /* Mimic end of previous loop: k in [4, 7] */
1070 k = 4 + (delays & 0x03);
1071 delays >>= 2;
1072 /* k = 4 -> i in [5, 4] -> 0 extra muladd;
1073 * k = 7 -> i in [5, 7] -> 3 extra muladd */
1074 for (i = 5; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001075 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001076 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001077 rdummy = rr[0];
1078 rr[0] = rr[1];
1079 rr[1] = rr[2];
1080 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001081
1082 /* Mimic start of next loop: k in [8, 11] */
1083 k = 11 - (delays & 0x03);
1084 delays >>= 2;
1085 /* k = 8 -> i in [5, 7] -> 3 extra muladd;
1086 * k = 11 -> i in [8, 7] -> 0 extra muladd */
1087 for (i = (k + 5) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001088 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001089 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001090 rdummy = rr[0];
1091 rr[0] = rr[1];
1092 rr[1] = rr[2];
1093 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001094
Jarno Lamsa18987a42019-04-24 15:40:43 +03001095 for (k = num_words; k < num_words * 2 - 1; ++k) {
1096
1097 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001098 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001099 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001100 result[k] = r[0];
1101 r[0] = r[1];
1102 r[1] = r[2];
1103 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001104 }
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001105
Kevin Bracey84f31d32020-09-29 17:51:04 +03001106 result[num_words * 2 - 1] = r[0];
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001107
1108 /* Mimic end of previous loop: k in [12, 15] */
1109 k = 15 - (delays & 0x03);
1110 delays >>= 2;
1111 /* k = 12 -> i in [5, 7] -> 3 extra muladd;
1112 * k = 15 -> i in [8, 7] -> 0 extra muladd */
1113 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001114 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001115 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001116 rdummy = rr[0];
1117 rr[0] = rr[1];
1118 rr[1] = rr[2];
1119 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001120
Kevin Bracey84f31d32020-09-29 17:51:04 +03001121 /* avoid warning that rdummy is set but not used */
1122 (void) rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001123}
1124
Jarno Lamsa18987a42019-04-24 15:40:43 +03001125void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001126 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001127{
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001128 uECC_word_t carry = uECC_vli_add(result, left, right);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001129 if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001130 /* result > mod (result = mod + remainder), so subtract mod to get
1131 * remainder. */
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001132 uECC_vli_sub(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001133 }
1134}
1135
1136void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001137 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001138{
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001139 uECC_word_t l_borrow = uECC_vli_sub(result, left, right);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001140 if (l_borrow) {
1141 /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
1142 * we can get the correct result from result + mod (with overflow). */
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001143 uECC_vli_add(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001144 }
1145}
1146
1147/* Computes result = product % mod, where product is 2N words long. */
1148/* Currently only designed to work for curve_p or curve_n. */
1149void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001150 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001151{
1152 uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
1153 uECC_word_t tmp[2 * NUM_ECC_WORDS];
1154 uECC_word_t *v[2] = {tmp, product};
1155 uECC_word_t index;
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +01001156 const wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001157
1158 /* Shift mod so its highest set bit is at the maximum position. */
1159 bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001160 uECC_vli_numBits(mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001161 wordcount_t word_shift = shift / uECC_WORD_BITS;
1162 wordcount_t bit_shift = shift % uECC_WORD_BITS;
1163 uECC_word_t carry = 0;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001164 uECC_vli_clear(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001165 if (bit_shift > 0) {
1166 for(index = 0; index < (uECC_word_t)num_words; ++index) {
1167 mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
1168 carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
1169 }
1170 } else {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001171 uECC_vli_set(mod_multiple + word_shift, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001172 }
1173
1174 for (index = 1; shift >= 0; --shift) {
1175 uECC_word_t borrow = 0;
1176 wordcount_t i;
1177 for (i = 0; i < num_words * 2; ++i) {
1178 uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
1179 if (diff != v[index][i]) {
1180 borrow = (diff > v[index][i]);
1181 }
1182 v[1 - index][i] = diff;
1183 }
1184 /* Swap the index if there was no borrow */
1185 index = !(index ^ borrow);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001186 uECC_vli_rshift1(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001187 mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
Andrzej Kurek0919b142020-07-06 15:28:59 -04001188 (uECC_WORD_BITS - 1);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001189 uECC_vli_rshift1(mod_multiple + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001190 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001191 uECC_vli_set(result, v[index]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001192}
1193
1194void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001195 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001196{
1197 uECC_word_t product[2 * NUM_ECC_WORDS];
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001198 uECC_vli_mult_rnd(product, left, right, NULL);
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +01001199 uECC_vli_mmod(result, product, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001200}
1201
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001202static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001203 const uECC_word_t *right, ecc_wait_state_t *s)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001204{
1205 uECC_word_t product[2 * NUM_ECC_WORDS];
1206 uECC_vli_mult_rnd(product, left, right, s);
1207
1208 vli_mmod_fast_secp256r1(result, product);
1209}
1210
Jarno Lamsa18987a42019-04-24 15:40:43 +03001211void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001212 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001213{
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001214 uECC_vli_modMult_rnd(result, left, right, NULL);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001215}
1216
Jarno Lamsa18987a42019-04-24 15:40:43 +03001217#define EVEN(vli) (!(vli[0] & 1))
1218
1219static void vli_modInv_update(uECC_word_t *uv,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001220 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001221{
1222
1223 uECC_word_t carry = 0;
1224
1225 if (!EVEN(uv)) {
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001226 carry = uECC_vli_add(uv, uv, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001227 }
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001228 uECC_vli_rshift1(uv);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001229 if (carry) {
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +01001230 uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001231 }
1232}
1233
1234void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001235 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001236{
1237 uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
1238 uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
1239 cmpresult_t cmpResult;
1240
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001241 if (uECC_vli_isZero(input)) {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001242 uECC_vli_clear(result);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001243 return;
1244 }
1245
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001246 uECC_vli_set(a, input);
1247 uECC_vli_set(b, mod);
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001248 uECC_vli_clear(u);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001249 u[0] = 1;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001250 uECC_vli_clear(v);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001251 while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001252 if (EVEN(a)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001253 uECC_vli_rshift1(a);
Andrzej Kurek0919b142020-07-06 15:28:59 -04001254 vli_modInv_update(u, mod);
1255 } else if (EVEN(b)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001256 uECC_vli_rshift1(b);
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +01001257 vli_modInv_update(v, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001258 } else if (cmpResult > 0) {
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001259 uECC_vli_sub(a, a, b);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001260 uECC_vli_rshift1(a);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001261 if (uECC_vli_cmp_unsafe(u, v) < 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001262 uECC_vli_add(u, u, mod);
1263 }
1264 uECC_vli_sub(u, u, v);
1265 vli_modInv_update(u, mod);
1266 } else {
1267 uECC_vli_sub(b, b, a);
1268 uECC_vli_rshift1(b);
1269 if (uECC_vli_cmp_unsafe(v, u) < 0) {
1270 uECC_vli_add(v, v, mod);
1271 }
1272 uECC_vli_sub(v, v, u);
1273 vli_modInv_update(v, mod);
1274 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001275 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001276 uECC_vli_set(result, u);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001277}
1278
1279/* ------ Point operations ------ */
1280
1281void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001282 uECC_word_t * Z1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001283{
1284 /* t1 = X, t2 = Y, t3 = Z */
1285 uECC_word_t t4[NUM_ECC_WORDS];
1286 uECC_word_t t5[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001287 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001288
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001289 if (uECC_vli_isZero(Z1)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001290 return;
1291 }
1292
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001293 uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */
1294 uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */
1295 uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */
1296 uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */
1297 uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001298
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001299 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = x1 + z1^2 */
1300 uECC_vli_modAdd(Z1, Z1, Z1, curve_p); /* t3 = 2*z1^2 */
1301 uECC_vli_modSub(Z1, X1, Z1, curve_p); /* t3 = x1 - z1^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001302 uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001303
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001304 uECC_vli_modAdd(Z1, X1, X1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
1305 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001306 if (uECC_vli_testBit(X1, 0)) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001307 uECC_word_t l_carry = uECC_vli_add(X1, X1, curve_p);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001308 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001309 X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
1310 } else {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001311 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001312 }
1313
1314 /* t1 = 3/2*(x1^2 - z1^4) = B */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001315 uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001316 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - A */
1317 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
1318 uECC_vli_modSub(t5, t5, Z1, curve_p); /* t5 = A - x3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001319 uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001320 /* t4 = B * (A - x3) - y1^4 = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001321 uECC_vli_modSub(t4, X1, t4, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001322
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001323 uECC_vli_set(X1, Z1);
1324 uECC_vli_set(Z1, Y1);
1325 uECC_vli_set(Y1, t4);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001326}
1327
Manuel Pégourié-Gonnard1c6f7ea2019-11-21 09:18:29 +01001328/*
1329 * @brief Computes x^3 + ax + b. result must not overlap x.
1330 * @param result OUT -- x^3 + ax + b
1331 * @param x IN -- value of x
1332 * @param curve IN -- elliptic curve
1333 */
1334static void x_side_default(uECC_word_t *result,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001335 const uECC_word_t *x)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001336{
1337 uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001338
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001339 uECC_vli_modMult_fast(result, x, x); /* r = x^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001340 uECC_vli_modSub(result, result, _3, curve_p); /* r = x^2 - 3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001341 uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001342 /* r = x^3 - 3x + b: */
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +01001343 uECC_vli_modAdd(result, result, curve_b, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001344}
1345
1346void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
1347{
1348 unsigned int tmp[NUM_ECC_WORDS];
1349 int carry;
1350
1351 /* t */
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001352 uECC_vli_set(result, product);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001353
1354 /* s1 */
1355 tmp[0] = tmp[1] = tmp[2] = 0;
1356 tmp[3] = product[11];
1357 tmp[4] = product[12];
1358 tmp[5] = product[13];
1359 tmp[6] = product[14];
1360 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001361 carry = uECC_vli_add(tmp, tmp, tmp);
1362 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001363
1364 /* s2 */
1365 tmp[3] = product[12];
1366 tmp[4] = product[13];
1367 tmp[5] = product[14];
1368 tmp[6] = product[15];
1369 tmp[7] = 0;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001370 carry += uECC_vli_add(tmp, tmp, tmp);
1371 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001372
1373 /* s3 */
1374 tmp[0] = product[8];
1375 tmp[1] = product[9];
1376 tmp[2] = product[10];
1377 tmp[3] = tmp[4] = tmp[5] = 0;
1378 tmp[6] = product[14];
1379 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001380 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001381
1382 /* s4 */
1383 tmp[0] = product[9];
1384 tmp[1] = product[10];
1385 tmp[2] = product[11];
1386 tmp[3] = product[13];
1387 tmp[4] = product[14];
1388 tmp[5] = product[15];
1389 tmp[6] = product[13];
1390 tmp[7] = product[8];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001391 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001392
1393 /* d1 */
1394 tmp[0] = product[11];
1395 tmp[1] = product[12];
1396 tmp[2] = product[13];
1397 tmp[3] = tmp[4] = tmp[5] = 0;
1398 tmp[6] = product[8];
1399 tmp[7] = product[10];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001400 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001401
1402 /* d2 */
1403 tmp[0] = product[12];
1404 tmp[1] = product[13];
1405 tmp[2] = product[14];
1406 tmp[3] = product[15];
1407 tmp[4] = tmp[5] = 0;
1408 tmp[6] = product[9];
1409 tmp[7] = product[11];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001410 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001411
1412 /* d3 */
1413 tmp[0] = product[13];
1414 tmp[1] = product[14];
1415 tmp[2] = product[15];
1416 tmp[3] = product[8];
1417 tmp[4] = product[9];
1418 tmp[5] = product[10];
1419 tmp[6] = 0;
1420 tmp[7] = product[12];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001421 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001422
1423 /* d4 */
1424 tmp[0] = product[14];
1425 tmp[1] = product[15];
1426 tmp[2] = 0;
1427 tmp[3] = product[9];
1428 tmp[4] = product[10];
1429 tmp[5] = product[11];
1430 tmp[6] = 0;
1431 tmp[7] = product[13];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001432 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001433
1434 if (carry < 0) {
1435 do {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001436 carry += uECC_vli_add(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001437 }
1438 while (carry < 0);
1439 } else {
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +02001440 while (carry ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001441 uECC_vli_cmp_unsafe(curve_p, result) != 1) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001442 carry -= uECC_vli_sub(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001443 }
1444 }
1445}
1446
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001447uECC_word_t EccPoint_isZero(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001448{
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001449 return uECC_vli_isZero(point);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001450}
1451
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001452void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001453{
1454 uECC_word_t t1[NUM_ECC_WORDS];
1455
Andrzej Kurek0919b142020-07-06 15:28:59 -04001456 uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001457 uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */
1458 uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */
1459 uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001460}
1461
1462/* P = (x1, y1) => 2P, (x2, y2) => P' */
1463static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
1464 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001465 const uECC_word_t * const initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001466{
1467 uECC_word_t z[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001468 if (initial_Z) {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001469 uECC_vli_set(z, initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001470 } else {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001471 uECC_vli_clear(z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001472 z[0] = 1;
1473 }
1474
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001475 uECC_vli_set(X2, X1);
1476 uECC_vli_set(Y2, Y1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001477
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001478 apply_z(X1, Y1, z);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001479 double_jacobian_default(X1, Y1, z);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001480 apply_z(X2, Y2, z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001481}
1482
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001483static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1484 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001485 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001486{
1487 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1488 uECC_word_t t5[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001489
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001490 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001491 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001492 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1493 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001494 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001495 uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001496
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001497 uECC_vli_modSub(t5, t5, X1, curve_p); /* t5 = D - B */
1498 uECC_vli_modSub(t5, t5, X2, curve_p); /* t5 = D - B - C = x3 */
1499 uECC_vli_modSub(X2, X2, X1, curve_p); /* t3 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001500 uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001501 uECC_vli_modSub(X2, X1, t5, curve_p); /* t3 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001502 uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001503 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001504
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001505 uECC_vli_set(X2, t5);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001506}
1507
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001508void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001509 uECC_word_t * X2, uECC_word_t * Y2)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001510{
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001511 XYcZ_add_rnd(X1, Y1, X2, Y2, NULL);
1512}
1513
Jarno Lamsa18987a42019-04-24 15:40:43 +03001514/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
1515 Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
1516 or P => P - Q, Q => P + Q
1517 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001518static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1519 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001520 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001521{
1522 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1523 uECC_word_t t5[NUM_ECC_WORDS];
1524 uECC_word_t t6[NUM_ECC_WORDS];
1525 uECC_word_t t7[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001526
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001527 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001528 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001529 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1530 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001531 uECC_vli_modAdd(t5, Y2, Y1, curve_p); /* t5 = y2 + y1 */
1532 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001533
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001534 uECC_vli_modSub(t6, X2, X1, curve_p); /* t6 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001535 uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001536 uECC_vli_modAdd(t6, X1, X2, curve_p); /* t6 = B + C */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001537 uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001538 uECC_vli_modSub(X2, X2, t6, curve_p); /* t3 = D - (B + C) = x3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001539
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001540 uECC_vli_modSub(t7, X1, X2, curve_p); /* t7 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001541 uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001542 /* t4 = (y2 - y1)*(B - x3) - E = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001543 uECC_vli_modSub(Y2, Y2, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001544
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001545 uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001546 uECC_vli_modSub(t7, t7, t6, curve_p); /* t7 = F - (B + C) = x3' */
1547 uECC_vli_modSub(t6, t7, X1, curve_p); /* t6 = x3' - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001548 uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001549 /* t2 = (y2+y1)*(x3' - B) - E = y3': */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001550 uECC_vli_modSub(Y1, t6, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001551
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001552 uECC_vli_set(X1, t7);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001553}
1554
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001555static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
Jarno Lamsa18987a42019-04-24 15:40:43 +03001556 const uECC_word_t * scalar,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001557 const uECC_word_t * initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001558{
1559 /* R0 and R1 */
1560 uECC_word_t Rx[2][NUM_ECC_WORDS];
1561 uECC_word_t Ry[2][NUM_ECC_WORDS];
1562 uECC_word_t z[NUM_ECC_WORDS];
1563 bitcount_t i;
1564 uECC_word_t nb;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001565 const wordcount_t num_words = NUM_ECC_WORDS;
1566 const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001567 ecc_wait_state_t wait_state;
1568 ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001569
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001570 uECC_vli_set(Rx[1], point);
1571 uECC_vli_set(Ry[1], point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001572
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001573 XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001574
1575 for (i = num_bits - 2; i > 0; --i) {
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001576 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001577 nb = !uECC_vli_testBit(scalar, i);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001578 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
1579 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001580 }
1581
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001582 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001583 nb = !uECC_vli_testBit(scalar, 0);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001584 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001585
1586 /* Find final 1/Z value. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001587 uECC_vli_modSub(z, Rx[1], Rx[0], curve_p); /* X1 - X0 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001588 uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */
1589 uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001590 uECC_vli_modInv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0))*/
Jarno Lamsa18987a42019-04-24 15:40:43 +03001591 /* yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001592 uECC_vli_modMult_fast(z, z, point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001593 /* Xb * yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001594 uECC_vli_modMult_fast(z, z, Rx[1 - nb]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001595 /* End 1/Z calculation */
1596
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001597 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001598 apply_z(Rx[0], Ry[0], z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001599
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001600 uECC_vli_set(result, Rx[0]);
1601 uECC_vli_set(result + num_words, Ry[0]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001602}
1603
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001604static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001605 uECC_word_t *k1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001606{
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001607 bitcount_t num_n_bits = NUM_ECC_BITS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001608
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001609 uECC_word_t carry = uECC_vli_add(k0, k, curve_n) ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001610 uECC_vli_testBit(k0, num_n_bits);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001611
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001612 uECC_vli_add(k1, k0, curve_n);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001613
1614 return carry;
1615}
1616
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001617int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001618 const uECC_word_t * scalar)
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001619{
1620 uECC_word_t tmp[NUM_ECC_WORDS];
1621 uECC_word_t s[NUM_ECC_WORDS];
1622 uECC_word_t *k2[2] = {tmp, s};
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001623 wordcount_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001624 uECC_word_t carry;
1625 uECC_word_t *initial_Z = 0;
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001626 int r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001627 volatile int problem;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001628
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001629 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001630 problem = -1;
1631 problem = uECC_check_curve_integrity();
1632 if (problem != 0) {
1633 return UECC_FAULT_DETECTED;
1634 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001635 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001636 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001637 return UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001638 }
1639
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001640 /* Protects against invalid curve attacks */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001641 problem = -1;
1642 problem = uECC_valid_point(point);
1643 if (problem != 0) {
1644 /* invalid input, can happen without fault */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001645 return UECC_FAILURE;
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001646 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001647 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001648 if (problem != 0) {
1649 /* failure on second check means fault, though */
1650 return UECC_FAULT_DETECTED;
1651 }
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001652
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001653 /* Regularize the bitcount for the private key so that attackers cannot use a
1654 * side channel attack to learn the number of leading zeros. */
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001655 carry = regularize_k(scalar, tmp, s);
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001656
1657 /* If an RNG function was specified, get a random initial Z value to
Andrzej Kurek0919b142020-07-06 15:28:59 -04001658 * protect against side-channel attacks such as Template SPA */
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001659 if (g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001660 if (uECC_generate_random_int(k2[carry], curve_p, num_words) != UECC_SUCCESS) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001661 r = UECC_FAILURE;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001662 goto clear_and_out;
1663 }
1664 initial_Z = k2[carry];
1665 }
1666
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001667 EccPoint_mult(result, point, k2[!carry], initial_Z);
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001668
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001669 /* Protect against fault injections that would make the resulting
1670 * point not lie on the intended curve */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001671 problem = -1;
1672 problem = uECC_valid_point(result);
1673 if (problem != 0) {
1674 r = UECC_FAULT_DETECTED;
1675 goto clear_and_out;
1676 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001677 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001678 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001679 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001680 goto clear_and_out;
1681 }
1682
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001683 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001684 problem = -1;
1685 problem = uECC_check_curve_integrity();
1686 if (problem != 0) {
1687 r = UECC_FAULT_DETECTED;
1688 goto clear_and_out;
1689 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001690 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001691 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001692 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001693 goto clear_and_out;
1694 }
1695
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001696 r = UECC_SUCCESS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001697
1698clear_and_out:
1699 /* erasing temporary buffer used to store secret: */
1700 mbedtls_platform_zeroize(k2, sizeof(k2));
1701 mbedtls_platform_zeroize(tmp, sizeof(tmp));
1702 mbedtls_platform_zeroize(s, sizeof(s));
1703
1704 return r;
1705}
1706
Jarno Lamsa18987a42019-04-24 15:40:43 +03001707uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001708 uECC_word_t *private_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001709{
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001710 return EccPoint_mult_safer(result, curve_G, private_key);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001711}
1712
1713/* Converts an integer in uECC native format to big-endian bytes. */
1714void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001715 const unsigned int *native)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001716{
1717 wordcount_t i;
1718 for (i = 0; i < num_bytes; ++i) {
1719 unsigned b = num_bytes - 1 - i;
1720 bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
1721 }
1722}
1723
1724/* Converts big-endian bytes to an integer in uECC native format. */
1725void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001726 int num_bytes)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001727{
1728 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001729 uECC_vli_clear(native);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001730 for (i = 0; i < num_bytes; ++i) {
1731 unsigned b = num_bytes - 1 - i;
1732 native[b / uECC_WORD_SIZE] |=
1733 (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
1734 }
1735}
1736
1737int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001738 wordcount_t num_words)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001739{
1740 uECC_word_t mask = (uECC_word_t)-1;
1741 uECC_word_t tries;
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001742 bitcount_t num_bits = uECC_vli_numBits(top);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001743
1744 if (!g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001745 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001746 }
1747
1748 for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
Andrzej Kurek090365f2020-06-08 11:00:51 -04001749 if (g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE) != num_words * uECC_WORD_SIZE) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001750 return UECC_FAILURE;
1751 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001752 random[num_words - 1] &=
Andrzej Kurek0919b142020-07-06 15:28:59 -04001753 mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001754 if (!uECC_vli_isZero(random) &&
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +01001755 uECC_vli_cmp(top, random) == 1) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001756 return UECC_SUCCESS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001757 }
1758 }
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001759 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001760}
1761
1762
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001763int uECC_valid_point(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001764{
1765 uECC_word_t tmp1[NUM_ECC_WORDS];
1766 uECC_word_t tmp2[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001767 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa83d78812019-12-04 14:40:57 +02001768 volatile uECC_word_t diff = 0xffffffff;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001769
1770 /* The point at infinity is invalid. */
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001771 if (EccPoint_isZero(point)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001772 return -1;
1773 }
1774
1775 /* x and y must be smaller than p. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001776 if (uECC_vli_cmp_unsafe(curve_p, point) != 1 ||
1777 uECC_vli_cmp_unsafe(curve_p, point + num_words) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001778 return -2;
1779 }
1780
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001781 uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001782 x_side_default(tmp2, point); /* tmp2 = x^3 + ax + b */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001783
1784 /* Make sure that y^2 == x^3 + ax + b */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001785 diff = uECC_vli_equal(tmp1, tmp2);
1786 if (diff == 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001787 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001788 if (diff == 0) {
1789 return 0;
1790 }
1791 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001792
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001793 return -3;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001794}
1795
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001796int uECC_valid_public_key(const uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001797{
1798
1799 uECC_word_t _public[NUM_ECC_WORDS * 2];
1800
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001801 uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001802 uECC_vli_bytesToNative(
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001803 _public + NUM_ECC_WORDS,
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001804 public_key + NUM_ECC_BYTES,
1805 NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001806
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +01001807 if (memcmp(_public, curve_G, NUM_ECC_WORDS * 2) == 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001808 return -4;
1809 }
1810
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001811 return uECC_valid_point(_public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001812}
1813
Andrzej Kurek0919b142020-07-06 15:28:59 -04001814int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001815{
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001816 int ret = UECC_FAULT_DETECTED;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001817 uECC_word_t _private[NUM_ECC_WORDS];
1818 uECC_word_t _public[NUM_ECC_WORDS * 2];
1819
1820 uECC_vli_bytesToNative(
1821 _private,
1822 private_key,
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +01001823 BITS_TO_BYTES(NUM_ECC_BITS));
Jarno Lamsa18987a42019-04-24 15:40:43 +03001824
1825 /* Make sure the private key is in the range [1, n-1]. */
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001826 if (uECC_vli_isZero(_private)) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001827 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001828 }
1829
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001830 if (uECC_vli_cmp(curve_n, _private) != 1) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001831 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001832 }
1833
1834 /* Compute public key. */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001835 ret = EccPoint_compute_public_key(_public, _private);
1836 if (ret != UECC_SUCCESS) {
1837 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001838 }
1839
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001840 uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001841 uECC_vli_nativeToBytes(
1842 public_key +
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001843 NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS);
Andrzej Kurekcf3e35c2020-07-15 22:32:08 -04001844
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001845 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001846}