blob: cfc527b2f91cf36332ec55aab6a90b98426ecaa2 [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"
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300255 ".syntax divided \n\t"
Kevin Bracey3be252e2020-10-09 12:54:48 +0300256 : "+r" (r0)
257 : "r" (r1), "r" (r2)
258 : "memory"
259#else
260 register uECC_word_t *r0 asm("r0") = vli;
261 register uECC_word_t r1 asm("r1") = 0;
262 asm volatile (
263 "STRD r1,r1,[r0,#0] \n\t" // Only Thumb2 STRD can store same reg twice, not ARM
264 "STRD r1,r1,[r0,#8] \n\t"
265 "STRD r1,r1,[r0,#16] \n\t"
266 "STRD r1,r1,[r0,#24] \n\t"
267 :
268 : "r" (r0), "r" (r1)
269 : "memory"
270#endif
271 );
272}
273#else
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100274void uECC_vli_clear(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300275{
276 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100277 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300278 vli[i] = 0;
279 }
280}
Kevin Bracey3be252e2020-10-09 12:54:48 +0300281#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300282
Kevin Bracey3be252e2020-10-09 12:54:48 +0300283#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
284__asm uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
285{
286#if NUM_ECC_WORDS != 8
287#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
288#endif
289#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
290 LDMIA r0!,{r1,r2,r3}
291 ORRS r1,r2
292 ORRS r1,r3
293 LDMIA r0!,{r2,r3}
294 ORRS r1,r2
295 ORRS r1,r3
296 LDMIA r0,{r0,r2,r3}
297 ORRS r1,r0
298 ORRS r1,r2
299 ORRS r1,r3
300 RSBS r1,r1,#0 // C set if zero
301 MOVS r0,#0
302 ADCS r0,r0
303 BX lr
304#else
305 LDMIA r0!,{r1,r2,r3,ip}
306 ORRS r1,r2
307 ORRS r1,r3
308 ORRS r1,ip
309 LDMIA r0,{r0,r2,r3,ip}
310 ORRS r1,r0
311 ORRS r1,r2
312 ORRS r1,r3
313 ORRS r1,ip
314#ifdef __ARM_FEATURE_CLZ
315 CLZ r0,r1 // 32 if zero
316 LSRS r0,r0,#5
317#else
318 RSBS r1,r1,#0 // C set if zero
319 MOVS r0,#0
320 ADCS r0,r0
321#endif
322 BX lr
323#endif
324}
325#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
326uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
327{
328 uECC_word_t ret;
329#if NUM_ECC_WORDS != 8
330#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
331#endif
332#if defined __thumb__ && !defined __thumb2__
333 register uECC_word_t r1 asm ("r1");
334 register uECC_word_t r2 asm ("r2");
335 register uECC_word_t r3 asm ("r3");
336 asm volatile (
337 ".syntax unified \n\t"
338 "LDMIA %[vli]!,{%[r1],%[r2],%[r3]} \n\t"
339 "ORRS %[r1],%[r2] \n\t"
340 "ORRS %[r1],%[r3] \n\t"
341 "LDMIA %[vli]!,{%[r2],%[r3]} \n\t"
342 "ORRS %[r1],%[r2] \n\t"
343 "ORRS %[r1],%[r3] \n\t"
344 "LDMIA %[vli],{%[vli],%[r2],%[r3]} \n\t"
345 "ORRS %[r1],%[vli] \n\t"
346 "ORRS %[r1],%[r2] \n\t"
347 "ORRS %[r1],%[r3] \n\t"
348 "RSBS %[r1],%[r1],#0 \n\t" // C set if zero
349 "MOVS %[ret],#0 \n\t"
350 "ADCS %[ret],r0 \n\t"
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300351 ".syntax divided \n\t"
Kevin Bracey3be252e2020-10-09 12:54:48 +0300352 : [ret]"=r" (ret), [r1]"=r" (r1), [r2]"=r" (r2), [r3]"=r" (r3)
353 : [vli]"[ret]" (vli)
354 : "cc", "memory"
355 );
356#else
357 register uECC_word_t r1 asm ("r1");
358 register uECC_word_t r2 asm ("r2");
359 register uECC_word_t r3 asm ("r3");
360 register uECC_word_t ip asm ("ip");
361 asm volatile (
362 "LDMIA %[vli]!,{%[r1],%[r2],%[r3],%[ip]}\n\t"
363 "ORRS %[r1],%[r2] \n\t"
364 "ORRS %[r1],%[r3] \n\t"
365 "ORRS %[r1],%[ip] \n\t"
366 "LDMIA %[vli],{%[vli],%[r2],%[r3],%[ip]}\n\t"
367 "ORRS %[r1],%[vli] \n\t"
368 "ORRS %[r1],%[r2] \n\t"
369 "ORRS %[r1],%[r3] \n\t"
370 "ORRS %[r1],%[ip] \n\t"
371#if __ARM_ARCH >= 5
372 "CLZ %[ret],%[r1] \n\t" // r0 = 32 if zero
373 "LSRS %[ret],%[ret],#5 \n\t"
374#else
375 "RSBS %[r1],%[r1],#0 \n\t" // C set if zero
376 "MOVS %[ret],#0 \n\t"
377 "ADCS %[ret],r0 \n\t"
378#endif
379 : [ret]"=r" (ret), [r1]"=r" (r1), [r2]"=r" (r2), [r3]"=r" (r3), [ip]"=r" (ip)
380 : [vli]"[ret]" (vli)
381 : "cc", "memory"
382 );
383#endif
384 return ret;
385}
386#else
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100387uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300388{
389 uECC_word_t bits = 0;
390 wordcount_t i;
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100391 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300392 bits |= vli[i];
393 }
394 return (bits == 0);
395}
Kevin Bracey3be252e2020-10-09 12:54:48 +0300396#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300397
398uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit)
399{
400 return (vli[bit >> uECC_WORD_BITS_SHIFT] &
401 ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
402}
403
404/* Counts the number of words in vli. */
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100405static wordcount_t vli_numDigits(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300406{
407
408 wordcount_t i;
409 /* Search from the end until we find a non-zero digit. We do it in reverse
410 * because we expect that most digits will be nonzero. */
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100411 for (i = NUM_ECC_WORDS - 1; i >= 0 && vli[i] == 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300412 }
413
414 return (i + 1);
415}
416
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100417bitcount_t uECC_vli_numBits(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300418{
419
420 uECC_word_t i;
421 uECC_word_t digit;
422
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100423 wordcount_t num_digits = vli_numDigits(vli);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300424 if (num_digits == 0) {
425 return 0;
426 }
427
428 digit = vli[num_digits - 1];
Kevin Bracey99c64e12020-10-06 12:25:28 +0300429#if defined __GNUC__ || defined __clang__ || defined __CC_ARM
430 i = uECC_WORD_BITS - __builtin_clz(digit);
431#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300432 for (i = 0; digit; ++i) {
433 digit >>= 1;
434 }
Kevin Bracey99c64e12020-10-06 12:25:28 +0300435#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300436
437 return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
438}
439
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100440void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300441{
442 wordcount_t i;
443
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100444 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300445 dest[i] = src[i];
446 }
447}
448
449cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100450 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300451{
452 wordcount_t i;
453
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100454 for (i = NUM_ECC_WORDS - 1; i >= 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300455 if (left[i] > right[i]) {
456 return 1;
457 } else if (left[i] < right[i]) {
458 return -1;
459 }
460 }
461 return 0;
462}
463
Manuel Pégourié-Gonnard2eca3d32019-11-04 14:33:09 +0100464uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300465{
466
467 uECC_word_t diff = 0;
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200468 uECC_word_t flow_monitor = 0;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100469 uECC_word_t tmp1, tmp2;
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100470 volatile int i;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300471
Piotr Nowickif0ab6d62020-05-25 12:48:30 +0200472 /* Start from a random location and check the correct number of iterations */
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200473 int start_offset = mbedtls_platform_random_in_range(NUM_ECC_WORDS);
474
475 for (i = start_offset; i < NUM_ECC_WORDS; ++i) {
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100476 tmp1 = left[i];
477 tmp2 = right[i];
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200478 flow_monitor++;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100479 diff |= (tmp1 ^ tmp2);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300480 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100481
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200482 for (i = 0; i < start_offset; ++i) {
483 tmp1 = left[i];
484 tmp2 = right[i];
485 flow_monitor++;
486 diff |= (tmp1 ^ tmp2);
487 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100488
Piotr Nowickif0ab6d62020-05-25 12:48:30 +0200489 /* Random delay to increase security */
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200490 mbedtls_platform_random_delay();
491
492 /* Return 0 only when diff is 0 and flow_counter is equal to NUM_ECC_WORDS */
493 return (diff | (flow_monitor ^ NUM_ECC_WORDS));
Jarno Lamsa18987a42019-04-24 15:40:43 +0300494}
495
496uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
497{
Kevin Bracey045e5762020-10-06 12:25:58 +0300498 return (p_true*(cond)) | (p_false*(cond ^ 1));
Jarno Lamsa18987a42019-04-24 15:40:43 +0300499}
500
501/* Computes result = left - right, returning borrow, in constant time.
502 * Can modify in place. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300503#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
504__asm uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
505 const uECC_word_t *right)
506{
507#if NUM_ECC_WORDS != 8
508#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
509#endif
510#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
511 PUSH {r4-r6,lr}
512 FRAME PUSH {r4-r6,lr}
513 LDMIA r1!,{r3,r4}
514 LDMIA r2!,{r5,r6}
515 SUBS r3,r5
516 SBCS r4,r6
517 STMIA r0!,{r3,r4}
518 LDMIA r1!,{r3,r4}
519 LDMIA r2!,{r5,r6}
520 SBCS r3,r5
521 SBCS r4,r6
522 STMIA r0!,{r3,r4}
523 LDMIA r1!,{r3,r4}
524 LDMIA r2!,{r5,r6}
525 SBCS r3,r5
526 SBCS r4,r6
527 STMIA r0!,{r3,r4}
528 LDMIA r1!,{r3,r4}
529 LDMIA r2!,{r5,r6}
530 SBCS r3,r5
531 SBCS r4,r6
532 STMIA r0!,{r3,r4}
533 SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow
534 RSBS r0,r0,#0 // r0 := borrow
535 POP {r4-r6,pc}
536#else
537 PUSH {r4-r8,lr}
538 FRAME PUSH {r4-r8,lr}
539 LDMIA r1!,{r3-r6}
540 LDMIA r2!,{r7,r8,r12,lr}
541 SUBS r3,r7
542 SBCS r4,r8
543 SBCS r5,r12
544 SBCS r6,lr
545 STMIA r0!,{r3-r6}
546 LDMIA r1!,{r3-r6}
547 LDMIA r2!,{r7,r8,r12,lr}
548 SBCS r3,r7
549 SBCS r4,r8
550 SBCS r5,r12
551 SBCS r6,lr
552 STMIA r0!,{r3-r6}
553 SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow
554 RSBS r0,r0,#0 // r0 := borrow
555 POP {r4-r8,pc}
556#endif
557}
Kevin Bracey4aea6252020-10-09 12:54:28 +0300558#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
559uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
560 const uECC_word_t *right)
561{
562#if NUM_ECC_WORDS != 8
563#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
564#endif
565 register uECC_word_t *r0 asm ("r0") = result;
566 register const uECC_word_t *r1 asm ("r1") = left;
567 register const uECC_word_t *r2 asm ("r2") = right;
568 asm volatile (
569#if defined __thumb__ && !defined __thumb2__
570 ".syntax unified \n\t"
571 "LDMIA r1!,{r3,r4} \n\t"
572 "LDMIA r2!,{r5,r6} \n\t"
573 "SUBS r3,r5 \n\t"
574 "SBCS r4,r6 \n\t"
575 "STMIA r0!,{r3,r4} \n\t"
576 "LDMIA r1!,{r3,r4} \n\t"
577 "LDMIA r2!,{r5,r6} \n\t"
578 "SBCS r3,r5 \n\t"
579 "SBCS r4,r6 \n\t"
580 "STMIA r0!,{r3,r4} \n\t"
581 "LDMIA r1!,{r3,r4} \n\t"
582 "LDMIA r2!,{r5,r6} \n\t"
583 "SBCS r3,r5 \n\t"
584 "SBCS r4,r6 \n\t"
585 "STMIA r0!,{r3,r4} \n\t"
586 "LDMIA r1!,{r3,r4} \n\t"
587 "LDMIA r2!,{r5,r6} \n\t"
588 "SBCS r3,r5 \n\t"
589 "SBCS r4,r6 \n\t"
590 "STMIA r0!,{r3,r4} \n\t"
591 "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow
592 "RSBS r0,r0,#0 \n\t" // r0 := borrow
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300593 ".syntax divided \n\t"
Kevin Bracey4aea6252020-10-09 12:54:28 +0300594 : "+r" (r0), "+r" (r1), "+r" (r2)
595 :
596 : "r3", "r4", "r5", "r6", "cc", "memory"
597#else
598 "LDMIA r1!,{r3-r6} \n\t"
599 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
600 "SUBS 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 "LDMIA r1!,{r3-r6} \n\t"
606 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
607 "SBCS r3,r7 \n\t"
608 "SBCS r4,r8 \n\t"
609 "SBCS r5,r12 \n\t"
610 "SBCS r6,lr \n\t"
611 "STMIA r0!,{r3-r6} \n\t"
612 "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow
613 "RSBS r0,r0,#0 \n\t" // r0 := borrow
614 : "+r" (r0), "+r" (r1), "+r" (r2)
615 :
616 : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory"
617#endif
618 );
619 return (uECC_word_t) r0;
620}
Kevin Bracey1959c182020-07-16 21:03:19 +0300621#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300622uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100623 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300624{
625 uECC_word_t borrow = 0;
626 wordcount_t i;
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100627 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300628 uECC_word_t diff = left[i] - right[i] - borrow;
629 uECC_word_t val = (diff > left[i]);
630 borrow = cond_set(val, borrow, (diff != left[i]));
631
632 result[i] = diff;
633 }
634 return borrow;
635}
Kevin Bracey1959c182020-07-16 21:03:19 +0300636#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300637
638/* Computes result = left + right, returning carry, in constant time.
639 * Can modify in place. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300640#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
641static __asm uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
642 const uECC_word_t *right)
643{
644#if NUM_ECC_WORDS != 8
645#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
646#endif
647#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
648 PUSH {r4-r6,lr}
649 FRAME PUSH {r4-r6,lr}
650 LDMIA r1!,{r3,r4}
651 LDMIA r2!,{r5,r6}
652 ADDS r3,r5
653 ADCS r4,r6
654 STMIA r0!,{r3,r4}
655 LDMIA r1!,{r3,r4}
656 LDMIA r2!,{r5,r6}
657 ADCS r3,r5
658 ADCS r4,r6
659 STMIA r0!,{r3,r4}
660 LDMIA r1!,{r3,r4}
661 LDMIA r2!,{r5,r6}
662 ADCS r3,r5
663 ADCS r4,r6
664 STMIA r0!,{r3,r4}
665 LDMIA r1!,{r3,r4}
666 LDMIA r2!,{r5,r6}
667 ADCS r3,r5
668 ADCS r4,r6
669 STMIA r0!,{r3,r4}
670 MOVS r0,#0 // does not affect C flag
671 ADCS r0,r0 // r0 := 0 + 0 + C = carry
672 POP {r4-r6,pc}
673#else
674 PUSH {r4-r8,lr}
675 FRAME PUSH {r4-r8,lr}
676 LDMIA r1!,{r3-r6}
677 LDMIA r2!,{r7,r8,r12,lr}
678 ADDS r3,r7
679 ADCS r4,r8
680 ADCS r5,r12
681 ADCS r6,lr
682 STMIA r0!,{r3-r6}
683 LDMIA r1!,{r3-r6}
684 LDMIA r2!,{r7,r8,r12,lr}
685 ADCS r3,r7
686 ADCS r4,r8
687 ADCS r5,r12
688 ADCS r6,lr
689 STMIA r0!,{r3-r6}
690 MOVS r0,#0 // does not affect C flag
691 ADCS r0,r0 // r0 := 0 + 0 + C = carry
692 POP {r4-r8,pc}
693#endif
694}
Kevin Bracey4aea6252020-10-09 12:54:28 +0300695#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
696static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
697 const uECC_word_t *right)
698{
699 register uECC_word_t *r0 asm ("r0") = result;
700 register const uECC_word_t *r1 asm ("r1") = left;
701 register const uECC_word_t *r2 asm ("r2") = right;
702
703 asm volatile (
704#if defined __thumb__ && !defined __thumb2__
705 ".syntax unified \n\t"
706 "LDMIA r1!,{r3,r4} \n\t"
707 "LDMIA r2!,{r5,r6} \n\t"
708 "ADDS r3,r5 \n\t"
709 "ADCS r4,r6 \n\t"
710 "STMIA r0!,{r3,r4} \n\t"
711 "LDMIA r1!,{r3,r4} \n\t"
712 "LDMIA r2!,{r5,r6} \n\t"
713 "ADCS r3,r5 \n\t"
714 "ADCS r4,r6 \n\t"
715 "STMIA r0!,{r3,r4} \n\t"
716 "LDMIA r1!,{r3,r4} \n\t"
717 "LDMIA r2!,{r5,r6} \n\t"
718 "ADCS r3,r5 \n\t"
719 "ADCS r4,r6 \n\t"
720 "STMIA r0!,{r3,r4} \n\t"
721 "LDMIA r1!,{r3,r4} \n\t"
722 "LDMIA r2!,{r5,r6} \n\t"
723 "ADCS r3,r5 \n\t"
724 "ADCS r4,r6 \n\t"
725 "STMIA r0!,{r3,r4} \n\t"
726 "MOVS r0,#0 \n\t" // does not affect C flag
727 "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300728 ".syntax divided \n\t"
Kevin Bracey4aea6252020-10-09 12:54:28 +0300729 : "+r" (r0), "+r" (r1), "+r" (r2)
730 :
731 : "r3", "r4", "r5", "r6", "cc", "memory"
732#else
733 "LDMIA r1!,{r3-r6} \n\t"
734 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
735 "ADDS r3,r7 \n\t"
736 "ADCS r4,r8 \n\t"
737 "ADCS r5,r12 \n\t"
738 "ADCS r6,lr \n\t"
739 "STMIA r0!,{r3-r6} \n\t"
740 "LDMIA r1!,{r3-r6} \n\t"
741 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
742 "ADCS r3,r7 \n\t"
743 "ADCS r4,r8 \n\t"
744 "ADCS r5,r12 \n\t"
745 "ADCS r6,lr \n\t"
746 "STMIA r0!,{r3-r6} \n\t"
747 "MOVS r0,#0 \n\t" // does not affect C flag
748 "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry
749 : "+r" (r0), "+r" (r1), "+r" (r2)
750 :
751 : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory"
752#endif
753 );
754 return (uECC_word_t) r0;
755}
Kevin Bracey1959c182020-07-16 21:03:19 +0300756#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300757static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100758 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300759{
760 uECC_word_t carry = 0;
761 wordcount_t i;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100762 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300763 uECC_word_t sum = left[i] + right[i] + carry;
764 uECC_word_t val = (sum < left[i]);
765 carry = cond_set(val, carry, (sum != left[i]));
766 result[i] = sum;
767 }
768 return carry;
769}
Kevin Bracey1959c182020-07-16 21:03:19 +0300770#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300771
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +0100772cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300773{
774 uECC_word_t tmp[NUM_ECC_WORDS];
Kevin Bracey045e5762020-10-06 12:25:58 +0300775 uECC_word_t neg = uECC_vli_sub(tmp, left, right);
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100776 uECC_word_t equal = uECC_vli_isZero(tmp);
Kevin Bracey045e5762020-10-06 12:25:58 +0300777 return ((equal ^ 1) - 2 * neg);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300778}
779
780/* Computes vli = vli >> 1. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300781#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
782static __asm void uECC_vli_rshift1(uECC_word_t *vli)
783{
784#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
785// RRX instruction is not available, so although we
786// can use C flag, it's not that effective. Does at
787// least save one working register, meaning we don't need stack
788 MOVS r3,#0 // initial carry = 0
789 MOVS r2,#__cpp(4 * (NUM_ECC_WORDS - 1))
79001 LDR r1,[r0,r2]
791 LSRS r1,r1,#1 // r2 = word >> 1
792 ORRS r1,r3 // merge in the previous carry
793 STR r1,[r0,r2]
794 ADCS r3,r3 // put C into bottom bit of r3
795 LSLS r3,r3,#31 // shift it up to the top ready for next word
796 SUBS r2,r2,#4
797 BPL %B01
798 BX lr
799#else
800#if NUM_ECC_WORDS != 8
801#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
802#endif
803// Smooth multiword operation, lots of 32-bit instructions
804 ADDS r0,#32
805 LDMDB r0,{r1-r3,ip}
806 LSRS ip,ip,#1
807 RRXS r3,r3
808 RRXS r2,r2
809 RRXS r1,r1
810 STMDB r0!,{r1-r3,ip}
811 LDMDB r0,{r1-r3,ip}
812 RRXS ip,ip
813 RRXS r3,r3
814 RRXS r2,r2
815 RRX r1,r1
816 STMDB r0!,{r1-r3,ip}
817 BX lr
818#endif
819}
Kevin Bracey06060332020-10-02 17:43:12 +0300820#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__ && defined __thumb2__
821static void uECC_vli_rshift1(uECC_word_t *vli)
822{
823 register uECC_word_t *r0 asm ("r0") = vli;
824#if NUM_ECC_WORDS != 8
825#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
826#endif
827 asm volatile (
828 "ADDS r0,#32 \n\t"
829 "LDMDB r0,{r1-r3,ip} \n\t"
830 "LSRS ip,ip,#1 \n\t"
831 "RRXS r3,r3 \n\t"
832 "RRXS r2,r2 \n\t"
833 "RRXS r1,r1 \n\t"
834 "STMDB r0!,{r1-r3,ip} \n\t"
835 "LDMDB r0,{r1-r3,ip} \n\t"
836 "RRXS ip,ip \n\t"
837 "RRXS r3,r3 \n\t"
838 "RRXS r2,r2 \n\t"
839 "RRX r1,r1 \n\t"
840 "STMDB r0!,{r1-r3,ip} \n\t"
841 : "+r" (r0)
842 :
843 : "r1", "r2", "r3", "ip", "cc", "memory"
844 );
845}
Kevin Bracey1959c182020-07-16 21:03:19 +0300846#else
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100847static void uECC_vli_rshift1(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300848{
849 uECC_word_t *end = vli;
850 uECC_word_t carry = 0;
851
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100852 vli += NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300853 while (vli-- > end) {
854 uECC_word_t temp = *vli;
855 *vli = (temp >> 1) | carry;
856 carry = temp << (uECC_WORD_BITS - 1);
857 }
858}
Kevin Bracey1959c182020-07-16 21:03:19 +0300859#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300860
Kevin Bracey84f31d32020-09-29 17:51:04 +0300861/* Compute a * b + r, where r is a triple-word with high-order word r[2] and
862 * low-order word r[0], and store the result in the same triple-word.
Manuel Pégourié-Gonnard86c4f812019-10-31 13:02:03 +0100863 *
Kevin Bracey84f31d32020-09-29 17:51:04 +0300864 * r[2..0] = a * b + r[2..0]:
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200865 * [in] a, b: operands to be multiplied
Kevin Bracey84f31d32020-09-29 17:51:04 +0300866 * [in] r: 3 words of operand to add
867 * [out] r: 3 words of result
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200868 */
Kevin Bracey1959c182020-07-16 21:03:19 +0300869#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
Kevin Bracey84f31d32020-09-29 17:51:04 +0300870static __asm void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Bracey1959c182020-07-16 21:03:19 +0300871{
872#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
Kevin Bracey84f31d32020-09-29 17:51:04 +0300873 PUSH {r4-r5}
874 FRAME PUSH {r4-r5}
875 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
876 // Separate operands into halfwords
877 UXTH r3,r0 // r3 := a.lo
878 LSRS r4,r0,#16 // r4 := a.hi
879 UXTH r5,r1 // r5 := b.lo
880 LSRS r1,r1,#16 // r1 := b.hi
881 // Multiply halfword pairs
882 MOVS r0,r3
883 MULS r0,r5,r0 // r0 := a.lo * b.lo
884 MULS r3,r1,r3 // r3 := a.lo * b.hi
885 MULS r5,r4,r5 // r5 := a.hi * b.lo
886 MULS r1,r4,r1 // r1 := a.hi * b.hi
887 // Split, shift and add a.lo * b.hi
888 LSRS r4,r3,#16 // r4 := (a.lo * b.hi).hi
889 LSLS r3,r3,#16 // r3 := (a.lo * b.hi).lo
890 ADDS r0,r0,r3 // r0 := a.lo * b.lo + (a.lo * b.hi).lo
891 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
892 // Split, shift and add a.hi * b.lo
893 LSRS r4,r5,#16 // r4 := (a.hi * b.lo).hi
894 LSLS r5,r5,#16 // r5 := (a.hi * b.lo).lo
895 ADDS r0,r0,r5 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
896 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
897 // Finally add r[]
898 LDMIA r2!,{r3,r4,r5}
899 ADDS r3,r3,r0
Kevin Bracey1959c182020-07-16 21:03:19 +0300900 ADCS r4,r1
Kevin Bracey1959c182020-07-16 21:03:19 +0300901 MOVS r0,#0
Kevin Bracey84f31d32020-09-29 17:51:04 +0300902 ADCS r5,r0
903 SUBS r2,#12
904 STMIA r2!,{r3,r4,r5}
905 POP {r4-r5}
906 FRAME POP {r4-r5}
907 BX lr
Kevin Bracey1959c182020-07-16 21:03:19 +0300908#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300909 UMULL r3,ip,r0,r1 // pre-ARMv6 requires Rd[Lo|Hi] != Rn
910 LDMIA r2,{r0,r1}
911 ADDS r0,r0,r3
912 LDR r3,[r2,#8]
913 ADCS r1,r1,ip
914 ADC r3,r3,#0
915 STMIA r2!,{r0,r1,r3}
Kevin Bracey1959c182020-07-16 21:03:19 +0300916 BX lr
917#endif
Kevin Braceye0f88d52020-09-30 12:52:15 +0300918}
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300919#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
920static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Braceye0f88d52020-09-30 12:52:15 +0300921{
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300922 register uECC_word_t r0 asm ("r0") = a;
923 register uECC_word_t r1 asm ("r1") = b;
924 register uECC_word_t *r2 asm ("r2") = r;
925 asm volatile (
Kevin Braceye0f88d52020-09-30 12:52:15 +0300926#if defined __thumb__ && !defined(__thumb2__)
927 ".syntax unified \n\t"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300928 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
929 // Separate operands into halfwords
930 "UXTH r3,r0 \n\t" // r3 := a.lo
931 "LSRS r4,r0,#16 \n\t" // r4 := a.hi
932 "UXTH r5,r1 \n\t" // r5 := b.lo
933 "LSRS r1,r1,#16 \n\t" // r1 := b.hi
934 // Multiply halfword pairs
935 "MOVS r0,r3 \n\t"
936 "MULS r0,r5,r0 \n\t" // r0 := a.lo * b.lo
937 "MULS r3,r1,r3 \n\t" // r3 := a.lo * b.hi
938 "MULS r5,r4,r5 \n\t" // r5 := a.hi * b.lo
939 "MULS r1,r4,r1 \n\t" // r1 := a.hi * b.hi
940 // Split, shift and add a.lo * b.hi
941 "LSRS r4,r3,#16 \n\t" // r4 := (a.lo * b.hi).hi
942 "LSLS r3,r3,#16 \n\t" // r3 := (a.lo * b.hi).lo
943 "ADDS r0,r0,r3 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo
944 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
945 // Split, shift and add a.hi * b.lo
946 "LSRS r4,r5,#16 \n\t" // r4 := (a.hi * b.lo).hi
947 "LSLS r5,r5,#16 \n\t" // r5 := (a.hi * b.lo).lo
948 "ADDS r0,r0,r5 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
949 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
950 // Finally add r[]
951 "LDMIA r2!,{r3,r4,r5} \n\t"
952 "ADDS r3,r3,r0 \n\t"
953 "ADCS r4,r1 \n\t"
954 "MOVS r0,#0 \n\t"
955 "ADCS r5,r0 \n\t"
956 "SUBS r2,#12 \n\t"
957 "STMIA r2!,{r3,r4,r5} \n\t"
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300958 ".syntax divided \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300959 : "+r" (r0), "+r" (r1), "+r" (r2)
960 :
961 : "r3", "r4", "r5", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300962#else
963 "UMULL r3,ip,r0,r1 \n\t" // pre-ARMv6 requires Rd[Lo|Hi] != Rn
964 "LDMIA r2,{r0,r1} \n\t"
965 "ADDS r0,r0,r3 \n\t"
966 "LDR r3,[r2,#8] \n\t"
967 "ADCS r1,r1,ip \n\t"
968 "ADC r3,r3,#0 \n\t"
969 "STMIA r2!,{r0,r1,r3} \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300970 : "+r" (r0), "+r" (r1), "+r" (r2)
971 :
972 : "r3", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300973#endif
974 );
Kevin Bracey1959c182020-07-16 21:03:19 +0300975}
976#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300977static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Jarno Lamsa18987a42019-04-24 15:40:43 +0300978{
979
980 uECC_dword_t p = (uECC_dword_t)a * b;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300981 uECC_dword_t r01 = ((uECC_dword_t)(r[1]) << uECC_WORD_BITS) | r[0];
Jarno Lamsa18987a42019-04-24 15:40:43 +0300982 r01 += p;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300983 r[2] += (r01 < p);
984 r[1] = r01 >> uECC_WORD_BITS;
985 r[0] = (uECC_word_t)r01;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300986}
Kevin Bracey1959c182020-07-16 21:03:19 +0300987#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300988
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200989/* State for implementing random delays in uECC_vli_mult_rnd().
990 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100991 * The state is initialized by randomizing delays and setting i = 0.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200992 * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i.
993 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100994 * Randomized vli multiplication is used only for point operations
995 * (XYcZ_add_rnd() * and XYcZ_addC_rnd()) in scalar multiplication
996 * (ECCPoint_mult()). Those go in pair, and each pair does 14 calls to
997 * uECC_vli_mult_rnd() (6 in XYcZ_add_rnd() and 8 in XYcZ_addC_rnd(),
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100998 * indirectly through uECC_vli_modMult_rnd().
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100999 *
1000 * Considering this, in order to minimize the number of calls to the RNG
1001 * (which impact performance) while keeping the size of the structure low,
1002 * make room for 14 randomized vli mults, which corresponds to one step in the
1003 * scalar multiplication routine.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001004 */
1005typedef struct {
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001006 uint8_t i;
1007 uint8_t delays[14];
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001008} ecc_wait_state_t;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001009
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001010/*
1011 * Reset wait_state so that it's ready to be used.
1012 */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001013void ecc_wait_state_reset(ecc_wait_state_t *ws)
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001014{
1015 if (ws == NULL)
1016 return;
1017
1018 ws->i = 0;
Shelly Liberman05beb9a2020-09-13 15:23:56 +03001019 mbedtls_platform_random_buf(ws->delays, sizeof(ws->delays));
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001020}
1021
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001022/* Computes result = left * right. Result must be 2 * num_words long.
1023 *
1024 * As a counter-measure against horizontal attacks, add noise by performing
1025 * a random number of extra computations performing random additional accesses
1026 * to limbs of the input.
1027 *
1028 * Each of the two actual computation loops is surrounded by two
1029 * similar-looking waiting loops, to make the beginning and end of the actual
1030 * computation harder to spot.
1031 *
1032 * We add 4 waiting loops of between 0 and 3 calls to muladd() each. That
1033 * makes an average of 6 extra calls. Compared to the main computation which
1034 * makes 64 such calls, this represents an average performance degradation of
1035 * less than 10%.
1036 *
1037 * Compared to the original uECC_vli_mult(), loose the num_words argument as we
1038 * know it's always 8. This saves a bit of code size and execution speed.
1039 */
1040static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001041 const uECC_word_t *right, ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001042{
1043
Kevin Bracey84f31d32020-09-29 17:51:04 +03001044 uECC_word_t r[3] = { 0, 0, 0 };
Jarno Lamsa18987a42019-04-24 15:40:43 +03001045 wordcount_t i, k;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001046 const uint8_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001047
1048 /* Fetch 8 bit worth of delay from the state; 0 if we have no state */
1049 uint8_t delays = s ? s->delays[s->i++] : 0;
Kevin Bracey84f31d32020-09-29 17:51:04 +03001050 uECC_word_t rr[3] = { 0, 0, 0 };
1051 volatile uECC_word_t rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001052
1053 /* Mimic start of next loop: k in [0, 3] */
1054 k = 0 + (delays & 0x03);
1055 delays >>= 2;
1056 /* k = 0 -> i in [1, 0] -> 0 extra muladd;
1057 * k = 3 -> i in [1, 3] -> 3 extra muladd */
Manuel Pégourié-Gonnardc8814862019-11-05 10:32:37 +01001058 for (i = 1; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001059 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001060 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001061 rdummy = rr[0];
1062 rr[0] = rr[1];
1063 rr[1] = rr[2];
1064 rr[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001065
1066 /* Compute each digit of result in sequence, maintaining the carries. */
1067 for (k = 0; k < num_words; ++k) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001068 for (i = 0; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001069 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001070 }
1071
Kevin Bracey84f31d32020-09-29 17:51:04 +03001072 result[k] = r[0];
1073 r[0] = r[1];
1074 r[1] = r[2];
1075 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001076 }
1077
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001078 /* Mimic end of previous loop: k in [4, 7] */
1079 k = 4 + (delays & 0x03);
1080 delays >>= 2;
1081 /* k = 4 -> i in [5, 4] -> 0 extra muladd;
1082 * k = 7 -> i in [5, 7] -> 3 extra muladd */
1083 for (i = 5; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001084 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001085 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001086 rdummy = rr[0];
1087 rr[0] = rr[1];
1088 rr[1] = rr[2];
1089 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001090
1091 /* Mimic start of next loop: k in [8, 11] */
1092 k = 11 - (delays & 0x03);
1093 delays >>= 2;
1094 /* k = 8 -> i in [5, 7] -> 3 extra muladd;
1095 * k = 11 -> i in [8, 7] -> 0 extra muladd */
1096 for (i = (k + 5) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001097 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001098 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001099 rdummy = rr[0];
1100 rr[0] = rr[1];
1101 rr[1] = rr[2];
1102 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001103
Jarno Lamsa18987a42019-04-24 15:40:43 +03001104 for (k = num_words; k < num_words * 2 - 1; ++k) {
1105
1106 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001107 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001108 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001109 result[k] = r[0];
1110 r[0] = r[1];
1111 r[1] = r[2];
1112 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001113 }
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001114
Kevin Bracey84f31d32020-09-29 17:51:04 +03001115 result[num_words * 2 - 1] = r[0];
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001116
1117 /* Mimic end of previous loop: k in [12, 15] */
1118 k = 15 - (delays & 0x03);
1119 delays >>= 2;
1120 /* k = 12 -> i in [5, 7] -> 3 extra muladd;
1121 * k = 15 -> i in [8, 7] -> 0 extra muladd */
1122 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001123 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001124 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001125 rdummy = rr[0];
1126 rr[0] = rr[1];
1127 rr[1] = rr[2];
1128 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001129
Kevin Bracey84f31d32020-09-29 17:51:04 +03001130 /* avoid warning that rdummy is set but not used */
1131 (void) rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001132}
1133
Jarno Lamsa18987a42019-04-24 15:40:43 +03001134void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001135 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001136{
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001137 uECC_word_t carry = uECC_vli_add(result, left, right);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001138 if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001139 /* result > mod (result = mod + remainder), so subtract mod to get
1140 * remainder. */
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001141 uECC_vli_sub(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001142 }
1143}
1144
1145void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001146 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001147{
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001148 uECC_word_t l_borrow = uECC_vli_sub(result, left, right);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001149 if (l_borrow) {
1150 /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
1151 * we can get the correct result from result + mod (with overflow). */
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001152 uECC_vli_add(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001153 }
1154}
1155
1156/* Computes result = product % mod, where product is 2N words long. */
1157/* Currently only designed to work for curve_p or curve_n. */
1158void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001159 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001160{
1161 uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
1162 uECC_word_t tmp[2 * NUM_ECC_WORDS];
1163 uECC_word_t *v[2] = {tmp, product};
1164 uECC_word_t index;
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +01001165 const wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001166
1167 /* Shift mod so its highest set bit is at the maximum position. */
1168 bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001169 uECC_vli_numBits(mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001170 wordcount_t word_shift = shift / uECC_WORD_BITS;
1171 wordcount_t bit_shift = shift % uECC_WORD_BITS;
1172 uECC_word_t carry = 0;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001173 uECC_vli_clear(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001174 if (bit_shift > 0) {
1175 for(index = 0; index < (uECC_word_t)num_words; ++index) {
1176 mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
1177 carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
1178 }
1179 } else {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001180 uECC_vli_set(mod_multiple + word_shift, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001181 }
1182
1183 for (index = 1; shift >= 0; --shift) {
1184 uECC_word_t borrow = 0;
1185 wordcount_t i;
1186 for (i = 0; i < num_words * 2; ++i) {
1187 uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
1188 if (diff != v[index][i]) {
1189 borrow = (diff > v[index][i]);
1190 }
1191 v[1 - index][i] = diff;
1192 }
1193 /* Swap the index if there was no borrow */
1194 index = !(index ^ borrow);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001195 uECC_vli_rshift1(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001196 mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
Andrzej Kurek0919b142020-07-06 15:28:59 -04001197 (uECC_WORD_BITS - 1);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001198 uECC_vli_rshift1(mod_multiple + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001199 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001200 uECC_vli_set(result, v[index]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001201}
1202
1203void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001204 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001205{
1206 uECC_word_t product[2 * NUM_ECC_WORDS];
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001207 uECC_vli_mult_rnd(product, left, right, NULL);
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +01001208 uECC_vli_mmod(result, product, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001209}
1210
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001211static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001212 const uECC_word_t *right, ecc_wait_state_t *s)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001213{
1214 uECC_word_t product[2 * NUM_ECC_WORDS];
1215 uECC_vli_mult_rnd(product, left, right, s);
1216
1217 vli_mmod_fast_secp256r1(result, product);
1218}
1219
Jarno Lamsa18987a42019-04-24 15:40:43 +03001220void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001221 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001222{
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001223 uECC_vli_modMult_rnd(result, left, right, NULL);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001224}
1225
Jarno Lamsa18987a42019-04-24 15:40:43 +03001226#define EVEN(vli) (!(vli[0] & 1))
1227
1228static void vli_modInv_update(uECC_word_t *uv,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001229 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001230{
1231
1232 uECC_word_t carry = 0;
1233
1234 if (!EVEN(uv)) {
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001235 carry = uECC_vli_add(uv, uv, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001236 }
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001237 uECC_vli_rshift1(uv);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001238 if (carry) {
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +01001239 uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001240 }
1241}
1242
1243void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001244 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001245{
1246 uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
1247 uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
1248 cmpresult_t cmpResult;
1249
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001250 if (uECC_vli_isZero(input)) {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001251 uECC_vli_clear(result);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001252 return;
1253 }
1254
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001255 uECC_vli_set(a, input);
1256 uECC_vli_set(b, mod);
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001257 uECC_vli_clear(u);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001258 u[0] = 1;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001259 uECC_vli_clear(v);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001260 while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001261 if (EVEN(a)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001262 uECC_vli_rshift1(a);
Andrzej Kurek0919b142020-07-06 15:28:59 -04001263 vli_modInv_update(u, mod);
1264 } else if (EVEN(b)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001265 uECC_vli_rshift1(b);
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +01001266 vli_modInv_update(v, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001267 } else if (cmpResult > 0) {
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001268 uECC_vli_sub(a, a, b);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001269 uECC_vli_rshift1(a);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001270 if (uECC_vli_cmp_unsafe(u, v) < 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001271 uECC_vli_add(u, u, mod);
1272 }
1273 uECC_vli_sub(u, u, v);
1274 vli_modInv_update(u, mod);
1275 } else {
1276 uECC_vli_sub(b, b, a);
1277 uECC_vli_rshift1(b);
1278 if (uECC_vli_cmp_unsafe(v, u) < 0) {
1279 uECC_vli_add(v, v, mod);
1280 }
1281 uECC_vli_sub(v, v, u);
1282 vli_modInv_update(v, mod);
1283 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001284 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001285 uECC_vli_set(result, u);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001286}
1287
1288/* ------ Point operations ------ */
1289
1290void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001291 uECC_word_t * Z1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001292{
1293 /* t1 = X, t2 = Y, t3 = Z */
1294 uECC_word_t t4[NUM_ECC_WORDS];
1295 uECC_word_t t5[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001296 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001297
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001298 if (uECC_vli_isZero(Z1)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001299 return;
1300 }
1301
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001302 uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */
1303 uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */
1304 uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */
1305 uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */
1306 uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001307
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001308 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = x1 + z1^2 */
1309 uECC_vli_modAdd(Z1, Z1, Z1, curve_p); /* t3 = 2*z1^2 */
1310 uECC_vli_modSub(Z1, X1, Z1, curve_p); /* t3 = x1 - z1^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001311 uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001312
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001313 uECC_vli_modAdd(Z1, X1, X1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
1314 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001315 if (uECC_vli_testBit(X1, 0)) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001316 uECC_word_t l_carry = uECC_vli_add(X1, X1, curve_p);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001317 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001318 X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
1319 } else {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001320 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001321 }
1322
1323 /* t1 = 3/2*(x1^2 - z1^4) = B */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001324 uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001325 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - A */
1326 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
1327 uECC_vli_modSub(t5, t5, Z1, curve_p); /* t5 = A - x3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001328 uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001329 /* t4 = B * (A - x3) - y1^4 = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001330 uECC_vli_modSub(t4, X1, t4, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001331
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001332 uECC_vli_set(X1, Z1);
1333 uECC_vli_set(Z1, Y1);
1334 uECC_vli_set(Y1, t4);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001335}
1336
Manuel Pégourié-Gonnard1c6f7ea2019-11-21 09:18:29 +01001337/*
1338 * @brief Computes x^3 + ax + b. result must not overlap x.
1339 * @param result OUT -- x^3 + ax + b
1340 * @param x IN -- value of x
1341 * @param curve IN -- elliptic curve
1342 */
1343static void x_side_default(uECC_word_t *result,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001344 const uECC_word_t *x)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001345{
1346 uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001347
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001348 uECC_vli_modMult_fast(result, x, x); /* r = x^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001349 uECC_vli_modSub(result, result, _3, curve_p); /* r = x^2 - 3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001350 uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001351 /* r = x^3 - 3x + b: */
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +01001352 uECC_vli_modAdd(result, result, curve_b, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001353}
1354
1355void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
1356{
1357 unsigned int tmp[NUM_ECC_WORDS];
1358 int carry;
1359
1360 /* t */
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001361 uECC_vli_set(result, product);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001362
1363 /* s1 */
1364 tmp[0] = tmp[1] = tmp[2] = 0;
1365 tmp[3] = product[11];
1366 tmp[4] = product[12];
1367 tmp[5] = product[13];
1368 tmp[6] = product[14];
1369 tmp[7] = product[15];
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 /* s2 */
1374 tmp[3] = product[12];
1375 tmp[4] = product[13];
1376 tmp[5] = product[14];
1377 tmp[6] = product[15];
1378 tmp[7] = 0;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001379 carry += uECC_vli_add(tmp, tmp, tmp);
1380 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001381
1382 /* s3 */
1383 tmp[0] = product[8];
1384 tmp[1] = product[9];
1385 tmp[2] = product[10];
1386 tmp[3] = tmp[4] = tmp[5] = 0;
1387 tmp[6] = product[14];
1388 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001389 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001390
1391 /* s4 */
1392 tmp[0] = product[9];
1393 tmp[1] = product[10];
1394 tmp[2] = product[11];
1395 tmp[3] = product[13];
1396 tmp[4] = product[14];
1397 tmp[5] = product[15];
1398 tmp[6] = product[13];
1399 tmp[7] = product[8];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001400 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001401
1402 /* d1 */
1403 tmp[0] = product[11];
1404 tmp[1] = product[12];
1405 tmp[2] = product[13];
1406 tmp[3] = tmp[4] = tmp[5] = 0;
1407 tmp[6] = product[8];
1408 tmp[7] = product[10];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001409 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001410
1411 /* d2 */
1412 tmp[0] = product[12];
1413 tmp[1] = product[13];
1414 tmp[2] = product[14];
1415 tmp[3] = product[15];
1416 tmp[4] = tmp[5] = 0;
1417 tmp[6] = product[9];
1418 tmp[7] = product[11];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001419 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001420
1421 /* d3 */
1422 tmp[0] = product[13];
1423 tmp[1] = product[14];
1424 tmp[2] = product[15];
1425 tmp[3] = product[8];
1426 tmp[4] = product[9];
1427 tmp[5] = product[10];
1428 tmp[6] = 0;
1429 tmp[7] = product[12];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001430 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001431
1432 /* d4 */
1433 tmp[0] = product[14];
1434 tmp[1] = product[15];
1435 tmp[2] = 0;
1436 tmp[3] = product[9];
1437 tmp[4] = product[10];
1438 tmp[5] = product[11];
1439 tmp[6] = 0;
1440 tmp[7] = product[13];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001441 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001442
1443 if (carry < 0) {
1444 do {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001445 carry += uECC_vli_add(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001446 }
1447 while (carry < 0);
1448 } else {
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +02001449 while (carry ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001450 uECC_vli_cmp_unsafe(curve_p, result) != 1) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001451 carry -= uECC_vli_sub(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001452 }
1453 }
1454}
1455
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001456uECC_word_t EccPoint_isZero(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001457{
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001458 return uECC_vli_isZero(point);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001459}
1460
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001461void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001462{
1463 uECC_word_t t1[NUM_ECC_WORDS];
1464
Andrzej Kurek0919b142020-07-06 15:28:59 -04001465 uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001466 uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */
1467 uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */
1468 uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001469}
1470
1471/* P = (x1, y1) => 2P, (x2, y2) => P' */
1472static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
1473 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001474 const uECC_word_t * const initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001475{
1476 uECC_word_t z[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001477 if (initial_Z) {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001478 uECC_vli_set(z, initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001479 } else {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001480 uECC_vli_clear(z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001481 z[0] = 1;
1482 }
1483
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001484 uECC_vli_set(X2, X1);
1485 uECC_vli_set(Y2, Y1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001486
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001487 apply_z(X1, Y1, z);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001488 double_jacobian_default(X1, Y1, z);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001489 apply_z(X2, Y2, z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001490}
1491
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001492static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1493 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001494 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001495{
1496 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1497 uECC_word_t t5[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001498
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001499 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001500 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001501 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1502 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001503 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001504 uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001505
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001506 uECC_vli_modSub(t5, t5, X1, curve_p); /* t5 = D - B */
1507 uECC_vli_modSub(t5, t5, X2, curve_p); /* t5 = D - B - C = x3 */
1508 uECC_vli_modSub(X2, X2, X1, curve_p); /* t3 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001509 uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001510 uECC_vli_modSub(X2, X1, t5, curve_p); /* t3 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001511 uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001512 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001513
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001514 uECC_vli_set(X2, t5);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001515}
1516
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001517void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001518 uECC_word_t * X2, uECC_word_t * Y2)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001519{
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001520 XYcZ_add_rnd(X1, Y1, X2, Y2, NULL);
1521}
1522
Jarno Lamsa18987a42019-04-24 15:40:43 +03001523/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
1524 Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
1525 or P => P - Q, Q => P + Q
1526 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001527static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1528 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001529 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001530{
1531 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1532 uECC_word_t t5[NUM_ECC_WORDS];
1533 uECC_word_t t6[NUM_ECC_WORDS];
1534 uECC_word_t t7[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001535
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001536 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001537 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001538 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1539 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001540 uECC_vli_modAdd(t5, Y2, Y1, curve_p); /* t5 = y2 + y1 */
1541 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001542
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001543 uECC_vli_modSub(t6, X2, X1, curve_p); /* t6 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001544 uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001545 uECC_vli_modAdd(t6, X1, X2, curve_p); /* t6 = B + C */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001546 uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001547 uECC_vli_modSub(X2, X2, t6, curve_p); /* t3 = D - (B + C) = x3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001548
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001549 uECC_vli_modSub(t7, X1, X2, curve_p); /* t7 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001550 uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001551 /* t4 = (y2 - y1)*(B - x3) - E = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001552 uECC_vli_modSub(Y2, Y2, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001553
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001554 uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001555 uECC_vli_modSub(t7, t7, t6, curve_p); /* t7 = F - (B + C) = x3' */
1556 uECC_vli_modSub(t6, t7, X1, curve_p); /* t6 = x3' - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001557 uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001558 /* t2 = (y2+y1)*(x3' - B) - E = y3': */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001559 uECC_vli_modSub(Y1, t6, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001560
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001561 uECC_vli_set(X1, t7);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001562}
1563
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001564static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
Jarno Lamsa18987a42019-04-24 15:40:43 +03001565 const uECC_word_t * scalar,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001566 const uECC_word_t * initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001567{
1568 /* R0 and R1 */
1569 uECC_word_t Rx[2][NUM_ECC_WORDS];
1570 uECC_word_t Ry[2][NUM_ECC_WORDS];
1571 uECC_word_t z[NUM_ECC_WORDS];
1572 bitcount_t i;
1573 uECC_word_t nb;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001574 const wordcount_t num_words = NUM_ECC_WORDS;
1575 const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001576 ecc_wait_state_t wait_state;
1577 ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001578
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001579 uECC_vli_set(Rx[1], point);
1580 uECC_vli_set(Ry[1], point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001581
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001582 XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001583
1584 for (i = num_bits - 2; i > 0; --i) {
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001585 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001586 nb = !uECC_vli_testBit(scalar, i);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001587 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
1588 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001589 }
1590
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001591 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001592 nb = !uECC_vli_testBit(scalar, 0);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001593 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001594
1595 /* Find final 1/Z value. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001596 uECC_vli_modSub(z, Rx[1], Rx[0], curve_p); /* X1 - X0 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001597 uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */
1598 uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001599 uECC_vli_modInv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0))*/
Jarno Lamsa18987a42019-04-24 15:40:43 +03001600 /* yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001601 uECC_vli_modMult_fast(z, z, point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001602 /* Xb * yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001603 uECC_vli_modMult_fast(z, z, Rx[1 - nb]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001604 /* End 1/Z calculation */
1605
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001606 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001607 apply_z(Rx[0], Ry[0], z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001608
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001609 uECC_vli_set(result, Rx[0]);
1610 uECC_vli_set(result + num_words, Ry[0]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001611}
1612
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001613static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001614 uECC_word_t *k1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001615{
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001616 bitcount_t num_n_bits = NUM_ECC_BITS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001617
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001618 uECC_word_t carry = uECC_vli_add(k0, k, curve_n) ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001619 uECC_vli_testBit(k0, num_n_bits);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001620
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001621 uECC_vli_add(k1, k0, curve_n);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001622
1623 return carry;
1624}
1625
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001626int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001627 const uECC_word_t * scalar)
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001628{
1629 uECC_word_t tmp[NUM_ECC_WORDS];
1630 uECC_word_t s[NUM_ECC_WORDS];
1631 uECC_word_t *k2[2] = {tmp, s};
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001632 wordcount_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001633 uECC_word_t carry;
1634 uECC_word_t *initial_Z = 0;
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001635 int r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001636 volatile int problem;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001637
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001638 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001639 problem = -1;
1640 problem = uECC_check_curve_integrity();
1641 if (problem != 0) {
1642 return UECC_FAULT_DETECTED;
1643 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001644 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001645 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001646 return UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001647 }
1648
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001649 /* Protects against invalid curve attacks */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001650 problem = -1;
1651 problem = uECC_valid_point(point);
1652 if (problem != 0) {
1653 /* invalid input, can happen without fault */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001654 return UECC_FAILURE;
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001655 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001656 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001657 if (problem != 0) {
1658 /* failure on second check means fault, though */
1659 return UECC_FAULT_DETECTED;
1660 }
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001661
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001662 /* Regularize the bitcount for the private key so that attackers cannot use a
1663 * side channel attack to learn the number of leading zeros. */
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001664 carry = regularize_k(scalar, tmp, s);
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001665
1666 /* If an RNG function was specified, get a random initial Z value to
Andrzej Kurek0919b142020-07-06 15:28:59 -04001667 * protect against side-channel attacks such as Template SPA */
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001668 if (g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001669 if (uECC_generate_random_int(k2[carry], curve_p, num_words) != UECC_SUCCESS) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001670 r = UECC_FAILURE;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001671 goto clear_and_out;
1672 }
1673 initial_Z = k2[carry];
1674 }
1675
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001676 EccPoint_mult(result, point, k2[!carry], initial_Z);
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001677
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001678 /* Protect against fault injections that would make the resulting
1679 * point not lie on the intended curve */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001680 problem = -1;
1681 problem = uECC_valid_point(result);
1682 if (problem != 0) {
1683 r = UECC_FAULT_DETECTED;
1684 goto clear_and_out;
1685 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001686 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001687 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001688 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001689 goto clear_and_out;
1690 }
1691
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001692 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001693 problem = -1;
1694 problem = uECC_check_curve_integrity();
1695 if (problem != 0) {
1696 r = UECC_FAULT_DETECTED;
1697 goto clear_and_out;
1698 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001699 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001700 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001701 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001702 goto clear_and_out;
1703 }
1704
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001705 r = UECC_SUCCESS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001706
1707clear_and_out:
1708 /* erasing temporary buffer used to store secret: */
1709 mbedtls_platform_zeroize(k2, sizeof(k2));
1710 mbedtls_platform_zeroize(tmp, sizeof(tmp));
1711 mbedtls_platform_zeroize(s, sizeof(s));
1712
1713 return r;
1714}
1715
Jarno Lamsa18987a42019-04-24 15:40:43 +03001716uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001717 uECC_word_t *private_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001718{
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001719 return EccPoint_mult_safer(result, curve_G, private_key);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001720}
1721
1722/* Converts an integer in uECC native format to big-endian bytes. */
1723void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001724 const unsigned int *native)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001725{
1726 wordcount_t i;
1727 for (i = 0; i < num_bytes; ++i) {
1728 unsigned b = num_bytes - 1 - i;
1729 bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
1730 }
1731}
1732
1733/* Converts big-endian bytes to an integer in uECC native format. */
1734void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001735 int num_bytes)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001736{
1737 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001738 uECC_vli_clear(native);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001739 for (i = 0; i < num_bytes; ++i) {
1740 unsigned b = num_bytes - 1 - i;
1741 native[b / uECC_WORD_SIZE] |=
1742 (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
1743 }
1744}
1745
1746int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001747 wordcount_t num_words)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001748{
1749 uECC_word_t mask = (uECC_word_t)-1;
1750 uECC_word_t tries;
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001751 bitcount_t num_bits = uECC_vli_numBits(top);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001752
1753 if (!g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001754 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001755 }
1756
1757 for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
Andrzej Kurek090365f2020-06-08 11:00:51 -04001758 if (g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE) != num_words * uECC_WORD_SIZE) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001759 return UECC_FAILURE;
1760 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001761 random[num_words - 1] &=
Andrzej Kurek0919b142020-07-06 15:28:59 -04001762 mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001763 if (!uECC_vli_isZero(random) &&
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +01001764 uECC_vli_cmp(top, random) == 1) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001765 return UECC_SUCCESS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001766 }
1767 }
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001768 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001769}
1770
1771
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001772int uECC_valid_point(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001773{
1774 uECC_word_t tmp1[NUM_ECC_WORDS];
1775 uECC_word_t tmp2[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001776 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa83d78812019-12-04 14:40:57 +02001777 volatile uECC_word_t diff = 0xffffffff;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001778
1779 /* The point at infinity is invalid. */
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001780 if (EccPoint_isZero(point)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001781 return -1;
1782 }
1783
1784 /* x and y must be smaller than p. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001785 if (uECC_vli_cmp_unsafe(curve_p, point) != 1 ||
1786 uECC_vli_cmp_unsafe(curve_p, point + num_words) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001787 return -2;
1788 }
1789
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001790 uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001791 x_side_default(tmp2, point); /* tmp2 = x^3 + ax + b */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001792
1793 /* Make sure that y^2 == x^3 + ax + b */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001794 diff = uECC_vli_equal(tmp1, tmp2);
1795 if (diff == 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001796 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001797 if (diff == 0) {
1798 return 0;
1799 }
1800 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001801
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001802 return -3;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001803}
1804
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001805int uECC_valid_public_key(const uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001806{
1807
1808 uECC_word_t _public[NUM_ECC_WORDS * 2];
1809
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001810 uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001811 uECC_vli_bytesToNative(
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001812 _public + NUM_ECC_WORDS,
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001813 public_key + NUM_ECC_BYTES,
1814 NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001815
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +01001816 if (memcmp(_public, curve_G, NUM_ECC_WORDS * 2) == 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001817 return -4;
1818 }
1819
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001820 return uECC_valid_point(_public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001821}
1822
Andrzej Kurek0919b142020-07-06 15:28:59 -04001823int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001824{
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001825 int ret = UECC_FAULT_DETECTED;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001826 uECC_word_t _private[NUM_ECC_WORDS];
1827 uECC_word_t _public[NUM_ECC_WORDS * 2];
1828
1829 uECC_vli_bytesToNative(
1830 _private,
1831 private_key,
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +01001832 BITS_TO_BYTES(NUM_ECC_BITS));
Jarno Lamsa18987a42019-04-24 15:40:43 +03001833
1834 /* Make sure the private key is in the range [1, n-1]. */
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001835 if (uECC_vli_isZero(_private)) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001836 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001837 }
1838
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001839 if (uECC_vli_cmp(curve_n, _private) != 1) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001840 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001841 }
1842
1843 /* Compute public key. */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001844 ret = EccPoint_compute_public_key(_public, _private);
1845 if (ret != UECC_SUCCESS) {
1846 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001847 }
1848
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001849 uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001850 uECC_vli_nativeToBytes(
1851 public_key +
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001852 NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS);
Andrzej Kurekcf3e35c2020-07-15 22:32:08 -04001853
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001854 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001855}