blob: edb6e051d09e5bdf72ce7d4e7f48387f1845d035 [file] [log] [blame]
Jarno Lamsa18987a42019-04-24 15:40:43 +03001/* ecc.c - TinyCrypt implementation of common ECC functions */
2
3/*
Simon Butcher92c3d1f2019-09-09 17:25:08 +01004 * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved.
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8/*
Jarno Lamsa18987a42019-04-24 15:40:43 +03009 * Copyright (c) 2014, Kenneth MacKay
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 * * Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions are met:
35 *
Andrzej Kurek0919b142020-07-06 15:28:59 -040036 * - Redistributions of source code must retain the above copyright notice,
37 * this list of conditions and the following disclaimer.
Jarno Lamsa18987a42019-04-24 15:40:43 +030038 *
Andrzej Kurek0919b142020-07-06 15:28:59 -040039 * - Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
Jarno Lamsa18987a42019-04-24 15:40:43 +030042 *
Andrzej Kurek0919b142020-07-06 15:28:59 -040043 * - Neither the name of Intel Corporation nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
Jarno Lamsa18987a42019-04-24 15:40:43 +030046 *
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 * POSSIBILITY OF SUCH DAMAGE.
58 */
59
Hanno Becker36ae7582019-07-23 15:52:35 +010060#if !defined(MBEDTLS_CONFIG_FILE)
61#include "mbedtls/config.h"
62#else
63#include MBEDTLS_CONFIG_FILE
64#endif
65
Jarno Lamsa18987a42019-04-24 15:40:43 +030066#include <tinycrypt/ecc.h>
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +010067#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +010068#include "mbedtls/sha256.h"
Jarno Lamsa18987a42019-04-24 15:40:43 +030069#include <string.h>
Shelly Liberman05beb9a2020-09-13 15:23:56 +030070#include "mbedtls/platform_util.h"
Jarno Lamsa18987a42019-04-24 15:40:43 +030071
Kevin Bracey1959c182020-07-16 21:03:19 +030072#ifdef __CC_ARM
73#pragma diag_suppress 667 // strict diagnostic: "asm" function is nonstandard
74#endif
75
76#if defined MBEDTLS_HAVE_ASM
77#ifndef asm
78#define asm __asm
79#endif
80#endif
81
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +010082/* Parameters for curve NIST P-256 aka secp256r1 */
83const uECC_word_t curve_p[NUM_ECC_WORDS] = {
84 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
85 BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
86 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
87 BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)
88};
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +010089const uECC_word_t curve_n[NUM_ECC_WORDS] = {
90 BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
91 BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
92 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
93 BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)
94};
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +010095const uECC_word_t curve_G[2 * NUM_ECC_WORDS] = {
96 BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
97 BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
98 BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
99 BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
100 BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
101 BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
102 BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
103 BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)
104};
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +0100105const uECC_word_t curve_b[NUM_ECC_WORDS] = {
106 BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
107 BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
108 BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
109 BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)
110};
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100111
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100112static int uECC_update_param_sha256(mbedtls_sha256_context *ctx,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400113 const uECC_word_t val[NUM_ECC_WORDS])
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100114{
115 uint8_t bytes[NUM_ECC_BYTES];
116
117 uECC_vli_nativeToBytes(bytes, NUM_ECC_BYTES, val);
118 return mbedtls_sha256_update_ret(ctx, bytes, NUM_ECC_BYTES);
119}
120
121static int uECC_compute_param_sha256(unsigned char output[32])
122{
123 int ret = UECC_FAILURE;
124 mbedtls_sha256_context ctx;
125
126 mbedtls_sha256_init( &ctx );
127
128 if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) {
129 goto exit;
130 }
131
132 if (uECC_update_param_sha256(&ctx, curve_p) != 0 ||
Andrzej Kurek0919b142020-07-06 15:28:59 -0400133 uECC_update_param_sha256(&ctx, curve_n) != 0 ||
134 uECC_update_param_sha256(&ctx, curve_G) != 0 ||
135 uECC_update_param_sha256(&ctx, curve_G + NUM_ECC_WORDS) != 0 ||
136 uECC_update_param_sha256(&ctx, curve_b) != 0)
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100137 {
138 goto exit;
139 }
140
141 if (mbedtls_sha256_finish_ret(&ctx, output) != 0) {
142 goto exit;
143 }
144
145 ret = UECC_SUCCESS;
146
147exit:
148 mbedtls_sha256_free( &ctx );
149
150 return ret;
151}
152
153/*
154 * Check integrity of curve parameters.
155 * Return 0 if everything's OK, non-zero otherwise.
156 */
157static int uECC_check_curve_integrity(void)
158{
159 unsigned char computed[32];
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100160 static const unsigned char reference[32] = {
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100161 0x2d, 0xa1, 0xa4, 0x64, 0x45, 0x28, 0x0d, 0xe1,
162 0x93, 0xf9, 0x29, 0x2f, 0xac, 0x3e, 0xe2, 0x92,
163 0x76, 0x0a, 0xe2, 0xbc, 0xce, 0x2a, 0xa2, 0xc6,
164 0x38, 0xf2, 0x19, 0x1d, 0x76, 0x72, 0x93, 0x49,
165 };
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100166 unsigned char diff = 0;
167 unsigned char tmp1, tmp2;
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100168 volatile unsigned i;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100169
170 if (uECC_compute_param_sha256(computed) != UECC_SUCCESS) {
171 return UECC_FAILURE;
172 }
173
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100174 for (i = 0; i < 32; i++) {
175 /* make sure the order of volatile accesses is well-defined */
176 tmp1 = computed[i];
177 tmp2 = reference[i];
178 diff |= tmp1 ^ tmp2;
179 }
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100180
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100181 /* i should be 32 */
Arto Kinnunenac6d2262020-01-09 10:11:20 +0200182 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnarde1cb8842019-11-28 12:21:34 +0100183 diff |= (unsigned char) i ^ 32;
184
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +0100185 return diff;
186}
187
Jarno Lamsa18987a42019-04-24 15:40:43 +0300188/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
189 * has access to enough entropy in order to feed the PRNG regularly. */
190#if default_RNG_defined
191static uECC_RNG_Function g_rng_function = &default_CSPRNG;
192#else
193static uECC_RNG_Function g_rng_function = 0;
194#endif
195
196void uECC_set_rng(uECC_RNG_Function rng_function)
197{
198 g_rng_function = rng_function;
199}
200
201uECC_RNG_Function uECC_get_rng(void)
202{
203 return g_rng_function;
204}
205
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +0100206int uECC_curve_private_key_size(void)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300207{
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +0100208 return BITS_TO_BYTES(NUM_ECC_BITS);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300209}
210
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +0100211int uECC_curve_public_key_size(void)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300212{
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +0100213 return 2 * NUM_ECC_BYTES;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300214}
215
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100216void uECC_vli_clear(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300217{
218 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100219 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300220 vli[i] = 0;
221 }
222}
223
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100224uECC_word_t uECC_vli_isZero(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300225{
226 uECC_word_t bits = 0;
227 wordcount_t i;
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100228 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300229 bits |= vli[i];
230 }
231 return (bits == 0);
232}
233
234uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit)
235{
236 return (vli[bit >> uECC_WORD_BITS_SHIFT] &
237 ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
238}
239
240/* Counts the number of words in vli. */
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100241static wordcount_t vli_numDigits(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300242{
243
244 wordcount_t i;
245 /* Search from the end until we find a non-zero digit. We do it in reverse
246 * because we expect that most digits will be nonzero. */
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100247 for (i = NUM_ECC_WORDS - 1; i >= 0 && vli[i] == 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300248 }
249
250 return (i + 1);
251}
252
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100253bitcount_t uECC_vli_numBits(const uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300254{
255
256 uECC_word_t i;
257 uECC_word_t digit;
258
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100259 wordcount_t num_digits = vli_numDigits(vli);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300260 if (num_digits == 0) {
261 return 0;
262 }
263
264 digit = vli[num_digits - 1];
265 for (i = 0; digit; ++i) {
266 digit >>= 1;
267 }
268
269 return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
270}
271
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100272void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300273{
274 wordcount_t i;
275
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100276 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300277 dest[i] = src[i];
278 }
279}
280
281cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100282 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300283{
284 wordcount_t i;
285
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100286 for (i = NUM_ECC_WORDS - 1; i >= 0; --i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300287 if (left[i] > right[i]) {
288 return 1;
289 } else if (left[i] < right[i]) {
290 return -1;
291 }
292 }
293 return 0;
294}
295
Manuel Pégourié-Gonnard2eca3d32019-11-04 14:33:09 +0100296uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300297{
298
299 uECC_word_t diff = 0;
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200300 uECC_word_t flow_monitor = 0;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100301 uECC_word_t tmp1, tmp2;
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100302 volatile int i;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300303
Piotr Nowickif0ab6d62020-05-25 12:48:30 +0200304 /* Start from a random location and check the correct number of iterations */
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200305 int start_offset = mbedtls_platform_random_in_range(NUM_ECC_WORDS);
306
307 for (i = start_offset; i < NUM_ECC_WORDS; ++i) {
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100308 tmp1 = left[i];
309 tmp2 = right[i];
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200310 flow_monitor++;
Manuel Pégourié-Gonnard645896e2019-12-05 15:30:09 +0100311 diff |= (tmp1 ^ tmp2);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300312 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100313
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200314 for (i = 0; i < start_offset; ++i) {
315 tmp1 = left[i];
316 tmp2 = right[i];
317 flow_monitor++;
318 diff |= (tmp1 ^ tmp2);
319 }
Manuel Pégourié-Gonnard98e1fe02019-11-27 11:57:49 +0100320
Piotr Nowickif0ab6d62020-05-25 12:48:30 +0200321 /* Random delay to increase security */
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +0200322 mbedtls_platform_random_delay();
323
324 /* Return 0 only when diff is 0 and flow_counter is equal to NUM_ECC_WORDS */
325 return (diff | (flow_monitor ^ NUM_ECC_WORDS));
Jarno Lamsa18987a42019-04-24 15:40:43 +0300326}
327
328uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
329{
330 return (p_true*(cond)) | (p_false*(!cond));
331}
332
333/* Computes result = left - right, returning borrow, in constant time.
334 * Can modify in place. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300335#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
336__asm uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
337 const uECC_word_t *right)
338{
339#if NUM_ECC_WORDS != 8
340#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
341#endif
342#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
343 PUSH {r4-r6,lr}
344 FRAME PUSH {r4-r6,lr}
345 LDMIA r1!,{r3,r4}
346 LDMIA r2!,{r5,r6}
347 SUBS r3,r5
348 SBCS r4,r6
349 STMIA r0!,{r3,r4}
350 LDMIA r1!,{r3,r4}
351 LDMIA r2!,{r5,r6}
352 SBCS r3,r5
353 SBCS r4,r6
354 STMIA r0!,{r3,r4}
355 LDMIA r1!,{r3,r4}
356 LDMIA r2!,{r5,r6}
357 SBCS r3,r5
358 SBCS r4,r6
359 STMIA r0!,{r3,r4}
360 LDMIA r1!,{r3,r4}
361 LDMIA r2!,{r5,r6}
362 SBCS r3,r5
363 SBCS r4,r6
364 STMIA r0!,{r3,r4}
365 SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow
366 RSBS r0,r0,#0 // r0 := borrow
367 POP {r4-r6,pc}
368#else
369 PUSH {r4-r8,lr}
370 FRAME PUSH {r4-r8,lr}
371 LDMIA r1!,{r3-r6}
372 LDMIA r2!,{r7,r8,r12,lr}
373 SUBS r3,r7
374 SBCS r4,r8
375 SBCS r5,r12
376 SBCS r6,lr
377 STMIA r0!,{r3-r6}
378 LDMIA r1!,{r3-r6}
379 LDMIA r2!,{r7,r8,r12,lr}
380 SBCS r3,r7
381 SBCS r4,r8
382 SBCS r5,r12
383 SBCS r6,lr
384 STMIA r0!,{r3-r6}
385 SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow
386 RSBS r0,r0,#0 // r0 := borrow
387 POP {r4-r8,pc}
388#endif
389}
Kevin Bracey4aea6252020-10-09 12:54:28 +0300390#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
391uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
392 const uECC_word_t *right)
393{
394#if NUM_ECC_WORDS != 8
395#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
396#endif
397 register uECC_word_t *r0 asm ("r0") = result;
398 register const uECC_word_t *r1 asm ("r1") = left;
399 register const uECC_word_t *r2 asm ("r2") = right;
400 asm volatile (
401#if defined __thumb__ && !defined __thumb2__
402 ".syntax unified \n\t"
403 "LDMIA r1!,{r3,r4} \n\t"
404 "LDMIA r2!,{r5,r6} \n\t"
405 "SUBS r3,r5 \n\t"
406 "SBCS r4,r6 \n\t"
407 "STMIA r0!,{r3,r4} \n\t"
408 "LDMIA r1!,{r3,r4} \n\t"
409 "LDMIA r2!,{r5,r6} \n\t"
410 "SBCS r3,r5 \n\t"
411 "SBCS r4,r6 \n\t"
412 "STMIA r0!,{r3,r4} \n\t"
413 "LDMIA r1!,{r3,r4} \n\t"
414 "LDMIA r2!,{r5,r6} \n\t"
415 "SBCS r3,r5 \n\t"
416 "SBCS r4,r6 \n\t"
417 "STMIA r0!,{r3,r4} \n\t"
418 "LDMIA r1!,{r3,r4} \n\t"
419 "LDMIA r2!,{r5,r6} \n\t"
420 "SBCS r3,r5 \n\t"
421 "SBCS r4,r6 \n\t"
422 "STMIA r0!,{r3,r4} \n\t"
423 "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow
424 "RSBS r0,r0,#0 \n\t" // r0 := borrow
425 : "+r" (r0), "+r" (r1), "+r" (r2)
426 :
427 : "r3", "r4", "r5", "r6", "cc", "memory"
428#else
429 "LDMIA r1!,{r3-r6} \n\t"
430 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
431 "SUBS r3,r7 \n\t"
432 "SBCS r4,r8 \n\t"
433 "SBCS r5,r12 \n\t"
434 "SBCS r6,lr \n\t"
435 "STMIA r0!,{r3-r6} \n\t"
436 "LDMIA r1!,{r3-r6} \n\t"
437 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
438 "SBCS r3,r7 \n\t"
439 "SBCS r4,r8 \n\t"
440 "SBCS r5,r12 \n\t"
441 "SBCS r6,lr \n\t"
442 "STMIA r0!,{r3-r6} \n\t"
443 "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow
444 "RSBS r0,r0,#0 \n\t" // r0 := borrow
445 : "+r" (r0), "+r" (r1), "+r" (r2)
446 :
447 : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory"
448#endif
449 );
450 return (uECC_word_t) r0;
451}
Kevin Bracey1959c182020-07-16 21:03:19 +0300452#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300453uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100454 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300455{
456 uECC_word_t borrow = 0;
457 wordcount_t i;
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100458 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300459 uECC_word_t diff = left[i] - right[i] - borrow;
460 uECC_word_t val = (diff > left[i]);
461 borrow = cond_set(val, borrow, (diff != left[i]));
462
463 result[i] = diff;
464 }
465 return borrow;
466}
Kevin Bracey1959c182020-07-16 21:03:19 +0300467#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300468
469/* Computes result = left + right, returning carry, in constant time.
470 * Can modify in place. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300471#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
472static __asm uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
473 const uECC_word_t *right)
474{
475#if NUM_ECC_WORDS != 8
476#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
477#endif
478#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
479 PUSH {r4-r6,lr}
480 FRAME PUSH {r4-r6,lr}
481 LDMIA r1!,{r3,r4}
482 LDMIA r2!,{r5,r6}
483 ADDS r3,r5
484 ADCS r4,r6
485 STMIA r0!,{r3,r4}
486 LDMIA r1!,{r3,r4}
487 LDMIA r2!,{r5,r6}
488 ADCS r3,r5
489 ADCS r4,r6
490 STMIA r0!,{r3,r4}
491 LDMIA r1!,{r3,r4}
492 LDMIA r2!,{r5,r6}
493 ADCS r3,r5
494 ADCS r4,r6
495 STMIA r0!,{r3,r4}
496 LDMIA r1!,{r3,r4}
497 LDMIA r2!,{r5,r6}
498 ADCS r3,r5
499 ADCS r4,r6
500 STMIA r0!,{r3,r4}
501 MOVS r0,#0 // does not affect C flag
502 ADCS r0,r0 // r0 := 0 + 0 + C = carry
503 POP {r4-r6,pc}
504#else
505 PUSH {r4-r8,lr}
506 FRAME PUSH {r4-r8,lr}
507 LDMIA r1!,{r3-r6}
508 LDMIA r2!,{r7,r8,r12,lr}
509 ADDS r3,r7
510 ADCS r4,r8
511 ADCS r5,r12
512 ADCS r6,lr
513 STMIA r0!,{r3-r6}
514 LDMIA r1!,{r3-r6}
515 LDMIA r2!,{r7,r8,r12,lr}
516 ADCS r3,r7
517 ADCS r4,r8
518 ADCS r5,r12
519 ADCS r6,lr
520 STMIA r0!,{r3-r6}
521 MOVS r0,#0 // does not affect C flag
522 ADCS r0,r0 // r0 := 0 + 0 + C = carry
523 POP {r4-r8,pc}
524#endif
525}
Kevin Bracey4aea6252020-10-09 12:54:28 +0300526#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
527static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
528 const uECC_word_t *right)
529{
530 register uECC_word_t *r0 asm ("r0") = result;
531 register const uECC_word_t *r1 asm ("r1") = left;
532 register const uECC_word_t *r2 asm ("r2") = right;
533
534 asm volatile (
535#if defined __thumb__ && !defined __thumb2__
536 ".syntax unified \n\t"
537 "LDMIA r1!,{r3,r4} \n\t"
538 "LDMIA r2!,{r5,r6} \n\t"
539 "ADDS r3,r5 \n\t"
540 "ADCS r4,r6 \n\t"
541 "STMIA r0!,{r3,r4} \n\t"
542 "LDMIA r1!,{r3,r4} \n\t"
543 "LDMIA r2!,{r5,r6} \n\t"
544 "ADCS r3,r5 \n\t"
545 "ADCS r4,r6 \n\t"
546 "STMIA r0!,{r3,r4} \n\t"
547 "LDMIA r1!,{r3,r4} \n\t"
548 "LDMIA r2!,{r5,r6} \n\t"
549 "ADCS r3,r5 \n\t"
550 "ADCS r4,r6 \n\t"
551 "STMIA r0!,{r3,r4} \n\t"
552 "LDMIA r1!,{r3,r4} \n\t"
553 "LDMIA r2!,{r5,r6} \n\t"
554 "ADCS r3,r5 \n\t"
555 "ADCS r4,r6 \n\t"
556 "STMIA r0!,{r3,r4} \n\t"
557 "MOVS r0,#0 \n\t" // does not affect C flag
558 "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry
559 : "+r" (r0), "+r" (r1), "+r" (r2)
560 :
561 : "r3", "r4", "r5", "r6", "cc", "memory"
562#else
563 "LDMIA r1!,{r3-r6} \n\t"
564 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
565 "ADDS r3,r7 \n\t"
566 "ADCS r4,r8 \n\t"
567 "ADCS r5,r12 \n\t"
568 "ADCS r6,lr \n\t"
569 "STMIA r0!,{r3-r6} \n\t"
570 "LDMIA r1!,{r3-r6} \n\t"
571 "LDMIA r2!,{r7,r8,r12,lr} \n\t"
572 "ADCS r3,r7 \n\t"
573 "ADCS r4,r8 \n\t"
574 "ADCS r5,r12 \n\t"
575 "ADCS r6,lr \n\t"
576 "STMIA r0!,{r3-r6} \n\t"
577 "MOVS r0,#0 \n\t" // does not affect C flag
578 "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry
579 : "+r" (r0), "+r" (r1), "+r" (r2)
580 :
581 : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory"
582#endif
583 );
584 return (uECC_word_t) r0;
585}
Kevin Bracey1959c182020-07-16 21:03:19 +0300586#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300587static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100588 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300589{
590 uECC_word_t carry = 0;
591 wordcount_t i;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100592 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300593 uECC_word_t sum = left[i] + right[i] + carry;
594 uECC_word_t val = (sum < left[i]);
595 carry = cond_set(val, carry, (sum != left[i]));
596 result[i] = sum;
597 }
598 return carry;
599}
Kevin Bracey1959c182020-07-16 21:03:19 +0300600#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300601
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +0100602cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300603{
604 uECC_word_t tmp[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100605 uECC_word_t neg = !!uECC_vli_sub(tmp, left, right);
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100606 uECC_word_t equal = uECC_vli_isZero(tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300607 return (!equal - 2 * neg);
608}
609
610/* Computes vli = vli >> 1. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300611#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
612static __asm void uECC_vli_rshift1(uECC_word_t *vli)
613{
614#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
615// RRX instruction is not available, so although we
616// can use C flag, it's not that effective. Does at
617// least save one working register, meaning we don't need stack
618 MOVS r3,#0 // initial carry = 0
619 MOVS r2,#__cpp(4 * (NUM_ECC_WORDS - 1))
62001 LDR r1,[r0,r2]
621 LSRS r1,r1,#1 // r2 = word >> 1
622 ORRS r1,r3 // merge in the previous carry
623 STR r1,[r0,r2]
624 ADCS r3,r3 // put C into bottom bit of r3
625 LSLS r3,r3,#31 // shift it up to the top ready for next word
626 SUBS r2,r2,#4
627 BPL %B01
628 BX lr
629#else
630#if NUM_ECC_WORDS != 8
631#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
632#endif
633// Smooth multiword operation, lots of 32-bit instructions
634 ADDS r0,#32
635 LDMDB r0,{r1-r3,ip}
636 LSRS ip,ip,#1
637 RRXS r3,r3
638 RRXS r2,r2
639 RRXS r1,r1
640 STMDB r0!,{r1-r3,ip}
641 LDMDB r0,{r1-r3,ip}
642 RRXS ip,ip
643 RRXS r3,r3
644 RRXS r2,r2
645 RRX r1,r1
646 STMDB r0!,{r1-r3,ip}
647 BX lr
648#endif
649}
Kevin Bracey06060332020-10-02 17:43:12 +0300650#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__ && defined __thumb2__
651static void uECC_vli_rshift1(uECC_word_t *vli)
652{
653 register uECC_word_t *r0 asm ("r0") = vli;
654#if NUM_ECC_WORDS != 8
655#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
656#endif
657 asm volatile (
658 "ADDS r0,#32 \n\t"
659 "LDMDB r0,{r1-r3,ip} \n\t"
660 "LSRS ip,ip,#1 \n\t"
661 "RRXS r3,r3 \n\t"
662 "RRXS r2,r2 \n\t"
663 "RRXS r1,r1 \n\t"
664 "STMDB r0!,{r1-r3,ip} \n\t"
665 "LDMDB r0,{r1-r3,ip} \n\t"
666 "RRXS ip,ip \n\t"
667 "RRXS r3,r3 \n\t"
668 "RRXS r2,r2 \n\t"
669 "RRX r1,r1 \n\t"
670 "STMDB r0!,{r1-r3,ip} \n\t"
671 : "+r" (r0)
672 :
673 : "r1", "r2", "r3", "ip", "cc", "memory"
674 );
675}
Kevin Bracey1959c182020-07-16 21:03:19 +0300676#else
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100677static void uECC_vli_rshift1(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300678{
679 uECC_word_t *end = vli;
680 uECC_word_t carry = 0;
681
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100682 vli += NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300683 while (vli-- > end) {
684 uECC_word_t temp = *vli;
685 *vli = (temp >> 1) | carry;
686 carry = temp << (uECC_WORD_BITS - 1);
687 }
688}
Kevin Bracey1959c182020-07-16 21:03:19 +0300689#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300690
Kevin Bracey84f31d32020-09-29 17:51:04 +0300691/* Compute a * b + r, where r is a triple-word with high-order word r[2] and
692 * low-order word r[0], and store the result in the same triple-word.
Manuel Pégourié-Gonnard86c4f812019-10-31 13:02:03 +0100693 *
Kevin Bracey84f31d32020-09-29 17:51:04 +0300694 * r[2..0] = a * b + r[2..0]:
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200695 * [in] a, b: operands to be multiplied
Kevin Bracey84f31d32020-09-29 17:51:04 +0300696 * [in] r: 3 words of operand to add
697 * [out] r: 3 words of result
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200698 */
Kevin Bracey1959c182020-07-16 21:03:19 +0300699#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
Kevin Bracey84f31d32020-09-29 17:51:04 +0300700static __asm void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Bracey1959c182020-07-16 21:03:19 +0300701{
702#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
Kevin Bracey84f31d32020-09-29 17:51:04 +0300703 PUSH {r4-r5}
704 FRAME PUSH {r4-r5}
705 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
706 // Separate operands into halfwords
707 UXTH r3,r0 // r3 := a.lo
708 LSRS r4,r0,#16 // r4 := a.hi
709 UXTH r5,r1 // r5 := b.lo
710 LSRS r1,r1,#16 // r1 := b.hi
711 // Multiply halfword pairs
712 MOVS r0,r3
713 MULS r0,r5,r0 // r0 := a.lo * b.lo
714 MULS r3,r1,r3 // r3 := a.lo * b.hi
715 MULS r5,r4,r5 // r5 := a.hi * b.lo
716 MULS r1,r4,r1 // r1 := a.hi * b.hi
717 // Split, shift and add a.lo * b.hi
718 LSRS r4,r3,#16 // r4 := (a.lo * b.hi).hi
719 LSLS r3,r3,#16 // r3 := (a.lo * b.hi).lo
720 ADDS r0,r0,r3 // r0 := a.lo * b.lo + (a.lo * b.hi).lo
721 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
722 // Split, shift and add a.hi * b.lo
723 LSRS r4,r5,#16 // r4 := (a.hi * b.lo).hi
724 LSLS r5,r5,#16 // r5 := (a.hi * b.lo).lo
725 ADDS r0,r0,r5 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
726 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
727 // Finally add r[]
728 LDMIA r2!,{r3,r4,r5}
729 ADDS r3,r3,r0
Kevin Bracey1959c182020-07-16 21:03:19 +0300730 ADCS r4,r1
Kevin Bracey1959c182020-07-16 21:03:19 +0300731 MOVS r0,#0
Kevin Bracey84f31d32020-09-29 17:51:04 +0300732 ADCS r5,r0
733 SUBS r2,#12
734 STMIA r2!,{r3,r4,r5}
735 POP {r4-r5}
736 FRAME POP {r4-r5}
737 BX lr
Kevin Bracey1959c182020-07-16 21:03:19 +0300738#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300739 UMULL r3,ip,r0,r1 // pre-ARMv6 requires Rd[Lo|Hi] != Rn
740 LDMIA r2,{r0,r1}
741 ADDS r0,r0,r3
742 LDR r3,[r2,#8]
743 ADCS r1,r1,ip
744 ADC r3,r3,#0
745 STMIA r2!,{r0,r1,r3}
Kevin Bracey1959c182020-07-16 21:03:19 +0300746 BX lr
747#endif
Kevin Braceye0f88d52020-09-30 12:52:15 +0300748}
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300749#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
750static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Braceye0f88d52020-09-30 12:52:15 +0300751{
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300752 register uECC_word_t r0 asm ("r0") = a;
753 register uECC_word_t r1 asm ("r1") = b;
754 register uECC_word_t *r2 asm ("r2") = r;
755 asm volatile (
Kevin Braceye0f88d52020-09-30 12:52:15 +0300756#if defined __thumb__ && !defined(__thumb2__)
757 ".syntax unified \n\t"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300758 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
759 // Separate operands into halfwords
760 "UXTH r3,r0 \n\t" // r3 := a.lo
761 "LSRS r4,r0,#16 \n\t" // r4 := a.hi
762 "UXTH r5,r1 \n\t" // r5 := b.lo
763 "LSRS r1,r1,#16 \n\t" // r1 := b.hi
764 // Multiply halfword pairs
765 "MOVS r0,r3 \n\t"
766 "MULS r0,r5,r0 \n\t" // r0 := a.lo * b.lo
767 "MULS r3,r1,r3 \n\t" // r3 := a.lo * b.hi
768 "MULS r5,r4,r5 \n\t" // r5 := a.hi * b.lo
769 "MULS r1,r4,r1 \n\t" // r1 := a.hi * b.hi
770 // Split, shift and add a.lo * b.hi
771 "LSRS r4,r3,#16 \n\t" // r4 := (a.lo * b.hi).hi
772 "LSLS r3,r3,#16 \n\t" // r3 := (a.lo * b.hi).lo
773 "ADDS r0,r0,r3 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo
774 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
775 // Split, shift and add a.hi * b.lo
776 "LSRS r4,r5,#16 \n\t" // r4 := (a.hi * b.lo).hi
777 "LSLS r5,r5,#16 \n\t" // r5 := (a.hi * b.lo).lo
778 "ADDS r0,r0,r5 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
779 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
780 // Finally add r[]
781 "LDMIA r2!,{r3,r4,r5} \n\t"
782 "ADDS r3,r3,r0 \n\t"
783 "ADCS r4,r1 \n\t"
784 "MOVS r0,#0 \n\t"
785 "ADCS r5,r0 \n\t"
786 "SUBS r2,#12 \n\t"
787 "STMIA r2!,{r3,r4,r5} \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300788 : "+r" (r0), "+r" (r1), "+r" (r2)
789 :
790 : "r3", "r4", "r5", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300791#else
792 "UMULL r3,ip,r0,r1 \n\t" // pre-ARMv6 requires Rd[Lo|Hi] != Rn
793 "LDMIA r2,{r0,r1} \n\t"
794 "ADDS r0,r0,r3 \n\t"
795 "LDR r3,[r2,#8] \n\t"
796 "ADCS r1,r1,ip \n\t"
797 "ADC r3,r3,#0 \n\t"
798 "STMIA r2!,{r0,r1,r3} \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300799 : "+r" (r0), "+r" (r1), "+r" (r2)
800 :
801 : "r3", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300802#endif
803 );
Kevin Bracey1959c182020-07-16 21:03:19 +0300804}
805#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300806static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Jarno Lamsa18987a42019-04-24 15:40:43 +0300807{
808
809 uECC_dword_t p = (uECC_dword_t)a * b;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300810 uECC_dword_t r01 = ((uECC_dword_t)(r[1]) << uECC_WORD_BITS) | r[0];
Jarno Lamsa18987a42019-04-24 15:40:43 +0300811 r01 += p;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300812 r[2] += (r01 < p);
813 r[1] = r01 >> uECC_WORD_BITS;
814 r[0] = (uECC_word_t)r01;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300815}
Kevin Bracey1959c182020-07-16 21:03:19 +0300816#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300817
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200818/* State for implementing random delays in uECC_vli_mult_rnd().
819 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100820 * The state is initialized by randomizing delays and setting i = 0.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200821 * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i.
822 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100823 * Randomized vli multiplication is used only for point operations
824 * (XYcZ_add_rnd() * and XYcZ_addC_rnd()) in scalar multiplication
825 * (ECCPoint_mult()). Those go in pair, and each pair does 14 calls to
826 * uECC_vli_mult_rnd() (6 in XYcZ_add_rnd() and 8 in XYcZ_addC_rnd(),
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100827 * indirectly through uECC_vli_modMult_rnd().
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100828 *
829 * Considering this, in order to minimize the number of calls to the RNG
830 * (which impact performance) while keeping the size of the structure low,
831 * make room for 14 randomized vli mults, which corresponds to one step in the
832 * scalar multiplication routine.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200833 */
834typedef struct {
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100835 uint8_t i;
836 uint8_t delays[14];
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100837} ecc_wait_state_t;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200838
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100839/*
840 * Reset wait_state so that it's ready to be used.
841 */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100842void ecc_wait_state_reset(ecc_wait_state_t *ws)
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100843{
844 if (ws == NULL)
845 return;
846
847 ws->i = 0;
Shelly Liberman05beb9a2020-09-13 15:23:56 +0300848 mbedtls_platform_random_buf(ws->delays, sizeof(ws->delays));
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100849}
850
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200851/* Computes result = left * right. Result must be 2 * num_words long.
852 *
853 * As a counter-measure against horizontal attacks, add noise by performing
854 * a random number of extra computations performing random additional accesses
855 * to limbs of the input.
856 *
857 * Each of the two actual computation loops is surrounded by two
858 * similar-looking waiting loops, to make the beginning and end of the actual
859 * computation harder to spot.
860 *
861 * We add 4 waiting loops of between 0 and 3 calls to muladd() each. That
862 * makes an average of 6 extra calls. Compared to the main computation which
863 * makes 64 such calls, this represents an average performance degradation of
864 * less than 10%.
865 *
866 * Compared to the original uECC_vli_mult(), loose the num_words argument as we
867 * know it's always 8. This saves a bit of code size and execution speed.
868 */
869static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400870 const uECC_word_t *right, ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300871{
872
Kevin Bracey84f31d32020-09-29 17:51:04 +0300873 uECC_word_t r[3] = { 0, 0, 0 };
Jarno Lamsa18987a42019-04-24 15:40:43 +0300874 wordcount_t i, k;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +0100875 const uint8_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200876
877 /* Fetch 8 bit worth of delay from the state; 0 if we have no state */
878 uint8_t delays = s ? s->delays[s->i++] : 0;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300879 uECC_word_t rr[3] = { 0, 0, 0 };
880 volatile uECC_word_t rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200881
882 /* Mimic start of next loop: k in [0, 3] */
883 k = 0 + (delays & 0x03);
884 delays >>= 2;
885 /* k = 0 -> i in [1, 0] -> 0 extra muladd;
886 * k = 3 -> i in [1, 3] -> 3 extra muladd */
Manuel Pégourié-Gonnardc8814862019-11-05 10:32:37 +0100887 for (i = 1; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300888 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200889 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300890 rdummy = rr[0];
891 rr[0] = rr[1];
892 rr[1] = rr[2];
893 rr[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300894
895 /* Compute each digit of result in sequence, maintaining the carries. */
896 for (k = 0; k < num_words; ++k) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300897 for (i = 0; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300898 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300899 }
900
Kevin Bracey84f31d32020-09-29 17:51:04 +0300901 result[k] = r[0];
902 r[0] = r[1];
903 r[1] = r[2];
904 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300905 }
906
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200907 /* Mimic end of previous loop: k in [4, 7] */
908 k = 4 + (delays & 0x03);
909 delays >>= 2;
910 /* k = 4 -> i in [5, 4] -> 0 extra muladd;
911 * k = 7 -> i in [5, 7] -> 3 extra muladd */
912 for (i = 5; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300913 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200914 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300915 rdummy = rr[0];
916 rr[0] = rr[1];
917 rr[1] = rr[2];
918 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200919
920 /* Mimic start of next loop: k in [8, 11] */
921 k = 11 - (delays & 0x03);
922 delays >>= 2;
923 /* k = 8 -> i in [5, 7] -> 3 extra muladd;
924 * k = 11 -> i in [8, 7] -> 0 extra muladd */
925 for (i = (k + 5) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300926 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200927 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300928 rdummy = rr[0];
929 rr[0] = rr[1];
930 rr[1] = rr[2];
931 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200932
Jarno Lamsa18987a42019-04-24 15:40:43 +0300933 for (k = num_words; k < num_words * 2 - 1; ++k) {
934
935 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300936 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300937 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300938 result[k] = r[0];
939 r[0] = r[1];
940 r[1] = r[2];
941 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300942 }
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200943
Kevin Bracey84f31d32020-09-29 17:51:04 +0300944 result[num_words * 2 - 1] = r[0];
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200945
946 /* Mimic end of previous loop: k in [12, 15] */
947 k = 15 - (delays & 0x03);
948 delays >>= 2;
949 /* k = 12 -> i in [5, 7] -> 3 extra muladd;
950 * k = 15 -> i in [8, 7] -> 0 extra muladd */
951 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300952 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200953 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300954 rdummy = rr[0];
955 rr[0] = rr[1];
956 rr[1] = rr[2];
957 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200958
Kevin Bracey84f31d32020-09-29 17:51:04 +0300959 /* avoid warning that rdummy is set but not used */
960 (void) rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200961}
962
Jarno Lamsa18987a42019-04-24 15:40:43 +0300963void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400964 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300965{
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100966 uECC_word_t carry = uECC_vli_add(result, left, right);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100967 if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300968 /* result > mod (result = mod + remainder), so subtract mod to get
969 * remainder. */
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100970 uECC_vli_sub(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300971 }
972}
973
974void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400975 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300976{
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100977 uECC_word_t l_borrow = uECC_vli_sub(result, left, right);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300978 if (l_borrow) {
979 /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
980 * we can get the correct result from result + mod (with overflow). */
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100981 uECC_vli_add(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300982 }
983}
984
985/* Computes result = product % mod, where product is 2N words long. */
986/* Currently only designed to work for curve_p or curve_n. */
987void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400988 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300989{
990 uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
991 uECC_word_t tmp[2 * NUM_ECC_WORDS];
992 uECC_word_t *v[2] = {tmp, product};
993 uECC_word_t index;
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +0100994 const wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300995
996 /* Shift mod so its highest set bit is at the maximum position. */
997 bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100998 uECC_vli_numBits(mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300999 wordcount_t word_shift = shift / uECC_WORD_BITS;
1000 wordcount_t bit_shift = shift % uECC_WORD_BITS;
1001 uECC_word_t carry = 0;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001002 uECC_vli_clear(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001003 if (bit_shift > 0) {
1004 for(index = 0; index < (uECC_word_t)num_words; ++index) {
1005 mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
1006 carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
1007 }
1008 } else {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001009 uECC_vli_set(mod_multiple + word_shift, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001010 }
1011
1012 for (index = 1; shift >= 0; --shift) {
1013 uECC_word_t borrow = 0;
1014 wordcount_t i;
1015 for (i = 0; i < num_words * 2; ++i) {
1016 uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
1017 if (diff != v[index][i]) {
1018 borrow = (diff > v[index][i]);
1019 }
1020 v[1 - index][i] = diff;
1021 }
1022 /* Swap the index if there was no borrow */
1023 index = !(index ^ borrow);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001024 uECC_vli_rshift1(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001025 mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
Andrzej Kurek0919b142020-07-06 15:28:59 -04001026 (uECC_WORD_BITS - 1);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001027 uECC_vli_rshift1(mod_multiple + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001028 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001029 uECC_vli_set(result, v[index]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001030}
1031
1032void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001033 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001034{
1035 uECC_word_t product[2 * NUM_ECC_WORDS];
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001036 uECC_vli_mult_rnd(product, left, right, NULL);
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +01001037 uECC_vli_mmod(result, product, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001038}
1039
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001040static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001041 const uECC_word_t *right, ecc_wait_state_t *s)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001042{
1043 uECC_word_t product[2 * NUM_ECC_WORDS];
1044 uECC_vli_mult_rnd(product, left, right, s);
1045
1046 vli_mmod_fast_secp256r1(result, product);
1047}
1048
Jarno Lamsa18987a42019-04-24 15:40:43 +03001049void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001050 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001051{
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001052 uECC_vli_modMult_rnd(result, left, right, NULL);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001053}
1054
Jarno Lamsa18987a42019-04-24 15:40:43 +03001055#define EVEN(vli) (!(vli[0] & 1))
1056
1057static void vli_modInv_update(uECC_word_t *uv,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001058 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001059{
1060
1061 uECC_word_t carry = 0;
1062
1063 if (!EVEN(uv)) {
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001064 carry = uECC_vli_add(uv, uv, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001065 }
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001066 uECC_vli_rshift1(uv);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001067 if (carry) {
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +01001068 uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001069 }
1070}
1071
1072void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001073 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001074{
1075 uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
1076 uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
1077 cmpresult_t cmpResult;
1078
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001079 if (uECC_vli_isZero(input)) {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001080 uECC_vli_clear(result);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001081 return;
1082 }
1083
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001084 uECC_vli_set(a, input);
1085 uECC_vli_set(b, mod);
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001086 uECC_vli_clear(u);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001087 u[0] = 1;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001088 uECC_vli_clear(v);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001089 while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001090 if (EVEN(a)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001091 uECC_vli_rshift1(a);
Andrzej Kurek0919b142020-07-06 15:28:59 -04001092 vli_modInv_update(u, mod);
1093 } else if (EVEN(b)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001094 uECC_vli_rshift1(b);
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +01001095 vli_modInv_update(v, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001096 } else if (cmpResult > 0) {
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001097 uECC_vli_sub(a, a, b);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001098 uECC_vli_rshift1(a);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +01001099 if (uECC_vli_cmp_unsafe(u, v) < 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001100 uECC_vli_add(u, u, mod);
1101 }
1102 uECC_vli_sub(u, u, v);
1103 vli_modInv_update(u, mod);
1104 } else {
1105 uECC_vli_sub(b, b, a);
1106 uECC_vli_rshift1(b);
1107 if (uECC_vli_cmp_unsafe(v, u) < 0) {
1108 uECC_vli_add(v, v, mod);
1109 }
1110 uECC_vli_sub(v, v, u);
1111 vli_modInv_update(v, mod);
1112 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001113 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001114 uECC_vli_set(result, u);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001115}
1116
1117/* ------ Point operations ------ */
1118
1119void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001120 uECC_word_t * Z1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001121{
1122 /* t1 = X, t2 = Y, t3 = Z */
1123 uECC_word_t t4[NUM_ECC_WORDS];
1124 uECC_word_t t5[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001125 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001126
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001127 if (uECC_vli_isZero(Z1)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001128 return;
1129 }
1130
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001131 uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */
1132 uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */
1133 uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */
1134 uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */
1135 uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001136
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001137 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = x1 + z1^2 */
1138 uECC_vli_modAdd(Z1, Z1, Z1, curve_p); /* t3 = 2*z1^2 */
1139 uECC_vli_modSub(Z1, X1, Z1, curve_p); /* t3 = x1 - z1^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001140 uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001141
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001142 uECC_vli_modAdd(Z1, X1, X1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
1143 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001144 if (uECC_vli_testBit(X1, 0)) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001145 uECC_word_t l_carry = uECC_vli_add(X1, X1, curve_p);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001146 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001147 X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
1148 } else {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001149 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001150 }
1151
1152 /* t1 = 3/2*(x1^2 - z1^4) = B */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001153 uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001154 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - A */
1155 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
1156 uECC_vli_modSub(t5, t5, Z1, curve_p); /* t5 = A - x3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001157 uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001158 /* t4 = B * (A - x3) - y1^4 = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001159 uECC_vli_modSub(t4, X1, t4, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001160
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001161 uECC_vli_set(X1, Z1);
1162 uECC_vli_set(Z1, Y1);
1163 uECC_vli_set(Y1, t4);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001164}
1165
Manuel Pégourié-Gonnard1c6f7ea2019-11-21 09:18:29 +01001166/*
1167 * @brief Computes x^3 + ax + b. result must not overlap x.
1168 * @param result OUT -- x^3 + ax + b
1169 * @param x IN -- value of x
1170 * @param curve IN -- elliptic curve
1171 */
1172static void x_side_default(uECC_word_t *result,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001173 const uECC_word_t *x)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001174{
1175 uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001176
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001177 uECC_vli_modMult_fast(result, x, x); /* r = x^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001178 uECC_vli_modSub(result, result, _3, curve_p); /* r = x^2 - 3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001179 uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001180 /* r = x^3 - 3x + b: */
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +01001181 uECC_vli_modAdd(result, result, curve_b, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001182}
1183
1184void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
1185{
1186 unsigned int tmp[NUM_ECC_WORDS];
1187 int carry;
1188
1189 /* t */
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001190 uECC_vli_set(result, product);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001191
1192 /* s1 */
1193 tmp[0] = tmp[1] = tmp[2] = 0;
1194 tmp[3] = product[11];
1195 tmp[4] = product[12];
1196 tmp[5] = product[13];
1197 tmp[6] = product[14];
1198 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001199 carry = uECC_vli_add(tmp, tmp, tmp);
1200 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001201
1202 /* s2 */
1203 tmp[3] = product[12];
1204 tmp[4] = product[13];
1205 tmp[5] = product[14];
1206 tmp[6] = product[15];
1207 tmp[7] = 0;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001208 carry += uECC_vli_add(tmp, tmp, tmp);
1209 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001210
1211 /* s3 */
1212 tmp[0] = product[8];
1213 tmp[1] = product[9];
1214 tmp[2] = product[10];
1215 tmp[3] = tmp[4] = tmp[5] = 0;
1216 tmp[6] = product[14];
1217 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001218 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001219
1220 /* s4 */
1221 tmp[0] = product[9];
1222 tmp[1] = product[10];
1223 tmp[2] = product[11];
1224 tmp[3] = product[13];
1225 tmp[4] = product[14];
1226 tmp[5] = product[15];
1227 tmp[6] = product[13];
1228 tmp[7] = product[8];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001229 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001230
1231 /* d1 */
1232 tmp[0] = product[11];
1233 tmp[1] = product[12];
1234 tmp[2] = product[13];
1235 tmp[3] = tmp[4] = tmp[5] = 0;
1236 tmp[6] = product[8];
1237 tmp[7] = product[10];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001238 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001239
1240 /* d2 */
1241 tmp[0] = product[12];
1242 tmp[1] = product[13];
1243 tmp[2] = product[14];
1244 tmp[3] = product[15];
1245 tmp[4] = tmp[5] = 0;
1246 tmp[6] = product[9];
1247 tmp[7] = product[11];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001248 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001249
1250 /* d3 */
1251 tmp[0] = product[13];
1252 tmp[1] = product[14];
1253 tmp[2] = product[15];
1254 tmp[3] = product[8];
1255 tmp[4] = product[9];
1256 tmp[5] = product[10];
1257 tmp[6] = 0;
1258 tmp[7] = product[12];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001259 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001260
1261 /* d4 */
1262 tmp[0] = product[14];
1263 tmp[1] = product[15];
1264 tmp[2] = 0;
1265 tmp[3] = product[9];
1266 tmp[4] = product[10];
1267 tmp[5] = product[11];
1268 tmp[6] = 0;
1269 tmp[7] = product[13];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001270 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001271
1272 if (carry < 0) {
1273 do {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001274 carry += uECC_vli_add(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001275 }
1276 while (carry < 0);
1277 } else {
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +02001278 while (carry ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001279 uECC_vli_cmp_unsafe(curve_p, result) != 1) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001280 carry -= uECC_vli_sub(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001281 }
1282 }
1283}
1284
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001285uECC_word_t EccPoint_isZero(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001286{
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001287 return uECC_vli_isZero(point);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001288}
1289
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001290void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001291{
1292 uECC_word_t t1[NUM_ECC_WORDS];
1293
Andrzej Kurek0919b142020-07-06 15:28:59 -04001294 uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001295 uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */
1296 uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */
1297 uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001298}
1299
1300/* P = (x1, y1) => 2P, (x2, y2) => P' */
1301static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
1302 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001303 const uECC_word_t * const initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001304{
1305 uECC_word_t z[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001306 if (initial_Z) {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001307 uECC_vli_set(z, initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001308 } else {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001309 uECC_vli_clear(z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001310 z[0] = 1;
1311 }
1312
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001313 uECC_vli_set(X2, X1);
1314 uECC_vli_set(Y2, Y1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001315
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001316 apply_z(X1, Y1, z);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001317 double_jacobian_default(X1, Y1, z);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001318 apply_z(X2, Y2, z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001319}
1320
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001321static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1322 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001323 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001324{
1325 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1326 uECC_word_t t5[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001327
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001328 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001329 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001330 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1331 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001332 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001333 uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001334
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001335 uECC_vli_modSub(t5, t5, X1, curve_p); /* t5 = D - B */
1336 uECC_vli_modSub(t5, t5, X2, curve_p); /* t5 = D - B - C = x3 */
1337 uECC_vli_modSub(X2, X2, X1, curve_p); /* t3 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001338 uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001339 uECC_vli_modSub(X2, X1, t5, curve_p); /* t3 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001340 uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001341 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001342
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001343 uECC_vli_set(X2, t5);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001344}
1345
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001346void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001347 uECC_word_t * X2, uECC_word_t * Y2)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001348{
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001349 XYcZ_add_rnd(X1, Y1, X2, Y2, NULL);
1350}
1351
Jarno Lamsa18987a42019-04-24 15:40:43 +03001352/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
1353 Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
1354 or P => P - Q, Q => P + Q
1355 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001356static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1357 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001358 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001359{
1360 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1361 uECC_word_t t5[NUM_ECC_WORDS];
1362 uECC_word_t t6[NUM_ECC_WORDS];
1363 uECC_word_t t7[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001364
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001365 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001366 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001367 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1368 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001369 uECC_vli_modAdd(t5, Y2, Y1, curve_p); /* t5 = y2 + y1 */
1370 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001371
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001372 uECC_vli_modSub(t6, X2, X1, curve_p); /* t6 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001373 uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001374 uECC_vli_modAdd(t6, X1, X2, curve_p); /* t6 = B + C */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001375 uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001376 uECC_vli_modSub(X2, X2, t6, curve_p); /* t3 = D - (B + C) = x3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001377
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001378 uECC_vli_modSub(t7, X1, X2, curve_p); /* t7 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001379 uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001380 /* t4 = (y2 - y1)*(B - x3) - E = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001381 uECC_vli_modSub(Y2, Y2, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001382
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001383 uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001384 uECC_vli_modSub(t7, t7, t6, curve_p); /* t7 = F - (B + C) = x3' */
1385 uECC_vli_modSub(t6, t7, X1, curve_p); /* t6 = x3' - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001386 uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001387 /* t2 = (y2+y1)*(x3' - B) - E = y3': */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001388 uECC_vli_modSub(Y1, t6, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001389
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001390 uECC_vli_set(X1, t7);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001391}
1392
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001393static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
Jarno Lamsa18987a42019-04-24 15:40:43 +03001394 const uECC_word_t * scalar,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001395 const uECC_word_t * initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001396{
1397 /* R0 and R1 */
1398 uECC_word_t Rx[2][NUM_ECC_WORDS];
1399 uECC_word_t Ry[2][NUM_ECC_WORDS];
1400 uECC_word_t z[NUM_ECC_WORDS];
1401 bitcount_t i;
1402 uECC_word_t nb;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001403 const wordcount_t num_words = NUM_ECC_WORDS;
1404 const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001405 ecc_wait_state_t wait_state;
1406 ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001407
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001408 uECC_vli_set(Rx[1], point);
1409 uECC_vli_set(Ry[1], point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001410
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001411 XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001412
1413 for (i = num_bits - 2; i > 0; --i) {
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001414 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001415 nb = !uECC_vli_testBit(scalar, i);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001416 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
1417 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001418 }
1419
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001420 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001421 nb = !uECC_vli_testBit(scalar, 0);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001422 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001423
1424 /* Find final 1/Z value. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001425 uECC_vli_modSub(z, Rx[1], Rx[0], curve_p); /* X1 - X0 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001426 uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */
1427 uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001428 uECC_vli_modInv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0))*/
Jarno Lamsa18987a42019-04-24 15:40:43 +03001429 /* yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001430 uECC_vli_modMult_fast(z, z, point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001431 /* Xb * yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001432 uECC_vli_modMult_fast(z, z, Rx[1 - nb]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001433 /* End 1/Z calculation */
1434
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001435 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001436 apply_z(Rx[0], Ry[0], z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001437
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001438 uECC_vli_set(result, Rx[0]);
1439 uECC_vli_set(result + num_words, Ry[0]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001440}
1441
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001442static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001443 uECC_word_t *k1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001444{
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001445 bitcount_t num_n_bits = NUM_ECC_BITS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001446
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001447 uECC_word_t carry = uECC_vli_add(k0, k, curve_n) ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001448 uECC_vli_testBit(k0, num_n_bits);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001449
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001450 uECC_vli_add(k1, k0, curve_n);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001451
1452 return carry;
1453}
1454
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001455int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001456 const uECC_word_t * scalar)
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001457{
1458 uECC_word_t tmp[NUM_ECC_WORDS];
1459 uECC_word_t s[NUM_ECC_WORDS];
1460 uECC_word_t *k2[2] = {tmp, s};
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001461 wordcount_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001462 uECC_word_t carry;
1463 uECC_word_t *initial_Z = 0;
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001464 int r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001465 volatile int problem;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001466
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001467 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001468 problem = -1;
1469 problem = uECC_check_curve_integrity();
1470 if (problem != 0) {
1471 return UECC_FAULT_DETECTED;
1472 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001473 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001474 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001475 return UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001476 }
1477
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001478 /* Protects against invalid curve attacks */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001479 problem = -1;
1480 problem = uECC_valid_point(point);
1481 if (problem != 0) {
1482 /* invalid input, can happen without fault */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001483 return UECC_FAILURE;
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001484 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001485 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001486 if (problem != 0) {
1487 /* failure on second check means fault, though */
1488 return UECC_FAULT_DETECTED;
1489 }
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001490
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001491 /* Regularize the bitcount for the private key so that attackers cannot use a
1492 * side channel attack to learn the number of leading zeros. */
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001493 carry = regularize_k(scalar, tmp, s);
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001494
1495 /* If an RNG function was specified, get a random initial Z value to
Andrzej Kurek0919b142020-07-06 15:28:59 -04001496 * protect against side-channel attacks such as Template SPA */
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001497 if (g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001498 if (uECC_generate_random_int(k2[carry], curve_p, num_words) != UECC_SUCCESS) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001499 r = UECC_FAILURE;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001500 goto clear_and_out;
1501 }
1502 initial_Z = k2[carry];
1503 }
1504
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001505 EccPoint_mult(result, point, k2[!carry], initial_Z);
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001506
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001507 /* Protect against fault injections that would make the resulting
1508 * point not lie on the intended curve */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001509 problem = -1;
1510 problem = uECC_valid_point(result);
1511 if (problem != 0) {
1512 r = UECC_FAULT_DETECTED;
1513 goto clear_and_out;
1514 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001515 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001516 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001517 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001518 goto clear_and_out;
1519 }
1520
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001521 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001522 problem = -1;
1523 problem = uECC_check_curve_integrity();
1524 if (problem != 0) {
1525 r = UECC_FAULT_DETECTED;
1526 goto clear_and_out;
1527 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001528 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001529 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001530 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001531 goto clear_and_out;
1532 }
1533
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001534 r = UECC_SUCCESS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001535
1536clear_and_out:
1537 /* erasing temporary buffer used to store secret: */
1538 mbedtls_platform_zeroize(k2, sizeof(k2));
1539 mbedtls_platform_zeroize(tmp, sizeof(tmp));
1540 mbedtls_platform_zeroize(s, sizeof(s));
1541
1542 return r;
1543}
1544
Jarno Lamsa18987a42019-04-24 15:40:43 +03001545uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001546 uECC_word_t *private_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001547{
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001548 return EccPoint_mult_safer(result, curve_G, private_key);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001549}
1550
1551/* Converts an integer in uECC native format to big-endian bytes. */
1552void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001553 const unsigned int *native)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001554{
1555 wordcount_t i;
1556 for (i = 0; i < num_bytes; ++i) {
1557 unsigned b = num_bytes - 1 - i;
1558 bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
1559 }
1560}
1561
1562/* Converts big-endian bytes to an integer in uECC native format. */
1563void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001564 int num_bytes)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001565{
1566 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001567 uECC_vli_clear(native);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001568 for (i = 0; i < num_bytes; ++i) {
1569 unsigned b = num_bytes - 1 - i;
1570 native[b / uECC_WORD_SIZE] |=
1571 (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
1572 }
1573}
1574
1575int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001576 wordcount_t num_words)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001577{
1578 uECC_word_t mask = (uECC_word_t)-1;
1579 uECC_word_t tries;
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001580 bitcount_t num_bits = uECC_vli_numBits(top);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001581
1582 if (!g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001583 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001584 }
1585
1586 for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
Andrzej Kurek090365f2020-06-08 11:00:51 -04001587 if (g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE) != num_words * uECC_WORD_SIZE) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001588 return UECC_FAILURE;
1589 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001590 random[num_words - 1] &=
Andrzej Kurek0919b142020-07-06 15:28:59 -04001591 mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001592 if (!uECC_vli_isZero(random) &&
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +01001593 uECC_vli_cmp(top, random) == 1) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001594 return UECC_SUCCESS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001595 }
1596 }
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001597 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001598}
1599
1600
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001601int uECC_valid_point(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001602{
1603 uECC_word_t tmp1[NUM_ECC_WORDS];
1604 uECC_word_t tmp2[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001605 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa83d78812019-12-04 14:40:57 +02001606 volatile uECC_word_t diff = 0xffffffff;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001607
1608 /* The point at infinity is invalid. */
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001609 if (EccPoint_isZero(point)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001610 return -1;
1611 }
1612
1613 /* x and y must be smaller than p. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001614 if (uECC_vli_cmp_unsafe(curve_p, point) != 1 ||
1615 uECC_vli_cmp_unsafe(curve_p, point + num_words) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001616 return -2;
1617 }
1618
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001619 uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001620 x_side_default(tmp2, point); /* tmp2 = x^3 + ax + b */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001621
1622 /* Make sure that y^2 == x^3 + ax + b */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001623 diff = uECC_vli_equal(tmp1, tmp2);
1624 if (diff == 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001625 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001626 if (diff == 0) {
1627 return 0;
1628 }
1629 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001630
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001631 return -3;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001632}
1633
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001634int uECC_valid_public_key(const uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001635{
1636
1637 uECC_word_t _public[NUM_ECC_WORDS * 2];
1638
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001639 uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001640 uECC_vli_bytesToNative(
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001641 _public + NUM_ECC_WORDS,
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001642 public_key + NUM_ECC_BYTES,
1643 NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001644
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +01001645 if (memcmp(_public, curve_G, NUM_ECC_WORDS * 2) == 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001646 return -4;
1647 }
1648
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001649 return uECC_valid_point(_public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001650}
1651
Andrzej Kurek0919b142020-07-06 15:28:59 -04001652int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001653{
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001654 int ret = UECC_FAULT_DETECTED;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001655 uECC_word_t _private[NUM_ECC_WORDS];
1656 uECC_word_t _public[NUM_ECC_WORDS * 2];
1657
1658 uECC_vli_bytesToNative(
1659 _private,
1660 private_key,
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +01001661 BITS_TO_BYTES(NUM_ECC_BITS));
Jarno Lamsa18987a42019-04-24 15:40:43 +03001662
1663 /* Make sure the private key is in the range [1, n-1]. */
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001664 if (uECC_vli_isZero(_private)) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001665 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001666 }
1667
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001668 if (uECC_vli_cmp(curve_n, _private) != 1) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001669 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001670 }
1671
1672 /* Compute public key. */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001673 ret = EccPoint_compute_public_key(_public, _private);
1674 if (ret != UECC_SUCCESS) {
1675 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001676 }
1677
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001678 uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001679 uECC_vli_nativeToBytes(
1680 public_key +
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001681 NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS);
Andrzej Kurekcf3e35c2020-07-15 22:32:08 -04001682
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001683 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001684}