blob: 2e99bc9c06cc6688e4f5c5985b33b1fea645fe45 [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 Kurekdb0e50e2020-10-14 12:24:20 +020073#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM
Kevin Bracey1959c182020-07-16 21:03:19 +030074#ifndef asm
75#define asm __asm
76#endif
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +020077#endif /* MBEDTLS_OPTIMIZE_TINYCRYPT_ASM */
Kevin Bracey1959c182020-07-16 21:03:19 +030078
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +010079/* Parameters for curve NIST P-256 aka secp256r1 */
80const uECC_word_t curve_p[NUM_ECC_WORDS] = {
81 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
82 BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
83 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
84 BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)
85};
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +010086const uECC_word_t curve_n[NUM_ECC_WORDS] = {
87 BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
88 BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
89 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
90 BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)
91};
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +010092const uECC_word_t curve_G[2 * NUM_ECC_WORDS] = {
93 BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
94 BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
95 BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
96 BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
97 BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
98 BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
99 BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
100 BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)
101};
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +0100102const uECC_word_t curve_b[NUM_ECC_WORDS] = {
103 BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
104 BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
105 BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
106 BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)
107};
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100108
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100109static int uECC_update_param_sha256(mbedtls_sha256_context *ctx,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400110 const uECC_word_t val[NUM_ECC_WORDS])
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100111{
112 uint8_t bytes[NUM_ECC_BYTES];
113
114 uECC_vli_nativeToBytes(bytes, NUM_ECC_BYTES, val);
115 return mbedtls_sha256_update_ret(ctx, bytes, NUM_ECC_BYTES);
116}
117
118static int uECC_compute_param_sha256(unsigned char output[32])
119{
120 int ret = UECC_FAILURE;
121 mbedtls_sha256_context ctx;
122
123 mbedtls_sha256_init( &ctx );
124
125 if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) {
126 goto exit;
127 }
128
129 if (uECC_update_param_sha256(&ctx, curve_p) != 0 ||
Andrzej Kurek0919b142020-07-06 15:28:59 -0400130 uECC_update_param_sha256(&ctx, curve_n) != 0 ||
131 uECC_update_param_sha256(&ctx, curve_G) != 0 ||
132 uECC_update_param_sha256(&ctx, curve_G + NUM_ECC_WORDS) != 0 ||
133 uECC_update_param_sha256(&ctx, curve_b) != 0)
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100134 {
135 goto exit;
136 }
137
138 if (mbedtls_sha256_finish_ret(&ctx, output) != 0) {
139 goto exit;
140 }
141
142 ret = UECC_SUCCESS;
143
144exit:
145 mbedtls_sha256_free( &ctx );
146
147 return ret;
148}
149
150/*
151 * Check integrity of curve parameters.
152 * Return 0 if everything's OK, non-zero otherwise.
153 */
154static int uECC_check_curve_integrity(void)
155{
156 unsigned char computed[32];
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100157 static const unsigned char reference[32] = {
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100158 0x2d, 0xa1, 0xa4, 0x64, 0x45, 0x28, 0x0d, 0xe1,
159 0x93, 0xf9, 0x29, 0x2f, 0xac, 0x3e, 0xe2, 0x92,
160 0x76, 0x0a, 0xe2, 0xbc, 0xce, 0x2a, 0xa2, 0xc6,
161 0x38, 0xf2, 0x19, 0x1d, 0x76, 0x72, 0x93, 0x49,
162 };
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100163 unsigned char diff = 0;
164 unsigned char tmp1, tmp2;
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100165 volatile unsigned i;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100166
167 if (uECC_compute_param_sha256(computed) != UECC_SUCCESS) {
168 return UECC_FAILURE;
169 }
170
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100171 for (i = 0; i < 32; i++) {
172 /* make sure the order of volatile accesses is well-defined */
173 tmp1 = computed[i];
174 tmp2 = reference[i];
175 diff |= tmp1 ^ tmp2;
176 }
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100177
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100178 /* i should be 32 */
Arto Kinnunenac6d2262020-01-09 10:11:20 +0200179 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100180 diff |= (unsigned char) i ^ 32;
181
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100182 return diff;
183}
184
Jarno Lamsa18987a42019-04-24 15:40:43 +0300185/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
186 * has access to enough entropy in order to feed the PRNG regularly. */
187#if default_RNG_defined
188static uECC_RNG_Function g_rng_function = &default_CSPRNG;
189#else
190static uECC_RNG_Function g_rng_function = 0;
191#endif
192
193void uECC_set_rng(uECC_RNG_Function rng_function)
194{
195 g_rng_function = rng_function;
196}
197
198uECC_RNG_Function uECC_get_rng(void)
199{
200 return g_rng_function;
201}
202
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +0100203int uECC_curve_private_key_size(void)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300204{
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +0100205 return BITS_TO_BYTES(NUM_ECC_BITS);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300206}
207
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +0100208int uECC_curve_public_key_size(void)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300209{
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +0100210 return 2 * NUM_ECC_BYTES;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300211}
212
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200213#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM
Kevin Bracey3be252e2020-10-09 12:54:48 +0300214__asm void uECC_vli_clear(uECC_word_t *vli)
215{
216#if NUM_ECC_WORDS != 8
217#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
218#endif
219#if !defined __thumb__ || __TARGET_ARCH_THUMB < 4
220 MOVS r1,#0
221 MOVS r2,#0
222 STMIA r0!,{r1,r2}
223 STMIA r0!,{r1,r2}
224 STMIA r0!,{r1,r2}
225 STMIA r0!,{r1,r2}
226 BX lr
227#else
228 MOVS r1,#0
229 STRD r1,r1,[r0,#0] // Only Thumb2 STRD can store same reg twice, not ARM
230 STRD r1,r1,[r0,#8]
231 STRD r1,r1,[r0,#16]
232 STRD r1,r1,[r0,#24]
233 BX lr
234#endif
235}
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200236#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__
Kevin Bracey3be252e2020-10-09 12:54:48 +0300237void uECC_vli_clear(uECC_word_t *vli)
238{
239#if NUM_ECC_WORDS != 8
240#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
241#endif
242#if !defined __thumb__ || !defined __thumb2__
243 register uECC_word_t *r0 asm("r0") = vli;
244 register uECC_word_t r1 asm("r1") = 0;
245 register uECC_word_t r2 asm("r2") = 0;
246 asm volatile (
247 ".syntax unified \n\t"
248 "STMIA r0!,{r1,r2} \n\t"
249 "STMIA r0!,{r1,r2} \n\t"
250 "STMIA r0!,{r1,r2} \n\t"
251 "STMIA r0!,{r1,r2} \n\t"
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300252 ".syntax divided \n\t"
Kevin Bracey3be252e2020-10-09 12:54:48 +0300253 : "+r" (r0)
254 : "r" (r1), "r" (r2)
255 : "memory"
256#else
257 register uECC_word_t *r0 asm("r0") = vli;
258 register uECC_word_t r1 asm("r1") = 0;
259 asm volatile (
260 "STRD r1,r1,[r0,#0] \n\t" // Only Thumb2 STRD can store same reg twice, not ARM
261 "STRD r1,r1,[r0,#8] \n\t"
262 "STRD r1,r1,[r0,#16] \n\t"
263 "STRD r1,r1,[r0,#24] \n\t"
264 :
265 : "r" (r0), "r" (r1)
266 : "memory"
267#endif
268 );
269}
270#else
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100271void uECC_vli_clear(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300272{
273 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100274 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300275 vli[i] = 0;
276 }
277}
Kevin Bracey3be252e2020-10-09 12:54:48 +0300278#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300279
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200280#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM
Kevin Bracey3be252e2020-10-09 12:54:48 +0300281__asm uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
282{
283#if NUM_ECC_WORDS != 8
284#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
285#endif
286#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
287 LDMIA r0!,{r1,r2,r3}
288 ORRS r1,r2
289 ORRS r1,r3
290 LDMIA r0!,{r2,r3}
291 ORRS r1,r2
292 ORRS r1,r3
293 LDMIA r0,{r0,r2,r3}
294 ORRS r1,r0
295 ORRS r1,r2
296 ORRS r1,r3
297 RSBS r1,r1,#0 // C set if zero
298 MOVS r0,#0
299 ADCS r0,r0
300 BX lr
301#else
302 LDMIA r0!,{r1,r2,r3,ip}
303 ORRS r1,r2
304 ORRS r1,r3
305 ORRS r1,ip
306 LDMIA r0,{r0,r2,r3,ip}
307 ORRS r1,r0
308 ORRS r1,r2
309 ORRS r1,r3
310 ORRS r1,ip
311#ifdef __ARM_FEATURE_CLZ
312 CLZ r0,r1 // 32 if zero
313 LSRS r0,r0,#5
314#else
315 RSBS r1,r1,#0 // C set if zero
316 MOVS r0,#0
317 ADCS r0,r0
318#endif
319 BX lr
320#endif
321}
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200322#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__
Kevin Bracey3be252e2020-10-09 12:54:48 +0300323uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
324{
325 uECC_word_t ret;
326#if NUM_ECC_WORDS != 8
327#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
328#endif
329#if defined __thumb__ && !defined __thumb2__
330 register uECC_word_t r1 asm ("r1");
331 register uECC_word_t r2 asm ("r2");
332 register uECC_word_t r3 asm ("r3");
333 asm volatile (
334 ".syntax unified \n\t"
335 "LDMIA %[vli]!,{%[r1],%[r2],%[r3]} \n\t"
336 "ORRS %[r1],%[r2] \n\t"
337 "ORRS %[r1],%[r3] \n\t"
338 "LDMIA %[vli]!,{%[r2],%[r3]} \n\t"
339 "ORRS %[r1],%[r2] \n\t"
340 "ORRS %[r1],%[r3] \n\t"
341 "LDMIA %[vli],{%[vli],%[r2],%[r3]} \n\t"
342 "ORRS %[r1],%[vli] \n\t"
343 "ORRS %[r1],%[r2] \n\t"
344 "ORRS %[r1],%[r3] \n\t"
345 "RSBS %[r1],%[r1],#0 \n\t" // C set if zero
346 "MOVS %[ret],#0 \n\t"
347 "ADCS %[ret],r0 \n\t"
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300348 ".syntax divided \n\t"
Kevin Bracey3be252e2020-10-09 12:54:48 +0300349 : [ret]"=r" (ret), [r1]"=r" (r1), [r2]"=r" (r2), [r3]"=r" (r3)
350 : [vli]"[ret]" (vli)
351 : "cc", "memory"
352 );
353#else
354 register uECC_word_t r1 asm ("r1");
355 register uECC_word_t r2 asm ("r2");
356 register uECC_word_t r3 asm ("r3");
357 register uECC_word_t ip asm ("ip");
358 asm volatile (
359 "LDMIA %[vli]!,{%[r1],%[r2],%[r3],%[ip]}\n\t"
360 "ORRS %[r1],%[r2] \n\t"
361 "ORRS %[r1],%[r3] \n\t"
362 "ORRS %[r1],%[ip] \n\t"
363 "LDMIA %[vli],{%[vli],%[r2],%[r3],%[ip]}\n\t"
364 "ORRS %[r1],%[vli] \n\t"
365 "ORRS %[r1],%[r2] \n\t"
366 "ORRS %[r1],%[r3] \n\t"
367 "ORRS %[r1],%[ip] \n\t"
368#if __ARM_ARCH >= 5
369 "CLZ %[ret],%[r1] \n\t" // r0 = 32 if zero
370 "LSRS %[ret],%[ret],#5 \n\t"
371#else
372 "RSBS %[r1],%[r1],#0 \n\t" // C set if zero
373 "MOVS %[ret],#0 \n\t"
374 "ADCS %[ret],r0 \n\t"
375#endif
376 : [ret]"=r" (ret), [r1]"=r" (r1), [r2]"=r" (r2), [r3]"=r" (r3), [ip]"=r" (ip)
377 : [vli]"[ret]" (vli)
378 : "cc", "memory"
379 );
380#endif
381 return ret;
382}
383#else
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100384uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300385{
386 uECC_word_t bits = 0;
387 wordcount_t i;
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100388 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300389 bits |= vli[i];
390 }
391 return (bits == 0);
392}
Kevin Bracey3be252e2020-10-09 12:54:48 +0300393#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300394
395uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit)
396{
397 return (vli[bit >> uECC_WORD_BITS_SHIFT] &
398 ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
399}
400
401/* Counts the number of words in vli. */
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100402static wordcount_t vli_numDigits(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300403{
404
405 wordcount_t i;
406 /* Search from the end until we find a non-zero digit. We do it in reverse
407 * because we expect that most digits will be nonzero. */
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100408 for (i = NUM_ECC_WORDS - 1; i >= 0 && vli[i] == 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300409 }
410
411 return (i + 1);
412}
413
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100414bitcount_t uECC_vli_numBits(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300415{
416
417 uECC_word_t i;
418 uECC_word_t digit;
419
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100420 wordcount_t num_digits = vli_numDigits(vli);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300421 if (num_digits == 0) {
422 return 0;
423 }
424
425 digit = vli[num_digits - 1];
Kevin Bracey99c64e12020-10-06 12:25:28 +0300426#if defined __GNUC__ || defined __clang__ || defined __CC_ARM
427 i = uECC_WORD_BITS - __builtin_clz(digit);
428#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300429 for (i = 0; digit; ++i) {
430 digit >>= 1;
431 }
Kevin Bracey99c64e12020-10-06 12:25:28 +0300432#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300433
434 return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
435}
436
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100437void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300438{
439 wordcount_t i;
440
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100441 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300442 dest[i] = src[i];
443 }
444}
445
446cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100447 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300448{
449 wordcount_t i;
450
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100451 for (i = NUM_ECC_WORDS - 1; i >= 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300452 if (left[i] > right[i]) {
453 return 1;
454 } else if (left[i] < right[i]) {
455 return -1;
456 }
457 }
458 return 0;
459}
460
Manuel Pégourié-Gonnard2eca3d32019-11-04 14:33:09 +0100461uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300462{
463
464 uECC_word_t diff = 0;
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200465 uECC_word_t flow_monitor = 0;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100466 uECC_word_t tmp1, tmp2;
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100467 volatile int i;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300468
Piotr Nowickif0ab6d62020-05-25 12:48:30 +0200469 /* Start from a random location and check the correct number of iterations */
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200470 int start_offset = mbedtls_platform_random_in_range(NUM_ECC_WORDS);
471
472 for (i = start_offset; i < NUM_ECC_WORDS; ++i) {
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100473 tmp1 = left[i];
474 tmp2 = right[i];
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200475 flow_monitor++;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100476 diff |= (tmp1 ^ tmp2);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300477 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100478
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200479 for (i = 0; i < start_offset; ++i) {
480 tmp1 = left[i];
481 tmp2 = right[i];
482 flow_monitor++;
483 diff |= (tmp1 ^ tmp2);
484 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100485
Piotr Nowickif0ab6d62020-05-25 12:48:30 +0200486 /* Random delay to increase security */
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200487 mbedtls_platform_random_delay();
488
489 /* Return 0 only when diff is 0 and flow_counter is equal to NUM_ECC_WORDS */
490 return (diff | (flow_monitor ^ NUM_ECC_WORDS));
Jarno Lamsa18987a42019-04-24 15:40:43 +0300491}
492
493uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
494{
Kevin Bracey045e5762020-10-06 12:25:58 +0300495 return (p_true*(cond)) | (p_false*(cond ^ 1));
Jarno Lamsa18987a42019-04-24 15:40:43 +0300496}
497
498/* Computes result = left - right, returning borrow, in constant time.
499 * Can modify in place. */
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200500#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM
Kevin Bracey1959c182020-07-16 21:03:19 +0300501__asm uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
502 const uECC_word_t *right)
503{
504#if NUM_ECC_WORDS != 8
505#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
506#endif
507#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
508 PUSH {r4-r6,lr}
509 FRAME PUSH {r4-r6,lr}
510 LDMIA r1!,{r3,r4}
511 LDMIA r2!,{r5,r6}
512 SUBS r3,r5
513 SBCS r4,r6
514 STMIA r0!,{r3,r4}
515 LDMIA r1!,{r3,r4}
516 LDMIA r2!,{r5,r6}
517 SBCS r3,r5
518 SBCS r4,r6
519 STMIA r0!,{r3,r4}
520 LDMIA r1!,{r3,r4}
521 LDMIA r2!,{r5,r6}
522 SBCS r3,r5
523 SBCS r4,r6
524 STMIA r0!,{r3,r4}
525 LDMIA r1!,{r3,r4}
526 LDMIA r2!,{r5,r6}
527 SBCS r3,r5
528 SBCS r4,r6
529 STMIA r0!,{r3,r4}
530 SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow
531 RSBS r0,r0,#0 // r0 := borrow
532 POP {r4-r6,pc}
533#else
534 PUSH {r4-r8,lr}
535 FRAME PUSH {r4-r8,lr}
536 LDMIA r1!,{r3-r6}
537 LDMIA r2!,{r7,r8,r12,lr}
538 SUBS r3,r7
539 SBCS r4,r8
540 SBCS r5,r12
541 SBCS r6,lr
542 STMIA r0!,{r3-r6}
543 LDMIA r1!,{r3-r6}
544 LDMIA r2!,{r7,r8,r12,lr}
545 SBCS r3,r7
546 SBCS r4,r8
547 SBCS r5,r12
548 SBCS r6,lr
549 STMIA r0!,{r3-r6}
550 SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow
551 RSBS r0,r0,#0 // r0 := borrow
552 POP {r4-r8,pc}
553#endif
554}
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200555#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__
Kevin Bracey4aea6252020-10-09 12:54:28 +0300556uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
557 const uECC_word_t *right)
558{
559#if NUM_ECC_WORDS != 8
560#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
561#endif
562 register uECC_word_t *r0 asm ("r0") = result;
563 register const uECC_word_t *r1 asm ("r1") = left;
564 register const uECC_word_t *r2 asm ("r2") = right;
565 asm volatile (
566#if defined __thumb__ && !defined __thumb2__
567 ".syntax unified \n\t"
568 "LDMIA r1!,{r3,r4} \n\t"
569 "LDMIA r2!,{r5,r6} \n\t"
570 "SUBS r3,r5 \n\t"
571 "SBCS r4,r6 \n\t"
572 "STMIA r0!,{r3,r4} \n\t"
573 "LDMIA r1!,{r3,r4} \n\t"
574 "LDMIA r2!,{r5,r6} \n\t"
575 "SBCS r3,r5 \n\t"
576 "SBCS r4,r6 \n\t"
577 "STMIA r0!,{r3,r4} \n\t"
578 "LDMIA r1!,{r3,r4} \n\t"
579 "LDMIA r2!,{r5,r6} \n\t"
580 "SBCS r3,r5 \n\t"
581 "SBCS r4,r6 \n\t"
582 "STMIA r0!,{r3,r4} \n\t"
583 "LDMIA r1!,{r3,r4} \n\t"
584 "LDMIA r2!,{r5,r6} \n\t"
585 "SBCS r3,r5 \n\t"
586 "SBCS r4,r6 \n\t"
587 "STMIA r0!,{r3,r4} \n\t"
588 "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow
589 "RSBS r0,r0,#0 \n\t" // r0 := borrow
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300590 ".syntax divided \n\t"
Kevin Bracey4aea6252020-10-09 12:54:28 +0300591 : "+r" (r0), "+r" (r1), "+r" (r2)
592 :
593 : "r3", "r4", "r5", "r6", "cc", "memory"
594#else
595 "LDMIA r1!,{r3-r6} \n\t"
596 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
597 "SUBS r3,r7 \n\t"
598 "SBCS r4,r8 \n\t"
599 "SBCS r5,r12 \n\t"
600 "SBCS r6,lr \n\t"
601 "STMIA r0!,{r3-r6} \n\t"
602 "LDMIA r1!,{r3-r6} \n\t"
603 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
604 "SBCS r3,r7 \n\t"
605 "SBCS r4,r8 \n\t"
606 "SBCS r5,r12 \n\t"
607 "SBCS r6,lr \n\t"
608 "STMIA r0!,{r3-r6} \n\t"
609 "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow
610 "RSBS r0,r0,#0 \n\t" // r0 := borrow
611 : "+r" (r0), "+r" (r1), "+r" (r2)
612 :
613 : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory"
614#endif
615 );
616 return (uECC_word_t) r0;
617}
Kevin Bracey1959c182020-07-16 21:03:19 +0300618#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300619uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100620 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300621{
622 uECC_word_t borrow = 0;
623 wordcount_t i;
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100624 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300625 uECC_word_t diff = left[i] - right[i] - borrow;
626 uECC_word_t val = (diff > left[i]);
627 borrow = cond_set(val, borrow, (diff != left[i]));
628
629 result[i] = diff;
630 }
631 return borrow;
632}
Kevin Bracey1959c182020-07-16 21:03:19 +0300633#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300634
635/* Computes result = left + right, returning carry, in constant time.
636 * Can modify in place. */
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200637#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM
Kevin Bracey1959c182020-07-16 21:03:19 +0300638static __asm uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
639 const uECC_word_t *right)
640{
641#if NUM_ECC_WORDS != 8
642#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
643#endif
644#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
645 PUSH {r4-r6,lr}
646 FRAME PUSH {r4-r6,lr}
647 LDMIA r1!,{r3,r4}
648 LDMIA r2!,{r5,r6}
649 ADDS r3,r5
650 ADCS r4,r6
651 STMIA r0!,{r3,r4}
652 LDMIA r1!,{r3,r4}
653 LDMIA r2!,{r5,r6}
654 ADCS r3,r5
655 ADCS r4,r6
656 STMIA r0!,{r3,r4}
657 LDMIA r1!,{r3,r4}
658 LDMIA r2!,{r5,r6}
659 ADCS r3,r5
660 ADCS r4,r6
661 STMIA r0!,{r3,r4}
662 LDMIA r1!,{r3,r4}
663 LDMIA r2!,{r5,r6}
664 ADCS r3,r5
665 ADCS r4,r6
666 STMIA r0!,{r3,r4}
667 MOVS r0,#0 // does not affect C flag
668 ADCS r0,r0 // r0 := 0 + 0 + C = carry
669 POP {r4-r6,pc}
670#else
671 PUSH {r4-r8,lr}
672 FRAME PUSH {r4-r8,lr}
673 LDMIA r1!,{r3-r6}
674 LDMIA r2!,{r7,r8,r12,lr}
675 ADDS r3,r7
676 ADCS r4,r8
677 ADCS r5,r12
678 ADCS r6,lr
679 STMIA r0!,{r3-r6}
680 LDMIA r1!,{r3-r6}
681 LDMIA r2!,{r7,r8,r12,lr}
682 ADCS r3,r7
683 ADCS r4,r8
684 ADCS r5,r12
685 ADCS r6,lr
686 STMIA r0!,{r3-r6}
687 MOVS r0,#0 // does not affect C flag
688 ADCS r0,r0 // r0 := 0 + 0 + C = carry
689 POP {r4-r8,pc}
690#endif
691}
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200692#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__
Kevin Bracey4aea6252020-10-09 12:54:28 +0300693static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
694 const uECC_word_t *right)
695{
696 register uECC_word_t *r0 asm ("r0") = result;
697 register const uECC_word_t *r1 asm ("r1") = left;
698 register const uECC_word_t *r2 asm ("r2") = right;
699
700 asm volatile (
701#if defined __thumb__ && !defined __thumb2__
702 ".syntax unified \n\t"
703 "LDMIA r1!,{r3,r4} \n\t"
704 "LDMIA r2!,{r5,r6} \n\t"
705 "ADDS r3,r5 \n\t"
706 "ADCS r4,r6 \n\t"
707 "STMIA r0!,{r3,r4} \n\t"
708 "LDMIA r1!,{r3,r4} \n\t"
709 "LDMIA r2!,{r5,r6} \n\t"
710 "ADCS r3,r5 \n\t"
711 "ADCS r4,r6 \n\t"
712 "STMIA r0!,{r3,r4} \n\t"
713 "LDMIA r1!,{r3,r4} \n\t"
714 "LDMIA r2!,{r5,r6} \n\t"
715 "ADCS r3,r5 \n\t"
716 "ADCS r4,r6 \n\t"
717 "STMIA r0!,{r3,r4} \n\t"
718 "LDMIA r1!,{r3,r4} \n\t"
719 "LDMIA r2!,{r5,r6} \n\t"
720 "ADCS r3,r5 \n\t"
721 "ADCS r4,r6 \n\t"
722 "STMIA r0!,{r3,r4} \n\t"
723 "MOVS r0,#0 \n\t" // does not affect C flag
724 "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300725 ".syntax divided \n\t"
Kevin Bracey4aea6252020-10-09 12:54:28 +0300726 : "+r" (r0), "+r" (r1), "+r" (r2)
727 :
728 : "r3", "r4", "r5", "r6", "cc", "memory"
729#else
730 "LDMIA r1!,{r3-r6} \n\t"
731 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
732 "ADDS r3,r7 \n\t"
733 "ADCS r4,r8 \n\t"
734 "ADCS r5,r12 \n\t"
735 "ADCS r6,lr \n\t"
736 "STMIA r0!,{r3-r6} \n\t"
737 "LDMIA r1!,{r3-r6} \n\t"
738 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
739 "ADCS r3,r7 \n\t"
740 "ADCS r4,r8 \n\t"
741 "ADCS r5,r12 \n\t"
742 "ADCS r6,lr \n\t"
743 "STMIA r0!,{r3-r6} \n\t"
744 "MOVS r0,#0 \n\t" // does not affect C flag
745 "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry
746 : "+r" (r0), "+r" (r1), "+r" (r2)
747 :
748 : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory"
749#endif
750 );
751 return (uECC_word_t) r0;
752}
Kevin Bracey1959c182020-07-16 21:03:19 +0300753#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300754static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100755 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300756{
757 uECC_word_t carry = 0;
758 wordcount_t i;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100759 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300760 uECC_word_t sum = left[i] + right[i] + carry;
761 uECC_word_t val = (sum < left[i]);
762 carry = cond_set(val, carry, (sum != left[i]));
763 result[i] = sum;
764 }
765 return carry;
766}
Kevin Bracey1959c182020-07-16 21:03:19 +0300767#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300768
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +0100769cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300770{
771 uECC_word_t tmp[NUM_ECC_WORDS];
Kevin Bracey045e5762020-10-06 12:25:58 +0300772 uECC_word_t neg = uECC_vli_sub(tmp, left, right);
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100773 uECC_word_t equal = uECC_vli_isZero(tmp);
Kevin Bracey045e5762020-10-06 12:25:58 +0300774 return ((equal ^ 1) - 2 * neg);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300775}
776
777/* Computes vli = vli >> 1. */
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200778#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM
Kevin Bracey1959c182020-07-16 21:03:19 +0300779static __asm void uECC_vli_rshift1(uECC_word_t *vli)
780{
781#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
782// RRX instruction is not available, so although we
783// can use C flag, it's not that effective. Does at
784// least save one working register, meaning we don't need stack
785 MOVS r3,#0 // initial carry = 0
786 MOVS r2,#__cpp(4 * (NUM_ECC_WORDS - 1))
78701 LDR r1,[r0,r2]
788 LSRS r1,r1,#1 // r2 = word >> 1
789 ORRS r1,r3 // merge in the previous carry
790 STR r1,[r0,r2]
791 ADCS r3,r3 // put C into bottom bit of r3
792 LSLS r3,r3,#31 // shift it up to the top ready for next word
793 SUBS r2,r2,#4
794 BPL %B01
795 BX lr
796#else
797#if NUM_ECC_WORDS != 8
798#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
799#endif
800// Smooth multiword operation, lots of 32-bit instructions
801 ADDS r0,#32
802 LDMDB r0,{r1-r3,ip}
803 LSRS ip,ip,#1
804 RRXS r3,r3
805 RRXS r2,r2
806 RRXS r1,r1
807 STMDB r0!,{r1-r3,ip}
808 LDMDB r0,{r1-r3,ip}
809 RRXS ip,ip
810 RRXS r3,r3
811 RRXS r2,r2
812 RRX r1,r1
813 STMDB r0!,{r1-r3,ip}
814 BX lr
815#endif
816}
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200817#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ && defined __thumb2__
Kevin Bracey06060332020-10-02 17:43:12 +0300818static void uECC_vli_rshift1(uECC_word_t *vli)
819{
820 register uECC_word_t *r0 asm ("r0") = vli;
821#if NUM_ECC_WORDS != 8
822#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
823#endif
824 asm volatile (
825 "ADDS r0,#32 \n\t"
826 "LDMDB r0,{r1-r3,ip} \n\t"
827 "LSRS ip,ip,#1 \n\t"
828 "RRXS r3,r3 \n\t"
829 "RRXS r2,r2 \n\t"
830 "RRXS r1,r1 \n\t"
831 "STMDB r0!,{r1-r3,ip} \n\t"
832 "LDMDB r0,{r1-r3,ip} \n\t"
833 "RRXS ip,ip \n\t"
834 "RRXS r3,r3 \n\t"
835 "RRXS r2,r2 \n\t"
836 "RRX r1,r1 \n\t"
837 "STMDB r0!,{r1-r3,ip} \n\t"
838 : "+r" (r0)
839 :
840 : "r1", "r2", "r3", "ip", "cc", "memory"
841 );
842}
Kevin Bracey1959c182020-07-16 21:03:19 +0300843#else
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100844static void uECC_vli_rshift1(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300845{
846 uECC_word_t *end = vli;
847 uECC_word_t carry = 0;
848
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100849 vli += NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300850 while (vli-- > end) {
851 uECC_word_t temp = *vli;
852 *vli = (temp >> 1) | carry;
853 carry = temp << (uECC_WORD_BITS - 1);
854 }
855}
Kevin Bracey1959c182020-07-16 21:03:19 +0300856#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300857
Kevin Bracey84f31d32020-09-29 17:51:04 +0300858/* Compute a * b + r, where r is a triple-word with high-order word r[2] and
859 * low-order word r[0], and store the result in the same triple-word.
Manuel Pégourié-Gonnard86c4f812019-10-31 13:02:03 +0100860 *
Kevin Bracey84f31d32020-09-29 17:51:04 +0300861 * r[2..0] = a * b + r[2..0]:
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200862 * [in] a, b: operands to be multiplied
Kevin Bracey84f31d32020-09-29 17:51:04 +0300863 * [in] r: 3 words of operand to add
864 * [out] r: 3 words of result
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200865 */
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200866#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM
Kevin Bracey84f31d32020-09-29 17:51:04 +0300867static __asm void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Bracey1959c182020-07-16 21:03:19 +0300868{
869#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
Kevin Bracey84f31d32020-09-29 17:51:04 +0300870 PUSH {r4-r5}
871 FRAME PUSH {r4-r5}
872 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
873 // Separate operands into halfwords
874 UXTH r3,r0 // r3 := a.lo
875 LSRS r4,r0,#16 // r4 := a.hi
876 UXTH r5,r1 // r5 := b.lo
877 LSRS r1,r1,#16 // r1 := b.hi
878 // Multiply halfword pairs
879 MOVS r0,r3
880 MULS r0,r5,r0 // r0 := a.lo * b.lo
881 MULS r3,r1,r3 // r3 := a.lo * b.hi
882 MULS r5,r4,r5 // r5 := a.hi * b.lo
883 MULS r1,r4,r1 // r1 := a.hi * b.hi
884 // Split, shift and add a.lo * b.hi
885 LSRS r4,r3,#16 // r4 := (a.lo * b.hi).hi
886 LSLS r3,r3,#16 // r3 := (a.lo * b.hi).lo
887 ADDS r0,r0,r3 // r0 := a.lo * b.lo + (a.lo * b.hi).lo
888 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
889 // Split, shift and add a.hi * b.lo
890 LSRS r4,r5,#16 // r4 := (a.hi * b.lo).hi
891 LSLS r5,r5,#16 // r5 := (a.hi * b.lo).lo
892 ADDS r0,r0,r5 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
893 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
894 // Finally add r[]
895 LDMIA r2!,{r3,r4,r5}
896 ADDS r3,r3,r0
Kevin Bracey1959c182020-07-16 21:03:19 +0300897 ADCS r4,r1
Kevin Bracey1959c182020-07-16 21:03:19 +0300898 MOVS r0,#0
Kevin Bracey84f31d32020-09-29 17:51:04 +0300899 ADCS r5,r0
900 SUBS r2,#12
901 STMIA r2!,{r3,r4,r5}
902 POP {r4-r5}
903 FRAME POP {r4-r5}
904 BX lr
Kevin Bracey1959c182020-07-16 21:03:19 +0300905#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300906 UMULL r3,ip,r0,r1 // pre-ARMv6 requires Rd[Lo|Hi] != Rn
907 LDMIA r2,{r0,r1}
908 ADDS r0,r0,r3
909 LDR r3,[r2,#8]
910 ADCS r1,r1,ip
911 ADC r3,r3,#0
912 STMIA r2!,{r0,r1,r3}
Kevin Bracey1959c182020-07-16 21:03:19 +0300913 BX lr
914#endif
Kevin Braceye0f88d52020-09-30 12:52:15 +0300915}
Andrzej Kurekdb0e50e2020-10-14 12:24:20 +0200916#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300917static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Braceye0f88d52020-09-30 12:52:15 +0300918{
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300919 register uECC_word_t r0 asm ("r0") = a;
920 register uECC_word_t r1 asm ("r1") = b;
921 register uECC_word_t *r2 asm ("r2") = r;
922 asm volatile (
Kevin Braceye0f88d52020-09-30 12:52:15 +0300923#if defined __thumb__ && !defined(__thumb2__)
924 ".syntax unified \n\t"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300925 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
926 // Separate operands into halfwords
927 "UXTH r3,r0 \n\t" // r3 := a.lo
928 "LSRS r4,r0,#16 \n\t" // r4 := a.hi
929 "UXTH r5,r1 \n\t" // r5 := b.lo
930 "LSRS r1,r1,#16 \n\t" // r1 := b.hi
931 // Multiply halfword pairs
932 "MOVS r0,r3 \n\t"
933 "MULS r0,r5,r0 \n\t" // r0 := a.lo * b.lo
934 "MULS r3,r1,r3 \n\t" // r3 := a.lo * b.hi
935 "MULS r5,r4,r5 \n\t" // r5 := a.hi * b.lo
936 "MULS r1,r4,r1 \n\t" // r1 := a.hi * b.hi
937 // Split, shift and add a.lo * b.hi
938 "LSRS r4,r3,#16 \n\t" // r4 := (a.lo * b.hi).hi
939 "LSLS r3,r3,#16 \n\t" // r3 := (a.lo * b.hi).lo
940 "ADDS r0,r0,r3 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo
941 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
942 // Split, shift and add a.hi * b.lo
943 "LSRS r4,r5,#16 \n\t" // r4 := (a.hi * b.lo).hi
944 "LSLS r5,r5,#16 \n\t" // r5 := (a.hi * b.lo).lo
945 "ADDS r0,r0,r5 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
946 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
947 // Finally add r[]
948 "LDMIA r2!,{r3,r4,r5} \n\t"
949 "ADDS r3,r3,r0 \n\t"
950 "ADCS r4,r1 \n\t"
951 "MOVS r0,#0 \n\t"
952 "ADCS r5,r0 \n\t"
953 "SUBS r2,#12 \n\t"
954 "STMIA r2!,{r3,r4,r5} \n\t"
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300955 ".syntax divided \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300956 : "+r" (r0), "+r" (r1), "+r" (r2)
957 :
958 : "r3", "r4", "r5", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300959#else
960 "UMULL r3,ip,r0,r1 \n\t" // pre-ARMv6 requires Rd[Lo|Hi] != Rn
961 "LDMIA r2,{r0,r1} \n\t"
962 "ADDS r0,r0,r3 \n\t"
963 "LDR r3,[r2,#8] \n\t"
964 "ADCS r1,r1,ip \n\t"
965 "ADC r3,r3,#0 \n\t"
966 "STMIA r2!,{r0,r1,r3} \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300967 : "+r" (r0), "+r" (r1), "+r" (r2)
968 :
969 : "r3", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300970#endif
971 );
Kevin Bracey1959c182020-07-16 21:03:19 +0300972}
973#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300974static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Jarno Lamsa18987a42019-04-24 15:40:43 +0300975{
976
977 uECC_dword_t p = (uECC_dword_t)a * b;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300978 uECC_dword_t r01 = ((uECC_dword_t)(r[1]) << uECC_WORD_BITS) | r[0];
Jarno Lamsa18987a42019-04-24 15:40:43 +0300979 r01 += p;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300980 r[2] += (r01 < p);
981 r[1] = r01 >> uECC_WORD_BITS;
982 r[0] = (uECC_word_t)r01;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300983}
Kevin Bracey1959c182020-07-16 21:03:19 +0300984#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300985
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200986/* State for implementing random delays in uECC_vli_mult_rnd().
987 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100988 * The state is initialized by randomizing delays and setting i = 0.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200989 * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i.
990 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100991 * Randomized vli multiplication is used only for point operations
992 * (XYcZ_add_rnd() * and XYcZ_addC_rnd()) in scalar multiplication
993 * (ECCPoint_mult()). Those go in pair, and each pair does 14 calls to
994 * uECC_vli_mult_rnd() (6 in XYcZ_add_rnd() and 8 in XYcZ_addC_rnd(),
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100995 * indirectly through uECC_vli_modMult_rnd().
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100996 *
997 * Considering this, in order to minimize the number of calls to the RNG
998 * (which impact performance) while keeping the size of the structure low,
999 * make room for 14 randomized vli mults, which corresponds to one step in the
1000 * scalar multiplication routine.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001001 */
1002typedef struct {
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001003 uint8_t i;
1004 uint8_t delays[14];
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001005} ecc_wait_state_t;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001006
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001007/*
1008 * Reset wait_state so that it's ready to be used.
1009 */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001010void ecc_wait_state_reset(ecc_wait_state_t *ws)
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001011{
1012 if (ws == NULL)
1013 return;
1014
1015 ws->i = 0;
Shelly Liberman05beb9a2020-09-13 15:23:56 +03001016 mbedtls_platform_random_buf(ws->delays, sizeof(ws->delays));
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001017}
1018
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001019/* Computes result = left * right. Result must be 2 * num_words long.
1020 *
1021 * As a counter-measure against horizontal attacks, add noise by performing
1022 * a random number of extra computations performing random additional accesses
1023 * to limbs of the input.
1024 *
1025 * Each of the two actual computation loops is surrounded by two
1026 * similar-looking waiting loops, to make the beginning and end of the actual
1027 * computation harder to spot.
1028 *
1029 * We add 4 waiting loops of between 0 and 3 calls to muladd() each. That
1030 * makes an average of 6 extra calls. Compared to the main computation which
1031 * makes 64 such calls, this represents an average performance degradation of
1032 * less than 10%.
1033 *
1034 * Compared to the original uECC_vli_mult(), loose the num_words argument as we
1035 * know it's always 8. This saves a bit of code size and execution speed.
1036 */
1037static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001038 const uECC_word_t *right, ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001039{
1040
Kevin Bracey84f31d32020-09-29 17:51:04 +03001041 uECC_word_t r[3] = { 0, 0, 0 };
Jarno Lamsa18987a42019-04-24 15:40:43 +03001042 wordcount_t i, k;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001043 const uint8_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001044
1045 /* Fetch 8 bit worth of delay from the state; 0 if we have no state */
1046 uint8_t delays = s ? s->delays[s->i++] : 0;
Kevin Bracey84f31d32020-09-29 17:51:04 +03001047 uECC_word_t rr[3] = { 0, 0, 0 };
1048 volatile uECC_word_t rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001049
1050 /* Mimic start of next loop: k in [0, 3] */
1051 k = 0 + (delays & 0x03);
1052 delays >>= 2;
1053 /* k = 0 -> i in [1, 0] -> 0 extra muladd;
1054 * k = 3 -> i in [1, 3] -> 3 extra muladd */
Manuel Pégourié-Gonnardc8814862019-11-05 10:32:37 +01001055 for (i = 1; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001056 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001057 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001058 rdummy = rr[0];
1059 rr[0] = rr[1];
1060 rr[1] = rr[2];
1061 rr[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001062
1063 /* Compute each digit of result in sequence, maintaining the carries. */
1064 for (k = 0; k < num_words; ++k) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001065 for (i = 0; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001066 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001067 }
1068
Kevin Bracey84f31d32020-09-29 17:51:04 +03001069 result[k] = r[0];
1070 r[0] = r[1];
1071 r[1] = r[2];
1072 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001073 }
1074
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001075 /* Mimic end of previous loop: k in [4, 7] */
1076 k = 4 + (delays & 0x03);
1077 delays >>= 2;
1078 /* k = 4 -> i in [5, 4] -> 0 extra muladd;
1079 * k = 7 -> i in [5, 7] -> 3 extra muladd */
1080 for (i = 5; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001081 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001082 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001083 rdummy = rr[0];
1084 rr[0] = rr[1];
1085 rr[1] = rr[2];
1086 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001087
1088 /* Mimic start of next loop: k in [8, 11] */
1089 k = 11 - (delays & 0x03);
1090 delays >>= 2;
1091 /* k = 8 -> i in [5, 7] -> 3 extra muladd;
1092 * k = 11 -> i in [8, 7] -> 0 extra muladd */
1093 for (i = (k + 5) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001094 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001095 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001096 rdummy = rr[0];
1097 rr[0] = rr[1];
1098 rr[1] = rr[2];
1099 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001100
Jarno Lamsa18987a42019-04-24 15:40:43 +03001101 for (k = num_words; k < num_words * 2 - 1; ++k) {
1102
1103 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001104 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001105 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001106 result[k] = r[0];
1107 r[0] = r[1];
1108 r[1] = r[2];
1109 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001110 }
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001111
Kevin Bracey84f31d32020-09-29 17:51:04 +03001112 result[num_words * 2 - 1] = r[0];
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001113
1114 /* Mimic end of previous loop: k in [12, 15] */
1115 k = 15 - (delays & 0x03);
1116 delays >>= 2;
1117 /* k = 12 -> i in [5, 7] -> 3 extra muladd;
1118 * k = 15 -> i in [8, 7] -> 0 extra muladd */
1119 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001120 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001121 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001122 rdummy = rr[0];
1123 rr[0] = rr[1];
1124 rr[1] = rr[2];
1125 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001126
Kevin Bracey84f31d32020-09-29 17:51:04 +03001127 /* avoid warning that rdummy is set but not used */
1128 (void) rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001129}
1130
Jarno Lamsa18987a42019-04-24 15:40:43 +03001131void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001132 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001133{
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001134 uECC_word_t carry = uECC_vli_add(result, left, right);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001135 if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001136 /* result > mod (result = mod + remainder), so subtract mod to get
1137 * remainder. */
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001138 uECC_vli_sub(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001139 }
1140}
1141
1142void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001143 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001144{
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001145 uECC_word_t l_borrow = uECC_vli_sub(result, left, right);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001146 if (l_borrow) {
1147 /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
1148 * we can get the correct result from result + mod (with overflow). */
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001149 uECC_vli_add(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001150 }
1151}
1152
1153/* Computes result = product % mod, where product is 2N words long. */
1154/* Currently only designed to work for curve_p or curve_n. */
1155void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001156 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001157{
1158 uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
1159 uECC_word_t tmp[2 * NUM_ECC_WORDS];
1160 uECC_word_t *v[2] = {tmp, product};
1161 uECC_word_t index;
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +01001162 const wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001163
1164 /* Shift mod so its highest set bit is at the maximum position. */
1165 bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001166 uECC_vli_numBits(mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001167 wordcount_t word_shift = shift / uECC_WORD_BITS;
1168 wordcount_t bit_shift = shift % uECC_WORD_BITS;
1169 uECC_word_t carry = 0;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001170 uECC_vli_clear(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001171 if (bit_shift > 0) {
1172 for(index = 0; index < (uECC_word_t)num_words; ++index) {
1173 mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
1174 carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
1175 }
1176 } else {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001177 uECC_vli_set(mod_multiple + word_shift, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001178 }
1179
1180 for (index = 1; shift >= 0; --shift) {
1181 uECC_word_t borrow = 0;
1182 wordcount_t i;
1183 for (i = 0; i < num_words * 2; ++i) {
1184 uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
1185 if (diff != v[index][i]) {
1186 borrow = (diff > v[index][i]);
1187 }
1188 v[1 - index][i] = diff;
1189 }
1190 /* Swap the index if there was no borrow */
1191 index = !(index ^ borrow);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001192 uECC_vli_rshift1(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001193 mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
Andrzej Kurek0919b142020-07-06 15:28:59 -04001194 (uECC_WORD_BITS - 1);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001195 uECC_vli_rshift1(mod_multiple + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001196 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001197 uECC_vli_set(result, v[index]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001198}
1199
1200void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001201 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001202{
1203 uECC_word_t product[2 * NUM_ECC_WORDS];
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001204 uECC_vli_mult_rnd(product, left, right, NULL);
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +01001205 uECC_vli_mmod(result, product, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001206}
1207
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001208static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001209 const uECC_word_t *right, ecc_wait_state_t *s)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001210{
1211 uECC_word_t product[2 * NUM_ECC_WORDS];
1212 uECC_vli_mult_rnd(product, left, right, s);
1213
1214 vli_mmod_fast_secp256r1(result, product);
1215}
1216
Jarno Lamsa18987a42019-04-24 15:40:43 +03001217void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001218 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001219{
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001220 uECC_vli_modMult_rnd(result, left, right, NULL);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001221}
1222
Jarno Lamsa18987a42019-04-24 15:40:43 +03001223#define EVEN(vli) (!(vli[0] & 1))
1224
1225static void vli_modInv_update(uECC_word_t *uv,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001226 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001227{
1228
1229 uECC_word_t carry = 0;
1230
1231 if (!EVEN(uv)) {
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001232 carry = uECC_vli_add(uv, uv, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001233 }
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001234 uECC_vli_rshift1(uv);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001235 if (carry) {
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +01001236 uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001237 }
1238}
1239
1240void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001241 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001242{
1243 uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
1244 uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
1245 cmpresult_t cmpResult;
1246
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001247 if (uECC_vli_isZero(input)) {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001248 uECC_vli_clear(result);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001249 return;
1250 }
1251
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001252 uECC_vli_set(a, input);
1253 uECC_vli_set(b, mod);
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001254 uECC_vli_clear(u);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001255 u[0] = 1;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001256 uECC_vli_clear(v);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001257 while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001258 if (EVEN(a)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001259 uECC_vli_rshift1(a);
Andrzej Kurek0919b142020-07-06 15:28:59 -04001260 vli_modInv_update(u, mod);
1261 } else if (EVEN(b)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001262 uECC_vli_rshift1(b);
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +01001263 vli_modInv_update(v, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001264 } else if (cmpResult > 0) {
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001265 uECC_vli_sub(a, a, b);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001266 uECC_vli_rshift1(a);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001267 if (uECC_vli_cmp_unsafe(u, v) < 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001268 uECC_vli_add(u, u, mod);
1269 }
1270 uECC_vli_sub(u, u, v);
1271 vli_modInv_update(u, mod);
1272 } else {
1273 uECC_vli_sub(b, b, a);
1274 uECC_vli_rshift1(b);
1275 if (uECC_vli_cmp_unsafe(v, u) < 0) {
1276 uECC_vli_add(v, v, mod);
1277 }
1278 uECC_vli_sub(v, v, u);
1279 vli_modInv_update(v, mod);
1280 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001281 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001282 uECC_vli_set(result, u);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001283}
1284
1285/* ------ Point operations ------ */
1286
1287void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001288 uECC_word_t * Z1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001289{
1290 /* t1 = X, t2 = Y, t3 = Z */
1291 uECC_word_t t4[NUM_ECC_WORDS];
1292 uECC_word_t t5[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001293 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001294
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001295 if (uECC_vli_isZero(Z1)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001296 return;
1297 }
1298
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001299 uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */
1300 uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */
1301 uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */
1302 uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */
1303 uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001304
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001305 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = x1 + z1^2 */
1306 uECC_vli_modAdd(Z1, Z1, Z1, curve_p); /* t3 = 2*z1^2 */
1307 uECC_vli_modSub(Z1, X1, Z1, curve_p); /* t3 = x1 - z1^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001308 uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001309
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001310 uECC_vli_modAdd(Z1, X1, X1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
1311 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001312 if (uECC_vli_testBit(X1, 0)) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001313 uECC_word_t l_carry = uECC_vli_add(X1, X1, curve_p);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001314 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001315 X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
1316 } else {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001317 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001318 }
1319
1320 /* t1 = 3/2*(x1^2 - z1^4) = B */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001321 uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001322 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - A */
1323 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
1324 uECC_vli_modSub(t5, t5, Z1, curve_p); /* t5 = A - x3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001325 uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001326 /* t4 = B * (A - x3) - y1^4 = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001327 uECC_vli_modSub(t4, X1, t4, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001328
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001329 uECC_vli_set(X1, Z1);
1330 uECC_vli_set(Z1, Y1);
1331 uECC_vli_set(Y1, t4);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001332}
1333
Manuel Pégourié-Gonnard1c6f7ea2019-11-21 09:18:29 +01001334/*
1335 * @brief Computes x^3 + ax + b. result must not overlap x.
1336 * @param result OUT -- x^3 + ax + b
1337 * @param x IN -- value of x
1338 * @param curve IN -- elliptic curve
1339 */
1340static void x_side_default(uECC_word_t *result,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001341 const uECC_word_t *x)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001342{
1343 uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001344
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001345 uECC_vli_modMult_fast(result, x, x); /* r = x^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001346 uECC_vli_modSub(result, result, _3, curve_p); /* r = x^2 - 3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001347 uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001348 /* r = x^3 - 3x + b: */
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +01001349 uECC_vli_modAdd(result, result, curve_b, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001350}
1351
1352void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
1353{
1354 unsigned int tmp[NUM_ECC_WORDS];
1355 int carry;
1356
1357 /* t */
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001358 uECC_vli_set(result, product);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001359
1360 /* s1 */
1361 tmp[0] = tmp[1] = tmp[2] = 0;
1362 tmp[3] = product[11];
1363 tmp[4] = product[12];
1364 tmp[5] = product[13];
1365 tmp[6] = product[14];
1366 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001367 carry = uECC_vli_add(tmp, tmp, tmp);
1368 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001369
1370 /* s2 */
1371 tmp[3] = product[12];
1372 tmp[4] = product[13];
1373 tmp[5] = product[14];
1374 tmp[6] = product[15];
1375 tmp[7] = 0;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001376 carry += uECC_vli_add(tmp, tmp, tmp);
1377 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001378
1379 /* s3 */
1380 tmp[0] = product[8];
1381 tmp[1] = product[9];
1382 tmp[2] = product[10];
1383 tmp[3] = tmp[4] = tmp[5] = 0;
1384 tmp[6] = product[14];
1385 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001386 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001387
1388 /* s4 */
1389 tmp[0] = product[9];
1390 tmp[1] = product[10];
1391 tmp[2] = product[11];
1392 tmp[3] = product[13];
1393 tmp[4] = product[14];
1394 tmp[5] = product[15];
1395 tmp[6] = product[13];
1396 tmp[7] = product[8];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001397 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001398
1399 /* d1 */
1400 tmp[0] = product[11];
1401 tmp[1] = product[12];
1402 tmp[2] = product[13];
1403 tmp[3] = tmp[4] = tmp[5] = 0;
1404 tmp[6] = product[8];
1405 tmp[7] = product[10];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001406 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001407
1408 /* d2 */
1409 tmp[0] = product[12];
1410 tmp[1] = product[13];
1411 tmp[2] = product[14];
1412 tmp[3] = product[15];
1413 tmp[4] = tmp[5] = 0;
1414 tmp[6] = product[9];
1415 tmp[7] = product[11];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001416 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001417
1418 /* d3 */
1419 tmp[0] = product[13];
1420 tmp[1] = product[14];
1421 tmp[2] = product[15];
1422 tmp[3] = product[8];
1423 tmp[4] = product[9];
1424 tmp[5] = product[10];
1425 tmp[6] = 0;
1426 tmp[7] = product[12];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001427 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001428
1429 /* d4 */
1430 tmp[0] = product[14];
1431 tmp[1] = product[15];
1432 tmp[2] = 0;
1433 tmp[3] = product[9];
1434 tmp[4] = product[10];
1435 tmp[5] = product[11];
1436 tmp[6] = 0;
1437 tmp[7] = product[13];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001438 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001439
1440 if (carry < 0) {
1441 do {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001442 carry += uECC_vli_add(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001443 }
1444 while (carry < 0);
1445 } else {
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +02001446 while (carry ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001447 uECC_vli_cmp_unsafe(curve_p, result) != 1) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001448 carry -= uECC_vli_sub(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001449 }
1450 }
1451}
1452
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001453uECC_word_t EccPoint_isZero(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001454{
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001455 return uECC_vli_isZero(point);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001456}
1457
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001458void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001459{
1460 uECC_word_t t1[NUM_ECC_WORDS];
1461
Andrzej Kurek0919b142020-07-06 15:28:59 -04001462 uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001463 uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */
1464 uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */
1465 uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001466}
1467
1468/* P = (x1, y1) => 2P, (x2, y2) => P' */
1469static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
1470 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001471 const uECC_word_t * const initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001472{
1473 uECC_word_t z[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001474 if (initial_Z) {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001475 uECC_vli_set(z, initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001476 } else {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001477 uECC_vli_clear(z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001478 z[0] = 1;
1479 }
1480
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001481 uECC_vli_set(X2, X1);
1482 uECC_vli_set(Y2, Y1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001483
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001484 apply_z(X1, Y1, z);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001485 double_jacobian_default(X1, Y1, z);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001486 apply_z(X2, Y2, z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001487}
1488
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001489static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1490 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001491 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001492{
1493 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1494 uECC_word_t t5[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001495
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001496 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001497 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001498 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1499 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001500 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001501 uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001502
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001503 uECC_vli_modSub(t5, t5, X1, curve_p); /* t5 = D - B */
1504 uECC_vli_modSub(t5, t5, X2, curve_p); /* t5 = D - B - C = x3 */
1505 uECC_vli_modSub(X2, X2, X1, curve_p); /* t3 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001506 uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001507 uECC_vli_modSub(X2, X1, t5, curve_p); /* t3 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001508 uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001509 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001510
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001511 uECC_vli_set(X2, t5);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001512}
1513
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001514void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001515 uECC_word_t * X2, uECC_word_t * Y2)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001516{
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001517 XYcZ_add_rnd(X1, Y1, X2, Y2, NULL);
1518}
1519
Jarno Lamsa18987a42019-04-24 15:40:43 +03001520/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
1521 Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
1522 or P => P - Q, Q => P + Q
1523 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001524static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1525 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001526 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001527{
1528 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1529 uECC_word_t t5[NUM_ECC_WORDS];
1530 uECC_word_t t6[NUM_ECC_WORDS];
1531 uECC_word_t t7[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001532
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001533 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001534 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001535 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1536 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001537 uECC_vli_modAdd(t5, Y2, Y1, curve_p); /* t5 = y2 + y1 */
1538 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001539
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001540 uECC_vli_modSub(t6, X2, X1, curve_p); /* t6 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001541 uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001542 uECC_vli_modAdd(t6, X1, X2, curve_p); /* t6 = B + C */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001543 uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001544 uECC_vli_modSub(X2, X2, t6, curve_p); /* t3 = D - (B + C) = x3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001545
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001546 uECC_vli_modSub(t7, X1, X2, curve_p); /* t7 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001547 uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001548 /* t4 = (y2 - y1)*(B - x3) - E = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001549 uECC_vli_modSub(Y2, Y2, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001550
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001551 uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001552 uECC_vli_modSub(t7, t7, t6, curve_p); /* t7 = F - (B + C) = x3' */
1553 uECC_vli_modSub(t6, t7, X1, curve_p); /* t6 = x3' - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001554 uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001555 /* t2 = (y2+y1)*(x3' - B) - E = y3': */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001556 uECC_vli_modSub(Y1, t6, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001557
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001558 uECC_vli_set(X1, t7);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001559}
1560
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001561static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
Jarno Lamsa18987a42019-04-24 15:40:43 +03001562 const uECC_word_t * scalar,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001563 const uECC_word_t * initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001564{
1565 /* R0 and R1 */
1566 uECC_word_t Rx[2][NUM_ECC_WORDS];
1567 uECC_word_t Ry[2][NUM_ECC_WORDS];
1568 uECC_word_t z[NUM_ECC_WORDS];
1569 bitcount_t i;
1570 uECC_word_t nb;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001571 const wordcount_t num_words = NUM_ECC_WORDS;
1572 const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001573 ecc_wait_state_t wait_state;
1574 ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001575
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001576 uECC_vli_set(Rx[1], point);
1577 uECC_vli_set(Ry[1], point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001578
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001579 XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001580
1581 for (i = num_bits - 2; i > 0; --i) {
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001582 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001583 nb = !uECC_vli_testBit(scalar, i);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001584 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
1585 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001586 }
1587
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001588 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001589 nb = !uECC_vli_testBit(scalar, 0);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001590 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001591
1592 /* Find final 1/Z value. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001593 uECC_vli_modSub(z, Rx[1], Rx[0], curve_p); /* X1 - X0 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001594 uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */
1595 uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001596 uECC_vli_modInv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0))*/
Jarno Lamsa18987a42019-04-24 15:40:43 +03001597 /* yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001598 uECC_vli_modMult_fast(z, z, point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001599 /* Xb * yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001600 uECC_vli_modMult_fast(z, z, Rx[1 - nb]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001601 /* End 1/Z calculation */
1602
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001603 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001604 apply_z(Rx[0], Ry[0], z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001605
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001606 uECC_vli_set(result, Rx[0]);
1607 uECC_vli_set(result + num_words, Ry[0]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001608}
1609
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001610static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001611 uECC_word_t *k1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001612{
Shelly Libermana23f5992020-10-25 18:48:06 +02001613 wordcount_t num_n_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001614 bitcount_t num_n_bits = NUM_ECC_BITS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001615
Shelly Libermana23f5992020-10-25 18:48:06 +02001616
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001617 uECC_word_t carry = uECC_vli_add(k0, k, curve_n) ||
Shelly Libermana23f5992020-10-25 18:48:06 +02001618 (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
1619 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}
Andrzej Kurek7e62c312020-10-14 12:02:40 +02001856#endif /* MBEDTLS_USE_TINYCRYPT */