blob: d48c3eecae68840493e4077d90096ea2a8de00ed [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];
Kevin Bracey99c64e12020-10-06 12:25:28 +0300427#if defined __GNUC__ || defined __clang__ || defined __CC_ARM
428 i = uECC_WORD_BITS - __builtin_clz(digit);
429#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300430 for (i = 0; digit; ++i) {
431 digit >>= 1;
432 }
Kevin Bracey99c64e12020-10-06 12:25:28 +0300433#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300434
435 return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
436}
437
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100438void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300439{
440 wordcount_t i;
441
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100442 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300443 dest[i] = src[i];
444 }
445}
446
447cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100448 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300449{
450 wordcount_t i;
451
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100452 for (i = NUM_ECC_WORDS - 1; i >= 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300453 if (left[i] > right[i]) {
454 return 1;
455 } else if (left[i] < right[i]) {
456 return -1;
457 }
458 }
459 return 0;
460}
461
Manuel Pégourié-Gonnard2eca3d32019-11-04 14:33:09 +0100462uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300463{
464
465 uECC_word_t diff = 0;
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200466 uECC_word_t flow_monitor = 0;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100467 uECC_word_t tmp1, tmp2;
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100468 volatile int i;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300469
Piotr Nowickif0ab6d62020-05-25 12:48:30 +0200470 /* Start from a random location and check the correct number of iterations */
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200471 int start_offset = mbedtls_platform_random_in_range(NUM_ECC_WORDS);
472
473 for (i = start_offset; i < NUM_ECC_WORDS; ++i) {
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100474 tmp1 = left[i];
475 tmp2 = right[i];
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200476 flow_monitor++;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100477 diff |= (tmp1 ^ tmp2);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300478 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100479
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200480 for (i = 0; i < start_offset; ++i) {
481 tmp1 = left[i];
482 tmp2 = right[i];
483 flow_monitor++;
484 diff |= (tmp1 ^ tmp2);
485 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100486
Piotr Nowickif0ab6d62020-05-25 12:48:30 +0200487 /* Random delay to increase security */
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200488 mbedtls_platform_random_delay();
489
490 /* Return 0 only when diff is 0 and flow_counter is equal to NUM_ECC_WORDS */
491 return (diff | (flow_monitor ^ NUM_ECC_WORDS));
Jarno Lamsa18987a42019-04-24 15:40:43 +0300492}
493
494uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
495{
Kevin Bracey045e5762020-10-06 12:25:58 +0300496 return (p_true*(cond)) | (p_false*(cond ^ 1));
Jarno Lamsa18987a42019-04-24 15:40:43 +0300497}
498
499/* Computes result = left - right, returning borrow, in constant time.
500 * Can modify in place. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300501#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
502__asm uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
503 const uECC_word_t *right)
504{
505#if NUM_ECC_WORDS != 8
506#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
507#endif
508#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
509 PUSH {r4-r6,lr}
510 FRAME PUSH {r4-r6,lr}
511 LDMIA r1!,{r3,r4}
512 LDMIA r2!,{r5,r6}
513 SUBS r3,r5
514 SBCS r4,r6
515 STMIA r0!,{r3,r4}
516 LDMIA r1!,{r3,r4}
517 LDMIA r2!,{r5,r6}
518 SBCS r3,r5
519 SBCS r4,r6
520 STMIA r0!,{r3,r4}
521 LDMIA r1!,{r3,r4}
522 LDMIA r2!,{r5,r6}
523 SBCS r3,r5
524 SBCS r4,r6
525 STMIA r0!,{r3,r4}
526 LDMIA r1!,{r3,r4}
527 LDMIA r2!,{r5,r6}
528 SBCS r3,r5
529 SBCS r4,r6
530 STMIA r0!,{r3,r4}
531 SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow
532 RSBS r0,r0,#0 // r0 := borrow
533 POP {r4-r6,pc}
534#else
535 PUSH {r4-r8,lr}
536 FRAME PUSH {r4-r8,lr}
537 LDMIA r1!,{r3-r6}
538 LDMIA r2!,{r7,r8,r12,lr}
539 SUBS r3,r7
540 SBCS r4,r8
541 SBCS r5,r12
542 SBCS r6,lr
543 STMIA r0!,{r3-r6}
544 LDMIA r1!,{r3-r6}
545 LDMIA r2!,{r7,r8,r12,lr}
546 SBCS r3,r7
547 SBCS r4,r8
548 SBCS r5,r12
549 SBCS r6,lr
550 STMIA r0!,{r3-r6}
551 SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow
552 RSBS r0,r0,#0 // r0 := borrow
553 POP {r4-r8,pc}
554#endif
555}
Kevin Bracey4aea6252020-10-09 12:54:28 +0300556#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
557uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
558 const uECC_word_t *right)
559{
560#if NUM_ECC_WORDS != 8
561#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
562#endif
563 register uECC_word_t *r0 asm ("r0") = result;
564 register const uECC_word_t *r1 asm ("r1") = left;
565 register const uECC_word_t *r2 asm ("r2") = right;
566 asm volatile (
567#if defined __thumb__ && !defined __thumb2__
568 ".syntax unified \n\t"
569 "LDMIA r1!,{r3,r4} \n\t"
570 "LDMIA r2!,{r5,r6} \n\t"
571 "SUBS r3,r5 \n\t"
572 "SBCS r4,r6 \n\t"
573 "STMIA r0!,{r3,r4} \n\t"
574 "LDMIA r1!,{r3,r4} \n\t"
575 "LDMIA r2!,{r5,r6} \n\t"
576 "SBCS r3,r5 \n\t"
577 "SBCS r4,r6 \n\t"
578 "STMIA r0!,{r3,r4} \n\t"
579 "LDMIA r1!,{r3,r4} \n\t"
580 "LDMIA r2!,{r5,r6} \n\t"
581 "SBCS r3,r5 \n\t"
582 "SBCS r4,r6 \n\t"
583 "STMIA r0!,{r3,r4} \n\t"
584 "LDMIA r1!,{r3,r4} \n\t"
585 "LDMIA r2!,{r5,r6} \n\t"
586 "SBCS r3,r5 \n\t"
587 "SBCS r4,r6 \n\t"
588 "STMIA r0!,{r3,r4} \n\t"
589 "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow
590 "RSBS r0,r0,#0 \n\t" // r0 := borrow
591 : "+r" (r0), "+r" (r1), "+r" (r2)
592 :
593 : "r3", "r4", "r5", "r6", "cc", "memory"
594#else
595 "LDMIA r1!,{r3-r6} \n\t"
596 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
597 "SUBS r3,r7 \n\t"
598 "SBCS r4,r8 \n\t"
599 "SBCS r5,r12 \n\t"
600 "SBCS r6,lr \n\t"
601 "STMIA r0!,{r3-r6} \n\t"
602 "LDMIA r1!,{r3-r6} \n\t"
603 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
604 "SBCS r3,r7 \n\t"
605 "SBCS r4,r8 \n\t"
606 "SBCS r5,r12 \n\t"
607 "SBCS r6,lr \n\t"
608 "STMIA r0!,{r3-r6} \n\t"
609 "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow
610 "RSBS r0,r0,#0 \n\t" // r0 := borrow
611 : "+r" (r0), "+r" (r1), "+r" (r2)
612 :
613 : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory"
614#endif
615 );
616 return (uECC_word_t) r0;
617}
Kevin Bracey1959c182020-07-16 21:03:19 +0300618#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300619uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100620 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300621{
622 uECC_word_t borrow = 0;
623 wordcount_t i;
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100624 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300625 uECC_word_t diff = left[i] - right[i] - borrow;
626 uECC_word_t val = (diff > left[i]);
627 borrow = cond_set(val, borrow, (diff != left[i]));
628
629 result[i] = diff;
630 }
631 return borrow;
632}
Kevin Bracey1959c182020-07-16 21:03:19 +0300633#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300634
635/* Computes result = left + right, returning carry, in constant time.
636 * Can modify in place. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300637#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
638static __asm uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
639 const uECC_word_t *right)
640{
641#if NUM_ECC_WORDS != 8
642#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
643#endif
644#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
645 PUSH {r4-r6,lr}
646 FRAME PUSH {r4-r6,lr}
647 LDMIA r1!,{r3,r4}
648 LDMIA r2!,{r5,r6}
649 ADDS r3,r5
650 ADCS r4,r6
651 STMIA r0!,{r3,r4}
652 LDMIA r1!,{r3,r4}
653 LDMIA r2!,{r5,r6}
654 ADCS r3,r5
655 ADCS r4,r6
656 STMIA r0!,{r3,r4}
657 LDMIA r1!,{r3,r4}
658 LDMIA r2!,{r5,r6}
659 ADCS r3,r5
660 ADCS r4,r6
661 STMIA r0!,{r3,r4}
662 LDMIA r1!,{r3,r4}
663 LDMIA r2!,{r5,r6}
664 ADCS r3,r5
665 ADCS r4,r6
666 STMIA r0!,{r3,r4}
667 MOVS r0,#0 // does not affect C flag
668 ADCS r0,r0 // r0 := 0 + 0 + C = carry
669 POP {r4-r6,pc}
670#else
671 PUSH {r4-r8,lr}
672 FRAME PUSH {r4-r8,lr}
673 LDMIA r1!,{r3-r6}
674 LDMIA r2!,{r7,r8,r12,lr}
675 ADDS r3,r7
676 ADCS r4,r8
677 ADCS r5,r12
678 ADCS r6,lr
679 STMIA r0!,{r3-r6}
680 LDMIA r1!,{r3-r6}
681 LDMIA r2!,{r7,r8,r12,lr}
682 ADCS r3,r7
683 ADCS r4,r8
684 ADCS r5,r12
685 ADCS r6,lr
686 STMIA r0!,{r3-r6}
687 MOVS r0,#0 // does not affect C flag
688 ADCS r0,r0 // r0 := 0 + 0 + C = carry
689 POP {r4-r8,pc}
690#endif
691}
Kevin Bracey4aea6252020-10-09 12:54:28 +0300692#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
693static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
694 const uECC_word_t *right)
695{
696 register uECC_word_t *r0 asm ("r0") = result;
697 register const uECC_word_t *r1 asm ("r1") = left;
698 register const uECC_word_t *r2 asm ("r2") = right;
699
700 asm volatile (
701#if defined __thumb__ && !defined __thumb2__
702 ".syntax unified \n\t"
703 "LDMIA r1!,{r3,r4} \n\t"
704 "LDMIA r2!,{r5,r6} \n\t"
705 "ADDS r3,r5 \n\t"
706 "ADCS r4,r6 \n\t"
707 "STMIA r0!,{r3,r4} \n\t"
708 "LDMIA r1!,{r3,r4} \n\t"
709 "LDMIA r2!,{r5,r6} \n\t"
710 "ADCS r3,r5 \n\t"
711 "ADCS r4,r6 \n\t"
712 "STMIA r0!,{r3,r4} \n\t"
713 "LDMIA r1!,{r3,r4} \n\t"
714 "LDMIA r2!,{r5,r6} \n\t"
715 "ADCS r3,r5 \n\t"
716 "ADCS r4,r6 \n\t"
717 "STMIA r0!,{r3,r4} \n\t"
718 "LDMIA r1!,{r3,r4} \n\t"
719 "LDMIA r2!,{r5,r6} \n\t"
720 "ADCS r3,r5 \n\t"
721 "ADCS r4,r6 \n\t"
722 "STMIA r0!,{r3,r4} \n\t"
723 "MOVS r0,#0 \n\t" // does not affect C flag
724 "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry
725 : "+r" (r0), "+r" (r1), "+r" (r2)
726 :
727 : "r3", "r4", "r5", "r6", "cc", "memory"
728#else
729 "LDMIA r1!,{r3-r6} \n\t"
730 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
731 "ADDS r3,r7 \n\t"
732 "ADCS r4,r8 \n\t"
733 "ADCS r5,r12 \n\t"
734 "ADCS r6,lr \n\t"
735 "STMIA r0!,{r3-r6} \n\t"
736 "LDMIA r1!,{r3-r6} \n\t"
737 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
738 "ADCS r3,r7 \n\t"
739 "ADCS r4,r8 \n\t"
740 "ADCS r5,r12 \n\t"
741 "ADCS r6,lr \n\t"
742 "STMIA r0!,{r3-r6} \n\t"
743 "MOVS r0,#0 \n\t" // does not affect C flag
744 "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry
745 : "+r" (r0), "+r" (r1), "+r" (r2)
746 :
747 : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory"
748#endif
749 );
750 return (uECC_word_t) r0;
751}
Kevin Bracey1959c182020-07-16 21:03:19 +0300752#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300753static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100754 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300755{
756 uECC_word_t carry = 0;
757 wordcount_t i;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100758 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300759 uECC_word_t sum = left[i] + right[i] + carry;
760 uECC_word_t val = (sum < left[i]);
761 carry = cond_set(val, carry, (sum != left[i]));
762 result[i] = sum;
763 }
764 return carry;
765}
Kevin Bracey1959c182020-07-16 21:03:19 +0300766#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300767
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +0100768cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300769{
770 uECC_word_t tmp[NUM_ECC_WORDS];
Kevin Bracey045e5762020-10-06 12:25:58 +0300771 uECC_word_t neg = uECC_vli_sub(tmp, left, right);
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100772 uECC_word_t equal = uECC_vli_isZero(tmp);
Kevin Bracey045e5762020-10-06 12:25:58 +0300773 return ((equal ^ 1) - 2 * neg);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300774}
775
776/* Computes vli = vli >> 1. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300777#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
778static __asm void uECC_vli_rshift1(uECC_word_t *vli)
779{
780#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
781// RRX instruction is not available, so although we
782// can use C flag, it's not that effective. Does at
783// least save one working register, meaning we don't need stack
784 MOVS r3,#0 // initial carry = 0
785 MOVS r2,#__cpp(4 * (NUM_ECC_WORDS - 1))
78601 LDR r1,[r0,r2]
787 LSRS r1,r1,#1 // r2 = word >> 1
788 ORRS r1,r3 // merge in the previous carry
789 STR r1,[r0,r2]
790 ADCS r3,r3 // put C into bottom bit of r3
791 LSLS r3,r3,#31 // shift it up to the top ready for next word
792 SUBS r2,r2,#4
793 BPL %B01
794 BX lr
795#else
796#if NUM_ECC_WORDS != 8
797#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
798#endif
799// Smooth multiword operation, lots of 32-bit instructions
800 ADDS r0,#32
801 LDMDB r0,{r1-r3,ip}
802 LSRS ip,ip,#1
803 RRXS r3,r3
804 RRXS r2,r2
805 RRXS r1,r1
806 STMDB r0!,{r1-r3,ip}
807 LDMDB r0,{r1-r3,ip}
808 RRXS ip,ip
809 RRXS r3,r3
810 RRXS r2,r2
811 RRX r1,r1
812 STMDB r0!,{r1-r3,ip}
813 BX lr
814#endif
815}
Kevin Bracey06060332020-10-02 17:43:12 +0300816#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__ && defined __thumb2__
817static void uECC_vli_rshift1(uECC_word_t *vli)
818{
819 register uECC_word_t *r0 asm ("r0") = vli;
820#if NUM_ECC_WORDS != 8
821#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
822#endif
823 asm volatile (
824 "ADDS r0,#32 \n\t"
825 "LDMDB r0,{r1-r3,ip} \n\t"
826 "LSRS ip,ip,#1 \n\t"
827 "RRXS r3,r3 \n\t"
828 "RRXS r2,r2 \n\t"
829 "RRXS r1,r1 \n\t"
830 "STMDB r0!,{r1-r3,ip} \n\t"
831 "LDMDB r0,{r1-r3,ip} \n\t"
832 "RRXS ip,ip \n\t"
833 "RRXS r3,r3 \n\t"
834 "RRXS r2,r2 \n\t"
835 "RRX r1,r1 \n\t"
836 "STMDB r0!,{r1-r3,ip} \n\t"
837 : "+r" (r0)
838 :
839 : "r1", "r2", "r3", "ip", "cc", "memory"
840 );
841}
Kevin Bracey1959c182020-07-16 21:03:19 +0300842#else
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100843static void uECC_vli_rshift1(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300844{
845 uECC_word_t *end = vli;
846 uECC_word_t carry = 0;
847
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100848 vli += NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300849 while (vli-- > end) {
850 uECC_word_t temp = *vli;
851 *vli = (temp >> 1) | carry;
852 carry = temp << (uECC_WORD_BITS - 1);
853 }
854}
Kevin Bracey1959c182020-07-16 21:03:19 +0300855#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300856
Kevin Bracey84f31d32020-09-29 17:51:04 +0300857/* Compute a * b + r, where r is a triple-word with high-order word r[2] and
858 * low-order word r[0], and store the result in the same triple-word.
Manuel Pégourié-Gonnard86c4f812019-10-31 13:02:03 +0100859 *
Kevin Bracey84f31d32020-09-29 17:51:04 +0300860 * r[2..0] = a * b + r[2..0]:
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200861 * [in] a, b: operands to be multiplied
Kevin Bracey84f31d32020-09-29 17:51:04 +0300862 * [in] r: 3 words of operand to add
863 * [out] r: 3 words of result
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200864 */
Kevin Bracey1959c182020-07-16 21:03:19 +0300865#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
Kevin Bracey84f31d32020-09-29 17:51:04 +0300866static __asm void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Bracey1959c182020-07-16 21:03:19 +0300867{
868#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
Kevin Bracey84f31d32020-09-29 17:51:04 +0300869 PUSH {r4-r5}
870 FRAME PUSH {r4-r5}
871 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
872 // Separate operands into halfwords
873 UXTH r3,r0 // r3 := a.lo
874 LSRS r4,r0,#16 // r4 := a.hi
875 UXTH r5,r1 // r5 := b.lo
876 LSRS r1,r1,#16 // r1 := b.hi
877 // Multiply halfword pairs
878 MOVS r0,r3
879 MULS r0,r5,r0 // r0 := a.lo * b.lo
880 MULS r3,r1,r3 // r3 := a.lo * b.hi
881 MULS r5,r4,r5 // r5 := a.hi * b.lo
882 MULS r1,r4,r1 // r1 := a.hi * b.hi
883 // Split, shift and add a.lo * b.hi
884 LSRS r4,r3,#16 // r4 := (a.lo * b.hi).hi
885 LSLS r3,r3,#16 // r3 := (a.lo * b.hi).lo
886 ADDS r0,r0,r3 // r0 := a.lo * b.lo + (a.lo * b.hi).lo
887 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
888 // Split, shift and add a.hi * b.lo
889 LSRS r4,r5,#16 // r4 := (a.hi * b.lo).hi
890 LSLS r5,r5,#16 // r5 := (a.hi * b.lo).lo
891 ADDS r0,r0,r5 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
892 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
893 // Finally add r[]
894 LDMIA r2!,{r3,r4,r5}
895 ADDS r3,r3,r0
Kevin Bracey1959c182020-07-16 21:03:19 +0300896 ADCS r4,r1
Kevin Bracey1959c182020-07-16 21:03:19 +0300897 MOVS r0,#0
Kevin Bracey84f31d32020-09-29 17:51:04 +0300898 ADCS r5,r0
899 SUBS r2,#12
900 STMIA r2!,{r3,r4,r5}
901 POP {r4-r5}
902 FRAME POP {r4-r5}
903 BX lr
Kevin Bracey1959c182020-07-16 21:03:19 +0300904#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300905 UMULL r3,ip,r0,r1 // pre-ARMv6 requires Rd[Lo|Hi] != Rn
906 LDMIA r2,{r0,r1}
907 ADDS r0,r0,r3
908 LDR r3,[r2,#8]
909 ADCS r1,r1,ip
910 ADC r3,r3,#0
911 STMIA r2!,{r0,r1,r3}
Kevin Bracey1959c182020-07-16 21:03:19 +0300912 BX lr
913#endif
Kevin Braceye0f88d52020-09-30 12:52:15 +0300914}
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300915#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
916static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Braceye0f88d52020-09-30 12:52:15 +0300917{
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300918 register uECC_word_t r0 asm ("r0") = a;
919 register uECC_word_t r1 asm ("r1") = b;
920 register uECC_word_t *r2 asm ("r2") = r;
921 asm volatile (
Kevin Braceye0f88d52020-09-30 12:52:15 +0300922#if defined __thumb__ && !defined(__thumb2__)
923 ".syntax unified \n\t"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300924 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
925 // Separate operands into halfwords
926 "UXTH r3,r0 \n\t" // r3 := a.lo
927 "LSRS r4,r0,#16 \n\t" // r4 := a.hi
928 "UXTH r5,r1 \n\t" // r5 := b.lo
929 "LSRS r1,r1,#16 \n\t" // r1 := b.hi
930 // Multiply halfword pairs
931 "MOVS r0,r3 \n\t"
932 "MULS r0,r5,r0 \n\t" // r0 := a.lo * b.lo
933 "MULS r3,r1,r3 \n\t" // r3 := a.lo * b.hi
934 "MULS r5,r4,r5 \n\t" // r5 := a.hi * b.lo
935 "MULS r1,r4,r1 \n\t" // r1 := a.hi * b.hi
936 // Split, shift and add a.lo * b.hi
937 "LSRS r4,r3,#16 \n\t" // r4 := (a.lo * b.hi).hi
938 "LSLS r3,r3,#16 \n\t" // r3 := (a.lo * b.hi).lo
939 "ADDS r0,r0,r3 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo
940 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
941 // Split, shift and add a.hi * b.lo
942 "LSRS r4,r5,#16 \n\t" // r4 := (a.hi * b.lo).hi
943 "LSLS r5,r5,#16 \n\t" // r5 := (a.hi * b.lo).lo
944 "ADDS r0,r0,r5 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
945 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
946 // Finally add r[]
947 "LDMIA r2!,{r3,r4,r5} \n\t"
948 "ADDS r3,r3,r0 \n\t"
949 "ADCS r4,r1 \n\t"
950 "MOVS r0,#0 \n\t"
951 "ADCS r5,r0 \n\t"
952 "SUBS r2,#12 \n\t"
953 "STMIA r2!,{r3,r4,r5} \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300954 : "+r" (r0), "+r" (r1), "+r" (r2)
955 :
956 : "r3", "r4", "r5", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300957#else
958 "UMULL r3,ip,r0,r1 \n\t" // pre-ARMv6 requires Rd[Lo|Hi] != Rn
959 "LDMIA r2,{r0,r1} \n\t"
960 "ADDS r0,r0,r3 \n\t"
961 "LDR r3,[r2,#8] \n\t"
962 "ADCS r1,r1,ip \n\t"
963 "ADC r3,r3,#0 \n\t"
964 "STMIA r2!,{r0,r1,r3} \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300965 : "+r" (r0), "+r" (r1), "+r" (r2)
966 :
967 : "r3", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300968#endif
969 );
Kevin Bracey1959c182020-07-16 21:03:19 +0300970}
971#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300972static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Jarno Lamsa18987a42019-04-24 15:40:43 +0300973{
974
975 uECC_dword_t p = (uECC_dword_t)a * b;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300976 uECC_dword_t r01 = ((uECC_dword_t)(r[1]) << uECC_WORD_BITS) | r[0];
Jarno Lamsa18987a42019-04-24 15:40:43 +0300977 r01 += p;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300978 r[2] += (r01 < p);
979 r[1] = r01 >> uECC_WORD_BITS;
980 r[0] = (uECC_word_t)r01;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300981}
Kevin Bracey1959c182020-07-16 21:03:19 +0300982#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300983
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200984/* State for implementing random delays in uECC_vli_mult_rnd().
985 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100986 * The state is initialized by randomizing delays and setting i = 0.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200987 * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i.
988 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100989 * Randomized vli multiplication is used only for point operations
990 * (XYcZ_add_rnd() * and XYcZ_addC_rnd()) in scalar multiplication
991 * (ECCPoint_mult()). Those go in pair, and each pair does 14 calls to
992 * uECC_vli_mult_rnd() (6 in XYcZ_add_rnd() and 8 in XYcZ_addC_rnd(),
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100993 * indirectly through uECC_vli_modMult_rnd().
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100994 *
995 * Considering this, in order to minimize the number of calls to the RNG
996 * (which impact performance) while keeping the size of the structure low,
997 * make room for 14 randomized vli mults, which corresponds to one step in the
998 * scalar multiplication routine.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200999 */
1000typedef struct {
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001001 uint8_t i;
1002 uint8_t delays[14];
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001003} ecc_wait_state_t;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001004
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001005/*
1006 * Reset wait_state so that it's ready to be used.
1007 */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001008void ecc_wait_state_reset(ecc_wait_state_t *ws)
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001009{
1010 if (ws == NULL)
1011 return;
1012
1013 ws->i = 0;
Shelly Liberman05beb9a2020-09-13 15:23:56 +03001014 mbedtls_platform_random_buf(ws->delays, sizeof(ws->delays));
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001015}
1016
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001017/* Computes result = left * right. Result must be 2 * num_words long.
1018 *
1019 * As a counter-measure against horizontal attacks, add noise by performing
1020 * a random number of extra computations performing random additional accesses
1021 * to limbs of the input.
1022 *
1023 * Each of the two actual computation loops is surrounded by two
1024 * similar-looking waiting loops, to make the beginning and end of the actual
1025 * computation harder to spot.
1026 *
1027 * We add 4 waiting loops of between 0 and 3 calls to muladd() each. That
1028 * makes an average of 6 extra calls. Compared to the main computation which
1029 * makes 64 such calls, this represents an average performance degradation of
1030 * less than 10%.
1031 *
1032 * Compared to the original uECC_vli_mult(), loose the num_words argument as we
1033 * know it's always 8. This saves a bit of code size and execution speed.
1034 */
1035static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001036 const uECC_word_t *right, ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001037{
1038
Kevin Bracey84f31d32020-09-29 17:51:04 +03001039 uECC_word_t r[3] = { 0, 0, 0 };
Jarno Lamsa18987a42019-04-24 15:40:43 +03001040 wordcount_t i, k;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001041 const uint8_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001042
1043 /* Fetch 8 bit worth of delay from the state; 0 if we have no state */
1044 uint8_t delays = s ? s->delays[s->i++] : 0;
Kevin Bracey84f31d32020-09-29 17:51:04 +03001045 uECC_word_t rr[3] = { 0, 0, 0 };
1046 volatile uECC_word_t rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001047
1048 /* Mimic start of next loop: k in [0, 3] */
1049 k = 0 + (delays & 0x03);
1050 delays >>= 2;
1051 /* k = 0 -> i in [1, 0] -> 0 extra muladd;
1052 * k = 3 -> i in [1, 3] -> 3 extra muladd */
Manuel Pégourié-Gonnardc8814862019-11-05 10:32:37 +01001053 for (i = 1; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001054 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001055 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001056 rdummy = rr[0];
1057 rr[0] = rr[1];
1058 rr[1] = rr[2];
1059 rr[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001060
1061 /* Compute each digit of result in sequence, maintaining the carries. */
1062 for (k = 0; k < num_words; ++k) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001063 for (i = 0; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001064 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001065 }
1066
Kevin Bracey84f31d32020-09-29 17:51:04 +03001067 result[k] = r[0];
1068 r[0] = r[1];
1069 r[1] = r[2];
1070 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001071 }
1072
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001073 /* Mimic end of previous loop: k in [4, 7] */
1074 k = 4 + (delays & 0x03);
1075 delays >>= 2;
1076 /* k = 4 -> i in [5, 4] -> 0 extra muladd;
1077 * k = 7 -> i in [5, 7] -> 3 extra muladd */
1078 for (i = 5; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001079 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001080 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001081 rdummy = rr[0];
1082 rr[0] = rr[1];
1083 rr[1] = rr[2];
1084 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001085
1086 /* Mimic start of next loop: k in [8, 11] */
1087 k = 11 - (delays & 0x03);
1088 delays >>= 2;
1089 /* k = 8 -> i in [5, 7] -> 3 extra muladd;
1090 * k = 11 -> i in [8, 7] -> 0 extra muladd */
1091 for (i = (k + 5) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001092 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001093 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001094 rdummy = rr[0];
1095 rr[0] = rr[1];
1096 rr[1] = rr[2];
1097 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001098
Jarno Lamsa18987a42019-04-24 15:40:43 +03001099 for (k = num_words; k < num_words * 2 - 1; ++k) {
1100
1101 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001102 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001103 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001104 result[k] = r[0];
1105 r[0] = r[1];
1106 r[1] = r[2];
1107 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001108 }
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001109
Kevin Bracey84f31d32020-09-29 17:51:04 +03001110 result[num_words * 2 - 1] = r[0];
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001111
1112 /* Mimic end of previous loop: k in [12, 15] */
1113 k = 15 - (delays & 0x03);
1114 delays >>= 2;
1115 /* k = 12 -> i in [5, 7] -> 3 extra muladd;
1116 * k = 15 -> i in [8, 7] -> 0 extra muladd */
1117 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001118 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001119 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001120 rdummy = rr[0];
1121 rr[0] = rr[1];
1122 rr[1] = rr[2];
1123 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001124
Kevin Bracey84f31d32020-09-29 17:51:04 +03001125 /* avoid warning that rdummy is set but not used */
1126 (void) rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001127}
1128
Jarno Lamsa18987a42019-04-24 15:40:43 +03001129void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001130 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001131{
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001132 uECC_word_t carry = uECC_vli_add(result, left, right);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001133 if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001134 /* result > mod (result = mod + remainder), so subtract mod to get
1135 * remainder. */
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001136 uECC_vli_sub(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001137 }
1138}
1139
1140void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001141 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001142{
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001143 uECC_word_t l_borrow = uECC_vli_sub(result, left, right);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001144 if (l_borrow) {
1145 /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
1146 * we can get the correct result from result + mod (with overflow). */
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001147 uECC_vli_add(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001148 }
1149}
1150
1151/* Computes result = product % mod, where product is 2N words long. */
1152/* Currently only designed to work for curve_p or curve_n. */
1153void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001154 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001155{
1156 uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
1157 uECC_word_t tmp[2 * NUM_ECC_WORDS];
1158 uECC_word_t *v[2] = {tmp, product};
1159 uECC_word_t index;
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +01001160 const wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001161
1162 /* Shift mod so its highest set bit is at the maximum position. */
1163 bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001164 uECC_vli_numBits(mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001165 wordcount_t word_shift = shift / uECC_WORD_BITS;
1166 wordcount_t bit_shift = shift % uECC_WORD_BITS;
1167 uECC_word_t carry = 0;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001168 uECC_vli_clear(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001169 if (bit_shift > 0) {
1170 for(index = 0; index < (uECC_word_t)num_words; ++index) {
1171 mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
1172 carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
1173 }
1174 } else {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001175 uECC_vli_set(mod_multiple + word_shift, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001176 }
1177
1178 for (index = 1; shift >= 0; --shift) {
1179 uECC_word_t borrow = 0;
1180 wordcount_t i;
1181 for (i = 0; i < num_words * 2; ++i) {
1182 uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
1183 if (diff != v[index][i]) {
1184 borrow = (diff > v[index][i]);
1185 }
1186 v[1 - index][i] = diff;
1187 }
1188 /* Swap the index if there was no borrow */
1189 index = !(index ^ borrow);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001190 uECC_vli_rshift1(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001191 mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
Andrzej Kurek0919b142020-07-06 15:28:59 -04001192 (uECC_WORD_BITS - 1);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001193 uECC_vli_rshift1(mod_multiple + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001194 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001195 uECC_vli_set(result, v[index]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001196}
1197
1198void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001199 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001200{
1201 uECC_word_t product[2 * NUM_ECC_WORDS];
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001202 uECC_vli_mult_rnd(product, left, right, NULL);
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +01001203 uECC_vli_mmod(result, product, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001204}
1205
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001206static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001207 const uECC_word_t *right, ecc_wait_state_t *s)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001208{
1209 uECC_word_t product[2 * NUM_ECC_WORDS];
1210 uECC_vli_mult_rnd(product, left, right, s);
1211
1212 vli_mmod_fast_secp256r1(result, product);
1213}
1214
Jarno Lamsa18987a42019-04-24 15:40:43 +03001215void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001216 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001217{
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001218 uECC_vli_modMult_rnd(result, left, right, NULL);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001219}
1220
Jarno Lamsa18987a42019-04-24 15:40:43 +03001221#define EVEN(vli) (!(vli[0] & 1))
1222
1223static void vli_modInv_update(uECC_word_t *uv,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001224 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001225{
1226
1227 uECC_word_t carry = 0;
1228
1229 if (!EVEN(uv)) {
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001230 carry = uECC_vli_add(uv, uv, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001231 }
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001232 uECC_vli_rshift1(uv);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001233 if (carry) {
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +01001234 uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001235 }
1236}
1237
1238void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001239 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001240{
1241 uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
1242 uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
1243 cmpresult_t cmpResult;
1244
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001245 if (uECC_vli_isZero(input)) {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001246 uECC_vli_clear(result);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001247 return;
1248 }
1249
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001250 uECC_vli_set(a, input);
1251 uECC_vli_set(b, mod);
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001252 uECC_vli_clear(u);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001253 u[0] = 1;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001254 uECC_vli_clear(v);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001255 while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001256 if (EVEN(a)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001257 uECC_vli_rshift1(a);
Andrzej Kurek0919b142020-07-06 15:28:59 -04001258 vli_modInv_update(u, mod);
1259 } else if (EVEN(b)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001260 uECC_vli_rshift1(b);
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +01001261 vli_modInv_update(v, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001262 } else if (cmpResult > 0) {
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001263 uECC_vli_sub(a, a, b);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001264 uECC_vli_rshift1(a);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001265 if (uECC_vli_cmp_unsafe(u, v) < 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001266 uECC_vli_add(u, u, mod);
1267 }
1268 uECC_vli_sub(u, u, v);
1269 vli_modInv_update(u, mod);
1270 } else {
1271 uECC_vli_sub(b, b, a);
1272 uECC_vli_rshift1(b);
1273 if (uECC_vli_cmp_unsafe(v, u) < 0) {
1274 uECC_vli_add(v, v, mod);
1275 }
1276 uECC_vli_sub(v, v, u);
1277 vli_modInv_update(v, mod);
1278 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001279 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001280 uECC_vli_set(result, u);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001281}
1282
1283/* ------ Point operations ------ */
1284
1285void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001286 uECC_word_t * Z1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001287{
1288 /* t1 = X, t2 = Y, t3 = Z */
1289 uECC_word_t t4[NUM_ECC_WORDS];
1290 uECC_word_t t5[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001291 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001292
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001293 if (uECC_vli_isZero(Z1)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001294 return;
1295 }
1296
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001297 uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */
1298 uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */
1299 uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */
1300 uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */
1301 uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001302
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001303 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = x1 + z1^2 */
1304 uECC_vli_modAdd(Z1, Z1, Z1, curve_p); /* t3 = 2*z1^2 */
1305 uECC_vli_modSub(Z1, X1, Z1, curve_p); /* t3 = x1 - z1^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001306 uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001307
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001308 uECC_vli_modAdd(Z1, X1, X1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
1309 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001310 if (uECC_vli_testBit(X1, 0)) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001311 uECC_word_t l_carry = uECC_vli_add(X1, X1, curve_p);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001312 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001313 X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
1314 } else {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001315 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001316 }
1317
1318 /* t1 = 3/2*(x1^2 - z1^4) = B */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001319 uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001320 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - A */
1321 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
1322 uECC_vli_modSub(t5, t5, Z1, curve_p); /* t5 = A - x3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001323 uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001324 /* t4 = B * (A - x3) - y1^4 = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001325 uECC_vli_modSub(t4, X1, t4, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001326
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001327 uECC_vli_set(X1, Z1);
1328 uECC_vli_set(Z1, Y1);
1329 uECC_vli_set(Y1, t4);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001330}
1331
Manuel Pégourié-Gonnard1c6f7ea2019-11-21 09:18:29 +01001332/*
1333 * @brief Computes x^3 + ax + b. result must not overlap x.
1334 * @param result OUT -- x^3 + ax + b
1335 * @param x IN -- value of x
1336 * @param curve IN -- elliptic curve
1337 */
1338static void x_side_default(uECC_word_t *result,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001339 const uECC_word_t *x)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001340{
1341 uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001342
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001343 uECC_vli_modMult_fast(result, x, x); /* r = x^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001344 uECC_vli_modSub(result, result, _3, curve_p); /* r = x^2 - 3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001345 uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001346 /* r = x^3 - 3x + b: */
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +01001347 uECC_vli_modAdd(result, result, curve_b, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001348}
1349
1350void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
1351{
1352 unsigned int tmp[NUM_ECC_WORDS];
1353 int carry;
1354
1355 /* t */
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001356 uECC_vli_set(result, product);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001357
1358 /* s1 */
1359 tmp[0] = tmp[1] = tmp[2] = 0;
1360 tmp[3] = product[11];
1361 tmp[4] = product[12];
1362 tmp[5] = product[13];
1363 tmp[6] = product[14];
1364 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001365 carry = uECC_vli_add(tmp, tmp, tmp);
1366 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001367
1368 /* s2 */
1369 tmp[3] = product[12];
1370 tmp[4] = product[13];
1371 tmp[5] = product[14];
1372 tmp[6] = product[15];
1373 tmp[7] = 0;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001374 carry += uECC_vli_add(tmp, tmp, tmp);
1375 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001376
1377 /* s3 */
1378 tmp[0] = product[8];
1379 tmp[1] = product[9];
1380 tmp[2] = product[10];
1381 tmp[3] = tmp[4] = tmp[5] = 0;
1382 tmp[6] = product[14];
1383 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001384 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001385
1386 /* s4 */
1387 tmp[0] = product[9];
1388 tmp[1] = product[10];
1389 tmp[2] = product[11];
1390 tmp[3] = product[13];
1391 tmp[4] = product[14];
1392 tmp[5] = product[15];
1393 tmp[6] = product[13];
1394 tmp[7] = product[8];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001395 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001396
1397 /* d1 */
1398 tmp[0] = product[11];
1399 tmp[1] = product[12];
1400 tmp[2] = product[13];
1401 tmp[3] = tmp[4] = tmp[5] = 0;
1402 tmp[6] = product[8];
1403 tmp[7] = product[10];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001404 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001405
1406 /* d2 */
1407 tmp[0] = product[12];
1408 tmp[1] = product[13];
1409 tmp[2] = product[14];
1410 tmp[3] = product[15];
1411 tmp[4] = tmp[5] = 0;
1412 tmp[6] = product[9];
1413 tmp[7] = product[11];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001414 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001415
1416 /* d3 */
1417 tmp[0] = product[13];
1418 tmp[1] = product[14];
1419 tmp[2] = product[15];
1420 tmp[3] = product[8];
1421 tmp[4] = product[9];
1422 tmp[5] = product[10];
1423 tmp[6] = 0;
1424 tmp[7] = product[12];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001425 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001426
1427 /* d4 */
1428 tmp[0] = product[14];
1429 tmp[1] = product[15];
1430 tmp[2] = 0;
1431 tmp[3] = product[9];
1432 tmp[4] = product[10];
1433 tmp[5] = product[11];
1434 tmp[6] = 0;
1435 tmp[7] = product[13];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001436 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001437
1438 if (carry < 0) {
1439 do {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001440 carry += uECC_vli_add(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001441 }
1442 while (carry < 0);
1443 } else {
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +02001444 while (carry ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001445 uECC_vli_cmp_unsafe(curve_p, result) != 1) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001446 carry -= uECC_vli_sub(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001447 }
1448 }
1449}
1450
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001451uECC_word_t EccPoint_isZero(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001452{
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001453 return uECC_vli_isZero(point);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001454}
1455
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001456void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001457{
1458 uECC_word_t t1[NUM_ECC_WORDS];
1459
Andrzej Kurek0919b142020-07-06 15:28:59 -04001460 uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001461 uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */
1462 uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */
1463 uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001464}
1465
1466/* P = (x1, y1) => 2P, (x2, y2) => P' */
1467static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
1468 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001469 const uECC_word_t * const initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001470{
1471 uECC_word_t z[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001472 if (initial_Z) {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001473 uECC_vli_set(z, initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001474 } else {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001475 uECC_vli_clear(z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001476 z[0] = 1;
1477 }
1478
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001479 uECC_vli_set(X2, X1);
1480 uECC_vli_set(Y2, Y1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001481
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001482 apply_z(X1, Y1, z);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001483 double_jacobian_default(X1, Y1, z);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001484 apply_z(X2, Y2, z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001485}
1486
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001487static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1488 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001489 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001490{
1491 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1492 uECC_word_t t5[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001493
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001494 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001495 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001496 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1497 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001498 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001499 uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001500
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001501 uECC_vli_modSub(t5, t5, X1, curve_p); /* t5 = D - B */
1502 uECC_vli_modSub(t5, t5, X2, curve_p); /* t5 = D - B - C = x3 */
1503 uECC_vli_modSub(X2, X2, X1, curve_p); /* t3 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001504 uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001505 uECC_vli_modSub(X2, X1, t5, curve_p); /* t3 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001506 uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001507 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001508
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001509 uECC_vli_set(X2, t5);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001510}
1511
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001512void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001513 uECC_word_t * X2, uECC_word_t * Y2)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001514{
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001515 XYcZ_add_rnd(X1, Y1, X2, Y2, NULL);
1516}
1517
Jarno Lamsa18987a42019-04-24 15:40:43 +03001518/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
1519 Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
1520 or P => P - Q, Q => P + Q
1521 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001522static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1523 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001524 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001525{
1526 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1527 uECC_word_t t5[NUM_ECC_WORDS];
1528 uECC_word_t t6[NUM_ECC_WORDS];
1529 uECC_word_t t7[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001530
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001531 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001532 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001533 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1534 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001535 uECC_vli_modAdd(t5, Y2, Y1, curve_p); /* t5 = y2 + y1 */
1536 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001537
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001538 uECC_vli_modSub(t6, X2, X1, curve_p); /* t6 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001539 uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001540 uECC_vli_modAdd(t6, X1, X2, curve_p); /* t6 = B + C */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001541 uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001542 uECC_vli_modSub(X2, X2, t6, curve_p); /* t3 = D - (B + C) = x3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001543
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001544 uECC_vli_modSub(t7, X1, X2, curve_p); /* t7 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001545 uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001546 /* t4 = (y2 - y1)*(B - x3) - E = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001547 uECC_vli_modSub(Y2, Y2, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001548
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001549 uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001550 uECC_vli_modSub(t7, t7, t6, curve_p); /* t7 = F - (B + C) = x3' */
1551 uECC_vli_modSub(t6, t7, X1, curve_p); /* t6 = x3' - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001552 uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001553 /* t2 = (y2+y1)*(x3' - B) - E = y3': */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001554 uECC_vli_modSub(Y1, t6, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001555
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001556 uECC_vli_set(X1, t7);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001557}
1558
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001559static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
Jarno Lamsa18987a42019-04-24 15:40:43 +03001560 const uECC_word_t * scalar,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001561 const uECC_word_t * initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001562{
1563 /* R0 and R1 */
1564 uECC_word_t Rx[2][NUM_ECC_WORDS];
1565 uECC_word_t Ry[2][NUM_ECC_WORDS];
1566 uECC_word_t z[NUM_ECC_WORDS];
1567 bitcount_t i;
1568 uECC_word_t nb;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001569 const wordcount_t num_words = NUM_ECC_WORDS;
1570 const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001571 ecc_wait_state_t wait_state;
1572 ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001573
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001574 uECC_vli_set(Rx[1], point);
1575 uECC_vli_set(Ry[1], point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001576
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001577 XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001578
1579 for (i = num_bits - 2; i > 0; --i) {
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001580 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001581 nb = !uECC_vli_testBit(scalar, i);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001582 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
1583 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001584 }
1585
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001586 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001587 nb = !uECC_vli_testBit(scalar, 0);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001588 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001589
1590 /* Find final 1/Z value. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001591 uECC_vli_modSub(z, Rx[1], Rx[0], curve_p); /* X1 - X0 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001592 uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */
1593 uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001594 uECC_vli_modInv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0))*/
Jarno Lamsa18987a42019-04-24 15:40:43 +03001595 /* yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001596 uECC_vli_modMult_fast(z, z, point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001597 /* Xb * yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001598 uECC_vli_modMult_fast(z, z, Rx[1 - nb]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001599 /* End 1/Z calculation */
1600
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001601 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001602 apply_z(Rx[0], Ry[0], z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001603
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001604 uECC_vli_set(result, Rx[0]);
1605 uECC_vli_set(result + num_words, Ry[0]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001606}
1607
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001608static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001609 uECC_word_t *k1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001610{
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001611 bitcount_t num_n_bits = NUM_ECC_BITS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001612
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001613 uECC_word_t carry = uECC_vli_add(k0, k, curve_n) ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001614 uECC_vli_testBit(k0, num_n_bits);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001615
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001616 uECC_vli_add(k1, k0, curve_n);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001617
1618 return carry;
1619}
1620
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001621int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001622 const uECC_word_t * scalar)
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001623{
1624 uECC_word_t tmp[NUM_ECC_WORDS];
1625 uECC_word_t s[NUM_ECC_WORDS];
1626 uECC_word_t *k2[2] = {tmp, s};
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001627 wordcount_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001628 uECC_word_t carry;
1629 uECC_word_t *initial_Z = 0;
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001630 int r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001631 volatile int problem;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001632
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001633 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001634 problem = -1;
1635 problem = uECC_check_curve_integrity();
1636 if (problem != 0) {
1637 return UECC_FAULT_DETECTED;
1638 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001639 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001640 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001641 return UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001642 }
1643
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001644 /* Protects against invalid curve attacks */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001645 problem = -1;
1646 problem = uECC_valid_point(point);
1647 if (problem != 0) {
1648 /* invalid input, can happen without fault */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001649 return UECC_FAILURE;
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001650 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001651 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001652 if (problem != 0) {
1653 /* failure on second check means fault, though */
1654 return UECC_FAULT_DETECTED;
1655 }
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001656
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001657 /* Regularize the bitcount for the private key so that attackers cannot use a
1658 * side channel attack to learn the number of leading zeros. */
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001659 carry = regularize_k(scalar, tmp, s);
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001660
1661 /* If an RNG function was specified, get a random initial Z value to
Andrzej Kurek0919b142020-07-06 15:28:59 -04001662 * protect against side-channel attacks such as Template SPA */
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001663 if (g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001664 if (uECC_generate_random_int(k2[carry], curve_p, num_words) != UECC_SUCCESS) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001665 r = UECC_FAILURE;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001666 goto clear_and_out;
1667 }
1668 initial_Z = k2[carry];
1669 }
1670
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001671 EccPoint_mult(result, point, k2[!carry], initial_Z);
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001672
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001673 /* Protect against fault injections that would make the resulting
1674 * point not lie on the intended curve */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001675 problem = -1;
1676 problem = uECC_valid_point(result);
1677 if (problem != 0) {
1678 r = UECC_FAULT_DETECTED;
1679 goto clear_and_out;
1680 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001681 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001682 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001683 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001684 goto clear_and_out;
1685 }
1686
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001687 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001688 problem = -1;
1689 problem = uECC_check_curve_integrity();
1690 if (problem != 0) {
1691 r = UECC_FAULT_DETECTED;
1692 goto clear_and_out;
1693 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001694 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001695 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001696 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001697 goto clear_and_out;
1698 }
1699
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001700 r = UECC_SUCCESS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001701
1702clear_and_out:
1703 /* erasing temporary buffer used to store secret: */
1704 mbedtls_platform_zeroize(k2, sizeof(k2));
1705 mbedtls_platform_zeroize(tmp, sizeof(tmp));
1706 mbedtls_platform_zeroize(s, sizeof(s));
1707
1708 return r;
1709}
1710
Jarno Lamsa18987a42019-04-24 15:40:43 +03001711uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001712 uECC_word_t *private_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001713{
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001714 return EccPoint_mult_safer(result, curve_G, private_key);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001715}
1716
1717/* Converts an integer in uECC native format to big-endian bytes. */
1718void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001719 const unsigned int *native)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001720{
1721 wordcount_t i;
1722 for (i = 0; i < num_bytes; ++i) {
1723 unsigned b = num_bytes - 1 - i;
1724 bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
1725 }
1726}
1727
1728/* Converts big-endian bytes to an integer in uECC native format. */
1729void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001730 int num_bytes)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001731{
1732 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001733 uECC_vli_clear(native);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001734 for (i = 0; i < num_bytes; ++i) {
1735 unsigned b = num_bytes - 1 - i;
1736 native[b / uECC_WORD_SIZE] |=
1737 (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
1738 }
1739}
1740
1741int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001742 wordcount_t num_words)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001743{
1744 uECC_word_t mask = (uECC_word_t)-1;
1745 uECC_word_t tries;
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001746 bitcount_t num_bits = uECC_vli_numBits(top);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001747
1748 if (!g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001749 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001750 }
1751
1752 for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
Andrzej Kurek090365f2020-06-08 11:00:51 -04001753 if (g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE) != num_words * uECC_WORD_SIZE) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001754 return UECC_FAILURE;
1755 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001756 random[num_words - 1] &=
Andrzej Kurek0919b142020-07-06 15:28:59 -04001757 mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001758 if (!uECC_vli_isZero(random) &&
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +01001759 uECC_vli_cmp(top, random) == 1) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001760 return UECC_SUCCESS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001761 }
1762 }
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001763 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001764}
1765
1766
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001767int uECC_valid_point(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001768{
1769 uECC_word_t tmp1[NUM_ECC_WORDS];
1770 uECC_word_t tmp2[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001771 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa83d78812019-12-04 14:40:57 +02001772 volatile uECC_word_t diff = 0xffffffff;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001773
1774 /* The point at infinity is invalid. */
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001775 if (EccPoint_isZero(point)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001776 return -1;
1777 }
1778
1779 /* x and y must be smaller than p. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001780 if (uECC_vli_cmp_unsafe(curve_p, point) != 1 ||
1781 uECC_vli_cmp_unsafe(curve_p, point + num_words) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001782 return -2;
1783 }
1784
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001785 uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001786 x_side_default(tmp2, point); /* tmp2 = x^3 + ax + b */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001787
1788 /* Make sure that y^2 == x^3 + ax + b */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001789 diff = uECC_vli_equal(tmp1, tmp2);
1790 if (diff == 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001791 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001792 if (diff == 0) {
1793 return 0;
1794 }
1795 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001796
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001797 return -3;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001798}
1799
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001800int uECC_valid_public_key(const uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001801{
1802
1803 uECC_word_t _public[NUM_ECC_WORDS * 2];
1804
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001805 uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001806 uECC_vli_bytesToNative(
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001807 _public + NUM_ECC_WORDS,
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001808 public_key + NUM_ECC_BYTES,
1809 NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001810
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +01001811 if (memcmp(_public, curve_G, NUM_ECC_WORDS * 2) == 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001812 return -4;
1813 }
1814
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001815 return uECC_valid_point(_public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001816}
1817
Andrzej Kurek0919b142020-07-06 15:28:59 -04001818int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001819{
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001820 int ret = UECC_FAULT_DETECTED;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001821 uECC_word_t _private[NUM_ECC_WORDS];
1822 uECC_word_t _public[NUM_ECC_WORDS * 2];
1823
1824 uECC_vli_bytesToNative(
1825 _private,
1826 private_key,
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +01001827 BITS_TO_BYTES(NUM_ECC_BITS));
Jarno Lamsa18987a42019-04-24 15:40:43 +03001828
1829 /* Make sure the private key is in the range [1, n-1]. */
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001830 if (uECC_vli_isZero(_private)) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001831 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001832 }
1833
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001834 if (uECC_vli_cmp(curve_n, _private) != 1) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001835 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001836 }
1837
1838 /* Compute public key. */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001839 ret = EccPoint_compute_public_key(_public, _private);
1840 if (ret != UECC_SUCCESS) {
1841 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001842 }
1843
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001844 uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001845 uECC_vli_nativeToBytes(
1846 public_key +
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001847 NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS);
Andrzej Kurekcf3e35c2020-07-15 22:32:08 -04001848
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001849 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001850}