blob: 1a1643836909615ba5af72cbb928f3af7196d542 [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
Andrzej Kurek7e62c312020-10-14 12:02:40 +020066#if defined(MBEDTLS_USE_TINYCRYPT)
Jarno Lamsa18987a42019-04-24 15:40:43 +030067#include <tinycrypt/ecc.h>
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +010068#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +010069#include "mbedtls/sha256.h"
Jarno Lamsa18987a42019-04-24 15:40:43 +030070#include <string.h>
Shelly Liberman05beb9a2020-09-13 15:23:56 +030071#include "mbedtls/platform_util.h"
Jarno Lamsa18987a42019-04-24 15:40:43 +030072
Andrzej Kurek7aebd7f2021-01-14 07:48:49 -050073#if defined(MBEDTLS_PLATFORM_FAULT_CALLBACKS)
74#include "platform_fault.h"
75#else
76static void mbedtls_platform_fault(){}
77#endif
78
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +020079#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM
Kevin Bracey1959c182020-07-16 21:03:19 +030080#ifndef asm
81#define asm __asm
82#endif
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +020083#endif /* MBEDTLS_OPTIMIZE_TINYCRYPT_ASM */
Kevin Bracey1959c182020-07-16 21:03:19 +030084
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +010085/* Parameters for curve NIST P-256 aka secp256r1 */
86const uECC_word_t curve_p[NUM_ECC_WORDS] = {
87 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
88 BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
89 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
90 BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)
91};
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +010092const uECC_word_t curve_n[NUM_ECC_WORDS] = {
93 BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
94 BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
95 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
96 BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)
97};
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +010098const uECC_word_t curve_G[2 * NUM_ECC_WORDS] = {
99 BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
100 BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
101 BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
102 BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
103 BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
104 BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
105 BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
106 BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)
107};
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +0100108const uECC_word_t curve_b[NUM_ECC_WORDS] = {
109 BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
110 BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
111 BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
112 BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)
113};
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100114
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100115static int uECC_update_param_sha256(mbedtls_sha256_context *ctx,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400116 const uECC_word_t val[NUM_ECC_WORDS])
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100117{
118 uint8_t bytes[NUM_ECC_BYTES];
119
120 uECC_vli_nativeToBytes(bytes, NUM_ECC_BYTES, val);
121 return mbedtls_sha256_update_ret(ctx, bytes, NUM_ECC_BYTES);
122}
123
124static int uECC_compute_param_sha256(unsigned char output[32])
125{
126 int ret = UECC_FAILURE;
127 mbedtls_sha256_context ctx;
128
129 mbedtls_sha256_init( &ctx );
130
131 if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) {
132 goto exit;
133 }
134
135 if (uECC_update_param_sha256(&ctx, curve_p) != 0 ||
Andrzej Kurek0919b142020-07-06 15:28:59 -0400136 uECC_update_param_sha256(&ctx, curve_n) != 0 ||
137 uECC_update_param_sha256(&ctx, curve_G) != 0 ||
138 uECC_update_param_sha256(&ctx, curve_G + NUM_ECC_WORDS) != 0 ||
139 uECC_update_param_sha256(&ctx, curve_b) != 0)
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100140 {
141 goto exit;
142 }
143
144 if (mbedtls_sha256_finish_ret(&ctx, output) != 0) {
145 goto exit;
146 }
147
148 ret = UECC_SUCCESS;
149
150exit:
151 mbedtls_sha256_free( &ctx );
152
153 return ret;
154}
155
156/*
157 * Check integrity of curve parameters.
158 * Return 0 if everything's OK, non-zero otherwise.
159 */
160static int uECC_check_curve_integrity(void)
161{
162 unsigned char computed[32];
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100163 static const unsigned char reference[32] = {
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100164 0x2d, 0xa1, 0xa4, 0x64, 0x45, 0x28, 0x0d, 0xe1,
165 0x93, 0xf9, 0x29, 0x2f, 0xac, 0x3e, 0xe2, 0x92,
166 0x76, 0x0a, 0xe2, 0xbc, 0xce, 0x2a, 0xa2, 0xc6,
167 0x38, 0xf2, 0x19, 0x1d, 0x76, 0x72, 0x93, 0x49,
168 };
Kevin Braceya967a582020-11-04 16:28:48 +0200169 int diff = 0;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100170 unsigned char tmp1, tmp2;
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100171 volatile unsigned i;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100172
173 if (uECC_compute_param_sha256(computed) != UECC_SUCCESS) {
174 return UECC_FAILURE;
175 }
176
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100177 for (i = 0; i < 32; i++) {
178 /* make sure the order of volatile accesses is well-defined */
179 tmp1 = computed[i];
180 tmp2 = reference[i];
181 diff |= tmp1 ^ tmp2;
182 }
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100183
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100184 /* i should be 32 */
Arto Kinnunenac6d2262020-01-09 10:11:20 +0200185 mbedtls_platform_random_delay();
Kevin Braceya967a582020-11-04 16:28:48 +0200186 diff |= i ^ 32;
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100187
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100188 return diff;
189}
190
Jarno Lamsa18987a42019-04-24 15:40:43 +0300191/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
192 * has access to enough entropy in order to feed the PRNG regularly. */
193#if default_RNG_defined
194static uECC_RNG_Function g_rng_function = &default_CSPRNG;
195#else
196static uECC_RNG_Function g_rng_function = 0;
197#endif
198
199void uECC_set_rng(uECC_RNG_Function rng_function)
200{
201 g_rng_function = rng_function;
202}
203
204uECC_RNG_Function uECC_get_rng(void)
205{
206 return g_rng_function;
207}
208
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +0100209int uECC_curve_private_key_size(void)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300210{
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +0100211 return BITS_TO_BYTES(NUM_ECC_BITS);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300212}
213
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +0100214int uECC_curve_public_key_size(void)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300215{
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +0100216 return 2 * NUM_ECC_BYTES;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300217}
218
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200219#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM
Kevin Bracey3be252e2020-10-09 12:54:48 +0300220__asm void uECC_vli_clear(uECC_word_t *vli)
221{
222#if NUM_ECC_WORDS != 8
223#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
224#endif
225#if !defined __thumb__ || __TARGET_ARCH_THUMB < 4
226 MOVS r1,#0
227 MOVS r2,#0
228 STMIA r0!,{r1,r2}
229 STMIA r0!,{r1,r2}
230 STMIA r0!,{r1,r2}
231 STMIA r0!,{r1,r2}
232 BX lr
233#else
234 MOVS r1,#0
235 STRD r1,r1,[r0,#0] // Only Thumb2 STRD can store same reg twice, not ARM
236 STRD r1,r1,[r0,#8]
237 STRD r1,r1,[r0,#16]
238 STRD r1,r1,[r0,#24]
239 BX lr
240#endif
241}
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200242#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__
Kevin Bracey3be252e2020-10-09 12:54:48 +0300243void uECC_vli_clear(uECC_word_t *vli)
244{
245#if NUM_ECC_WORDS != 8
246#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
247#endif
248#if !defined __thumb__ || !defined __thumb2__
249 register uECC_word_t *r0 asm("r0") = vli;
250 register uECC_word_t r1 asm("r1") = 0;
251 register uECC_word_t r2 asm("r2") = 0;
252 asm volatile (
253 ".syntax unified \n\t"
254 "STMIA r0!,{r1,r2} \n\t"
255 "STMIA r0!,{r1,r2} \n\t"
256 "STMIA r0!,{r1,r2} \n\t"
257 "STMIA r0!,{r1,r2} \n\t"
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300258 ".syntax divided \n\t"
Kevin Bracey3be252e2020-10-09 12:54:48 +0300259 : "+r" (r0)
260 : "r" (r1), "r" (r2)
261 : "memory"
262#else
263 register uECC_word_t *r0 asm("r0") = vli;
264 register uECC_word_t r1 asm("r1") = 0;
265 asm volatile (
266 "STRD r1,r1,[r0,#0] \n\t" // Only Thumb2 STRD can store same reg twice, not ARM
267 "STRD r1,r1,[r0,#8] \n\t"
268 "STRD r1,r1,[r0,#16] \n\t"
269 "STRD r1,r1,[r0,#24] \n\t"
270 :
271 : "r" (r0), "r" (r1)
272 : "memory"
273#endif
274 );
275}
276#else
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100277void uECC_vli_clear(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300278{
279 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100280 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300281 vli[i] = 0;
282 }
283}
Kevin Bracey3be252e2020-10-09 12:54:48 +0300284#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300285
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200286#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM
Kevin Bracey3be252e2020-10-09 12:54:48 +0300287__asm uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
288{
289#if NUM_ECC_WORDS != 8
290#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
291#endif
292#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
293 LDMIA r0!,{r1,r2,r3}
294 ORRS r1,r2
295 ORRS r1,r3
296 LDMIA r0!,{r2,r3}
297 ORRS r1,r2
298 ORRS r1,r3
299 LDMIA r0,{r0,r2,r3}
300 ORRS r1,r0
301 ORRS r1,r2
302 ORRS r1,r3
303 RSBS r1,r1,#0 // C set if zero
304 MOVS r0,#0
305 ADCS r0,r0
306 BX lr
307#else
308 LDMIA r0!,{r1,r2,r3,ip}
309 ORRS r1,r2
310 ORRS r1,r3
311 ORRS r1,ip
312 LDMIA r0,{r0,r2,r3,ip}
313 ORRS r1,r0
314 ORRS r1,r2
315 ORRS r1,r3
316 ORRS r1,ip
317#ifdef __ARM_FEATURE_CLZ
318 CLZ r0,r1 // 32 if zero
319 LSRS r0,r0,#5
320#else
321 RSBS r1,r1,#0 // C set if zero
322 MOVS r0,#0
323 ADCS r0,r0
324#endif
325 BX lr
326#endif
327}
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200328#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__
Kevin Bracey3be252e2020-10-09 12:54:48 +0300329uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
330{
331 uECC_word_t ret;
332#if NUM_ECC_WORDS != 8
333#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
334#endif
335#if defined __thumb__ && !defined __thumb2__
336 register uECC_word_t r1 asm ("r1");
337 register uECC_word_t r2 asm ("r2");
338 register uECC_word_t r3 asm ("r3");
339 asm volatile (
340 ".syntax unified \n\t"
341 "LDMIA %[vli]!,{%[r1],%[r2],%[r3]} \n\t"
342 "ORRS %[r1],%[r2] \n\t"
343 "ORRS %[r1],%[r3] \n\t"
344 "LDMIA %[vli]!,{%[r2],%[r3]} \n\t"
345 "ORRS %[r1],%[r2] \n\t"
346 "ORRS %[r1],%[r3] \n\t"
347 "LDMIA %[vli],{%[vli],%[r2],%[r3]} \n\t"
348 "ORRS %[r1],%[vli] \n\t"
349 "ORRS %[r1],%[r2] \n\t"
350 "ORRS %[r1],%[r3] \n\t"
351 "RSBS %[r1],%[r1],#0 \n\t" // C set if zero
352 "MOVS %[ret],#0 \n\t"
353 "ADCS %[ret],r0 \n\t"
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300354 ".syntax divided \n\t"
Kevin Bracey3be252e2020-10-09 12:54:48 +0300355 : [ret]"=r" (ret), [r1]"=r" (r1), [r2]"=r" (r2), [r3]"=r" (r3)
356 : [vli]"[ret]" (vli)
357 : "cc", "memory"
358 );
359#else
360 register uECC_word_t r1 asm ("r1");
361 register uECC_word_t r2 asm ("r2");
362 register uECC_word_t r3 asm ("r3");
363 register uECC_word_t ip asm ("ip");
364 asm volatile (
365 "LDMIA %[vli]!,{%[r1],%[r2],%[r3],%[ip]}\n\t"
366 "ORRS %[r1],%[r2] \n\t"
367 "ORRS %[r1],%[r3] \n\t"
368 "ORRS %[r1],%[ip] \n\t"
369 "LDMIA %[vli],{%[vli],%[r2],%[r3],%[ip]}\n\t"
370 "ORRS %[r1],%[vli] \n\t"
371 "ORRS %[r1],%[r2] \n\t"
372 "ORRS %[r1],%[r3] \n\t"
373 "ORRS %[r1],%[ip] \n\t"
374#if __ARM_ARCH >= 5
375 "CLZ %[ret],%[r1] \n\t" // r0 = 32 if zero
376 "LSRS %[ret],%[ret],#5 \n\t"
377#else
378 "RSBS %[r1],%[r1],#0 \n\t" // C set if zero
379 "MOVS %[ret],#0 \n\t"
380 "ADCS %[ret],r0 \n\t"
381#endif
382 : [ret]"=r" (ret), [r1]"=r" (r1), [r2]"=r" (r2), [r3]"=r" (r3), [ip]"=r" (ip)
383 : [vli]"[ret]" (vli)
384 : "cc", "memory"
385 );
386#endif
387 return ret;
388}
389#else
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100390uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300391{
392 uECC_word_t bits = 0;
393 wordcount_t i;
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100394 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300395 bits |= vli[i];
396 }
397 return (bits == 0);
398}
Kevin Bracey3be252e2020-10-09 12:54:48 +0300399#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300400
401uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit)
402{
403 return (vli[bit >> uECC_WORD_BITS_SHIFT] &
404 ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
405}
406
407/* Counts the number of words in vli. */
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100408static wordcount_t vli_numDigits(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300409{
410
411 wordcount_t i;
412 /* Search from the end until we find a non-zero digit. We do it in reverse
413 * because we expect that most digits will be nonzero. */
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100414 for (i = NUM_ECC_WORDS - 1; i >= 0 && vli[i] == 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300415 }
416
417 return (i + 1);
418}
419
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100420bitcount_t uECC_vli_numBits(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300421{
422
423 uECC_word_t i;
424 uECC_word_t digit;
425
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100426 wordcount_t num_digits = vli_numDigits(vli);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300427 if (num_digits == 0) {
428 return 0;
429 }
430
431 digit = vli[num_digits - 1];
Kevin Bracey99c64e12020-10-06 12:25:28 +0300432#if defined __GNUC__ || defined __clang__ || defined __CC_ARM
433 i = uECC_WORD_BITS - __builtin_clz(digit);
434#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300435 for (i = 0; digit; ++i) {
436 digit >>= 1;
437 }
Kevin Bracey99c64e12020-10-06 12:25:28 +0300438#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300439
440 return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
441}
442
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100443void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300444{
445 wordcount_t i;
446
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100447 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300448 dest[i] = src[i];
449 }
450}
451
452cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100453 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300454{
455 wordcount_t i;
456
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100457 for (i = NUM_ECC_WORDS - 1; i >= 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300458 if (left[i] > right[i]) {
459 return 1;
460 } else if (left[i] < right[i]) {
461 return -1;
462 }
463 }
464 return 0;
465}
466
Manuel Pégourié-Gonnard2eca3d32019-11-04 14:33:09 +0100467uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300468{
469
470 uECC_word_t diff = 0;
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200471 uECC_word_t flow_monitor = 0;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100472 uECC_word_t tmp1, tmp2;
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100473 volatile int i;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300474
Piotr Nowickif0ab6d62020-05-25 12:48:30 +0200475 /* Start from a random location and check the correct number of iterations */
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200476 int start_offset = mbedtls_platform_random_in_range(NUM_ECC_WORDS);
477
478 for (i = start_offset; i < NUM_ECC_WORDS; ++i) {
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100479 tmp1 = left[i];
480 tmp2 = right[i];
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200481 flow_monitor++;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100482 diff |= (tmp1 ^ tmp2);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300483 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100484
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200485 for (i = 0; i < start_offset; ++i) {
486 tmp1 = left[i];
487 tmp2 = right[i];
488 flow_monitor++;
489 diff |= (tmp1 ^ tmp2);
490 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100491
Piotr Nowickif0ab6d62020-05-25 12:48:30 +0200492 /* Random delay to increase security */
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200493 mbedtls_platform_random_delay();
494
495 /* Return 0 only when diff is 0 and flow_counter is equal to NUM_ECC_WORDS */
496 return (diff | (flow_monitor ^ NUM_ECC_WORDS));
Jarno Lamsa18987a42019-04-24 15:40:43 +0300497}
498
499uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
500{
Kevin Bracey045e5762020-10-06 12:25:58 +0300501 return (p_true*(cond)) | (p_false*(cond ^ 1));
Jarno Lamsa18987a42019-04-24 15:40:43 +0300502}
503
504/* Computes result = left - right, returning borrow, in constant time.
505 * Can modify in place. */
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200506#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM
Kevin Bracey1959c182020-07-16 21:03:19 +0300507__asm uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
508 const uECC_word_t *right)
509{
510#if NUM_ECC_WORDS != 8
511#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
512#endif
513#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
514 PUSH {r4-r6,lr}
515 FRAME PUSH {r4-r6,lr}
516 LDMIA r1!,{r3,r4}
517 LDMIA r2!,{r5,r6}
518 SUBS 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 LDMIA r1!,{r3,r4}
532 LDMIA r2!,{r5,r6}
533 SBCS r3,r5
534 SBCS r4,r6
535 STMIA r0!,{r3,r4}
536 SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow
537 RSBS r0,r0,#0 // r0 := borrow
538 POP {r4-r6,pc}
539#else
540 PUSH {r4-r8,lr}
541 FRAME PUSH {r4-r8,lr}
542 LDMIA r1!,{r3-r6}
543 LDMIA r2!,{r7,r8,r12,lr}
544 SUBS r3,r7
545 SBCS r4,r8
546 SBCS r5,r12
547 SBCS r6,lr
548 STMIA r0!,{r3-r6}
549 LDMIA r1!,{r3-r6}
550 LDMIA r2!,{r7,r8,r12,lr}
551 SBCS r3,r7
552 SBCS r4,r8
553 SBCS r5,r12
554 SBCS r6,lr
555 STMIA r0!,{r3-r6}
556 SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow
557 RSBS r0,r0,#0 // r0 := borrow
558 POP {r4-r8,pc}
559#endif
560}
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200561#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__
Kevin Bracey4aea6252020-10-09 12:54:28 +0300562uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
563 const uECC_word_t *right)
564{
565#if NUM_ECC_WORDS != 8
566#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
567#endif
568 register uECC_word_t *r0 asm ("r0") = result;
569 register const uECC_word_t *r1 asm ("r1") = left;
570 register const uECC_word_t *r2 asm ("r2") = right;
571 asm volatile (
572#if defined __thumb__ && !defined __thumb2__
573 ".syntax unified \n\t"
574 "LDMIA r1!,{r3,r4} \n\t"
575 "LDMIA r2!,{r5,r6} \n\t"
576 "SUBS 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 "LDMIA r1!,{r3,r4} \n\t"
590 "LDMIA r2!,{r5,r6} \n\t"
591 "SBCS r3,r5 \n\t"
592 "SBCS r4,r6 \n\t"
593 "STMIA r0!,{r3,r4} \n\t"
594 "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow
595 "RSBS r0,r0,#0 \n\t" // r0 := borrow
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300596 ".syntax divided \n\t"
Kevin Bracey4aea6252020-10-09 12:54:28 +0300597 : "+r" (r0), "+r" (r1), "+r" (r2)
598 :
599 : "r3", "r4", "r5", "r6", "cc", "memory"
600#else
601 "LDMIA r1!,{r3-r6} \n\t"
602 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
603 "SUBS r3,r7 \n\t"
604 "SBCS r4,r8 \n\t"
605 "SBCS r5,r12 \n\t"
606 "SBCS r6,lr \n\t"
607 "STMIA r0!,{r3-r6} \n\t"
608 "LDMIA r1!,{r3-r6} \n\t"
609 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
610 "SBCS r3,r7 \n\t"
611 "SBCS r4,r8 \n\t"
612 "SBCS r5,r12 \n\t"
613 "SBCS r6,lr \n\t"
614 "STMIA r0!,{r3-r6} \n\t"
615 "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow
616 "RSBS r0,r0,#0 \n\t" // r0 := borrow
617 : "+r" (r0), "+r" (r1), "+r" (r2)
618 :
619 : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory"
620#endif
621 );
622 return (uECC_word_t) r0;
623}
Kevin Bracey1959c182020-07-16 21:03:19 +0300624#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300625uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100626 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300627{
628 uECC_word_t borrow = 0;
629 wordcount_t i;
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100630 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300631 uECC_word_t diff = left[i] - right[i] - borrow;
632 uECC_word_t val = (diff > left[i]);
633 borrow = cond_set(val, borrow, (diff != left[i]));
634
635 result[i] = diff;
636 }
637 return borrow;
638}
Kevin Bracey1959c182020-07-16 21:03:19 +0300639#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300640
641/* Computes result = left + right, returning carry, in constant time.
642 * Can modify in place. */
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200643#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM
Kevin Bracey1959c182020-07-16 21:03:19 +0300644static __asm uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
645 const uECC_word_t *right)
646{
647#if NUM_ECC_WORDS != 8
648#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
649#endif
650#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
651 PUSH {r4-r6,lr}
652 FRAME PUSH {r4-r6,lr}
653 LDMIA r1!,{r3,r4}
654 LDMIA r2!,{r5,r6}
655 ADDS r3,r5
656 ADCS r4,r6
657 STMIA r0!,{r3,r4}
658 LDMIA r1!,{r3,r4}
659 LDMIA r2!,{r5,r6}
660 ADCS r3,r5
661 ADCS r4,r6
662 STMIA r0!,{r3,r4}
663 LDMIA r1!,{r3,r4}
664 LDMIA r2!,{r5,r6}
665 ADCS r3,r5
666 ADCS r4,r6
667 STMIA r0!,{r3,r4}
668 LDMIA r1!,{r3,r4}
669 LDMIA r2!,{r5,r6}
670 ADCS r3,r5
671 ADCS r4,r6
672 STMIA r0!,{r3,r4}
673 MOVS r0,#0 // does not affect C flag
674 ADCS r0,r0 // r0 := 0 + 0 + C = carry
675 POP {r4-r6,pc}
676#else
677 PUSH {r4-r8,lr}
678 FRAME PUSH {r4-r8,lr}
679 LDMIA r1!,{r3-r6}
680 LDMIA r2!,{r7,r8,r12,lr}
681 ADDS r3,r7
682 ADCS r4,r8
683 ADCS r5,r12
684 ADCS r6,lr
685 STMIA r0!,{r3-r6}
686 LDMIA r1!,{r3-r6}
687 LDMIA r2!,{r7,r8,r12,lr}
688 ADCS r3,r7
689 ADCS r4,r8
690 ADCS r5,r12
691 ADCS r6,lr
692 STMIA r0!,{r3-r6}
693 MOVS r0,#0 // does not affect C flag
694 ADCS r0,r0 // r0 := 0 + 0 + C = carry
695 POP {r4-r8,pc}
696#endif
697}
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200698#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__
Kevin Bracey4aea6252020-10-09 12:54:28 +0300699static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
700 const uECC_word_t *right)
701{
702 register uECC_word_t *r0 asm ("r0") = result;
703 register const uECC_word_t *r1 asm ("r1") = left;
704 register const uECC_word_t *r2 asm ("r2") = right;
705
706 asm volatile (
707#if defined __thumb__ && !defined __thumb2__
708 ".syntax unified \n\t"
709 "LDMIA r1!,{r3,r4} \n\t"
710 "LDMIA r2!,{r5,r6} \n\t"
711 "ADDS r3,r5 \n\t"
712 "ADCS r4,r6 \n\t"
713 "STMIA r0!,{r3,r4} \n\t"
714 "LDMIA r1!,{r3,r4} \n\t"
715 "LDMIA r2!,{r5,r6} \n\t"
716 "ADCS r3,r5 \n\t"
717 "ADCS r4,r6 \n\t"
718 "STMIA r0!,{r3,r4} \n\t"
719 "LDMIA r1!,{r3,r4} \n\t"
720 "LDMIA r2!,{r5,r6} \n\t"
721 "ADCS r3,r5 \n\t"
722 "ADCS r4,r6 \n\t"
723 "STMIA r0!,{r3,r4} \n\t"
724 "LDMIA r1!,{r3,r4} \n\t"
725 "LDMIA r2!,{r5,r6} \n\t"
726 "ADCS r3,r5 \n\t"
727 "ADCS r4,r6 \n\t"
728 "STMIA r0!,{r3,r4} \n\t"
729 "MOVS r0,#0 \n\t" // does not affect C flag
730 "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300731 ".syntax divided \n\t"
Kevin Bracey4aea6252020-10-09 12:54:28 +0300732 : "+r" (r0), "+r" (r1), "+r" (r2)
733 :
734 : "r3", "r4", "r5", "r6", "cc", "memory"
735#else
736 "LDMIA r1!,{r3-r6} \n\t"
737 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
738 "ADDS 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 "LDMIA r1!,{r3-r6} \n\t"
744 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
745 "ADCS r3,r7 \n\t"
746 "ADCS r4,r8 \n\t"
747 "ADCS r5,r12 \n\t"
748 "ADCS r6,lr \n\t"
749 "STMIA r0!,{r3-r6} \n\t"
750 "MOVS r0,#0 \n\t" // does not affect C flag
751 "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry
752 : "+r" (r0), "+r" (r1), "+r" (r2)
753 :
754 : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory"
755#endif
756 );
757 return (uECC_word_t) r0;
758}
Kevin Bracey1959c182020-07-16 21:03:19 +0300759#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300760static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100761 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300762{
763 uECC_word_t carry = 0;
764 wordcount_t i;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100765 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300766 uECC_word_t sum = left[i] + right[i] + carry;
767 uECC_word_t val = (sum < left[i]);
768 carry = cond_set(val, carry, (sum != left[i]));
769 result[i] = sum;
770 }
771 return carry;
772}
Kevin Bracey1959c182020-07-16 21:03:19 +0300773#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300774
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +0100775cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300776{
777 uECC_word_t tmp[NUM_ECC_WORDS];
Kevin Bracey045e5762020-10-06 12:25:58 +0300778 uECC_word_t neg = uECC_vli_sub(tmp, left, right);
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100779 uECC_word_t equal = uECC_vli_isZero(tmp);
Kevin Bracey045e5762020-10-06 12:25:58 +0300780 return ((equal ^ 1) - 2 * neg);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300781}
782
783/* Computes vli = vli >> 1. */
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200784#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM
Kevin Bracey1959c182020-07-16 21:03:19 +0300785static __asm void uECC_vli_rshift1(uECC_word_t *vli)
786{
787#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
788// RRX instruction is not available, so although we
789// can use C flag, it's not that effective. Does at
790// least save one working register, meaning we don't need stack
791 MOVS r3,#0 // initial carry = 0
792 MOVS r2,#__cpp(4 * (NUM_ECC_WORDS - 1))
79301 LDR r1,[r0,r2]
794 LSRS r1,r1,#1 // r2 = word >> 1
795 ORRS r1,r3 // merge in the previous carry
796 STR r1,[r0,r2]
797 ADCS r3,r3 // put C into bottom bit of r3
798 LSLS r3,r3,#31 // shift it up to the top ready for next word
799 SUBS r2,r2,#4
800 BPL %B01
801 BX lr
802#else
803#if NUM_ECC_WORDS != 8
804#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
805#endif
806// Smooth multiword operation, lots of 32-bit instructions
807 ADDS r0,#32
808 LDMDB r0,{r1-r3,ip}
809 LSRS ip,ip,#1
810 RRXS r3,r3
811 RRXS r2,r2
812 RRXS r1,r1
813 STMDB r0!,{r1-r3,ip}
814 LDMDB r0,{r1-r3,ip}
815 RRXS ip,ip
816 RRXS r3,r3
817 RRXS r2,r2
818 RRX r1,r1
819 STMDB r0!,{r1-r3,ip}
820 BX lr
821#endif
822}
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200823#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ && defined __thumb2__
Kevin Bracey06060332020-10-02 17:43:12 +0300824static void uECC_vli_rshift1(uECC_word_t *vli)
825{
826 register uECC_word_t *r0 asm ("r0") = vli;
827#if NUM_ECC_WORDS != 8
828#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
829#endif
830 asm volatile (
831 "ADDS r0,#32 \n\t"
832 "LDMDB r0,{r1-r3,ip} \n\t"
833 "LSRS ip,ip,#1 \n\t"
834 "RRXS r3,r3 \n\t"
835 "RRXS r2,r2 \n\t"
836 "RRXS r1,r1 \n\t"
837 "STMDB r0!,{r1-r3,ip} \n\t"
838 "LDMDB r0,{r1-r3,ip} \n\t"
839 "RRXS ip,ip \n\t"
840 "RRXS r3,r3 \n\t"
841 "RRXS r2,r2 \n\t"
842 "RRX r1,r1 \n\t"
843 "STMDB r0!,{r1-r3,ip} \n\t"
844 : "+r" (r0)
845 :
846 : "r1", "r2", "r3", "ip", "cc", "memory"
847 );
848}
Kevin Bracey1959c182020-07-16 21:03:19 +0300849#else
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100850static void uECC_vli_rshift1(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300851{
852 uECC_word_t *end = vli;
853 uECC_word_t carry = 0;
854
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100855 vli += NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300856 while (vli-- > end) {
857 uECC_word_t temp = *vli;
858 *vli = (temp >> 1) | carry;
859 carry = temp << (uECC_WORD_BITS - 1);
860 }
861}
Kevin Bracey1959c182020-07-16 21:03:19 +0300862#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300863
Kevin Bracey84f31d32020-09-29 17:51:04 +0300864/* Compute a * b + r, where r is a triple-word with high-order word r[2] and
865 * low-order word r[0], and store the result in the same triple-word.
Manuel Pégourié-Gonnard86c4f812019-10-31 13:02:03 +0100866 *
Kevin Bracey84f31d32020-09-29 17:51:04 +0300867 * r[2..0] = a * b + r[2..0]:
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200868 * [in] a, b: operands to be multiplied
Kevin Bracey84f31d32020-09-29 17:51:04 +0300869 * [in] r: 3 words of operand to add
870 * [out] r: 3 words of result
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200871 */
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200872#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM
Kevin Bracey84f31d32020-09-29 17:51:04 +0300873static __asm void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Bracey1959c182020-07-16 21:03:19 +0300874{
875#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
Kevin Bracey84f31d32020-09-29 17:51:04 +0300876 PUSH {r4-r5}
877 FRAME PUSH {r4-r5}
878 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
879 // Separate operands into halfwords
880 UXTH r3,r0 // r3 := a.lo
881 LSRS r4,r0,#16 // r4 := a.hi
882 UXTH r5,r1 // r5 := b.lo
883 LSRS r1,r1,#16 // r1 := b.hi
884 // Multiply halfword pairs
885 MOVS r0,r3
886 MULS r0,r5,r0 // r0 := a.lo * b.lo
887 MULS r3,r1,r3 // r3 := a.lo * b.hi
888 MULS r5,r4,r5 // r5 := a.hi * b.lo
889 MULS r1,r4,r1 // r1 := a.hi * b.hi
890 // Split, shift and add a.lo * b.hi
891 LSRS r4,r3,#16 // r4 := (a.lo * b.hi).hi
892 LSLS r3,r3,#16 // r3 := (a.lo * b.hi).lo
893 ADDS r0,r0,r3 // r0 := a.lo * b.lo + (a.lo * b.hi).lo
894 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
895 // Split, shift and add a.hi * b.lo
896 LSRS r4,r5,#16 // r4 := (a.hi * b.lo).hi
897 LSLS r5,r5,#16 // r5 := (a.hi * b.lo).lo
898 ADDS r0,r0,r5 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
899 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
900 // Finally add r[]
901 LDMIA r2!,{r3,r4,r5}
902 ADDS r3,r3,r0
Kevin Bracey1959c182020-07-16 21:03:19 +0300903 ADCS r4,r1
Kevin Bracey1959c182020-07-16 21:03:19 +0300904 MOVS r0,#0
Kevin Bracey84f31d32020-09-29 17:51:04 +0300905 ADCS r5,r0
906 SUBS r2,#12
907 STMIA r2!,{r3,r4,r5}
908 POP {r4-r5}
909 FRAME POP {r4-r5}
910 BX lr
Kevin Bracey1959c182020-07-16 21:03:19 +0300911#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300912 UMULL r3,ip,r0,r1 // pre-ARMv6 requires Rd[Lo|Hi] != Rn
913 LDMIA r2,{r0,r1}
914 ADDS r0,r0,r3
915 LDR r3,[r2,#8]
916 ADCS r1,r1,ip
917 ADC r3,r3,#0
918 STMIA r2!,{r0,r1,r3}
Kevin Bracey1959c182020-07-16 21:03:19 +0300919 BX lr
920#endif
Kevin Braceye0f88d52020-09-30 12:52:15 +0300921}
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200922#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300923static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Braceye0f88d52020-09-30 12:52:15 +0300924{
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300925 register uECC_word_t r0 asm ("r0") = a;
926 register uECC_word_t r1 asm ("r1") = b;
927 register uECC_word_t *r2 asm ("r2") = r;
928 asm volatile (
Kevin Braceye0f88d52020-09-30 12:52:15 +0300929#if defined __thumb__ && !defined(__thumb2__)
930 ".syntax unified \n\t"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300931 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
932 // Separate operands into halfwords
933 "UXTH r3,r0 \n\t" // r3 := a.lo
934 "LSRS r4,r0,#16 \n\t" // r4 := a.hi
935 "UXTH r5,r1 \n\t" // r5 := b.lo
936 "LSRS r1,r1,#16 \n\t" // r1 := b.hi
937 // Multiply halfword pairs
938 "MOVS r0,r3 \n\t"
939 "MULS r0,r5,r0 \n\t" // r0 := a.lo * b.lo
940 "MULS r3,r1,r3 \n\t" // r3 := a.lo * b.hi
941 "MULS r5,r4,r5 \n\t" // r5 := a.hi * b.lo
942 "MULS r1,r4,r1 \n\t" // r1 := a.hi * b.hi
943 // Split, shift and add a.lo * b.hi
944 "LSRS r4,r3,#16 \n\t" // r4 := (a.lo * b.hi).hi
945 "LSLS r3,r3,#16 \n\t" // r3 := (a.lo * b.hi).lo
946 "ADDS r0,r0,r3 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo
947 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
948 // Split, shift and add a.hi * b.lo
949 "LSRS r4,r5,#16 \n\t" // r4 := (a.hi * b.lo).hi
950 "LSLS r5,r5,#16 \n\t" // r5 := (a.hi * b.lo).lo
951 "ADDS r0,r0,r5 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
952 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
953 // Finally add r[]
954 "LDMIA r2!,{r3,r4,r5} \n\t"
955 "ADDS r3,r3,r0 \n\t"
956 "ADCS r4,r1 \n\t"
957 "MOVS r0,#0 \n\t"
958 "ADCS r5,r0 \n\t"
959 "SUBS r2,#12 \n\t"
960 "STMIA r2!,{r3,r4,r5} \n\t"
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300961 ".syntax divided \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300962 : "+r" (r0), "+r" (r1), "+r" (r2)
963 :
964 : "r3", "r4", "r5", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300965#else
966 "UMULL r3,ip,r0,r1 \n\t" // pre-ARMv6 requires Rd[Lo|Hi] != Rn
967 "LDMIA r2,{r0,r1} \n\t"
968 "ADDS r0,r0,r3 \n\t"
969 "LDR r3,[r2,#8] \n\t"
970 "ADCS r1,r1,ip \n\t"
971 "ADC r3,r3,#0 \n\t"
972 "STMIA r2!,{r0,r1,r3} \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300973 : "+r" (r0), "+r" (r1), "+r" (r2)
974 :
975 : "r3", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300976#endif
977 );
Kevin Bracey1959c182020-07-16 21:03:19 +0300978}
979#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300980static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Jarno Lamsa18987a42019-04-24 15:40:43 +0300981{
982
983 uECC_dword_t p = (uECC_dword_t)a * b;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300984 uECC_dword_t r01 = ((uECC_dword_t)(r[1]) << uECC_WORD_BITS) | r[0];
Jarno Lamsa18987a42019-04-24 15:40:43 +0300985 r01 += p;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300986 r[2] += (r01 < p);
987 r[1] = r01 >> uECC_WORD_BITS;
988 r[0] = (uECC_word_t)r01;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300989}
Kevin Bracey1959c182020-07-16 21:03:19 +0300990#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300991
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200992/* State for implementing random delays in uECC_vli_mult_rnd().
993 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100994 * The state is initialized by randomizing delays and setting i = 0.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200995 * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i.
996 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100997 * Randomized vli multiplication is used only for point operations
998 * (XYcZ_add_rnd() * and XYcZ_addC_rnd()) in scalar multiplication
999 * (ECCPoint_mult()). Those go in pair, and each pair does 14 calls to
1000 * uECC_vli_mult_rnd() (6 in XYcZ_add_rnd() and 8 in XYcZ_addC_rnd(),
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001001 * indirectly through uECC_vli_modMult_rnd().
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001002 *
1003 * Considering this, in order to minimize the number of calls to the RNG
1004 * (which impact performance) while keeping the size of the structure low,
1005 * make room for 14 randomized vli mults, which corresponds to one step in the
1006 * scalar multiplication routine.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001007 */
1008typedef struct {
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001009 uint8_t i;
1010 uint8_t delays[14];
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001011} ecc_wait_state_t;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001012
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001013/*
1014 * Reset wait_state so that it's ready to be used.
1015 */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001016void ecc_wait_state_reset(ecc_wait_state_t *ws)
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001017{
1018 if (ws == NULL)
1019 return;
1020
1021 ws->i = 0;
Shelly Liberman05beb9a2020-09-13 15:23:56 +03001022 mbedtls_platform_random_buf(ws->delays, sizeof(ws->delays));
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001023}
1024
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001025/* Computes result = left * right. Result must be 2 * num_words long.
1026 *
1027 * As a counter-measure against horizontal attacks, add noise by performing
1028 * a random number of extra computations performing random additional accesses
1029 * to limbs of the input.
1030 *
1031 * Each of the two actual computation loops is surrounded by two
1032 * similar-looking waiting loops, to make the beginning and end of the actual
1033 * computation harder to spot.
1034 *
1035 * We add 4 waiting loops of between 0 and 3 calls to muladd() each. That
1036 * makes an average of 6 extra calls. Compared to the main computation which
1037 * makes 64 such calls, this represents an average performance degradation of
1038 * less than 10%.
1039 *
1040 * Compared to the original uECC_vli_mult(), loose the num_words argument as we
1041 * know it's always 8. This saves a bit of code size and execution speed.
1042 */
1043static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001044 const uECC_word_t *right, ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001045{
1046
Kevin Bracey84f31d32020-09-29 17:51:04 +03001047 uECC_word_t r[3] = { 0, 0, 0 };
Jarno Lamsa18987a42019-04-24 15:40:43 +03001048 wordcount_t i, k;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001049 const uint8_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001050
1051 /* Fetch 8 bit worth of delay from the state; 0 if we have no state */
1052 uint8_t delays = s ? s->delays[s->i++] : 0;
Kevin Bracey84f31d32020-09-29 17:51:04 +03001053 uECC_word_t rr[3] = { 0, 0, 0 };
1054 volatile uECC_word_t rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001055
1056 /* Mimic start of next loop: k in [0, 3] */
1057 k = 0 + (delays & 0x03);
1058 delays >>= 2;
1059 /* k = 0 -> i in [1, 0] -> 0 extra muladd;
1060 * k = 3 -> i in [1, 3] -> 3 extra muladd */
Manuel Pégourié-Gonnardc8814862019-11-05 10:32:37 +01001061 for (i = 1; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001062 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001063 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001064 rdummy = rr[0];
1065 rr[0] = rr[1];
1066 rr[1] = rr[2];
1067 rr[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001068
1069 /* Compute each digit of result in sequence, maintaining the carries. */
1070 for (k = 0; k < num_words; ++k) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001071 for (i = 0; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001072 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001073 }
1074
Kevin Bracey84f31d32020-09-29 17:51:04 +03001075 result[k] = r[0];
1076 r[0] = r[1];
1077 r[1] = r[2];
1078 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001079 }
1080
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001081 /* Mimic end of previous loop: k in [4, 7] */
1082 k = 4 + (delays & 0x03);
1083 delays >>= 2;
1084 /* k = 4 -> i in [5, 4] -> 0 extra muladd;
1085 * k = 7 -> i in [5, 7] -> 3 extra muladd */
1086 for (i = 5; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001087 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001088 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001089 rdummy = rr[0];
1090 rr[0] = rr[1];
1091 rr[1] = rr[2];
1092 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001093
1094 /* Mimic start of next loop: k in [8, 11] */
1095 k = 11 - (delays & 0x03);
1096 delays >>= 2;
1097 /* k = 8 -> i in [5, 7] -> 3 extra muladd;
1098 * k = 11 -> i in [8, 7] -> 0 extra muladd */
1099 for (i = (k + 5) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001100 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001101 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001102 rdummy = rr[0];
1103 rr[0] = rr[1];
1104 rr[1] = rr[2];
1105 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001106
Jarno Lamsa18987a42019-04-24 15:40:43 +03001107 for (k = num_words; k < num_words * 2 - 1; ++k) {
1108
1109 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001110 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001111 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001112 result[k] = r[0];
1113 r[0] = r[1];
1114 r[1] = r[2];
1115 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001116 }
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001117
Kevin Bracey84f31d32020-09-29 17:51:04 +03001118 result[num_words * 2 - 1] = r[0];
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001119
1120 /* Mimic end of previous loop: k in [12, 15] */
1121 k = 15 - (delays & 0x03);
1122 delays >>= 2;
1123 /* k = 12 -> i in [5, 7] -> 3 extra muladd;
1124 * k = 15 -> i in [8, 7] -> 0 extra muladd */
1125 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001126 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001127 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001128 rdummy = rr[0];
1129 rr[0] = rr[1];
1130 rr[1] = rr[2];
1131 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001132
Kevin Bracey84f31d32020-09-29 17:51:04 +03001133 /* avoid warning that rdummy is set but not used */
1134 (void) rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001135}
1136
Jarno Lamsa18987a42019-04-24 15:40:43 +03001137void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001138 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001139{
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001140 uECC_word_t carry = uECC_vli_add(result, left, right);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001141 if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001142 /* result > mod (result = mod + remainder), so subtract mod to get
1143 * remainder. */
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001144 uECC_vli_sub(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001145 }
1146}
1147
1148void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001149 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001150{
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001151 uECC_word_t l_borrow = uECC_vli_sub(result, left, right);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001152 if (l_borrow) {
1153 /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
1154 * we can get the correct result from result + mod (with overflow). */
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001155 uECC_vli_add(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001156 }
1157}
1158
1159/* Computes result = product % mod, where product is 2N words long. */
1160/* Currently only designed to work for curve_p or curve_n. */
1161void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001162 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001163{
1164 uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
1165 uECC_word_t tmp[2 * NUM_ECC_WORDS];
1166 uECC_word_t *v[2] = {tmp, product};
1167 uECC_word_t index;
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +01001168 const wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001169
1170 /* Shift mod so its highest set bit is at the maximum position. */
1171 bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001172 uECC_vli_numBits(mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001173 wordcount_t word_shift = shift / uECC_WORD_BITS;
1174 wordcount_t bit_shift = shift % uECC_WORD_BITS;
1175 uECC_word_t carry = 0;
Andrzej Kurek7aebd7f2021-01-14 07:48:49 -05001176
1177 if(word_shift > NUM_ECC_WORDS)
1178 {
1179 mbedtls_platform_fault();
1180 }
1181
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001182 uECC_vli_clear(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001183 if (bit_shift > 0) {
1184 for(index = 0; index < (uECC_word_t)num_words; ++index) {
1185 mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
1186 carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
1187 }
1188 } else {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001189 uECC_vli_set(mod_multiple + word_shift, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001190 }
1191
1192 for (index = 1; shift >= 0; --shift) {
1193 uECC_word_t borrow = 0;
1194 wordcount_t i;
1195 for (i = 0; i < num_words * 2; ++i) {
1196 uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
1197 if (diff != v[index][i]) {
1198 borrow = (diff > v[index][i]);
1199 }
1200 v[1 - index][i] = diff;
1201 }
1202 /* Swap the index if there was no borrow */
1203 index = !(index ^ borrow);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001204 uECC_vli_rshift1(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001205 mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
Andrzej Kurek0919b142020-07-06 15:28:59 -04001206 (uECC_WORD_BITS - 1);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001207 uECC_vli_rshift1(mod_multiple + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001208 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001209 uECC_vli_set(result, v[index]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001210}
1211
1212void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001213 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001214{
1215 uECC_word_t product[2 * NUM_ECC_WORDS];
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001216 uECC_vli_mult_rnd(product, left, right, NULL);
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +01001217 uECC_vli_mmod(result, product, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001218}
1219
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001220static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001221 const uECC_word_t *right, ecc_wait_state_t *s)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001222{
1223 uECC_word_t product[2 * NUM_ECC_WORDS];
1224 uECC_vli_mult_rnd(product, left, right, s);
1225
1226 vli_mmod_fast_secp256r1(result, product);
1227}
1228
Jarno Lamsa18987a42019-04-24 15:40:43 +03001229void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001230 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001231{
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001232 uECC_vli_modMult_rnd(result, left, right, NULL);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001233}
1234
Jarno Lamsa18987a42019-04-24 15:40:43 +03001235#define EVEN(vli) (!(vli[0] & 1))
1236
1237static void vli_modInv_update(uECC_word_t *uv,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001238 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001239{
1240
1241 uECC_word_t carry = 0;
1242
1243 if (!EVEN(uv)) {
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001244 carry = uECC_vli_add(uv, uv, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001245 }
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001246 uECC_vli_rshift1(uv);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001247 if (carry) {
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +01001248 uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001249 }
1250}
1251
1252void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001253 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001254{
1255 uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
1256 uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
1257 cmpresult_t cmpResult;
1258
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001259 if (uECC_vli_isZero(input)) {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001260 uECC_vli_clear(result);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001261 return;
1262 }
1263
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001264 uECC_vli_set(a, input);
1265 uECC_vli_set(b, mod);
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001266 uECC_vli_clear(u);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001267 u[0] = 1;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001268 uECC_vli_clear(v);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001269 while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001270 if (EVEN(a)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001271 uECC_vli_rshift1(a);
Andrzej Kurek0919b142020-07-06 15:28:59 -04001272 vli_modInv_update(u, mod);
1273 } else if (EVEN(b)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001274 uECC_vli_rshift1(b);
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +01001275 vli_modInv_update(v, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001276 } else if (cmpResult > 0) {
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001277 uECC_vli_sub(a, a, b);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001278 uECC_vli_rshift1(a);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001279 if (uECC_vli_cmp_unsafe(u, v) < 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001280 uECC_vli_add(u, u, mod);
1281 }
1282 uECC_vli_sub(u, u, v);
1283 vli_modInv_update(u, mod);
1284 } else {
1285 uECC_vli_sub(b, b, a);
1286 uECC_vli_rshift1(b);
1287 if (uECC_vli_cmp_unsafe(v, u) < 0) {
1288 uECC_vli_add(v, v, mod);
1289 }
1290 uECC_vli_sub(v, v, u);
1291 vli_modInv_update(v, mod);
1292 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001293 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001294 uECC_vli_set(result, u);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001295}
1296
1297/* ------ Point operations ------ */
1298
1299void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001300 uECC_word_t * Z1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001301{
1302 /* t1 = X, t2 = Y, t3 = Z */
1303 uECC_word_t t4[NUM_ECC_WORDS];
1304 uECC_word_t t5[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001305 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001306
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001307 if (uECC_vli_isZero(Z1)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001308 return;
1309 }
1310
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001311 uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */
1312 uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */
1313 uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */
1314 uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */
1315 uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001316
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001317 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = x1 + z1^2 */
1318 uECC_vli_modAdd(Z1, Z1, Z1, curve_p); /* t3 = 2*z1^2 */
1319 uECC_vli_modSub(Z1, X1, Z1, curve_p); /* t3 = x1 - z1^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001320 uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001321
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001322 uECC_vli_modAdd(Z1, X1, X1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
1323 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001324 if (uECC_vli_testBit(X1, 0)) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001325 uECC_word_t l_carry = uECC_vli_add(X1, X1, curve_p);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001326 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001327 X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
1328 } else {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001329 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001330 }
1331
1332 /* t1 = 3/2*(x1^2 - z1^4) = B */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001333 uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001334 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - A */
1335 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
1336 uECC_vli_modSub(t5, t5, Z1, curve_p); /* t5 = A - x3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001337 uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001338 /* t4 = B * (A - x3) - y1^4 = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001339 uECC_vli_modSub(t4, X1, t4, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001340
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001341 uECC_vli_set(X1, Z1);
1342 uECC_vli_set(Z1, Y1);
1343 uECC_vli_set(Y1, t4);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001344}
1345
Manuel Pégourié-Gonnard1c6f7ea2019-11-21 09:18:29 +01001346/*
1347 * @brief Computes x^3 + ax + b. result must not overlap x.
1348 * @param result OUT -- x^3 + ax + b
1349 * @param x IN -- value of x
1350 * @param curve IN -- elliptic curve
1351 */
1352static void x_side_default(uECC_word_t *result,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001353 const uECC_word_t *x)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001354{
1355 uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001356
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001357 uECC_vli_modMult_fast(result, x, x); /* r = x^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001358 uECC_vli_modSub(result, result, _3, curve_p); /* r = x^2 - 3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001359 uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001360 /* r = x^3 - 3x + b: */
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +01001361 uECC_vli_modAdd(result, result, curve_b, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001362}
1363
1364void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
1365{
1366 unsigned int tmp[NUM_ECC_WORDS];
1367 int carry;
1368
1369 /* t */
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001370 uECC_vli_set(result, product);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001371
1372 /* s1 */
1373 tmp[0] = tmp[1] = tmp[2] = 0;
1374 tmp[3] = product[11];
1375 tmp[4] = product[12];
1376 tmp[5] = product[13];
1377 tmp[6] = product[14];
1378 tmp[7] = product[15];
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 /* s2 */
1383 tmp[3] = product[12];
1384 tmp[4] = product[13];
1385 tmp[5] = product[14];
1386 tmp[6] = product[15];
1387 tmp[7] = 0;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001388 carry += uECC_vli_add(tmp, tmp, tmp);
1389 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001390
1391 /* s3 */
1392 tmp[0] = product[8];
1393 tmp[1] = product[9];
1394 tmp[2] = product[10];
1395 tmp[3] = tmp[4] = tmp[5] = 0;
1396 tmp[6] = product[14];
1397 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001398 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001399
1400 /* s4 */
1401 tmp[0] = product[9];
1402 tmp[1] = product[10];
1403 tmp[2] = product[11];
1404 tmp[3] = product[13];
1405 tmp[4] = product[14];
1406 tmp[5] = product[15];
1407 tmp[6] = product[13];
1408 tmp[7] = product[8];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001409 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001410
1411 /* d1 */
1412 tmp[0] = product[11];
1413 tmp[1] = product[12];
1414 tmp[2] = product[13];
1415 tmp[3] = tmp[4] = tmp[5] = 0;
1416 tmp[6] = product[8];
1417 tmp[7] = product[10];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001418 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001419
1420 /* d2 */
1421 tmp[0] = product[12];
1422 tmp[1] = product[13];
1423 tmp[2] = product[14];
1424 tmp[3] = product[15];
1425 tmp[4] = tmp[5] = 0;
1426 tmp[6] = product[9];
1427 tmp[7] = product[11];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001428 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001429
1430 /* d3 */
1431 tmp[0] = product[13];
1432 tmp[1] = product[14];
1433 tmp[2] = product[15];
1434 tmp[3] = product[8];
1435 tmp[4] = product[9];
1436 tmp[5] = product[10];
1437 tmp[6] = 0;
1438 tmp[7] = product[12];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001439 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001440
1441 /* d4 */
1442 tmp[0] = product[14];
1443 tmp[1] = product[15];
1444 tmp[2] = 0;
1445 tmp[3] = product[9];
1446 tmp[4] = product[10];
1447 tmp[5] = product[11];
1448 tmp[6] = 0;
1449 tmp[7] = product[13];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001450 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001451
1452 if (carry < 0) {
1453 do {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001454 carry += uECC_vli_add(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001455 }
1456 while (carry < 0);
1457 } else {
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +02001458 while (carry ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001459 uECC_vli_cmp_unsafe(curve_p, result) != 1) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001460 carry -= uECC_vli_sub(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001461 }
1462 }
1463}
1464
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001465uECC_word_t EccPoint_isZero(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001466{
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001467 return uECC_vli_isZero(point);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001468}
1469
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001470void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001471{
1472 uECC_word_t t1[NUM_ECC_WORDS];
1473
Andrzej Kurek0919b142020-07-06 15:28:59 -04001474 uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001475 uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */
1476 uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */
1477 uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001478}
1479
1480/* P = (x1, y1) => 2P, (x2, y2) => P' */
1481static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
1482 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001483 const uECC_word_t * const initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001484{
1485 uECC_word_t z[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001486 if (initial_Z) {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001487 uECC_vli_set(z, initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001488 } else {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001489 uECC_vli_clear(z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001490 z[0] = 1;
1491 }
1492
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001493 uECC_vli_set(X2, X1);
1494 uECC_vli_set(Y2, Y1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001495
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001496 apply_z(X1, Y1, z);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001497 double_jacobian_default(X1, Y1, z);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001498 apply_z(X2, Y2, z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001499}
1500
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001501static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1502 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001503 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001504{
1505 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1506 uECC_word_t t5[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001507
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001508 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001509 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001510 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1511 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001512 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001513 uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001514
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001515 uECC_vli_modSub(t5, t5, X1, curve_p); /* t5 = D - B */
1516 uECC_vli_modSub(t5, t5, X2, curve_p); /* t5 = D - B - C = x3 */
1517 uECC_vli_modSub(X2, X2, X1, curve_p); /* t3 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001518 uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001519 uECC_vli_modSub(X2, X1, t5, curve_p); /* t3 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001520 uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001521 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001522
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001523 uECC_vli_set(X2, t5);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001524}
1525
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001526void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001527 uECC_word_t * X2, uECC_word_t * Y2)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001528{
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001529 XYcZ_add_rnd(X1, Y1, X2, Y2, NULL);
1530}
1531
Jarno Lamsa18987a42019-04-24 15:40:43 +03001532/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
1533 Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
1534 or P => P - Q, Q => P + Q
1535 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001536static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1537 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001538 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001539{
1540 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1541 uECC_word_t t5[NUM_ECC_WORDS];
1542 uECC_word_t t6[NUM_ECC_WORDS];
1543 uECC_word_t t7[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001544
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001545 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001546 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001547 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1548 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001549 uECC_vli_modAdd(t5, Y2, Y1, curve_p); /* t5 = y2 + y1 */
1550 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001551
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001552 uECC_vli_modSub(t6, X2, X1, curve_p); /* t6 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001553 uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001554 uECC_vli_modAdd(t6, X1, X2, curve_p); /* t6 = B + C */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001555 uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001556 uECC_vli_modSub(X2, X2, t6, curve_p); /* t3 = D - (B + C) = x3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001557
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001558 uECC_vli_modSub(t7, X1, X2, curve_p); /* t7 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001559 uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001560 /* t4 = (y2 - y1)*(B - x3) - E = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001561 uECC_vli_modSub(Y2, Y2, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001562
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001563 uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001564 uECC_vli_modSub(t7, t7, t6, curve_p); /* t7 = F - (B + C) = x3' */
1565 uECC_vli_modSub(t6, t7, X1, curve_p); /* t6 = x3' - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001566 uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001567 /* t2 = (y2+y1)*(x3' - B) - E = y3': */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001568 uECC_vli_modSub(Y1, t6, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001569
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001570 uECC_vli_set(X1, t7);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001571}
1572
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001573static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
Jarno Lamsa18987a42019-04-24 15:40:43 +03001574 const uECC_word_t * scalar,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001575 const uECC_word_t * initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001576{
1577 /* R0 and R1 */
1578 uECC_word_t Rx[2][NUM_ECC_WORDS];
1579 uECC_word_t Ry[2][NUM_ECC_WORDS];
1580 uECC_word_t z[NUM_ECC_WORDS];
1581 bitcount_t i;
1582 uECC_word_t nb;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001583 const wordcount_t num_words = NUM_ECC_WORDS;
1584 const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001585 ecc_wait_state_t wait_state;
1586 ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001587
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001588 uECC_vli_set(Rx[1], point);
1589 uECC_vli_set(Ry[1], point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001590
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001591 XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001592
1593 for (i = num_bits - 2; i > 0; --i) {
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001594 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001595 nb = !uECC_vli_testBit(scalar, i);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001596 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
1597 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001598 }
1599
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001600 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001601 nb = !uECC_vli_testBit(scalar, 0);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001602 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001603
1604 /* Find final 1/Z value. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001605 uECC_vli_modSub(z, Rx[1], Rx[0], curve_p); /* X1 - X0 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001606 uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */
1607 uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001608 uECC_vli_modInv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0))*/
Jarno Lamsa18987a42019-04-24 15:40:43 +03001609 /* yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001610 uECC_vli_modMult_fast(z, z, point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001611 /* Xb * yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001612 uECC_vli_modMult_fast(z, z, Rx[1 - nb]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001613 /* End 1/Z calculation */
1614
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001615 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001616 apply_z(Rx[0], Ry[0], z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001617
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001618 uECC_vli_set(result, Rx[0]);
1619 uECC_vli_set(result + num_words, Ry[0]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001620}
1621
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001622static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001623 uECC_word_t *k1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001624{
Shelly Liberman81760222020-10-25 18:48:06 +02001625 wordcount_t num_n_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001626 bitcount_t num_n_bits = NUM_ECC_BITS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001627
Shelly Liberman81760222020-10-25 18:48:06 +02001628 /* With our constant NUM_ECC_BITS and NUM_ECC_WORDS the
1629 * check (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) always would have "false" result (256 < 256),
1630 * therefore Coverity warning may be detected. Removing of this line without changing the entire check will cause to
1631 * array overrun.
1632 * The entire check is not changed on purpose to be aligned with original tinycrypt
1633 * implementation and to allow upstreaming to other curves if required.
1634 * Coverity specific annotation may be added to silence warning if exists.
1635 */
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001636 uECC_word_t carry = uECC_vli_add(k0, k, curve_n) ||
Shelly Liberman81760222020-10-25 18:48:06 +02001637 (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
1638 uECC_vli_testBit(k0, num_n_bits));
Jarno Lamsa18987a42019-04-24 15:40:43 +03001639
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001640 uECC_vli_add(k1, k0, curve_n);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001641
1642 return carry;
1643}
1644
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001645int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001646 const uECC_word_t * scalar)
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001647{
1648 uECC_word_t tmp[NUM_ECC_WORDS];
1649 uECC_word_t s[NUM_ECC_WORDS];
1650 uECC_word_t *k2[2] = {tmp, s};
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001651 wordcount_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001652 uECC_word_t carry;
1653 uECC_word_t *initial_Z = 0;
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001654 int r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001655 volatile int problem;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001656
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001657 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001658 problem = -1;
1659 problem = uECC_check_curve_integrity();
1660 if (problem != 0) {
1661 return UECC_FAULT_DETECTED;
1662 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001663 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001664 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001665 return UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001666 }
1667
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001668 /* Protects against invalid curve attacks */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001669 problem = -1;
1670 problem = uECC_valid_point(point);
1671 if (problem != 0) {
1672 /* invalid input, can happen without fault */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001673 return UECC_FAILURE;
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001674 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001675 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001676 if (problem != 0) {
1677 /* failure on second check means fault, though */
1678 return UECC_FAULT_DETECTED;
1679 }
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001680
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001681 /* Regularize the bitcount for the private key so that attackers cannot use a
1682 * side channel attack to learn the number of leading zeros. */
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001683 carry = regularize_k(scalar, tmp, s);
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001684
1685 /* If an RNG function was specified, get a random initial Z value to
Andrzej Kurek0919b142020-07-06 15:28:59 -04001686 * protect against side-channel attacks such as Template SPA */
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001687 if (g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001688 if (uECC_generate_random_int(k2[carry], curve_p, num_words) != UECC_SUCCESS) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001689 r = UECC_FAILURE;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001690 goto clear_and_out;
1691 }
1692 initial_Z = k2[carry];
1693 }
1694
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001695 EccPoint_mult(result, point, k2[!carry], initial_Z);
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001696
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001697 /* Protect against fault injections that would make the resulting
1698 * point not lie on the intended curve */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001699 problem = -1;
1700 problem = uECC_valid_point(result);
1701 if (problem != 0) {
1702 r = UECC_FAULT_DETECTED;
1703 goto clear_and_out;
1704 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001705 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001706 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001707 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001708 goto clear_and_out;
1709 }
1710
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001711 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001712 problem = -1;
1713 problem = uECC_check_curve_integrity();
1714 if (problem != 0) {
1715 r = UECC_FAULT_DETECTED;
1716 goto clear_and_out;
1717 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001718 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001719 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001720 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001721 goto clear_and_out;
1722 }
1723
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001724 r = UECC_SUCCESS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001725
1726clear_and_out:
1727 /* erasing temporary buffer used to store secret: */
1728 mbedtls_platform_zeroize(k2, sizeof(k2));
1729 mbedtls_platform_zeroize(tmp, sizeof(tmp));
1730 mbedtls_platform_zeroize(s, sizeof(s));
1731
1732 return r;
1733}
1734
Jarno Lamsa18987a42019-04-24 15:40:43 +03001735uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001736 uECC_word_t *private_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001737{
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001738 return EccPoint_mult_safer(result, curve_G, private_key);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001739}
1740
1741/* Converts an integer in uECC native format to big-endian bytes. */
1742void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001743 const unsigned int *native)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001744{
1745 wordcount_t i;
1746 for (i = 0; i < num_bytes; ++i) {
1747 unsigned b = num_bytes - 1 - i;
1748 bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
1749 }
1750}
1751
1752/* Converts big-endian bytes to an integer in uECC native format. */
1753void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001754 int num_bytes)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001755{
1756 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001757 uECC_vli_clear(native);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001758 for (i = 0; i < num_bytes; ++i) {
1759 unsigned b = num_bytes - 1 - i;
1760 native[b / uECC_WORD_SIZE] |=
1761 (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
1762 }
1763}
1764
1765int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001766 wordcount_t num_words)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001767{
1768 uECC_word_t mask = (uECC_word_t)-1;
1769 uECC_word_t tries;
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001770 bitcount_t num_bits = uECC_vli_numBits(top);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001771
1772 if (!g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001773 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001774 }
1775
1776 for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
Andrzej Kurek090365f2020-06-08 11:00:51 -04001777 if (g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE) != num_words * uECC_WORD_SIZE) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001778 return UECC_FAILURE;
1779 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001780 random[num_words - 1] &=
Andrzej Kurek0919b142020-07-06 15:28:59 -04001781 mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001782 if (!uECC_vli_isZero(random) &&
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +01001783 uECC_vli_cmp(top, random) == 1) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001784 return UECC_SUCCESS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001785 }
1786 }
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001787 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001788}
1789
1790
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001791int uECC_valid_point(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001792{
1793 uECC_word_t tmp1[NUM_ECC_WORDS];
1794 uECC_word_t tmp2[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001795 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa83d78812019-12-04 14:40:57 +02001796 volatile uECC_word_t diff = 0xffffffff;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001797
1798 /* The point at infinity is invalid. */
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001799 if (EccPoint_isZero(point)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001800 return -1;
1801 }
1802
1803 /* x and y must be smaller than p. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001804 if (uECC_vli_cmp_unsafe(curve_p, point) != 1 ||
1805 uECC_vli_cmp_unsafe(curve_p, point + num_words) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001806 return -2;
1807 }
1808
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001809 uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001810 x_side_default(tmp2, point); /* tmp2 = x^3 + ax + b */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001811
1812 /* Make sure that y^2 == x^3 + ax + b */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001813 diff = uECC_vli_equal(tmp1, tmp2);
1814 if (diff == 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001815 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001816 if (diff == 0) {
1817 return 0;
1818 }
1819 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001820
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001821 return -3;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001822}
1823
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001824int uECC_valid_public_key(const uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001825{
1826
1827 uECC_word_t _public[NUM_ECC_WORDS * 2];
1828
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001829 uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001830 uECC_vli_bytesToNative(
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001831 _public + NUM_ECC_WORDS,
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001832 public_key + NUM_ECC_BYTES,
1833 NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001834
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +01001835 if (memcmp(_public, curve_G, NUM_ECC_WORDS * 2) == 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001836 return -4;
1837 }
1838
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001839 return uECC_valid_point(_public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001840}
1841
Andrzej Kurek0919b142020-07-06 15:28:59 -04001842int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001843{
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001844 int ret = UECC_FAULT_DETECTED;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001845 uECC_word_t _private[NUM_ECC_WORDS];
1846 uECC_word_t _public[NUM_ECC_WORDS * 2];
1847
1848 uECC_vli_bytesToNative(
1849 _private,
1850 private_key,
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +01001851 BITS_TO_BYTES(NUM_ECC_BITS));
Jarno Lamsa18987a42019-04-24 15:40:43 +03001852
1853 /* Make sure the private key is in the range [1, n-1]. */
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001854 if (uECC_vli_isZero(_private)) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001855 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001856 }
1857
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001858 if (uECC_vli_cmp(curve_n, _private) != 1) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001859 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001860 }
1861
1862 /* Compute public key. */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001863 ret = EccPoint_compute_public_key(_public, _private);
1864 if (ret != UECC_SUCCESS) {
1865 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001866 }
1867
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001868 uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001869 uECC_vli_nativeToBytes(
1870 public_key +
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001871 NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS);
Andrzej Kurekcf3e35c2020-07-15 22:32:08 -04001872
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001873 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001874}
Andrzej Kurek7e62c312020-10-14 12:02:40 +02001875#endif /* MBEDTLS_USE_TINYCRYPT */