blob: 6c944d33fca9d4d61e21ac4c6170f695c9026f67 [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
Kevin Bracey1959c182020-07-16 21:03:19 +030073#ifdef __CC_ARM
74#pragma diag_suppress 667 // strict diagnostic: "asm" function is nonstandard
75#endif
76
77#if defined MBEDTLS_HAVE_ASM
78#ifndef asm
79#define asm __asm
80#endif
81#endif
82
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +010083/* Parameters for curve NIST P-256 aka secp256r1 */
84const uECC_word_t curve_p[NUM_ECC_WORDS] = {
85 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
86 BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
87 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
88 BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)
89};
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +010090const uECC_word_t curve_n[NUM_ECC_WORDS] = {
91 BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
92 BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
93 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
94 BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)
95};
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +010096const uECC_word_t curve_G[2 * NUM_ECC_WORDS] = {
97 BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
98 BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
99 BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
100 BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
101 BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
102 BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
103 BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
104 BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)
105};
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +0100106const uECC_word_t curve_b[NUM_ECC_WORDS] = {
107 BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
108 BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
109 BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
110 BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)
111};
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100112
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100113static int uECC_update_param_sha256(mbedtls_sha256_context *ctx,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400114 const uECC_word_t val[NUM_ECC_WORDS])
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100115{
116 uint8_t bytes[NUM_ECC_BYTES];
117
118 uECC_vli_nativeToBytes(bytes, NUM_ECC_BYTES, val);
119 return mbedtls_sha256_update_ret(ctx, bytes, NUM_ECC_BYTES);
120}
121
122static int uECC_compute_param_sha256(unsigned char output[32])
123{
124 int ret = UECC_FAILURE;
125 mbedtls_sha256_context ctx;
126
127 mbedtls_sha256_init( &ctx );
128
129 if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) {
130 goto exit;
131 }
132
133 if (uECC_update_param_sha256(&ctx, curve_p) != 0 ||
Andrzej Kurek0919b142020-07-06 15:28:59 -0400134 uECC_update_param_sha256(&ctx, curve_n) != 0 ||
135 uECC_update_param_sha256(&ctx, curve_G) != 0 ||
136 uECC_update_param_sha256(&ctx, curve_G + NUM_ECC_WORDS) != 0 ||
137 uECC_update_param_sha256(&ctx, curve_b) != 0)
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100138 {
139 goto exit;
140 }
141
142 if (mbedtls_sha256_finish_ret(&ctx, output) != 0) {
143 goto exit;
144 }
145
146 ret = UECC_SUCCESS;
147
148exit:
149 mbedtls_sha256_free( &ctx );
150
151 return ret;
152}
153
154/*
155 * Check integrity of curve parameters.
156 * Return 0 if everything's OK, non-zero otherwise.
157 */
158static int uECC_check_curve_integrity(void)
159{
160 unsigned char computed[32];
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100161 static const unsigned char reference[32] = {
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100162 0x2d, 0xa1, 0xa4, 0x64, 0x45, 0x28, 0x0d, 0xe1,
163 0x93, 0xf9, 0x29, 0x2f, 0xac, 0x3e, 0xe2, 0x92,
164 0x76, 0x0a, 0xe2, 0xbc, 0xce, 0x2a, 0xa2, 0xc6,
165 0x38, 0xf2, 0x19, 0x1d, 0x76, 0x72, 0x93, 0x49,
166 };
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100167 unsigned char diff = 0;
168 unsigned char tmp1, tmp2;
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100169 volatile unsigned i;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100170
171 if (uECC_compute_param_sha256(computed) != UECC_SUCCESS) {
172 return UECC_FAILURE;
173 }
174
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100175 for (i = 0; i < 32; i++) {
176 /* make sure the order of volatile accesses is well-defined */
177 tmp1 = computed[i];
178 tmp2 = reference[i];
179 diff |= tmp1 ^ tmp2;
180 }
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100181
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100182 /* i should be 32 */
Arto Kinnunenac6d2262020-01-09 10:11:20 +0200183 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100184 diff |= (unsigned char) i ^ 32;
185
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100186 return diff;
187}
188
Jarno Lamsa18987a42019-04-24 15:40:43 +0300189/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
190 * has access to enough entropy in order to feed the PRNG regularly. */
191#if default_RNG_defined
192static uECC_RNG_Function g_rng_function = &default_CSPRNG;
193#else
194static uECC_RNG_Function g_rng_function = 0;
195#endif
196
197void uECC_set_rng(uECC_RNG_Function rng_function)
198{
199 g_rng_function = rng_function;
200}
201
202uECC_RNG_Function uECC_get_rng(void)
203{
204 return g_rng_function;
205}
206
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +0100207int uECC_curve_private_key_size(void)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300208{
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +0100209 return BITS_TO_BYTES(NUM_ECC_BITS);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300210}
211
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +0100212int uECC_curve_public_key_size(void)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300213{
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +0100214 return 2 * NUM_ECC_BYTES;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300215}
216
Kevin Bracey3be252e2020-10-09 12:54:48 +0300217#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
218__asm void uECC_vli_clear(uECC_word_t *vli)
219{
220#if NUM_ECC_WORDS != 8
221#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
222#endif
223#if !defined __thumb__ || __TARGET_ARCH_THUMB < 4
224 MOVS r1,#0
225 MOVS r2,#0
226 STMIA r0!,{r1,r2}
227 STMIA r0!,{r1,r2}
228 STMIA r0!,{r1,r2}
229 STMIA r0!,{r1,r2}
230 BX lr
231#else
232 MOVS r1,#0
233 STRD r1,r1,[r0,#0] // Only Thumb2 STRD can store same reg twice, not ARM
234 STRD r1,r1,[r0,#8]
235 STRD r1,r1,[r0,#16]
236 STRD r1,r1,[r0,#24]
237 BX lr
238#endif
239}
240#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
241void uECC_vli_clear(uECC_word_t *vli)
242{
243#if NUM_ECC_WORDS != 8
244#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
245#endif
246#if !defined __thumb__ || !defined __thumb2__
247 register uECC_word_t *r0 asm("r0") = vli;
248 register uECC_word_t r1 asm("r1") = 0;
249 register uECC_word_t r2 asm("r2") = 0;
250 asm volatile (
251 ".syntax unified \n\t"
252 "STMIA r0!,{r1,r2} \n\t"
253 "STMIA r0!,{r1,r2} \n\t"
254 "STMIA r0!,{r1,r2} \n\t"
255 "STMIA r0!,{r1,r2} \n\t"
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300256 ".syntax divided \n\t"
Kevin Bracey3be252e2020-10-09 12:54:48 +0300257 : "+r" (r0)
258 : "r" (r1), "r" (r2)
259 : "memory"
260#else
261 register uECC_word_t *r0 asm("r0") = vli;
262 register uECC_word_t r1 asm("r1") = 0;
263 asm volatile (
264 "STRD r1,r1,[r0,#0] \n\t" // Only Thumb2 STRD can store same reg twice, not ARM
265 "STRD r1,r1,[r0,#8] \n\t"
266 "STRD r1,r1,[r0,#16] \n\t"
267 "STRD r1,r1,[r0,#24] \n\t"
268 :
269 : "r" (r0), "r" (r1)
270 : "memory"
271#endif
272 );
273}
274#else
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100275void uECC_vli_clear(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300276{
277 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100278 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300279 vli[i] = 0;
280 }
281}
Kevin Bracey3be252e2020-10-09 12:54:48 +0300282#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300283
Kevin Bracey3be252e2020-10-09 12:54:48 +0300284#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
285__asm uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
286{
287#if NUM_ECC_WORDS != 8
288#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
289#endif
290#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
291 LDMIA r0!,{r1,r2,r3}
292 ORRS r1,r2
293 ORRS r1,r3
294 LDMIA r0!,{r2,r3}
295 ORRS r1,r2
296 ORRS r1,r3
297 LDMIA r0,{r0,r2,r3}
298 ORRS r1,r0
299 ORRS r1,r2
300 ORRS r1,r3
301 RSBS r1,r1,#0 // C set if zero
302 MOVS r0,#0
303 ADCS r0,r0
304 BX lr
305#else
306 LDMIA r0!,{r1,r2,r3,ip}
307 ORRS r1,r2
308 ORRS r1,r3
309 ORRS r1,ip
310 LDMIA r0,{r0,r2,r3,ip}
311 ORRS r1,r0
312 ORRS r1,r2
313 ORRS r1,r3
314 ORRS r1,ip
315#ifdef __ARM_FEATURE_CLZ
316 CLZ r0,r1 // 32 if zero
317 LSRS r0,r0,#5
318#else
319 RSBS r1,r1,#0 // C set if zero
320 MOVS r0,#0
321 ADCS r0,r0
322#endif
323 BX lr
324#endif
325}
326#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
327uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
328{
329 uECC_word_t ret;
330#if NUM_ECC_WORDS != 8
331#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
332#endif
333#if defined __thumb__ && !defined __thumb2__
334 register uECC_word_t r1 asm ("r1");
335 register uECC_word_t r2 asm ("r2");
336 register uECC_word_t r3 asm ("r3");
337 asm volatile (
338 ".syntax unified \n\t"
339 "LDMIA %[vli]!,{%[r1],%[r2],%[r3]} \n\t"
340 "ORRS %[r1],%[r2] \n\t"
341 "ORRS %[r1],%[r3] \n\t"
342 "LDMIA %[vli]!,{%[r2],%[r3]} \n\t"
343 "ORRS %[r1],%[r2] \n\t"
344 "ORRS %[r1],%[r3] \n\t"
345 "LDMIA %[vli],{%[vli],%[r2],%[r3]} \n\t"
346 "ORRS %[r1],%[vli] \n\t"
347 "ORRS %[r1],%[r2] \n\t"
348 "ORRS %[r1],%[r3] \n\t"
349 "RSBS %[r1],%[r1],#0 \n\t" // C set if zero
350 "MOVS %[ret],#0 \n\t"
351 "ADCS %[ret],r0 \n\t"
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300352 ".syntax divided \n\t"
Kevin Bracey3be252e2020-10-09 12:54:48 +0300353 : [ret]"=r" (ret), [r1]"=r" (r1), [r2]"=r" (r2), [r3]"=r" (r3)
354 : [vli]"[ret]" (vli)
355 : "cc", "memory"
356 );
357#else
358 register uECC_word_t r1 asm ("r1");
359 register uECC_word_t r2 asm ("r2");
360 register uECC_word_t r3 asm ("r3");
361 register uECC_word_t ip asm ("ip");
362 asm volatile (
363 "LDMIA %[vli]!,{%[r1],%[r2],%[r3],%[ip]}\n\t"
364 "ORRS %[r1],%[r2] \n\t"
365 "ORRS %[r1],%[r3] \n\t"
366 "ORRS %[r1],%[ip] \n\t"
367 "LDMIA %[vli],{%[vli],%[r2],%[r3],%[ip]}\n\t"
368 "ORRS %[r1],%[vli] \n\t"
369 "ORRS %[r1],%[r2] \n\t"
370 "ORRS %[r1],%[r3] \n\t"
371 "ORRS %[r1],%[ip] \n\t"
372#if __ARM_ARCH >= 5
373 "CLZ %[ret],%[r1] \n\t" // r0 = 32 if zero
374 "LSRS %[ret],%[ret],#5 \n\t"
375#else
376 "RSBS %[r1],%[r1],#0 \n\t" // C set if zero
377 "MOVS %[ret],#0 \n\t"
378 "ADCS %[ret],r0 \n\t"
379#endif
380 : [ret]"=r" (ret), [r1]"=r" (r1), [r2]"=r" (r2), [r3]"=r" (r3), [ip]"=r" (ip)
381 : [vli]"[ret]" (vli)
382 : "cc", "memory"
383 );
384#endif
385 return ret;
386}
387#else
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100388uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300389{
390 uECC_word_t bits = 0;
391 wordcount_t i;
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100392 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300393 bits |= vli[i];
394 }
395 return (bits == 0);
396}
Kevin Bracey3be252e2020-10-09 12:54:48 +0300397#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300398
399uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit)
400{
401 return (vli[bit >> uECC_WORD_BITS_SHIFT] &
402 ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
403}
404
405/* Counts the number of words in vli. */
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100406static wordcount_t vli_numDigits(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300407{
408
409 wordcount_t i;
410 /* Search from the end until we find a non-zero digit. We do it in reverse
411 * because we expect that most digits will be nonzero. */
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100412 for (i = NUM_ECC_WORDS - 1; i >= 0 && vli[i] == 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300413 }
414
415 return (i + 1);
416}
417
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100418bitcount_t uECC_vli_numBits(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300419{
420
421 uECC_word_t i;
422 uECC_word_t digit;
423
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100424 wordcount_t num_digits = vli_numDigits(vli);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300425 if (num_digits == 0) {
426 return 0;
427 }
428
429 digit = vli[num_digits - 1];
Kevin Bracey99c64e12020-10-06 12:25:28 +0300430#if defined __GNUC__ || defined __clang__ || defined __CC_ARM
431 i = uECC_WORD_BITS - __builtin_clz(digit);
432#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300433 for (i = 0; digit; ++i) {
434 digit >>= 1;
435 }
Kevin Bracey99c64e12020-10-06 12:25:28 +0300436#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300437
438 return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
439}
440
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100441void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300442{
443 wordcount_t i;
444
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100445 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300446 dest[i] = src[i];
447 }
448}
449
450cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100451 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300452{
453 wordcount_t i;
454
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100455 for (i = NUM_ECC_WORDS - 1; i >= 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300456 if (left[i] > right[i]) {
457 return 1;
458 } else if (left[i] < right[i]) {
459 return -1;
460 }
461 }
462 return 0;
463}
464
Manuel Pégourié-Gonnard2eca3d32019-11-04 14:33:09 +0100465uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300466{
467
468 uECC_word_t diff = 0;
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200469 uECC_word_t flow_monitor = 0;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100470 uECC_word_t tmp1, tmp2;
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100471 volatile int i;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300472
Piotr Nowickif0ab6d62020-05-25 12:48:30 +0200473 /* Start from a random location and check the correct number of iterations */
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200474 int start_offset = mbedtls_platform_random_in_range(NUM_ECC_WORDS);
475
476 for (i = start_offset; i < NUM_ECC_WORDS; ++i) {
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100477 tmp1 = left[i];
478 tmp2 = right[i];
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200479 flow_monitor++;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100480 diff |= (tmp1 ^ tmp2);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300481 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100482
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200483 for (i = 0; i < start_offset; ++i) {
484 tmp1 = left[i];
485 tmp2 = right[i];
486 flow_monitor++;
487 diff |= (tmp1 ^ tmp2);
488 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100489
Piotr Nowickif0ab6d62020-05-25 12:48:30 +0200490 /* Random delay to increase security */
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200491 mbedtls_platform_random_delay();
492
493 /* Return 0 only when diff is 0 and flow_counter is equal to NUM_ECC_WORDS */
494 return (diff | (flow_monitor ^ NUM_ECC_WORDS));
Jarno Lamsa18987a42019-04-24 15:40:43 +0300495}
496
497uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
498{
Kevin Bracey045e5762020-10-06 12:25:58 +0300499 return (p_true*(cond)) | (p_false*(cond ^ 1));
Jarno Lamsa18987a42019-04-24 15:40:43 +0300500}
501
502/* Computes result = left - right, returning borrow, in constant time.
503 * Can modify in place. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300504#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
505__asm uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
506 const uECC_word_t *right)
507{
508#if NUM_ECC_WORDS != 8
509#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
510#endif
511#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
512 PUSH {r4-r6,lr}
513 FRAME PUSH {r4-r6,lr}
514 LDMIA r1!,{r3,r4}
515 LDMIA r2!,{r5,r6}
516 SUBS r3,r5
517 SBCS r4,r6
518 STMIA r0!,{r3,r4}
519 LDMIA r1!,{r3,r4}
520 LDMIA r2!,{r5,r6}
521 SBCS r3,r5
522 SBCS r4,r6
523 STMIA r0!,{r3,r4}
524 LDMIA r1!,{r3,r4}
525 LDMIA r2!,{r5,r6}
526 SBCS r3,r5
527 SBCS r4,r6
528 STMIA r0!,{r3,r4}
529 LDMIA r1!,{r3,r4}
530 LDMIA r2!,{r5,r6}
531 SBCS r3,r5
532 SBCS r4,r6
533 STMIA r0!,{r3,r4}
534 SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow
535 RSBS r0,r0,#0 // r0 := borrow
536 POP {r4-r6,pc}
537#else
538 PUSH {r4-r8,lr}
539 FRAME PUSH {r4-r8,lr}
540 LDMIA r1!,{r3-r6}
541 LDMIA r2!,{r7,r8,r12,lr}
542 SUBS r3,r7
543 SBCS r4,r8
544 SBCS r5,r12
545 SBCS r6,lr
546 STMIA r0!,{r3-r6}
547 LDMIA r1!,{r3-r6}
548 LDMIA r2!,{r7,r8,r12,lr}
549 SBCS r3,r7
550 SBCS r4,r8
551 SBCS r5,r12
552 SBCS r6,lr
553 STMIA r0!,{r3-r6}
554 SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow
555 RSBS r0,r0,#0 // r0 := borrow
556 POP {r4-r8,pc}
557#endif
558}
Kevin Bracey4aea6252020-10-09 12:54:28 +0300559#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
560uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
561 const uECC_word_t *right)
562{
563#if NUM_ECC_WORDS != 8
564#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
565#endif
566 register uECC_word_t *r0 asm ("r0") = result;
567 register const uECC_word_t *r1 asm ("r1") = left;
568 register const uECC_word_t *r2 asm ("r2") = right;
569 asm volatile (
570#if defined __thumb__ && !defined __thumb2__
571 ".syntax unified \n\t"
572 "LDMIA r1!,{r3,r4} \n\t"
573 "LDMIA r2!,{r5,r6} \n\t"
574 "SUBS r3,r5 \n\t"
575 "SBCS r4,r6 \n\t"
576 "STMIA r0!,{r3,r4} \n\t"
577 "LDMIA r1!,{r3,r4} \n\t"
578 "LDMIA r2!,{r5,r6} \n\t"
579 "SBCS r3,r5 \n\t"
580 "SBCS r4,r6 \n\t"
581 "STMIA r0!,{r3,r4} \n\t"
582 "LDMIA r1!,{r3,r4} \n\t"
583 "LDMIA r2!,{r5,r6} \n\t"
584 "SBCS r3,r5 \n\t"
585 "SBCS r4,r6 \n\t"
586 "STMIA r0!,{r3,r4} \n\t"
587 "LDMIA r1!,{r3,r4} \n\t"
588 "LDMIA r2!,{r5,r6} \n\t"
589 "SBCS r3,r5 \n\t"
590 "SBCS r4,r6 \n\t"
591 "STMIA r0!,{r3,r4} \n\t"
592 "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow
593 "RSBS r0,r0,#0 \n\t" // r0 := borrow
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300594 ".syntax divided \n\t"
Kevin Bracey4aea6252020-10-09 12:54:28 +0300595 : "+r" (r0), "+r" (r1), "+r" (r2)
596 :
597 : "r3", "r4", "r5", "r6", "cc", "memory"
598#else
599 "LDMIA r1!,{r3-r6} \n\t"
600 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
601 "SUBS r3,r7 \n\t"
602 "SBCS r4,r8 \n\t"
603 "SBCS r5,r12 \n\t"
604 "SBCS r6,lr \n\t"
605 "STMIA r0!,{r3-r6} \n\t"
606 "LDMIA r1!,{r3-r6} \n\t"
607 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
608 "SBCS r3,r7 \n\t"
609 "SBCS r4,r8 \n\t"
610 "SBCS r5,r12 \n\t"
611 "SBCS r6,lr \n\t"
612 "STMIA r0!,{r3-r6} \n\t"
613 "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow
614 "RSBS r0,r0,#0 \n\t" // r0 := borrow
615 : "+r" (r0), "+r" (r1), "+r" (r2)
616 :
617 : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory"
618#endif
619 );
620 return (uECC_word_t) r0;
621}
Kevin Bracey1959c182020-07-16 21:03:19 +0300622#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300623uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100624 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300625{
626 uECC_word_t borrow = 0;
627 wordcount_t i;
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100628 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300629 uECC_word_t diff = left[i] - right[i] - borrow;
630 uECC_word_t val = (diff > left[i]);
631 borrow = cond_set(val, borrow, (diff != left[i]));
632
633 result[i] = diff;
634 }
635 return borrow;
636}
Kevin Bracey1959c182020-07-16 21:03:19 +0300637#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300638
639/* Computes result = left + right, returning carry, in constant time.
640 * Can modify in place. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300641#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
642static __asm uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
643 const uECC_word_t *right)
644{
645#if NUM_ECC_WORDS != 8
646#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
647#endif
648#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
649 PUSH {r4-r6,lr}
650 FRAME PUSH {r4-r6,lr}
651 LDMIA r1!,{r3,r4}
652 LDMIA r2!,{r5,r6}
653 ADDS r3,r5
654 ADCS r4,r6
655 STMIA r0!,{r3,r4}
656 LDMIA r1!,{r3,r4}
657 LDMIA r2!,{r5,r6}
658 ADCS r3,r5
659 ADCS r4,r6
660 STMIA r0!,{r3,r4}
661 LDMIA r1!,{r3,r4}
662 LDMIA r2!,{r5,r6}
663 ADCS r3,r5
664 ADCS r4,r6
665 STMIA r0!,{r3,r4}
666 LDMIA r1!,{r3,r4}
667 LDMIA r2!,{r5,r6}
668 ADCS r3,r5
669 ADCS r4,r6
670 STMIA r0!,{r3,r4}
671 MOVS r0,#0 // does not affect C flag
672 ADCS r0,r0 // r0 := 0 + 0 + C = carry
673 POP {r4-r6,pc}
674#else
675 PUSH {r4-r8,lr}
676 FRAME PUSH {r4-r8,lr}
677 LDMIA r1!,{r3-r6}
678 LDMIA r2!,{r7,r8,r12,lr}
679 ADDS r3,r7
680 ADCS r4,r8
681 ADCS r5,r12
682 ADCS r6,lr
683 STMIA r0!,{r3-r6}
684 LDMIA r1!,{r3-r6}
685 LDMIA r2!,{r7,r8,r12,lr}
686 ADCS r3,r7
687 ADCS r4,r8
688 ADCS r5,r12
689 ADCS r6,lr
690 STMIA r0!,{r3-r6}
691 MOVS r0,#0 // does not affect C flag
692 ADCS r0,r0 // r0 := 0 + 0 + C = carry
693 POP {r4-r8,pc}
694#endif
695}
Kevin Bracey4aea6252020-10-09 12:54:28 +0300696#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
697static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
698 const uECC_word_t *right)
699{
700 register uECC_word_t *r0 asm ("r0") = result;
701 register const uECC_word_t *r1 asm ("r1") = left;
702 register const uECC_word_t *r2 asm ("r2") = right;
703
704 asm volatile (
705#if defined __thumb__ && !defined __thumb2__
706 ".syntax unified \n\t"
707 "LDMIA r1!,{r3,r4} \n\t"
708 "LDMIA r2!,{r5,r6} \n\t"
709 "ADDS r3,r5 \n\t"
710 "ADCS r4,r6 \n\t"
711 "STMIA r0!,{r3,r4} \n\t"
712 "LDMIA r1!,{r3,r4} \n\t"
713 "LDMIA r2!,{r5,r6} \n\t"
714 "ADCS r3,r5 \n\t"
715 "ADCS r4,r6 \n\t"
716 "STMIA r0!,{r3,r4} \n\t"
717 "LDMIA r1!,{r3,r4} \n\t"
718 "LDMIA r2!,{r5,r6} \n\t"
719 "ADCS r3,r5 \n\t"
720 "ADCS r4,r6 \n\t"
721 "STMIA r0!,{r3,r4} \n\t"
722 "LDMIA r1!,{r3,r4} \n\t"
723 "LDMIA r2!,{r5,r6} \n\t"
724 "ADCS r3,r5 \n\t"
725 "ADCS r4,r6 \n\t"
726 "STMIA r0!,{r3,r4} \n\t"
727 "MOVS r0,#0 \n\t" // does not affect C flag
728 "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300729 ".syntax divided \n\t"
Kevin Bracey4aea6252020-10-09 12:54:28 +0300730 : "+r" (r0), "+r" (r1), "+r" (r2)
731 :
732 : "r3", "r4", "r5", "r6", "cc", "memory"
733#else
734 "LDMIA r1!,{r3-r6} \n\t"
735 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
736 "ADDS r3,r7 \n\t"
737 "ADCS r4,r8 \n\t"
738 "ADCS r5,r12 \n\t"
739 "ADCS r6,lr \n\t"
740 "STMIA r0!,{r3-r6} \n\t"
741 "LDMIA r1!,{r3-r6} \n\t"
742 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
743 "ADCS r3,r7 \n\t"
744 "ADCS r4,r8 \n\t"
745 "ADCS r5,r12 \n\t"
746 "ADCS r6,lr \n\t"
747 "STMIA r0!,{r3-r6} \n\t"
748 "MOVS r0,#0 \n\t" // does not affect C flag
749 "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry
750 : "+r" (r0), "+r" (r1), "+r" (r2)
751 :
752 : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory"
753#endif
754 );
755 return (uECC_word_t) r0;
756}
Kevin Bracey1959c182020-07-16 21:03:19 +0300757#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300758static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100759 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300760{
761 uECC_word_t carry = 0;
762 wordcount_t i;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100763 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300764 uECC_word_t sum = left[i] + right[i] + carry;
765 uECC_word_t val = (sum < left[i]);
766 carry = cond_set(val, carry, (sum != left[i]));
767 result[i] = sum;
768 }
769 return carry;
770}
Kevin Bracey1959c182020-07-16 21:03:19 +0300771#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300772
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +0100773cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300774{
775 uECC_word_t tmp[NUM_ECC_WORDS];
Kevin Bracey045e5762020-10-06 12:25:58 +0300776 uECC_word_t neg = uECC_vli_sub(tmp, left, right);
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100777 uECC_word_t equal = uECC_vli_isZero(tmp);
Kevin Bracey045e5762020-10-06 12:25:58 +0300778 return ((equal ^ 1) - 2 * neg);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300779}
780
781/* Computes vli = vli >> 1. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300782#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
783static __asm void uECC_vli_rshift1(uECC_word_t *vli)
784{
785#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
786// RRX instruction is not available, so although we
787// can use C flag, it's not that effective. Does at
788// least save one working register, meaning we don't need stack
789 MOVS r3,#0 // initial carry = 0
790 MOVS r2,#__cpp(4 * (NUM_ECC_WORDS - 1))
79101 LDR r1,[r0,r2]
792 LSRS r1,r1,#1 // r2 = word >> 1
793 ORRS r1,r3 // merge in the previous carry
794 STR r1,[r0,r2]
795 ADCS r3,r3 // put C into bottom bit of r3
796 LSLS r3,r3,#31 // shift it up to the top ready for next word
797 SUBS r2,r2,#4
798 BPL %B01
799 BX lr
800#else
801#if NUM_ECC_WORDS != 8
802#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
803#endif
804// Smooth multiword operation, lots of 32-bit instructions
805 ADDS r0,#32
806 LDMDB r0,{r1-r3,ip}
807 LSRS ip,ip,#1
808 RRXS r3,r3
809 RRXS r2,r2
810 RRXS r1,r1
811 STMDB r0!,{r1-r3,ip}
812 LDMDB r0,{r1-r3,ip}
813 RRXS ip,ip
814 RRXS r3,r3
815 RRXS r2,r2
816 RRX r1,r1
817 STMDB r0!,{r1-r3,ip}
818 BX lr
819#endif
820}
Kevin Bracey06060332020-10-02 17:43:12 +0300821#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__ && defined __thumb2__
822static void uECC_vli_rshift1(uECC_word_t *vli)
823{
824 register uECC_word_t *r0 asm ("r0") = vli;
825#if NUM_ECC_WORDS != 8
826#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
827#endif
828 asm volatile (
829 "ADDS r0,#32 \n\t"
830 "LDMDB r0,{r1-r3,ip} \n\t"
831 "LSRS ip,ip,#1 \n\t"
832 "RRXS r3,r3 \n\t"
833 "RRXS r2,r2 \n\t"
834 "RRXS r1,r1 \n\t"
835 "STMDB r0!,{r1-r3,ip} \n\t"
836 "LDMDB r0,{r1-r3,ip} \n\t"
837 "RRXS ip,ip \n\t"
838 "RRXS r3,r3 \n\t"
839 "RRXS r2,r2 \n\t"
840 "RRX r1,r1 \n\t"
841 "STMDB r0!,{r1-r3,ip} \n\t"
842 : "+r" (r0)
843 :
844 : "r1", "r2", "r3", "ip", "cc", "memory"
845 );
846}
Kevin Bracey1959c182020-07-16 21:03:19 +0300847#else
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100848static void uECC_vli_rshift1(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300849{
850 uECC_word_t *end = vli;
851 uECC_word_t carry = 0;
852
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100853 vli += NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300854 while (vli-- > end) {
855 uECC_word_t temp = *vli;
856 *vli = (temp >> 1) | carry;
857 carry = temp << (uECC_WORD_BITS - 1);
858 }
859}
Kevin Bracey1959c182020-07-16 21:03:19 +0300860#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300861
Kevin Bracey84f31d32020-09-29 17:51:04 +0300862/* Compute a * b + r, where r is a triple-word with high-order word r[2] and
863 * low-order word r[0], and store the result in the same triple-word.
Manuel Pégourié-Gonnard86c4f812019-10-31 13:02:03 +0100864 *
Kevin Bracey84f31d32020-09-29 17:51:04 +0300865 * r[2..0] = a * b + r[2..0]:
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200866 * [in] a, b: operands to be multiplied
Kevin Bracey84f31d32020-09-29 17:51:04 +0300867 * [in] r: 3 words of operand to add
868 * [out] r: 3 words of result
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200869 */
Kevin Bracey1959c182020-07-16 21:03:19 +0300870#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
Kevin Bracey84f31d32020-09-29 17:51:04 +0300871static __asm void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Bracey1959c182020-07-16 21:03:19 +0300872{
873#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
Kevin Bracey84f31d32020-09-29 17:51:04 +0300874 PUSH {r4-r5}
875 FRAME PUSH {r4-r5}
876 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
877 // Separate operands into halfwords
878 UXTH r3,r0 // r3 := a.lo
879 LSRS r4,r0,#16 // r4 := a.hi
880 UXTH r5,r1 // r5 := b.lo
881 LSRS r1,r1,#16 // r1 := b.hi
882 // Multiply halfword pairs
883 MOVS r0,r3
884 MULS r0,r5,r0 // r0 := a.lo * b.lo
885 MULS r3,r1,r3 // r3 := a.lo * b.hi
886 MULS r5,r4,r5 // r5 := a.hi * b.lo
887 MULS r1,r4,r1 // r1 := a.hi * b.hi
888 // Split, shift and add a.lo * b.hi
889 LSRS r4,r3,#16 // r4 := (a.lo * b.hi).hi
890 LSLS r3,r3,#16 // r3 := (a.lo * b.hi).lo
891 ADDS r0,r0,r3 // r0 := a.lo * b.lo + (a.lo * b.hi).lo
892 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
893 // Split, shift and add a.hi * b.lo
894 LSRS r4,r5,#16 // r4 := (a.hi * b.lo).hi
895 LSLS r5,r5,#16 // r5 := (a.hi * b.lo).lo
896 ADDS r0,r0,r5 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
897 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
898 // Finally add r[]
899 LDMIA r2!,{r3,r4,r5}
900 ADDS r3,r3,r0
Kevin Bracey1959c182020-07-16 21:03:19 +0300901 ADCS r4,r1
Kevin Bracey1959c182020-07-16 21:03:19 +0300902 MOVS r0,#0
Kevin Bracey84f31d32020-09-29 17:51:04 +0300903 ADCS r5,r0
904 SUBS r2,#12
905 STMIA r2!,{r3,r4,r5}
906 POP {r4-r5}
907 FRAME POP {r4-r5}
908 BX lr
Kevin Bracey1959c182020-07-16 21:03:19 +0300909#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300910 UMULL r3,ip,r0,r1 // pre-ARMv6 requires Rd[Lo|Hi] != Rn
911 LDMIA r2,{r0,r1}
912 ADDS r0,r0,r3
913 LDR r3,[r2,#8]
914 ADCS r1,r1,ip
915 ADC r3,r3,#0
916 STMIA r2!,{r0,r1,r3}
Kevin Bracey1959c182020-07-16 21:03:19 +0300917 BX lr
918#endif
Kevin Braceye0f88d52020-09-30 12:52:15 +0300919}
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300920#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
921static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Braceye0f88d52020-09-30 12:52:15 +0300922{
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300923 register uECC_word_t r0 asm ("r0") = a;
924 register uECC_word_t r1 asm ("r1") = b;
925 register uECC_word_t *r2 asm ("r2") = r;
926 asm volatile (
Kevin Braceye0f88d52020-09-30 12:52:15 +0300927#if defined __thumb__ && !defined(__thumb2__)
928 ".syntax unified \n\t"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300929 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
930 // Separate operands into halfwords
931 "UXTH r3,r0 \n\t" // r3 := a.lo
932 "LSRS r4,r0,#16 \n\t" // r4 := a.hi
933 "UXTH r5,r1 \n\t" // r5 := b.lo
934 "LSRS r1,r1,#16 \n\t" // r1 := b.hi
935 // Multiply halfword pairs
936 "MOVS r0,r3 \n\t"
937 "MULS r0,r5,r0 \n\t" // r0 := a.lo * b.lo
938 "MULS r3,r1,r3 \n\t" // r3 := a.lo * b.hi
939 "MULS r5,r4,r5 \n\t" // r5 := a.hi * b.lo
940 "MULS r1,r4,r1 \n\t" // r1 := a.hi * b.hi
941 // Split, shift and add a.lo * b.hi
942 "LSRS r4,r3,#16 \n\t" // r4 := (a.lo * b.hi).hi
943 "LSLS r3,r3,#16 \n\t" // r3 := (a.lo * b.hi).lo
944 "ADDS r0,r0,r3 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo
945 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
946 // Split, shift and add a.hi * b.lo
947 "LSRS r4,r5,#16 \n\t" // r4 := (a.hi * b.lo).hi
948 "LSLS r5,r5,#16 \n\t" // r5 := (a.hi * b.lo).lo
949 "ADDS r0,r0,r5 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
950 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
951 // Finally add r[]
952 "LDMIA r2!,{r3,r4,r5} \n\t"
953 "ADDS r3,r3,r0 \n\t"
954 "ADCS r4,r1 \n\t"
955 "MOVS r0,#0 \n\t"
956 "ADCS r5,r0 \n\t"
957 "SUBS r2,#12 \n\t"
958 "STMIA r2!,{r3,r4,r5} \n\t"
Kevin Bracey8b2014b2020-10-07 16:53:00 +0300959 ".syntax divided \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300960 : "+r" (r0), "+r" (r1), "+r" (r2)
961 :
962 : "r3", "r4", "r5", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300963#else
964 "UMULL r3,ip,r0,r1 \n\t" // pre-ARMv6 requires Rd[Lo|Hi] != Rn
965 "LDMIA r2,{r0,r1} \n\t"
966 "ADDS r0,r0,r3 \n\t"
967 "LDR r3,[r2,#8] \n\t"
968 "ADCS r1,r1,ip \n\t"
969 "ADC r3,r3,#0 \n\t"
970 "STMIA r2!,{r0,r1,r3} \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300971 : "+r" (r0), "+r" (r1), "+r" (r2)
972 :
973 : "r3", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300974#endif
975 );
Kevin Bracey1959c182020-07-16 21:03:19 +0300976}
977#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300978static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Jarno Lamsa18987a42019-04-24 15:40:43 +0300979{
980
981 uECC_dword_t p = (uECC_dword_t)a * b;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300982 uECC_dword_t r01 = ((uECC_dword_t)(r[1]) << uECC_WORD_BITS) | r[0];
Jarno Lamsa18987a42019-04-24 15:40:43 +0300983 r01 += p;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300984 r[2] += (r01 < p);
985 r[1] = r01 >> uECC_WORD_BITS;
986 r[0] = (uECC_word_t)r01;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300987}
Kevin Bracey1959c182020-07-16 21:03:19 +0300988#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300989
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200990/* State for implementing random delays in uECC_vli_mult_rnd().
991 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100992 * The state is initialized by randomizing delays and setting i = 0.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200993 * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i.
994 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100995 * Randomized vli multiplication is used only for point operations
996 * (XYcZ_add_rnd() * and XYcZ_addC_rnd()) in scalar multiplication
997 * (ECCPoint_mult()). Those go in pair, and each pair does 14 calls to
998 * uECC_vli_mult_rnd() (6 in XYcZ_add_rnd() and 8 in XYcZ_addC_rnd(),
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100999 * indirectly through uECC_vli_modMult_rnd().
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001000 *
1001 * Considering this, in order to minimize the number of calls to the RNG
1002 * (which impact performance) while keeping the size of the structure low,
1003 * make room for 14 randomized vli mults, which corresponds to one step in the
1004 * scalar multiplication routine.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001005 */
1006typedef struct {
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001007 uint8_t i;
1008 uint8_t delays[14];
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001009} ecc_wait_state_t;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001010
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001011/*
1012 * Reset wait_state so that it's ready to be used.
1013 */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001014void ecc_wait_state_reset(ecc_wait_state_t *ws)
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001015{
1016 if (ws == NULL)
1017 return;
1018
1019 ws->i = 0;
Shelly Liberman05beb9a2020-09-13 15:23:56 +03001020 mbedtls_platform_random_buf(ws->delays, sizeof(ws->delays));
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +01001021}
1022
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001023/* Computes result = left * right. Result must be 2 * num_words long.
1024 *
1025 * As a counter-measure against horizontal attacks, add noise by performing
1026 * a random number of extra computations performing random additional accesses
1027 * to limbs of the input.
1028 *
1029 * Each of the two actual computation loops is surrounded by two
1030 * similar-looking waiting loops, to make the beginning and end of the actual
1031 * computation harder to spot.
1032 *
1033 * We add 4 waiting loops of between 0 and 3 calls to muladd() each. That
1034 * makes an average of 6 extra calls. Compared to the main computation which
1035 * makes 64 such calls, this represents an average performance degradation of
1036 * less than 10%.
1037 *
1038 * Compared to the original uECC_vli_mult(), loose the num_words argument as we
1039 * know it's always 8. This saves a bit of code size and execution speed.
1040 */
1041static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001042 const uECC_word_t *right, ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001043{
1044
Kevin Bracey84f31d32020-09-29 17:51:04 +03001045 uECC_word_t r[3] = { 0, 0, 0 };
Jarno Lamsa18987a42019-04-24 15:40:43 +03001046 wordcount_t i, k;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001047 const uint8_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001048
1049 /* Fetch 8 bit worth of delay from the state; 0 if we have no state */
1050 uint8_t delays = s ? s->delays[s->i++] : 0;
Kevin Bracey84f31d32020-09-29 17:51:04 +03001051 uECC_word_t rr[3] = { 0, 0, 0 };
1052 volatile uECC_word_t rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001053
1054 /* Mimic start of next loop: k in [0, 3] */
1055 k = 0 + (delays & 0x03);
1056 delays >>= 2;
1057 /* k = 0 -> i in [1, 0] -> 0 extra muladd;
1058 * k = 3 -> i in [1, 3] -> 3 extra muladd */
Manuel Pégourié-Gonnardc8814862019-11-05 10:32:37 +01001059 for (i = 1; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001060 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001061 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001062 rdummy = rr[0];
1063 rr[0] = rr[1];
1064 rr[1] = rr[2];
1065 rr[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001066
1067 /* Compute each digit of result in sequence, maintaining the carries. */
1068 for (k = 0; k < num_words; ++k) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001069 for (i = 0; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001070 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001071 }
1072
Kevin Bracey84f31d32020-09-29 17:51:04 +03001073 result[k] = r[0];
1074 r[0] = r[1];
1075 r[1] = r[2];
1076 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001077 }
1078
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001079 /* Mimic end of previous loop: k in [4, 7] */
1080 k = 4 + (delays & 0x03);
1081 delays >>= 2;
1082 /* k = 4 -> i in [5, 4] -> 0 extra muladd;
1083 * k = 7 -> i in [5, 7] -> 3 extra muladd */
1084 for (i = 5; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001085 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001086 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001087 rdummy = rr[0];
1088 rr[0] = rr[1];
1089 rr[1] = rr[2];
1090 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001091
1092 /* Mimic start of next loop: k in [8, 11] */
1093 k = 11 - (delays & 0x03);
1094 delays >>= 2;
1095 /* k = 8 -> i in [5, 7] -> 3 extra muladd;
1096 * k = 11 -> i in [8, 7] -> 0 extra muladd */
1097 for (i = (k + 5) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001098 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001099 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001100 rdummy = rr[0];
1101 rr[0] = rr[1];
1102 rr[1] = rr[2];
1103 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001104
Jarno Lamsa18987a42019-04-24 15:40:43 +03001105 for (k = num_words; k < num_words * 2 - 1; ++k) {
1106
1107 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001108 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001109 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001110 result[k] = r[0];
1111 r[0] = r[1];
1112 r[1] = r[2];
1113 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001114 }
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001115
Kevin Bracey84f31d32020-09-29 17:51:04 +03001116 result[num_words * 2 - 1] = r[0];
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001117
1118 /* Mimic end of previous loop: k in [12, 15] */
1119 k = 15 - (delays & 0x03);
1120 delays >>= 2;
1121 /* k = 12 -> i in [5, 7] -> 3 extra muladd;
1122 * k = 15 -> i in [8, 7] -> 0 extra muladd */
1123 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +03001124 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001125 }
Kevin Bracey84f31d32020-09-29 17:51:04 +03001126 rdummy = rr[0];
1127 rr[0] = rr[1];
1128 rr[1] = rr[2];
1129 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001130
Kevin Bracey84f31d32020-09-29 17:51:04 +03001131 /* avoid warning that rdummy is set but not used */
1132 (void) rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +02001133}
1134
Jarno Lamsa18987a42019-04-24 15:40:43 +03001135void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001136 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001137{
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001138 uECC_word_t carry = uECC_vli_add(result, left, right);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001139 if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001140 /* result > mod (result = mod + remainder), so subtract mod to get
1141 * remainder. */
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001142 uECC_vli_sub(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001143 }
1144}
1145
1146void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001147 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001148{
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001149 uECC_word_t l_borrow = uECC_vli_sub(result, left, right);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001150 if (l_borrow) {
1151 /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
1152 * we can get the correct result from result + mod (with overflow). */
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001153 uECC_vli_add(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001154 }
1155}
1156
1157/* Computes result = product % mod, where product is 2N words long. */
1158/* Currently only designed to work for curve_p or curve_n. */
1159void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001160 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001161{
1162 uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
1163 uECC_word_t tmp[2 * NUM_ECC_WORDS];
1164 uECC_word_t *v[2] = {tmp, product};
1165 uECC_word_t index;
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +01001166 const wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001167
1168 /* Shift mod so its highest set bit is at the maximum position. */
1169 bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001170 uECC_vli_numBits(mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001171 wordcount_t word_shift = shift / uECC_WORD_BITS;
1172 wordcount_t bit_shift = shift % uECC_WORD_BITS;
1173 uECC_word_t carry = 0;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001174 uECC_vli_clear(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001175 if (bit_shift > 0) {
1176 for(index = 0; index < (uECC_word_t)num_words; ++index) {
1177 mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
1178 carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
1179 }
1180 } else {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001181 uECC_vli_set(mod_multiple + word_shift, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001182 }
1183
1184 for (index = 1; shift >= 0; --shift) {
1185 uECC_word_t borrow = 0;
1186 wordcount_t i;
1187 for (i = 0; i < num_words * 2; ++i) {
1188 uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
1189 if (diff != v[index][i]) {
1190 borrow = (diff > v[index][i]);
1191 }
1192 v[1 - index][i] = diff;
1193 }
1194 /* Swap the index if there was no borrow */
1195 index = !(index ^ borrow);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001196 uECC_vli_rshift1(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001197 mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
Andrzej Kurek0919b142020-07-06 15:28:59 -04001198 (uECC_WORD_BITS - 1);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001199 uECC_vli_rshift1(mod_multiple + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001200 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001201 uECC_vli_set(result, v[index]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001202}
1203
1204void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001205 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001206{
1207 uECC_word_t product[2 * NUM_ECC_WORDS];
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001208 uECC_vli_mult_rnd(product, left, right, NULL);
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +01001209 uECC_vli_mmod(result, product, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001210}
1211
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001212static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001213 const uECC_word_t *right, ecc_wait_state_t *s)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001214{
1215 uECC_word_t product[2 * NUM_ECC_WORDS];
1216 uECC_vli_mult_rnd(product, left, right, s);
1217
1218 vli_mmod_fast_secp256r1(result, product);
1219}
1220
Jarno Lamsa18987a42019-04-24 15:40:43 +03001221void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001222 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001223{
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001224 uECC_vli_modMult_rnd(result, left, right, NULL);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001225}
1226
Jarno Lamsa18987a42019-04-24 15:40:43 +03001227#define EVEN(vli) (!(vli[0] & 1))
1228
1229static void vli_modInv_update(uECC_word_t *uv,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001230 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001231{
1232
1233 uECC_word_t carry = 0;
1234
1235 if (!EVEN(uv)) {
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001236 carry = uECC_vli_add(uv, uv, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001237 }
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001238 uECC_vli_rshift1(uv);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001239 if (carry) {
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +01001240 uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001241 }
1242}
1243
1244void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001245 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001246{
1247 uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
1248 uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
1249 cmpresult_t cmpResult;
1250
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001251 if (uECC_vli_isZero(input)) {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001252 uECC_vli_clear(result);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001253 return;
1254 }
1255
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001256 uECC_vli_set(a, input);
1257 uECC_vli_set(b, mod);
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001258 uECC_vli_clear(u);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001259 u[0] = 1;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001260 uECC_vli_clear(v);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001261 while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001262 if (EVEN(a)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001263 uECC_vli_rshift1(a);
Andrzej Kurek0919b142020-07-06 15:28:59 -04001264 vli_modInv_update(u, mod);
1265 } else if (EVEN(b)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001266 uECC_vli_rshift1(b);
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +01001267 vli_modInv_update(v, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001268 } else if (cmpResult > 0) {
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001269 uECC_vli_sub(a, a, b);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001270 uECC_vli_rshift1(a);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001271 if (uECC_vli_cmp_unsafe(u, v) < 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001272 uECC_vli_add(u, u, mod);
1273 }
1274 uECC_vli_sub(u, u, v);
1275 vli_modInv_update(u, mod);
1276 } else {
1277 uECC_vli_sub(b, b, a);
1278 uECC_vli_rshift1(b);
1279 if (uECC_vli_cmp_unsafe(v, u) < 0) {
1280 uECC_vli_add(v, v, mod);
1281 }
1282 uECC_vli_sub(v, v, u);
1283 vli_modInv_update(v, mod);
1284 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001285 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001286 uECC_vli_set(result, u);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001287}
1288
1289/* ------ Point operations ------ */
1290
1291void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001292 uECC_word_t * Z1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001293{
1294 /* t1 = X, t2 = Y, t3 = Z */
1295 uECC_word_t t4[NUM_ECC_WORDS];
1296 uECC_word_t t5[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001297 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001298
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001299 if (uECC_vli_isZero(Z1)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001300 return;
1301 }
1302
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001303 uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */
1304 uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */
1305 uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */
1306 uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */
1307 uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001308
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001309 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = x1 + z1^2 */
1310 uECC_vli_modAdd(Z1, Z1, Z1, curve_p); /* t3 = 2*z1^2 */
1311 uECC_vli_modSub(Z1, X1, Z1, curve_p); /* t3 = x1 - z1^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001312 uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001313
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001314 uECC_vli_modAdd(Z1, X1, X1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
1315 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001316 if (uECC_vli_testBit(X1, 0)) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001317 uECC_word_t l_carry = uECC_vli_add(X1, X1, curve_p);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001318 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001319 X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
1320 } else {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001321 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001322 }
1323
1324 /* t1 = 3/2*(x1^2 - z1^4) = B */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001325 uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001326 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - A */
1327 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
1328 uECC_vli_modSub(t5, t5, Z1, curve_p); /* t5 = A - x3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001329 uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001330 /* t4 = B * (A - x3) - y1^4 = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001331 uECC_vli_modSub(t4, X1, t4, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001332
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001333 uECC_vli_set(X1, Z1);
1334 uECC_vli_set(Z1, Y1);
1335 uECC_vli_set(Y1, t4);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001336}
1337
Manuel Pégourié-Gonnard1c6f7ea2019-11-21 09:18:29 +01001338/*
1339 * @brief Computes x^3 + ax + b. result must not overlap x.
1340 * @param result OUT -- x^3 + ax + b
1341 * @param x IN -- value of x
1342 * @param curve IN -- elliptic curve
1343 */
1344static void x_side_default(uECC_word_t *result,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001345 const uECC_word_t *x)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001346{
1347 uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001348
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001349 uECC_vli_modMult_fast(result, x, x); /* r = x^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001350 uECC_vli_modSub(result, result, _3, curve_p); /* r = x^2 - 3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001351 uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001352 /* r = x^3 - 3x + b: */
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +01001353 uECC_vli_modAdd(result, result, curve_b, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001354}
1355
1356void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
1357{
1358 unsigned int tmp[NUM_ECC_WORDS];
1359 int carry;
1360
1361 /* t */
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001362 uECC_vli_set(result, product);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001363
1364 /* s1 */
1365 tmp[0] = tmp[1] = tmp[2] = 0;
1366 tmp[3] = product[11];
1367 tmp[4] = product[12];
1368 tmp[5] = product[13];
1369 tmp[6] = product[14];
1370 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001371 carry = uECC_vli_add(tmp, tmp, tmp);
1372 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001373
1374 /* s2 */
1375 tmp[3] = product[12];
1376 tmp[4] = product[13];
1377 tmp[5] = product[14];
1378 tmp[6] = product[15];
1379 tmp[7] = 0;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001380 carry += uECC_vli_add(tmp, tmp, tmp);
1381 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001382
1383 /* s3 */
1384 tmp[0] = product[8];
1385 tmp[1] = product[9];
1386 tmp[2] = product[10];
1387 tmp[3] = tmp[4] = tmp[5] = 0;
1388 tmp[6] = product[14];
1389 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001390 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001391
1392 /* s4 */
1393 tmp[0] = product[9];
1394 tmp[1] = product[10];
1395 tmp[2] = product[11];
1396 tmp[3] = product[13];
1397 tmp[4] = product[14];
1398 tmp[5] = product[15];
1399 tmp[6] = product[13];
1400 tmp[7] = product[8];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001401 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001402
1403 /* d1 */
1404 tmp[0] = product[11];
1405 tmp[1] = product[12];
1406 tmp[2] = product[13];
1407 tmp[3] = tmp[4] = tmp[5] = 0;
1408 tmp[6] = product[8];
1409 tmp[7] = product[10];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001410 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001411
1412 /* d2 */
1413 tmp[0] = product[12];
1414 tmp[1] = product[13];
1415 tmp[2] = product[14];
1416 tmp[3] = product[15];
1417 tmp[4] = tmp[5] = 0;
1418 tmp[6] = product[9];
1419 tmp[7] = product[11];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001420 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001421
1422 /* d3 */
1423 tmp[0] = product[13];
1424 tmp[1] = product[14];
1425 tmp[2] = product[15];
1426 tmp[3] = product[8];
1427 tmp[4] = product[9];
1428 tmp[5] = product[10];
1429 tmp[6] = 0;
1430 tmp[7] = product[12];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001431 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001432
1433 /* d4 */
1434 tmp[0] = product[14];
1435 tmp[1] = product[15];
1436 tmp[2] = 0;
1437 tmp[3] = product[9];
1438 tmp[4] = product[10];
1439 tmp[5] = product[11];
1440 tmp[6] = 0;
1441 tmp[7] = product[13];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001442 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001443
1444 if (carry < 0) {
1445 do {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001446 carry += uECC_vli_add(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001447 }
1448 while (carry < 0);
1449 } else {
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +02001450 while (carry ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001451 uECC_vli_cmp_unsafe(curve_p, result) != 1) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001452 carry -= uECC_vli_sub(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001453 }
1454 }
1455}
1456
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001457uECC_word_t EccPoint_isZero(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001458{
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001459 return uECC_vli_isZero(point);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001460}
1461
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001462void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001463{
1464 uECC_word_t t1[NUM_ECC_WORDS];
1465
Andrzej Kurek0919b142020-07-06 15:28:59 -04001466 uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001467 uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */
1468 uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */
1469 uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001470}
1471
1472/* P = (x1, y1) => 2P, (x2, y2) => P' */
1473static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
1474 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001475 const uECC_word_t * const initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001476{
1477 uECC_word_t z[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001478 if (initial_Z) {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001479 uECC_vli_set(z, initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001480 } else {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001481 uECC_vli_clear(z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001482 z[0] = 1;
1483 }
1484
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001485 uECC_vli_set(X2, X1);
1486 uECC_vli_set(Y2, Y1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001487
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001488 apply_z(X1, Y1, z);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001489 double_jacobian_default(X1, Y1, z);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001490 apply_z(X2, Y2, z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001491}
1492
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001493static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1494 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001495 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001496{
1497 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1498 uECC_word_t t5[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001499
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001500 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001501 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001502 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1503 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001504 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001505 uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001506
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001507 uECC_vli_modSub(t5, t5, X1, curve_p); /* t5 = D - B */
1508 uECC_vli_modSub(t5, t5, X2, curve_p); /* t5 = D - B - C = x3 */
1509 uECC_vli_modSub(X2, X2, X1, curve_p); /* t3 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001510 uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001511 uECC_vli_modSub(X2, X1, t5, curve_p); /* t3 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001512 uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001513 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001514
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001515 uECC_vli_set(X2, t5);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001516}
1517
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001518void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001519 uECC_word_t * X2, uECC_word_t * Y2)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001520{
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001521 XYcZ_add_rnd(X1, Y1, X2, Y2, NULL);
1522}
1523
Jarno Lamsa18987a42019-04-24 15:40:43 +03001524/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
1525 Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
1526 or P => P - Q, Q => P + Q
1527 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001528static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1529 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001530 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001531{
1532 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1533 uECC_word_t t5[NUM_ECC_WORDS];
1534 uECC_word_t t6[NUM_ECC_WORDS];
1535 uECC_word_t t7[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001536
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001537 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001538 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001539 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1540 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001541 uECC_vli_modAdd(t5, Y2, Y1, curve_p); /* t5 = y2 + y1 */
1542 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001543
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001544 uECC_vli_modSub(t6, X2, X1, curve_p); /* t6 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001545 uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001546 uECC_vli_modAdd(t6, X1, X2, curve_p); /* t6 = B + C */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001547 uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001548 uECC_vli_modSub(X2, X2, t6, curve_p); /* t3 = D - (B + C) = x3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001549
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001550 uECC_vli_modSub(t7, X1, X2, curve_p); /* t7 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001551 uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001552 /* t4 = (y2 - y1)*(B - x3) - E = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001553 uECC_vli_modSub(Y2, Y2, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001554
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001555 uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001556 uECC_vli_modSub(t7, t7, t6, curve_p); /* t7 = F - (B + C) = x3' */
1557 uECC_vli_modSub(t6, t7, X1, curve_p); /* t6 = x3' - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001558 uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001559 /* t2 = (y2+y1)*(x3' - B) - E = y3': */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001560 uECC_vli_modSub(Y1, t6, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001561
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001562 uECC_vli_set(X1, t7);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001563}
1564
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001565static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
Jarno Lamsa18987a42019-04-24 15:40:43 +03001566 const uECC_word_t * scalar,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001567 const uECC_word_t * initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001568{
1569 /* R0 and R1 */
1570 uECC_word_t Rx[2][NUM_ECC_WORDS];
1571 uECC_word_t Ry[2][NUM_ECC_WORDS];
1572 uECC_word_t z[NUM_ECC_WORDS];
1573 bitcount_t i;
1574 uECC_word_t nb;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001575 const wordcount_t num_words = NUM_ECC_WORDS;
1576 const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001577 ecc_wait_state_t wait_state;
1578 ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001579
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001580 uECC_vli_set(Rx[1], point);
1581 uECC_vli_set(Ry[1], point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001582
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001583 XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001584
1585 for (i = num_bits - 2; i > 0; --i) {
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001586 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001587 nb = !uECC_vli_testBit(scalar, i);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001588 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
1589 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001590 }
1591
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001592 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001593 nb = !uECC_vli_testBit(scalar, 0);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001594 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001595
1596 /* Find final 1/Z value. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001597 uECC_vli_modSub(z, Rx[1], Rx[0], curve_p); /* X1 - X0 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001598 uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */
1599 uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001600 uECC_vli_modInv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0))*/
Jarno Lamsa18987a42019-04-24 15:40:43 +03001601 /* yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001602 uECC_vli_modMult_fast(z, z, point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001603 /* Xb * yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001604 uECC_vli_modMult_fast(z, z, Rx[1 - nb]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001605 /* End 1/Z calculation */
1606
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001607 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001608 apply_z(Rx[0], Ry[0], z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001609
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001610 uECC_vli_set(result, Rx[0]);
1611 uECC_vli_set(result + num_words, Ry[0]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001612}
1613
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001614static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001615 uECC_word_t *k1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001616{
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001617 bitcount_t num_n_bits = NUM_ECC_BITS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001618
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001619 uECC_word_t carry = uECC_vli_add(k0, k, curve_n) ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001620 uECC_vli_testBit(k0, num_n_bits);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001621
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001622 uECC_vli_add(k1, k0, curve_n);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001623
1624 return carry;
1625}
1626
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001627int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001628 const uECC_word_t * scalar)
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001629{
1630 uECC_word_t tmp[NUM_ECC_WORDS];
1631 uECC_word_t s[NUM_ECC_WORDS];
1632 uECC_word_t *k2[2] = {tmp, s};
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001633 wordcount_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001634 uECC_word_t carry;
1635 uECC_word_t *initial_Z = 0;
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001636 int r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001637 volatile int problem;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001638
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001639 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001640 problem = -1;
1641 problem = uECC_check_curve_integrity();
1642 if (problem != 0) {
1643 return UECC_FAULT_DETECTED;
1644 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001645 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001646 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001647 return UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001648 }
1649
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001650 /* Protects against invalid curve attacks */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001651 problem = -1;
1652 problem = uECC_valid_point(point);
1653 if (problem != 0) {
1654 /* invalid input, can happen without fault */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001655 return UECC_FAILURE;
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001656 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001657 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001658 if (problem != 0) {
1659 /* failure on second check means fault, though */
1660 return UECC_FAULT_DETECTED;
1661 }
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001662
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001663 /* Regularize the bitcount for the private key so that attackers cannot use a
1664 * side channel attack to learn the number of leading zeros. */
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001665 carry = regularize_k(scalar, tmp, s);
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001666
1667 /* If an RNG function was specified, get a random initial Z value to
Andrzej Kurek0919b142020-07-06 15:28:59 -04001668 * protect against side-channel attacks such as Template SPA */
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001669 if (g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001670 if (uECC_generate_random_int(k2[carry], curve_p, num_words) != UECC_SUCCESS) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001671 r = UECC_FAILURE;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001672 goto clear_and_out;
1673 }
1674 initial_Z = k2[carry];
1675 }
1676
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001677 EccPoint_mult(result, point, k2[!carry], initial_Z);
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001678
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001679 /* Protect against fault injections that would make the resulting
1680 * point not lie on the intended curve */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001681 problem = -1;
1682 problem = uECC_valid_point(result);
1683 if (problem != 0) {
1684 r = UECC_FAULT_DETECTED;
1685 goto clear_and_out;
1686 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001687 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001688 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001689 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001690 goto clear_and_out;
1691 }
1692
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001693 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001694 problem = -1;
1695 problem = uECC_check_curve_integrity();
1696 if (problem != 0) {
1697 r = UECC_FAULT_DETECTED;
1698 goto clear_and_out;
1699 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001700 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001701 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001702 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001703 goto clear_and_out;
1704 }
1705
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001706 r = UECC_SUCCESS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001707
1708clear_and_out:
1709 /* erasing temporary buffer used to store secret: */
1710 mbedtls_platform_zeroize(k2, sizeof(k2));
1711 mbedtls_platform_zeroize(tmp, sizeof(tmp));
1712 mbedtls_platform_zeroize(s, sizeof(s));
1713
1714 return r;
1715}
1716
Jarno Lamsa18987a42019-04-24 15:40:43 +03001717uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001718 uECC_word_t *private_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001719{
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001720 return EccPoint_mult_safer(result, curve_G, private_key);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001721}
1722
1723/* Converts an integer in uECC native format to big-endian bytes. */
1724void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001725 const unsigned int *native)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001726{
1727 wordcount_t i;
1728 for (i = 0; i < num_bytes; ++i) {
1729 unsigned b = num_bytes - 1 - i;
1730 bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
1731 }
1732}
1733
1734/* Converts big-endian bytes to an integer in uECC native format. */
1735void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001736 int num_bytes)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001737{
1738 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001739 uECC_vli_clear(native);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001740 for (i = 0; i < num_bytes; ++i) {
1741 unsigned b = num_bytes - 1 - i;
1742 native[b / uECC_WORD_SIZE] |=
1743 (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
1744 }
1745}
1746
1747int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001748 wordcount_t num_words)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001749{
1750 uECC_word_t mask = (uECC_word_t)-1;
1751 uECC_word_t tries;
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001752 bitcount_t num_bits = uECC_vli_numBits(top);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001753
1754 if (!g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001755 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001756 }
1757
1758 for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
Andrzej Kurek090365f2020-06-08 11:00:51 -04001759 if (g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE) != num_words * uECC_WORD_SIZE) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001760 return UECC_FAILURE;
1761 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001762 random[num_words - 1] &=
Andrzej Kurek0919b142020-07-06 15:28:59 -04001763 mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001764 if (!uECC_vli_isZero(random) &&
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +01001765 uECC_vli_cmp(top, random) == 1) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001766 return UECC_SUCCESS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001767 }
1768 }
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001769 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001770}
1771
1772
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001773int uECC_valid_point(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001774{
1775 uECC_word_t tmp1[NUM_ECC_WORDS];
1776 uECC_word_t tmp2[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001777 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa83d78812019-12-04 14:40:57 +02001778 volatile uECC_word_t diff = 0xffffffff;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001779
1780 /* The point at infinity is invalid. */
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001781 if (EccPoint_isZero(point)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001782 return -1;
1783 }
1784
1785 /* x and y must be smaller than p. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001786 if (uECC_vli_cmp_unsafe(curve_p, point) != 1 ||
1787 uECC_vli_cmp_unsafe(curve_p, point + num_words) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001788 return -2;
1789 }
1790
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001791 uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001792 x_side_default(tmp2, point); /* tmp2 = x^3 + ax + b */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001793
1794 /* Make sure that y^2 == x^3 + ax + b */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001795 diff = uECC_vli_equal(tmp1, tmp2);
1796 if (diff == 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001797 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001798 if (diff == 0) {
1799 return 0;
1800 }
1801 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001802
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001803 return -3;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001804}
1805
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001806int uECC_valid_public_key(const uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001807{
1808
1809 uECC_word_t _public[NUM_ECC_WORDS * 2];
1810
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001811 uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001812 uECC_vli_bytesToNative(
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001813 _public + NUM_ECC_WORDS,
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001814 public_key + NUM_ECC_BYTES,
1815 NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001816
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +01001817 if (memcmp(_public, curve_G, NUM_ECC_WORDS * 2) == 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001818 return -4;
1819 }
1820
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001821 return uECC_valid_point(_public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001822}
1823
Andrzej Kurek0919b142020-07-06 15:28:59 -04001824int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001825{
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001826 int ret = UECC_FAULT_DETECTED;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001827 uECC_word_t _private[NUM_ECC_WORDS];
1828 uECC_word_t _public[NUM_ECC_WORDS * 2];
1829
1830 uECC_vli_bytesToNative(
1831 _private,
1832 private_key,
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +01001833 BITS_TO_BYTES(NUM_ECC_BITS));
Jarno Lamsa18987a42019-04-24 15:40:43 +03001834
1835 /* Make sure the private key is in the range [1, n-1]. */
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001836 if (uECC_vli_isZero(_private)) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001837 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001838 }
1839
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001840 if (uECC_vli_cmp(curve_n, _private) != 1) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001841 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001842 }
1843
1844 /* Compute public key. */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001845 ret = EccPoint_compute_public_key(_public, _private);
1846 if (ret != UECC_SUCCESS) {
1847 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001848 }
1849
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001850 uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001851 uECC_vli_nativeToBytes(
1852 public_key +
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001853 NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS);
Andrzej Kurekcf3e35c2020-07-15 22:32:08 -04001854
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001855 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001856}
Andrzej Kurek7e62c312020-10-14 12:02:40 +02001857#endif /* MBEDTLS_USE_TINYCRYPT */