blob: 40256dc31fdfb7c971f5427342e0ce994e3ae52e [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}
390#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300391uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100392 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300393{
394 uECC_word_t borrow = 0;
395 wordcount_t i;
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100396 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300397 uECC_word_t diff = left[i] - right[i] - borrow;
398 uECC_word_t val = (diff > left[i]);
399 borrow = cond_set(val, borrow, (diff != left[i]));
400
401 result[i] = diff;
402 }
403 return borrow;
404}
Kevin Bracey1959c182020-07-16 21:03:19 +0300405#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300406
407/* Computes result = left + right, returning carry, in constant time.
408 * Can modify in place. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300409#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
410static __asm uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
411 const uECC_word_t *right)
412{
413#if NUM_ECC_WORDS != 8
414#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
415#endif
416#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
417 PUSH {r4-r6,lr}
418 FRAME PUSH {r4-r6,lr}
419 LDMIA r1!,{r3,r4}
420 LDMIA r2!,{r5,r6}
421 ADDS r3,r5
422 ADCS r4,r6
423 STMIA r0!,{r3,r4}
424 LDMIA r1!,{r3,r4}
425 LDMIA r2!,{r5,r6}
426 ADCS r3,r5
427 ADCS r4,r6
428 STMIA r0!,{r3,r4}
429 LDMIA r1!,{r3,r4}
430 LDMIA r2!,{r5,r6}
431 ADCS r3,r5
432 ADCS r4,r6
433 STMIA r0!,{r3,r4}
434 LDMIA r1!,{r3,r4}
435 LDMIA r2!,{r5,r6}
436 ADCS r3,r5
437 ADCS r4,r6
438 STMIA r0!,{r3,r4}
439 MOVS r0,#0 // does not affect C flag
440 ADCS r0,r0 // r0 := 0 + 0 + C = carry
441 POP {r4-r6,pc}
442#else
443 PUSH {r4-r8,lr}
444 FRAME PUSH {r4-r8,lr}
445 LDMIA r1!,{r3-r6}
446 LDMIA r2!,{r7,r8,r12,lr}
447 ADDS r3,r7
448 ADCS r4,r8
449 ADCS r5,r12
450 ADCS r6,lr
451 STMIA r0!,{r3-r6}
452 LDMIA r1!,{r3-r6}
453 LDMIA r2!,{r7,r8,r12,lr}
454 ADCS r3,r7
455 ADCS r4,r8
456 ADCS r5,r12
457 ADCS r6,lr
458 STMIA r0!,{r3-r6}
459 MOVS r0,#0 // does not affect C flag
460 ADCS r0,r0 // r0 := 0 + 0 + C = carry
461 POP {r4-r8,pc}
462#endif
463}
464#else
Jarno Lamsa18987a42019-04-24 15:40:43 +0300465static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100466 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300467{
468 uECC_word_t carry = 0;
469 wordcount_t i;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100470 for (i = 0; i < NUM_ECC_WORDS; ++i) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300471 uECC_word_t sum = left[i] + right[i] + carry;
472 uECC_word_t val = (sum < left[i]);
473 carry = cond_set(val, carry, (sum != left[i]));
474 result[i] = sum;
475 }
476 return carry;
477}
Kevin Bracey1959c182020-07-16 21:03:19 +0300478#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300479
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +0100480cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300481{
482 uECC_word_t tmp[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100483 uECC_word_t neg = !!uECC_vli_sub(tmp, left, right);
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100484 uECC_word_t equal = uECC_vli_isZero(tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300485 return (!equal - 2 * neg);
486}
487
488/* Computes vli = vli >> 1. */
Kevin Bracey1959c182020-07-16 21:03:19 +0300489#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
490static __asm void uECC_vli_rshift1(uECC_word_t *vli)
491{
492#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
493// RRX instruction is not available, so although we
494// can use C flag, it's not that effective. Does at
495// least save one working register, meaning we don't need stack
496 MOVS r3,#0 // initial carry = 0
497 MOVS r2,#__cpp(4 * (NUM_ECC_WORDS - 1))
49801 LDR r1,[r0,r2]
499 LSRS r1,r1,#1 // r2 = word >> 1
500 ORRS r1,r3 // merge in the previous carry
501 STR r1,[r0,r2]
502 ADCS r3,r3 // put C into bottom bit of r3
503 LSLS r3,r3,#31 // shift it up to the top ready for next word
504 SUBS r2,r2,#4
505 BPL %B01
506 BX lr
507#else
508#if NUM_ECC_WORDS != 8
509#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
510#endif
511// Smooth multiword operation, lots of 32-bit instructions
512 ADDS r0,#32
513 LDMDB r0,{r1-r3,ip}
514 LSRS ip,ip,#1
515 RRXS r3,r3
516 RRXS r2,r2
517 RRXS r1,r1
518 STMDB r0!,{r1-r3,ip}
519 LDMDB r0,{r1-r3,ip}
520 RRXS ip,ip
521 RRXS r3,r3
522 RRXS r2,r2
523 RRX r1,r1
524 STMDB r0!,{r1-r3,ip}
525 BX lr
526#endif
527}
Kevin Bracey06060332020-10-02 17:43:12 +0300528#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__ && defined __thumb2__
529static void uECC_vli_rshift1(uECC_word_t *vli)
530{
531 register uECC_word_t *r0 asm ("r0") = vli;
532#if NUM_ECC_WORDS != 8
533#error adjust ARM assembly to handle NUM_ECC_WORDS != 8
534#endif
535 asm volatile (
536 "ADDS r0,#32 \n\t"
537 "LDMDB r0,{r1-r3,ip} \n\t"
538 "LSRS ip,ip,#1 \n\t"
539 "RRXS r3,r3 \n\t"
540 "RRXS r2,r2 \n\t"
541 "RRXS r1,r1 \n\t"
542 "STMDB r0!,{r1-r3,ip} \n\t"
543 "LDMDB r0,{r1-r3,ip} \n\t"
544 "RRXS ip,ip \n\t"
545 "RRXS r3,r3 \n\t"
546 "RRXS r2,r2 \n\t"
547 "RRX r1,r1 \n\t"
548 "STMDB r0!,{r1-r3,ip} \n\t"
549 : "+r" (r0)
550 :
551 : "r1", "r2", "r3", "ip", "cc", "memory"
552 );
553}
Kevin Bracey1959c182020-07-16 21:03:19 +0300554#else
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100555static void uECC_vli_rshift1(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300556{
557 uECC_word_t *end = vli;
558 uECC_word_t carry = 0;
559
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100560 vli += NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300561 while (vli-- > end) {
562 uECC_word_t temp = *vli;
563 *vli = (temp >> 1) | carry;
564 carry = temp << (uECC_WORD_BITS - 1);
565 }
566}
Kevin Bracey1959c182020-07-16 21:03:19 +0300567#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300568
Kevin Bracey84f31d32020-09-29 17:51:04 +0300569/* Compute a * b + r, where r is a triple-word with high-order word r[2] and
570 * low-order word r[0], and store the result in the same triple-word.
Manuel Pégourié-Gonnard86c4f812019-10-31 13:02:03 +0100571 *
Kevin Bracey84f31d32020-09-29 17:51:04 +0300572 * r[2..0] = a * b + r[2..0]:
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200573 * [in] a, b: operands to be multiplied
Kevin Bracey84f31d32020-09-29 17:51:04 +0300574 * [in] r: 3 words of operand to add
575 * [out] r: 3 words of result
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200576 */
Kevin Bracey1959c182020-07-16 21:03:19 +0300577#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
Kevin Bracey84f31d32020-09-29 17:51:04 +0300578static __asm void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Bracey1959c182020-07-16 21:03:19 +0300579{
580#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
Kevin Bracey84f31d32020-09-29 17:51:04 +0300581 PUSH {r4-r5}
582 FRAME PUSH {r4-r5}
583 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
584 // Separate operands into halfwords
585 UXTH r3,r0 // r3 := a.lo
586 LSRS r4,r0,#16 // r4 := a.hi
587 UXTH r5,r1 // r5 := b.lo
588 LSRS r1,r1,#16 // r1 := b.hi
589 // Multiply halfword pairs
590 MOVS r0,r3
591 MULS r0,r5,r0 // r0 := a.lo * b.lo
592 MULS r3,r1,r3 // r3 := a.lo * b.hi
593 MULS r5,r4,r5 // r5 := a.hi * b.lo
594 MULS r1,r4,r1 // r1 := a.hi * b.hi
595 // Split, shift and add a.lo * b.hi
596 LSRS r4,r3,#16 // r4 := (a.lo * b.hi).hi
597 LSLS r3,r3,#16 // r3 := (a.lo * b.hi).lo
598 ADDS r0,r0,r3 // r0 := a.lo * b.lo + (a.lo * b.hi).lo
599 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
600 // Split, shift and add a.hi * b.lo
601 LSRS r4,r5,#16 // r4 := (a.hi * b.lo).hi
602 LSLS r5,r5,#16 // r5 := (a.hi * b.lo).lo
603 ADDS r0,r0,r5 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
604 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
605 // Finally add r[]
606 LDMIA r2!,{r3,r4,r5}
607 ADDS r3,r3,r0
Kevin Bracey1959c182020-07-16 21:03:19 +0300608 ADCS r4,r1
Kevin Bracey1959c182020-07-16 21:03:19 +0300609 MOVS r0,#0
Kevin Bracey84f31d32020-09-29 17:51:04 +0300610 ADCS r5,r0
611 SUBS r2,#12
612 STMIA r2!,{r3,r4,r5}
613 POP {r4-r5}
614 FRAME POP {r4-r5}
615 BX lr
Kevin Bracey1959c182020-07-16 21:03:19 +0300616#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300617 UMULL r3,ip,r0,r1 // pre-ARMv6 requires Rd[Lo|Hi] != Rn
618 LDMIA r2,{r0,r1}
619 ADDS r0,r0,r3
620 LDR r3,[r2,#8]
621 ADCS r1,r1,ip
622 ADC r3,r3,#0
623 STMIA r2!,{r0,r1,r3}
Kevin Bracey1959c182020-07-16 21:03:19 +0300624 BX lr
625#endif
Kevin Braceye0f88d52020-09-30 12:52:15 +0300626}
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300627#elif defined MBEDTLS_HAVE_ASM && defined __GNUC__ && defined __arm__
628static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Braceye0f88d52020-09-30 12:52:15 +0300629{
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300630 register uECC_word_t r0 asm ("r0") = a;
631 register uECC_word_t r1 asm ("r1") = b;
632 register uECC_word_t *r2 asm ("r2") = r;
633 asm volatile (
Kevin Braceye0f88d52020-09-30 12:52:15 +0300634#if defined __thumb__ && !defined(__thumb2__)
635 ".syntax unified \n\t"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300636 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
637 // Separate operands into halfwords
638 "UXTH r3,r0 \n\t" // r3 := a.lo
639 "LSRS r4,r0,#16 \n\t" // r4 := a.hi
640 "UXTH r5,r1 \n\t" // r5 := b.lo
641 "LSRS r1,r1,#16 \n\t" // r1 := b.hi
642 // Multiply halfword pairs
643 "MOVS r0,r3 \n\t"
644 "MULS r0,r5,r0 \n\t" // r0 := a.lo * b.lo
645 "MULS r3,r1,r3 \n\t" // r3 := a.lo * b.hi
646 "MULS r5,r4,r5 \n\t" // r5 := a.hi * b.lo
647 "MULS r1,r4,r1 \n\t" // r1 := a.hi * b.hi
648 // Split, shift and add a.lo * b.hi
649 "LSRS r4,r3,#16 \n\t" // r4 := (a.lo * b.hi).hi
650 "LSLS r3,r3,#16 \n\t" // r3 := (a.lo * b.hi).lo
651 "ADDS r0,r0,r3 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo
652 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
653 // Split, shift and add a.hi * b.lo
654 "LSRS r4,r5,#16 \n\t" // r4 := (a.hi * b.lo).hi
655 "LSLS r5,r5,#16 \n\t" // r5 := (a.hi * b.lo).lo
656 "ADDS r0,r0,r5 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
657 "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
658 // Finally add r[]
659 "LDMIA r2!,{r3,r4,r5} \n\t"
660 "ADDS r3,r3,r0 \n\t"
661 "ADCS r4,r1 \n\t"
662 "MOVS r0,#0 \n\t"
663 "ADCS r5,r0 \n\t"
664 "SUBS r2,#12 \n\t"
665 "STMIA r2!,{r3,r4,r5} \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300666 : "+r" (r0), "+r" (r1), "+r" (r2)
667 :
668 : "r3", "r4", "r5", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300669#else
670 "UMULL r3,ip,r0,r1 \n\t" // pre-ARMv6 requires Rd[Lo|Hi] != Rn
671 "LDMIA r2,{r0,r1} \n\t"
672 "ADDS r0,r0,r3 \n\t"
673 "LDR r3,[r2,#8] \n\t"
674 "ADCS r1,r1,ip \n\t"
675 "ADC r3,r3,#0 \n\t"
676 "STMIA r2!,{r0,r1,r3} \n\t"
Kevin Bracey0a1884b2020-10-02 14:44:40 +0300677 : "+r" (r0), "+r" (r1), "+r" (r2)
678 :
679 : "r3", "ip", "cc", "memory"
Kevin Braceye0f88d52020-09-30 12:52:15 +0300680#endif
681 );
Kevin Bracey1959c182020-07-16 21:03:19 +0300682}
683#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300684static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Jarno Lamsa18987a42019-04-24 15:40:43 +0300685{
686
687 uECC_dword_t p = (uECC_dword_t)a * b;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300688 uECC_dword_t r01 = ((uECC_dword_t)(r[1]) << uECC_WORD_BITS) | r[0];
Jarno Lamsa18987a42019-04-24 15:40:43 +0300689 r01 += p;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300690 r[2] += (r01 < p);
691 r[1] = r01 >> uECC_WORD_BITS;
692 r[0] = (uECC_word_t)r01;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300693}
Kevin Bracey1959c182020-07-16 21:03:19 +0300694#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300695
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200696/* State for implementing random delays in uECC_vli_mult_rnd().
697 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100698 * The state is initialized by randomizing delays and setting i = 0.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200699 * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i.
700 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100701 * Randomized vli multiplication is used only for point operations
702 * (XYcZ_add_rnd() * and XYcZ_addC_rnd()) in scalar multiplication
703 * (ECCPoint_mult()). Those go in pair, and each pair does 14 calls to
704 * uECC_vli_mult_rnd() (6 in XYcZ_add_rnd() and 8 in XYcZ_addC_rnd(),
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100705 * indirectly through uECC_vli_modMult_rnd().
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100706 *
707 * Considering this, in order to minimize the number of calls to the RNG
708 * (which impact performance) while keeping the size of the structure low,
709 * make room for 14 randomized vli mults, which corresponds to one step in the
710 * scalar multiplication routine.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200711 */
712typedef struct {
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100713 uint8_t i;
714 uint8_t delays[14];
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100715} ecc_wait_state_t;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200716
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100717/*
718 * Reset wait_state so that it's ready to be used.
719 */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100720void ecc_wait_state_reset(ecc_wait_state_t *ws)
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100721{
722 if (ws == NULL)
723 return;
724
725 ws->i = 0;
Shelly Liberman05beb9a2020-09-13 15:23:56 +0300726 mbedtls_platform_random_buf(ws->delays, sizeof(ws->delays));
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100727}
728
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200729/* Computes result = left * right. Result must be 2 * num_words long.
730 *
731 * As a counter-measure against horizontal attacks, add noise by performing
732 * a random number of extra computations performing random additional accesses
733 * to limbs of the input.
734 *
735 * Each of the two actual computation loops is surrounded by two
736 * similar-looking waiting loops, to make the beginning and end of the actual
737 * computation harder to spot.
738 *
739 * We add 4 waiting loops of between 0 and 3 calls to muladd() each. That
740 * makes an average of 6 extra calls. Compared to the main computation which
741 * makes 64 such calls, this represents an average performance degradation of
742 * less than 10%.
743 *
744 * Compared to the original uECC_vli_mult(), loose the num_words argument as we
745 * know it's always 8. This saves a bit of code size and execution speed.
746 */
747static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400748 const uECC_word_t *right, ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300749{
750
Kevin Bracey84f31d32020-09-29 17:51:04 +0300751 uECC_word_t r[3] = { 0, 0, 0 };
Jarno Lamsa18987a42019-04-24 15:40:43 +0300752 wordcount_t i, k;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +0100753 const uint8_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200754
755 /* Fetch 8 bit worth of delay from the state; 0 if we have no state */
756 uint8_t delays = s ? s->delays[s->i++] : 0;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300757 uECC_word_t rr[3] = { 0, 0, 0 };
758 volatile uECC_word_t rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200759
760 /* Mimic start of next loop: k in [0, 3] */
761 k = 0 + (delays & 0x03);
762 delays >>= 2;
763 /* k = 0 -> i in [1, 0] -> 0 extra muladd;
764 * k = 3 -> i in [1, 3] -> 3 extra muladd */
Manuel Pégourié-Gonnardc8814862019-11-05 10:32:37 +0100765 for (i = 1; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300766 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200767 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300768 rdummy = rr[0];
769 rr[0] = rr[1];
770 rr[1] = rr[2];
771 rr[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300772
773 /* Compute each digit of result in sequence, maintaining the carries. */
774 for (k = 0; k < num_words; ++k) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300775 for (i = 0; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300776 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300777 }
778
Kevin Bracey84f31d32020-09-29 17:51:04 +0300779 result[k] = r[0];
780 r[0] = r[1];
781 r[1] = r[2];
782 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300783 }
784
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200785 /* Mimic end of previous loop: k in [4, 7] */
786 k = 4 + (delays & 0x03);
787 delays >>= 2;
788 /* k = 4 -> i in [5, 4] -> 0 extra muladd;
789 * k = 7 -> i in [5, 7] -> 3 extra muladd */
790 for (i = 5; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300791 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200792 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300793 rdummy = rr[0];
794 rr[0] = rr[1];
795 rr[1] = rr[2];
796 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200797
798 /* Mimic start of next loop: k in [8, 11] */
799 k = 11 - (delays & 0x03);
800 delays >>= 2;
801 /* k = 8 -> i in [5, 7] -> 3 extra muladd;
802 * k = 11 -> i in [8, 7] -> 0 extra muladd */
803 for (i = (k + 5) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300804 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200805 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300806 rdummy = rr[0];
807 rr[0] = rr[1];
808 rr[1] = rr[2];
809 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200810
Jarno Lamsa18987a42019-04-24 15:40:43 +0300811 for (k = num_words; k < num_words * 2 - 1; ++k) {
812
813 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300814 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300815 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300816 result[k] = r[0];
817 r[0] = r[1];
818 r[1] = r[2];
819 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300820 }
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200821
Kevin Bracey84f31d32020-09-29 17:51:04 +0300822 result[num_words * 2 - 1] = r[0];
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200823
824 /* Mimic end of previous loop: k in [12, 15] */
825 k = 15 - (delays & 0x03);
826 delays >>= 2;
827 /* k = 12 -> i in [5, 7] -> 3 extra muladd;
828 * k = 15 -> i in [8, 7] -> 0 extra muladd */
829 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300830 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200831 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300832 rdummy = rr[0];
833 rr[0] = rr[1];
834 rr[1] = rr[2];
835 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200836
Kevin Bracey84f31d32020-09-29 17:51:04 +0300837 /* avoid warning that rdummy is set but not used */
838 (void) rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200839}
840
Jarno Lamsa18987a42019-04-24 15:40:43 +0300841void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400842 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300843{
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100844 uECC_word_t carry = uECC_vli_add(result, left, right);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100845 if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300846 /* result > mod (result = mod + remainder), so subtract mod to get
847 * remainder. */
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100848 uECC_vli_sub(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300849 }
850}
851
852void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400853 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300854{
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100855 uECC_word_t l_borrow = uECC_vli_sub(result, left, right);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300856 if (l_borrow) {
857 /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
858 * we can get the correct result from result + mod (with overflow). */
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100859 uECC_vli_add(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300860 }
861}
862
863/* Computes result = product % mod, where product is 2N words long. */
864/* Currently only designed to work for curve_p or curve_n. */
865void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400866 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300867{
868 uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
869 uECC_word_t tmp[2 * NUM_ECC_WORDS];
870 uECC_word_t *v[2] = {tmp, product};
871 uECC_word_t index;
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +0100872 const wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300873
874 /* Shift mod so its highest set bit is at the maximum position. */
875 bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100876 uECC_vli_numBits(mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300877 wordcount_t word_shift = shift / uECC_WORD_BITS;
878 wordcount_t bit_shift = shift % uECC_WORD_BITS;
879 uECC_word_t carry = 0;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100880 uECC_vli_clear(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300881 if (bit_shift > 0) {
882 for(index = 0; index < (uECC_word_t)num_words; ++index) {
883 mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
884 carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
885 }
886 } else {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100887 uECC_vli_set(mod_multiple + word_shift, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300888 }
889
890 for (index = 1; shift >= 0; --shift) {
891 uECC_word_t borrow = 0;
892 wordcount_t i;
893 for (i = 0; i < num_words * 2; ++i) {
894 uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
895 if (diff != v[index][i]) {
896 borrow = (diff > v[index][i]);
897 }
898 v[1 - index][i] = diff;
899 }
900 /* Swap the index if there was no borrow */
901 index = !(index ^ borrow);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100902 uECC_vli_rshift1(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300903 mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
Andrzej Kurek0919b142020-07-06 15:28:59 -0400904 (uECC_WORD_BITS - 1);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100905 uECC_vli_rshift1(mod_multiple + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300906 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100907 uECC_vli_set(result, v[index]);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300908}
909
910void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400911 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300912{
913 uECC_word_t product[2 * NUM_ECC_WORDS];
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100914 uECC_vli_mult_rnd(product, left, right, NULL);
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +0100915 uECC_vli_mmod(result, product, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300916}
917
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100918static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100919 const uECC_word_t *right, ecc_wait_state_t *s)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100920{
921 uECC_word_t product[2 * NUM_ECC_WORDS];
922 uECC_vli_mult_rnd(product, left, right, s);
923
924 vli_mmod_fast_secp256r1(result, product);
925}
926
Jarno Lamsa18987a42019-04-24 15:40:43 +0300927void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100928 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300929{
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100930 uECC_vli_modMult_rnd(result, left, right, NULL);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300931}
932
Jarno Lamsa18987a42019-04-24 15:40:43 +0300933#define EVEN(vli) (!(vli[0] & 1))
934
935static void vli_modInv_update(uECC_word_t *uv,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400936 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300937{
938
939 uECC_word_t carry = 0;
940
941 if (!EVEN(uv)) {
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100942 carry = uECC_vli_add(uv, uv, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300943 }
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100944 uECC_vli_rshift1(uv);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300945 if (carry) {
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +0100946 uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300947 }
948}
949
950void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400951 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300952{
953 uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
954 uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
955 cmpresult_t cmpResult;
956
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100957 if (uECC_vli_isZero(input)) {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100958 uECC_vli_clear(result);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300959 return;
960 }
961
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100962 uECC_vli_set(a, input);
963 uECC_vli_set(b, mod);
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100964 uECC_vli_clear(u);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300965 u[0] = 1;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100966 uECC_vli_clear(v);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100967 while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300968 if (EVEN(a)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100969 uECC_vli_rshift1(a);
Andrzej Kurek0919b142020-07-06 15:28:59 -0400970 vli_modInv_update(u, mod);
971 } else if (EVEN(b)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100972 uECC_vli_rshift1(b);
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +0100973 vli_modInv_update(v, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300974 } else if (cmpResult > 0) {
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100975 uECC_vli_sub(a, a, b);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100976 uECC_vli_rshift1(a);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100977 if (uECC_vli_cmp_unsafe(u, v) < 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -0400978 uECC_vli_add(u, u, mod);
979 }
980 uECC_vli_sub(u, u, v);
981 vli_modInv_update(u, mod);
982 } else {
983 uECC_vli_sub(b, b, a);
984 uECC_vli_rshift1(b);
985 if (uECC_vli_cmp_unsafe(v, u) < 0) {
986 uECC_vli_add(v, v, mod);
987 }
988 uECC_vli_sub(v, v, u);
989 vli_modInv_update(v, mod);
990 }
Jarno Lamsa18987a42019-04-24 15:40:43 +0300991 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100992 uECC_vli_set(result, u);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300993}
994
995/* ------ Point operations ------ */
996
997void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400998 uECC_word_t * Z1)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300999{
1000 /* t1 = X, t2 = Y, t3 = Z */
1001 uECC_word_t t4[NUM_ECC_WORDS];
1002 uECC_word_t t5[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001003 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001004
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001005 if (uECC_vli_isZero(Z1)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001006 return;
1007 }
1008
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001009 uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */
1010 uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */
1011 uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */
1012 uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */
1013 uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001014
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001015 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = x1 + z1^2 */
1016 uECC_vli_modAdd(Z1, Z1, Z1, curve_p); /* t3 = 2*z1^2 */
1017 uECC_vli_modSub(Z1, X1, Z1, curve_p); /* t3 = x1 - z1^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001018 uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001019
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001020 uECC_vli_modAdd(Z1, X1, X1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
1021 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001022 if (uECC_vli_testBit(X1, 0)) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001023 uECC_word_t l_carry = uECC_vli_add(X1, X1, curve_p);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001024 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001025 X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
1026 } else {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +01001027 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001028 }
1029
1030 /* t1 = 3/2*(x1^2 - z1^4) = B */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001031 uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001032 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - A */
1033 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
1034 uECC_vli_modSub(t5, t5, Z1, curve_p); /* t5 = A - x3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001035 uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001036 /* t4 = B * (A - x3) - y1^4 = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001037 uECC_vli_modSub(t4, X1, t4, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001038
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001039 uECC_vli_set(X1, Z1);
1040 uECC_vli_set(Z1, Y1);
1041 uECC_vli_set(Y1, t4);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001042}
1043
Manuel Pégourié-Gonnard1c6f7ea2019-11-21 09:18:29 +01001044/*
1045 * @brief Computes x^3 + ax + b. result must not overlap x.
1046 * @param result OUT -- x^3 + ax + b
1047 * @param x IN -- value of x
1048 * @param curve IN -- elliptic curve
1049 */
1050static void x_side_default(uECC_word_t *result,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001051 const uECC_word_t *x)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001052{
1053 uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001054
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001055 uECC_vli_modMult_fast(result, x, x); /* r = x^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001056 uECC_vli_modSub(result, result, _3, curve_p); /* r = x^2 - 3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001057 uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001058 /* r = x^3 - 3x + b: */
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +01001059 uECC_vli_modAdd(result, result, curve_b, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001060}
1061
1062void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
1063{
1064 unsigned int tmp[NUM_ECC_WORDS];
1065 int carry;
1066
1067 /* t */
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001068 uECC_vli_set(result, product);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001069
1070 /* s1 */
1071 tmp[0] = tmp[1] = tmp[2] = 0;
1072 tmp[3] = product[11];
1073 tmp[4] = product[12];
1074 tmp[5] = product[13];
1075 tmp[6] = product[14];
1076 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001077 carry = uECC_vli_add(tmp, tmp, tmp);
1078 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001079
1080 /* s2 */
1081 tmp[3] = product[12];
1082 tmp[4] = product[13];
1083 tmp[5] = product[14];
1084 tmp[6] = product[15];
1085 tmp[7] = 0;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001086 carry += uECC_vli_add(tmp, tmp, tmp);
1087 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001088
1089 /* s3 */
1090 tmp[0] = product[8];
1091 tmp[1] = product[9];
1092 tmp[2] = product[10];
1093 tmp[3] = tmp[4] = tmp[5] = 0;
1094 tmp[6] = product[14];
1095 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001096 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001097
1098 /* s4 */
1099 tmp[0] = product[9];
1100 tmp[1] = product[10];
1101 tmp[2] = product[11];
1102 tmp[3] = product[13];
1103 tmp[4] = product[14];
1104 tmp[5] = product[15];
1105 tmp[6] = product[13];
1106 tmp[7] = product[8];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001107 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001108
1109 /* d1 */
1110 tmp[0] = product[11];
1111 tmp[1] = product[12];
1112 tmp[2] = product[13];
1113 tmp[3] = tmp[4] = tmp[5] = 0;
1114 tmp[6] = product[8];
1115 tmp[7] = product[10];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001116 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001117
1118 /* d2 */
1119 tmp[0] = product[12];
1120 tmp[1] = product[13];
1121 tmp[2] = product[14];
1122 tmp[3] = product[15];
1123 tmp[4] = tmp[5] = 0;
1124 tmp[6] = product[9];
1125 tmp[7] = product[11];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001126 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001127
1128 /* d3 */
1129 tmp[0] = product[13];
1130 tmp[1] = product[14];
1131 tmp[2] = product[15];
1132 tmp[3] = product[8];
1133 tmp[4] = product[9];
1134 tmp[5] = product[10];
1135 tmp[6] = 0;
1136 tmp[7] = product[12];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001137 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001138
1139 /* d4 */
1140 tmp[0] = product[14];
1141 tmp[1] = product[15];
1142 tmp[2] = 0;
1143 tmp[3] = product[9];
1144 tmp[4] = product[10];
1145 tmp[5] = product[11];
1146 tmp[6] = 0;
1147 tmp[7] = product[13];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001148 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001149
1150 if (carry < 0) {
1151 do {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001152 carry += uECC_vli_add(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001153 }
1154 while (carry < 0);
1155 } else {
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +02001156 while (carry ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001157 uECC_vli_cmp_unsafe(curve_p, result) != 1) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001158 carry -= uECC_vli_sub(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001159 }
1160 }
1161}
1162
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001163uECC_word_t EccPoint_isZero(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001164{
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001165 return uECC_vli_isZero(point);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001166}
1167
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001168void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001169{
1170 uECC_word_t t1[NUM_ECC_WORDS];
1171
Andrzej Kurek0919b142020-07-06 15:28:59 -04001172 uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001173 uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */
1174 uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */
1175 uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001176}
1177
1178/* P = (x1, y1) => 2P, (x2, y2) => P' */
1179static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
1180 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001181 const uECC_word_t * const initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001182{
1183 uECC_word_t z[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001184 if (initial_Z) {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001185 uECC_vli_set(z, initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001186 } else {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001187 uECC_vli_clear(z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001188 z[0] = 1;
1189 }
1190
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001191 uECC_vli_set(X2, X1);
1192 uECC_vli_set(Y2, Y1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001193
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001194 apply_z(X1, Y1, z);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001195 double_jacobian_default(X1, Y1, z);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001196 apply_z(X2, Y2, z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001197}
1198
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001199static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1200 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001201 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001202{
1203 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1204 uECC_word_t t5[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001205
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001206 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001207 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001208 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1209 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001210 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001211 uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001212
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001213 uECC_vli_modSub(t5, t5, X1, curve_p); /* t5 = D - B */
1214 uECC_vli_modSub(t5, t5, X2, curve_p); /* t5 = D - B - C = x3 */
1215 uECC_vli_modSub(X2, X2, X1, curve_p); /* t3 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001216 uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001217 uECC_vli_modSub(X2, X1, t5, curve_p); /* t3 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001218 uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001219 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001220
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001221 uECC_vli_set(X2, t5);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001222}
1223
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001224void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001225 uECC_word_t * X2, uECC_word_t * Y2)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001226{
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001227 XYcZ_add_rnd(X1, Y1, X2, Y2, NULL);
1228}
1229
Jarno Lamsa18987a42019-04-24 15:40:43 +03001230/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
1231 Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
1232 or P => P - Q, Q => P + Q
1233 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001234static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1235 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001236 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001237{
1238 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1239 uECC_word_t t5[NUM_ECC_WORDS];
1240 uECC_word_t t6[NUM_ECC_WORDS];
1241 uECC_word_t t7[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001242
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001243 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001244 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001245 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1246 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001247 uECC_vli_modAdd(t5, Y2, Y1, curve_p); /* t5 = y2 + y1 */
1248 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001249
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001250 uECC_vli_modSub(t6, X2, X1, curve_p); /* t6 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001251 uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001252 uECC_vli_modAdd(t6, X1, X2, curve_p); /* t6 = B + C */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001253 uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001254 uECC_vli_modSub(X2, X2, t6, curve_p); /* t3 = D - (B + C) = x3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001255
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001256 uECC_vli_modSub(t7, X1, X2, curve_p); /* t7 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001257 uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001258 /* t4 = (y2 - y1)*(B - x3) - E = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001259 uECC_vli_modSub(Y2, Y2, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001260
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001261 uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001262 uECC_vli_modSub(t7, t7, t6, curve_p); /* t7 = F - (B + C) = x3' */
1263 uECC_vli_modSub(t6, t7, X1, curve_p); /* t6 = x3' - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001264 uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001265 /* t2 = (y2+y1)*(x3' - B) - E = y3': */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001266 uECC_vli_modSub(Y1, t6, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001267
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001268 uECC_vli_set(X1, t7);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001269}
1270
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001271static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
Jarno Lamsa18987a42019-04-24 15:40:43 +03001272 const uECC_word_t * scalar,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001273 const uECC_word_t * initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001274{
1275 /* R0 and R1 */
1276 uECC_word_t Rx[2][NUM_ECC_WORDS];
1277 uECC_word_t Ry[2][NUM_ECC_WORDS];
1278 uECC_word_t z[NUM_ECC_WORDS];
1279 bitcount_t i;
1280 uECC_word_t nb;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001281 const wordcount_t num_words = NUM_ECC_WORDS;
1282 const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001283 ecc_wait_state_t wait_state;
1284 ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001285
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001286 uECC_vli_set(Rx[1], point);
1287 uECC_vli_set(Ry[1], point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001288
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001289 XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001290
1291 for (i = num_bits - 2; i > 0; --i) {
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001292 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001293 nb = !uECC_vli_testBit(scalar, i);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001294 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
1295 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001296 }
1297
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001298 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001299 nb = !uECC_vli_testBit(scalar, 0);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001300 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001301
1302 /* Find final 1/Z value. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001303 uECC_vli_modSub(z, Rx[1], Rx[0], curve_p); /* X1 - X0 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001304 uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */
1305 uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001306 uECC_vli_modInv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0))*/
Jarno Lamsa18987a42019-04-24 15:40:43 +03001307 /* yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001308 uECC_vli_modMult_fast(z, z, point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001309 /* Xb * yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001310 uECC_vli_modMult_fast(z, z, Rx[1 - nb]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001311 /* End 1/Z calculation */
1312
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001313 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001314 apply_z(Rx[0], Ry[0], z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001315
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001316 uECC_vli_set(result, Rx[0]);
1317 uECC_vli_set(result + num_words, Ry[0]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001318}
1319
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001320static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001321 uECC_word_t *k1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001322{
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001323 bitcount_t num_n_bits = NUM_ECC_BITS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001324
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001325 uECC_word_t carry = uECC_vli_add(k0, k, curve_n) ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001326 uECC_vli_testBit(k0, num_n_bits);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001327
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001328 uECC_vli_add(k1, k0, curve_n);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001329
1330 return carry;
1331}
1332
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001333int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001334 const uECC_word_t * scalar)
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001335{
1336 uECC_word_t tmp[NUM_ECC_WORDS];
1337 uECC_word_t s[NUM_ECC_WORDS];
1338 uECC_word_t *k2[2] = {tmp, s};
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001339 wordcount_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001340 uECC_word_t carry;
1341 uECC_word_t *initial_Z = 0;
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001342 int r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001343 volatile int problem;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001344
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001345 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001346 problem = -1;
1347 problem = uECC_check_curve_integrity();
1348 if (problem != 0) {
1349 return UECC_FAULT_DETECTED;
1350 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001351 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001352 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001353 return UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001354 }
1355
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001356 /* Protects against invalid curve attacks */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001357 problem = -1;
1358 problem = uECC_valid_point(point);
1359 if (problem != 0) {
1360 /* invalid input, can happen without fault */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001361 return UECC_FAILURE;
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001362 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001363 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001364 if (problem != 0) {
1365 /* failure on second check means fault, though */
1366 return UECC_FAULT_DETECTED;
1367 }
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001368
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001369 /* Regularize the bitcount for the private key so that attackers cannot use a
1370 * side channel attack to learn the number of leading zeros. */
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001371 carry = regularize_k(scalar, tmp, s);
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001372
1373 /* If an RNG function was specified, get a random initial Z value to
Andrzej Kurek0919b142020-07-06 15:28:59 -04001374 * protect against side-channel attacks such as Template SPA */
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001375 if (g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001376 if (uECC_generate_random_int(k2[carry], curve_p, num_words) != UECC_SUCCESS) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001377 r = UECC_FAILURE;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001378 goto clear_and_out;
1379 }
1380 initial_Z = k2[carry];
1381 }
1382
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001383 EccPoint_mult(result, point, k2[!carry], initial_Z);
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001384
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001385 /* Protect against fault injections that would make the resulting
1386 * point not lie on the intended curve */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001387 problem = -1;
1388 problem = uECC_valid_point(result);
1389 if (problem != 0) {
1390 r = UECC_FAULT_DETECTED;
1391 goto clear_and_out;
1392 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001393 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001394 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001395 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001396 goto clear_and_out;
1397 }
1398
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001399 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001400 problem = -1;
1401 problem = uECC_check_curve_integrity();
1402 if (problem != 0) {
1403 r = UECC_FAULT_DETECTED;
1404 goto clear_and_out;
1405 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001406 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001407 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001408 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001409 goto clear_and_out;
1410 }
1411
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001412 r = UECC_SUCCESS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001413
1414clear_and_out:
1415 /* erasing temporary buffer used to store secret: */
1416 mbedtls_platform_zeroize(k2, sizeof(k2));
1417 mbedtls_platform_zeroize(tmp, sizeof(tmp));
1418 mbedtls_platform_zeroize(s, sizeof(s));
1419
1420 return r;
1421}
1422
Jarno Lamsa18987a42019-04-24 15:40:43 +03001423uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001424 uECC_word_t *private_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001425{
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001426 return EccPoint_mult_safer(result, curve_G, private_key);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001427}
1428
1429/* Converts an integer in uECC native format to big-endian bytes. */
1430void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001431 const unsigned int *native)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001432{
1433 wordcount_t i;
1434 for (i = 0; i < num_bytes; ++i) {
1435 unsigned b = num_bytes - 1 - i;
1436 bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
1437 }
1438}
1439
1440/* Converts big-endian bytes to an integer in uECC native format. */
1441void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001442 int num_bytes)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001443{
1444 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001445 uECC_vli_clear(native);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001446 for (i = 0; i < num_bytes; ++i) {
1447 unsigned b = num_bytes - 1 - i;
1448 native[b / uECC_WORD_SIZE] |=
1449 (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
1450 }
1451}
1452
1453int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001454 wordcount_t num_words)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001455{
1456 uECC_word_t mask = (uECC_word_t)-1;
1457 uECC_word_t tries;
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001458 bitcount_t num_bits = uECC_vli_numBits(top);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001459
1460 if (!g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001461 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001462 }
1463
1464 for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
Andrzej Kurek090365f2020-06-08 11:00:51 -04001465 if (g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE) != num_words * uECC_WORD_SIZE) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001466 return UECC_FAILURE;
1467 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001468 random[num_words - 1] &=
Andrzej Kurek0919b142020-07-06 15:28:59 -04001469 mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001470 if (!uECC_vli_isZero(random) &&
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +01001471 uECC_vli_cmp(top, random) == 1) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001472 return UECC_SUCCESS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001473 }
1474 }
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001475 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001476}
1477
1478
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001479int uECC_valid_point(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001480{
1481 uECC_word_t tmp1[NUM_ECC_WORDS];
1482 uECC_word_t tmp2[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001483 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa83d78812019-12-04 14:40:57 +02001484 volatile uECC_word_t diff = 0xffffffff;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001485
1486 /* The point at infinity is invalid. */
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001487 if (EccPoint_isZero(point)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001488 return -1;
1489 }
1490
1491 /* x and y must be smaller than p. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001492 if (uECC_vli_cmp_unsafe(curve_p, point) != 1 ||
1493 uECC_vli_cmp_unsafe(curve_p, point + num_words) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001494 return -2;
1495 }
1496
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001497 uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001498 x_side_default(tmp2, point); /* tmp2 = x^3 + ax + b */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001499
1500 /* Make sure that y^2 == x^3 + ax + b */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001501 diff = uECC_vli_equal(tmp1, tmp2);
1502 if (diff == 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001503 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001504 if (diff == 0) {
1505 return 0;
1506 }
1507 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001508
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001509 return -3;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001510}
1511
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001512int uECC_valid_public_key(const uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001513{
1514
1515 uECC_word_t _public[NUM_ECC_WORDS * 2];
1516
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001517 uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001518 uECC_vli_bytesToNative(
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001519 _public + NUM_ECC_WORDS,
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001520 public_key + NUM_ECC_BYTES,
1521 NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001522
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +01001523 if (memcmp(_public, curve_G, NUM_ECC_WORDS * 2) == 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001524 return -4;
1525 }
1526
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001527 return uECC_valid_point(_public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001528}
1529
Andrzej Kurek0919b142020-07-06 15:28:59 -04001530int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001531{
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001532 int ret = UECC_FAULT_DETECTED;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001533 uECC_word_t _private[NUM_ECC_WORDS];
1534 uECC_word_t _public[NUM_ECC_WORDS * 2];
1535
1536 uECC_vli_bytesToNative(
1537 _private,
1538 private_key,
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +01001539 BITS_TO_BYTES(NUM_ECC_BITS));
Jarno Lamsa18987a42019-04-24 15:40:43 +03001540
1541 /* Make sure the private key is in the range [1, n-1]. */
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001542 if (uECC_vli_isZero(_private)) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001543 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001544 }
1545
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001546 if (uECC_vli_cmp(curve_n, _private) != 1) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001547 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001548 }
1549
1550 /* Compute public key. */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001551 ret = EccPoint_compute_public_key(_public, _private);
1552 if (ret != UECC_SUCCESS) {
1553 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001554 }
1555
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001556 uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001557 uECC_vli_nativeToBytes(
1558 public_key +
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001559 NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS);
Andrzej Kurekcf3e35c2020-07-15 22:32:08 -04001560
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001561 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001562}