blob: 26577848d5ab1b10ccb57942df714129aabe0286 [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}
528#else
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100529static void uECC_vli_rshift1(uECC_word_t *vli)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300530{
531 uECC_word_t *end = vli;
532 uECC_word_t carry = 0;
533
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100534 vli += NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300535 while (vli-- > end) {
536 uECC_word_t temp = *vli;
537 *vli = (temp >> 1) | carry;
538 carry = temp << (uECC_WORD_BITS - 1);
539 }
540}
Kevin Bracey1959c182020-07-16 21:03:19 +0300541#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300542
Kevin Bracey84f31d32020-09-29 17:51:04 +0300543/* Compute a * b + r, where r is a triple-word with high-order word r[2] and
544 * low-order word r[0], and store the result in the same triple-word.
Manuel Pégourié-Gonnard86c4f812019-10-31 13:02:03 +0100545 *
Kevin Bracey84f31d32020-09-29 17:51:04 +0300546 * r[2..0] = a * b + r[2..0]:
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200547 * [in] a, b: operands to be multiplied
Kevin Bracey84f31d32020-09-29 17:51:04 +0300548 * [in] r: 3 words of operand to add
549 * [out] r: 3 words of result
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200550 */
Kevin Bracey1959c182020-07-16 21:03:19 +0300551#if defined MBEDTLS_HAVE_ASM && defined __CC_ARM
Kevin Bracey84f31d32020-09-29 17:51:04 +0300552static __asm void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Kevin Bracey1959c182020-07-16 21:03:19 +0300553{
554#if defined __thumb__ && __TARGET_ARCH_THUMB < 4
Kevin Bracey84f31d32020-09-29 17:51:04 +0300555 PUSH {r4-r5}
556 FRAME PUSH {r4-r5}
557 // __ARM_common_mul_uu replacement - inline, faster, don't touch R2
558 // Separate operands into halfwords
559 UXTH r3,r0 // r3 := a.lo
560 LSRS r4,r0,#16 // r4 := a.hi
561 UXTH r5,r1 // r5 := b.lo
562 LSRS r1,r1,#16 // r1 := b.hi
563 // Multiply halfword pairs
564 MOVS r0,r3
565 MULS r0,r5,r0 // r0 := a.lo * b.lo
566 MULS r3,r1,r3 // r3 := a.lo * b.hi
567 MULS r5,r4,r5 // r5 := a.hi * b.lo
568 MULS r1,r4,r1 // r1 := a.hi * b.hi
569 // Split, shift and add a.lo * b.hi
570 LSRS r4,r3,#16 // r4 := (a.lo * b.hi).hi
571 LSLS r3,r3,#16 // r3 := (a.lo * b.hi).lo
572 ADDS r0,r0,r3 // r0 := a.lo * b.lo + (a.lo * b.hi).lo
573 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry
574 // Split, shift and add a.hi * b.lo
575 LSRS r4,r5,#16 // r4 := (a.hi * b.lo).hi
576 LSLS r5,r5,#16 // r5 := (a.hi * b.lo).lo
577 ADDS r0,r0,r5 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo
578 ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries
579 // Finally add r[]
580 LDMIA r2!,{r3,r4,r5}
581 ADDS r3,r3,r0
Kevin Bracey1959c182020-07-16 21:03:19 +0300582 ADCS r4,r1
Kevin Bracey1959c182020-07-16 21:03:19 +0300583 MOVS r0,#0
Kevin Bracey84f31d32020-09-29 17:51:04 +0300584 ADCS r5,r0
585 SUBS r2,#12
586 STMIA r2!,{r3,r4,r5}
587 POP {r4-r5}
588 FRAME POP {r4-r5}
589 BX lr
Kevin Bracey1959c182020-07-16 21:03:19 +0300590#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300591 UMULL r3,ip,r0,r1 // pre-ARMv6 requires Rd[Lo|Hi] != Rn
592 LDMIA r2,{r0,r1}
593 ADDS r0,r0,r3
594 LDR r3,[r2,#8]
595 ADCS r1,r1,ip
596 ADC r3,r3,#0
597 STMIA r2!,{r0,r1,r3}
Kevin Bracey1959c182020-07-16 21:03:19 +0300598 BX lr
599#endif
600
601}
602#else
Kevin Bracey84f31d32020-09-29 17:51:04 +0300603static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3])
Jarno Lamsa18987a42019-04-24 15:40:43 +0300604{
605
606 uECC_dword_t p = (uECC_dword_t)a * b;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300607 uECC_dword_t r01 = ((uECC_dword_t)(r[1]) << uECC_WORD_BITS) | r[0];
Jarno Lamsa18987a42019-04-24 15:40:43 +0300608 r01 += p;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300609 r[2] += (r01 < p);
610 r[1] = r01 >> uECC_WORD_BITS;
611 r[0] = (uECC_word_t)r01;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300612}
Kevin Bracey1959c182020-07-16 21:03:19 +0300613#endif
Jarno Lamsa18987a42019-04-24 15:40:43 +0300614
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200615/* State for implementing random delays in uECC_vli_mult_rnd().
616 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100617 * The state is initialized by randomizing delays and setting i = 0.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200618 * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i.
619 *
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100620 * Randomized vli multiplication is used only for point operations
621 * (XYcZ_add_rnd() * and XYcZ_addC_rnd()) in scalar multiplication
622 * (ECCPoint_mult()). Those go in pair, and each pair does 14 calls to
623 * uECC_vli_mult_rnd() (6 in XYcZ_add_rnd() and 8 in XYcZ_addC_rnd(),
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100624 * indirectly through uECC_vli_modMult_rnd().
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100625 *
626 * Considering this, in order to minimize the number of calls to the RNG
627 * (which impact performance) while keeping the size of the structure low,
628 * make room for 14 randomized vli mults, which corresponds to one step in the
629 * scalar multiplication routine.
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200630 */
631typedef struct {
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100632 uint8_t i;
633 uint8_t delays[14];
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100634} ecc_wait_state_t;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200635
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100636/*
637 * Reset wait_state so that it's ready to be used.
638 */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100639void ecc_wait_state_reset(ecc_wait_state_t *ws)
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100640{
641 if (ws == NULL)
642 return;
643
644 ws->i = 0;
Shelly Liberman05beb9a2020-09-13 15:23:56 +0300645 mbedtls_platform_random_buf(ws->delays, sizeof(ws->delays));
Manuel Pégourié-Gonnardd4671162019-10-31 11:26:26 +0100646}
647
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200648/* Computes result = left * right. Result must be 2 * num_words long.
649 *
650 * As a counter-measure against horizontal attacks, add noise by performing
651 * a random number of extra computations performing random additional accesses
652 * to limbs of the input.
653 *
654 * Each of the two actual computation loops is surrounded by two
655 * similar-looking waiting loops, to make the beginning and end of the actual
656 * computation harder to spot.
657 *
658 * We add 4 waiting loops of between 0 and 3 calls to muladd() each. That
659 * makes an average of 6 extra calls. Compared to the main computation which
660 * makes 64 such calls, this represents an average performance degradation of
661 * less than 10%.
662 *
663 * Compared to the original uECC_vli_mult(), loose the num_words argument as we
664 * know it's always 8. This saves a bit of code size and execution speed.
665 */
666static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400667 const uECC_word_t *right, ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300668{
669
Kevin Bracey84f31d32020-09-29 17:51:04 +0300670 uECC_word_t r[3] = { 0, 0, 0 };
Jarno Lamsa18987a42019-04-24 15:40:43 +0300671 wordcount_t i, k;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +0100672 const uint8_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200673
674 /* Fetch 8 bit worth of delay from the state; 0 if we have no state */
675 uint8_t delays = s ? s->delays[s->i++] : 0;
Kevin Bracey84f31d32020-09-29 17:51:04 +0300676 uECC_word_t rr[3] = { 0, 0, 0 };
677 volatile uECC_word_t rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200678
679 /* Mimic start of next loop: k in [0, 3] */
680 k = 0 + (delays & 0x03);
681 delays >>= 2;
682 /* k = 0 -> i in [1, 0] -> 0 extra muladd;
683 * k = 3 -> i in [1, 3] -> 3 extra muladd */
Manuel Pégourié-Gonnardc8814862019-11-05 10:32:37 +0100684 for (i = 1; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300685 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200686 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300687 rdummy = rr[0];
688 rr[0] = rr[1];
689 rr[1] = rr[2];
690 rr[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300691
692 /* Compute each digit of result in sequence, maintaining the carries. */
693 for (k = 0; k < num_words; ++k) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300694 for (i = 0; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300695 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300696 }
697
Kevin Bracey84f31d32020-09-29 17:51:04 +0300698 result[k] = r[0];
699 r[0] = r[1];
700 r[1] = r[2];
701 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300702 }
703
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200704 /* Mimic end of previous loop: k in [4, 7] */
705 k = 4 + (delays & 0x03);
706 delays >>= 2;
707 /* k = 4 -> i in [5, 4] -> 0 extra muladd;
708 * k = 7 -> i in [5, 7] -> 3 extra muladd */
709 for (i = 5; i <= k; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300710 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200711 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300712 rdummy = rr[0];
713 rr[0] = rr[1];
714 rr[1] = rr[2];
715 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200716
717 /* Mimic start of next loop: k in [8, 11] */
718 k = 11 - (delays & 0x03);
719 delays >>= 2;
720 /* k = 8 -> i in [5, 7] -> 3 extra muladd;
721 * k = 11 -> i in [8, 7] -> 0 extra muladd */
722 for (i = (k + 5) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300723 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200724 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300725 rdummy = rr[0];
726 rr[0] = rr[1];
727 rr[1] = rr[2];
728 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200729
Jarno Lamsa18987a42019-04-24 15:40:43 +0300730 for (k = num_words; k < num_words * 2 - 1; ++k) {
731
732 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300733 muladd(left[i], right[k - i], r);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300734 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300735 result[k] = r[0];
736 r[0] = r[1];
737 r[1] = r[2];
738 r[2] = 0;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300739 }
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200740
Kevin Bracey84f31d32020-09-29 17:51:04 +0300741 result[num_words * 2 - 1] = r[0];
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200742
743 /* Mimic end of previous loop: k in [12, 15] */
744 k = 15 - (delays & 0x03);
745 delays >>= 2;
746 /* k = 12 -> i in [5, 7] -> 3 extra muladd;
747 * k = 15 -> i in [8, 7] -> 0 extra muladd */
748 for (i = (k + 1) - num_words; i < num_words; ++i) {
Kevin Bracey84f31d32020-09-29 17:51:04 +0300749 muladd(left[i], right[k - i], rr);
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200750 }
Kevin Bracey84f31d32020-09-29 17:51:04 +0300751 rdummy = rr[0];
752 rr[0] = rr[1];
753 rr[1] = rr[2];
754 rr[2] = 0;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200755
Kevin Bracey84f31d32020-09-29 17:51:04 +0300756 /* avoid warning that rdummy is set but not used */
757 (void) rdummy;
Manuel Pégourié-Gonnard14ab9c22019-10-22 09:49:53 +0200758}
759
Jarno Lamsa18987a42019-04-24 15:40:43 +0300760void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400761 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300762{
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100763 uECC_word_t carry = uECC_vli_add(result, left, right);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100764 if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300765 /* result > mod (result = mod + remainder), so subtract mod to get
766 * remainder. */
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100767 uECC_vli_sub(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300768 }
769}
770
771void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400772 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300773{
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100774 uECC_word_t l_borrow = uECC_vli_sub(result, left, right);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300775 if (l_borrow) {
776 /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
777 * we can get the correct result from result + mod (with overflow). */
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100778 uECC_vli_add(result, result, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300779 }
780}
781
782/* Computes result = product % mod, where product is 2N words long. */
783/* Currently only designed to work for curve_p or curve_n. */
784void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400785 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300786{
787 uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
788 uECC_word_t tmp[2 * NUM_ECC_WORDS];
789 uECC_word_t *v[2] = {tmp, product};
790 uECC_word_t index;
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +0100791 const wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300792
793 /* Shift mod so its highest set bit is at the maximum position. */
794 bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +0100795 uECC_vli_numBits(mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300796 wordcount_t word_shift = shift / uECC_WORD_BITS;
797 wordcount_t bit_shift = shift % uECC_WORD_BITS;
798 uECC_word_t carry = 0;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100799 uECC_vli_clear(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300800 if (bit_shift > 0) {
801 for(index = 0; index < (uECC_word_t)num_words; ++index) {
802 mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
803 carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
804 }
805 } else {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100806 uECC_vli_set(mod_multiple + word_shift, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300807 }
808
809 for (index = 1; shift >= 0; --shift) {
810 uECC_word_t borrow = 0;
811 wordcount_t i;
812 for (i = 0; i < num_words * 2; ++i) {
813 uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
814 if (diff != v[index][i]) {
815 borrow = (diff > v[index][i]);
816 }
817 v[1 - index][i] = diff;
818 }
819 /* Swap the index if there was no borrow */
820 index = !(index ^ borrow);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100821 uECC_vli_rshift1(mod_multiple);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300822 mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
Andrzej Kurek0919b142020-07-06 15:28:59 -0400823 (uECC_WORD_BITS - 1);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100824 uECC_vli_rshift1(mod_multiple + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300825 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100826 uECC_vli_set(result, v[index]);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300827}
828
829void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400830 const uECC_word_t *right, const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300831{
832 uECC_word_t product[2 * NUM_ECC_WORDS];
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +0100833 uECC_vli_mult_rnd(product, left, right, NULL);
Manuel Pégourié-Gonnard10349e42019-11-04 14:57:53 +0100834 uECC_vli_mmod(result, product, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300835}
836
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100837static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +0100838 const uECC_word_t *right, ecc_wait_state_t *s)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +0100839{
840 uECC_word_t product[2 * NUM_ECC_WORDS];
841 uECC_vli_mult_rnd(product, left, right, s);
842
843 vli_mmod_fast_secp256r1(result, product);
844}
845
Jarno Lamsa18987a42019-04-24 15:40:43 +0300846void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100847 const uECC_word_t *right)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300848{
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100849 uECC_vli_modMult_rnd(result, left, right, NULL);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300850}
851
Jarno Lamsa18987a42019-04-24 15:40:43 +0300852#define EVEN(vli) (!(vli[0] & 1))
853
854static void vli_modInv_update(uECC_word_t *uv,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400855 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300856{
857
858 uECC_word_t carry = 0;
859
860 if (!EVEN(uv)) {
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100861 carry = uECC_vli_add(uv, uv, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300862 }
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100863 uECC_vli_rshift1(uv);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300864 if (carry) {
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +0100865 uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300866 }
867}
868
869void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400870 const uECC_word_t *mod)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300871{
872 uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
873 uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
874 cmpresult_t cmpResult;
875
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100876 if (uECC_vli_isZero(input)) {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100877 uECC_vli_clear(result);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300878 return;
879 }
880
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100881 uECC_vli_set(a, input);
882 uECC_vli_set(b, mod);
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100883 uECC_vli_clear(u);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300884 u[0] = 1;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +0100885 uECC_vli_clear(v);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100886 while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300887 if (EVEN(a)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100888 uECC_vli_rshift1(a);
Andrzej Kurek0919b142020-07-06 15:28:59 -0400889 vli_modInv_update(u, mod);
890 } else if (EVEN(b)) {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100891 uECC_vli_rshift1(b);
Manuel Pégourié-Gonnard91353482019-11-04 15:04:20 +0100892 vli_modInv_update(v, mod);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300893 } else if (cmpResult > 0) {
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +0100894 uECC_vli_sub(a, a, b);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100895 uECC_vli_rshift1(a);
Manuel Pégourié-Gonnarda7521912019-11-04 14:31:35 +0100896 if (uECC_vli_cmp_unsafe(u, v) < 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -0400897 uECC_vli_add(u, u, mod);
898 }
899 uECC_vli_sub(u, u, v);
900 vli_modInv_update(u, mod);
901 } else {
902 uECC_vli_sub(b, b, a);
903 uECC_vli_rshift1(b);
904 if (uECC_vli_cmp_unsafe(v, u) < 0) {
905 uECC_vli_add(v, v, mod);
906 }
907 uECC_vli_sub(v, v, u);
908 vli_modInv_update(v, mod);
909 }
Jarno Lamsa18987a42019-04-24 15:40:43 +0300910 }
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100911 uECC_vli_set(result, u);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300912}
913
914/* ------ Point operations ------ */
915
916void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400917 uECC_word_t * Z1)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300918{
919 /* t1 = X, t2 = Y, t3 = Z */
920 uECC_word_t t4[NUM_ECC_WORDS];
921 uECC_word_t t5[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +0100922 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa18987a42019-04-24 15:40:43 +0300923
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +0100924 if (uECC_vli_isZero(Z1)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +0300925 return;
926 }
927
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100928 uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */
929 uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */
930 uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */
931 uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */
932 uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300933
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100934 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = x1 + z1^2 */
935 uECC_vli_modAdd(Z1, Z1, Z1, curve_p); /* t3 = 2*z1^2 */
936 uECC_vli_modSub(Z1, X1, Z1, curve_p); /* t3 = x1 - z1^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100937 uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300938
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100939 uECC_vli_modAdd(Z1, X1, X1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
940 uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300941 if (uECC_vli_testBit(X1, 0)) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100942 uECC_word_t l_carry = uECC_vli_add(X1, X1, curve_p);
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100943 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300944 X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
945 } else {
Manuel Pégourié-Gonnard5e3baf22019-11-04 14:46:10 +0100946 uECC_vli_rshift1(X1);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300947 }
948
949 /* t1 = 3/2*(x1^2 - z1^4) = B */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100950 uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100951 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - A */
952 uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
953 uECC_vli_modSub(t5, t5, Z1, curve_p); /* t5 = A - x3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100954 uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300955 /* t4 = B * (A - x3) - y1^4 = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100956 uECC_vli_modSub(t4, X1, t4, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300957
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100958 uECC_vli_set(X1, Z1);
959 uECC_vli_set(Z1, Y1);
960 uECC_vli_set(Y1, t4);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300961}
962
Manuel Pégourié-Gonnard1c6f7ea2019-11-21 09:18:29 +0100963/*
964 * @brief Computes x^3 + ax + b. result must not overlap x.
965 * @param result OUT -- x^3 + ax + b
966 * @param x IN -- value of x
967 * @param curve IN -- elliptic curve
968 */
969static void x_side_default(uECC_word_t *result,
Andrzej Kurek0919b142020-07-06 15:28:59 -0400970 const uECC_word_t *x)
Jarno Lamsa18987a42019-04-24 15:40:43 +0300971{
972 uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300973
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100974 uECC_vli_modMult_fast(result, x, x); /* r = x^2 */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +0100975 uECC_vli_modSub(result, result, _3, curve_p); /* r = x^2 - 3 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +0100976 uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */
Jarno Lamsa18987a42019-04-24 15:40:43 +0300977 /* r = x^3 - 3x + b: */
Manuel Pégourié-Gonnardffd13992019-11-21 10:39:06 +0100978 uECC_vli_modAdd(result, result, curve_b, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300979}
980
981void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
982{
983 unsigned int tmp[NUM_ECC_WORDS];
984 int carry;
985
986 /* t */
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +0100987 uECC_vli_set(result, product);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300988
989 /* s1 */
990 tmp[0] = tmp[1] = tmp[2] = 0;
991 tmp[3] = product[11];
992 tmp[4] = product[12];
993 tmp[5] = product[13];
994 tmp[6] = product[14];
995 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +0100996 carry = uECC_vli_add(tmp, tmp, tmp);
997 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +0300998
999 /* s2 */
1000 tmp[3] = product[12];
1001 tmp[4] = product[13];
1002 tmp[5] = product[14];
1003 tmp[6] = product[15];
1004 tmp[7] = 0;
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001005 carry += uECC_vli_add(tmp, tmp, tmp);
1006 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001007
1008 /* s3 */
1009 tmp[0] = product[8];
1010 tmp[1] = product[9];
1011 tmp[2] = product[10];
1012 tmp[3] = tmp[4] = tmp[5] = 0;
1013 tmp[6] = product[14];
1014 tmp[7] = product[15];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001015 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001016
1017 /* s4 */
1018 tmp[0] = product[9];
1019 tmp[1] = product[10];
1020 tmp[2] = product[11];
1021 tmp[3] = product[13];
1022 tmp[4] = product[14];
1023 tmp[5] = product[15];
1024 tmp[6] = product[13];
1025 tmp[7] = product[8];
Manuel Pégourié-Gonnard02d9d212019-11-04 12:37:08 +01001026 carry += uECC_vli_add(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001027
1028 /* d1 */
1029 tmp[0] = product[11];
1030 tmp[1] = product[12];
1031 tmp[2] = product[13];
1032 tmp[3] = tmp[4] = tmp[5] = 0;
1033 tmp[6] = product[8];
1034 tmp[7] = product[10];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001035 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001036
1037 /* d2 */
1038 tmp[0] = product[12];
1039 tmp[1] = product[13];
1040 tmp[2] = product[14];
1041 tmp[3] = product[15];
1042 tmp[4] = tmp[5] = 0;
1043 tmp[6] = product[9];
1044 tmp[7] = product[11];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001045 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001046
1047 /* d3 */
1048 tmp[0] = product[13];
1049 tmp[1] = product[14];
1050 tmp[2] = product[15];
1051 tmp[3] = product[8];
1052 tmp[4] = product[9];
1053 tmp[5] = product[10];
1054 tmp[6] = 0;
1055 tmp[7] = product[12];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001056 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001057
1058 /* d4 */
1059 tmp[0] = product[14];
1060 tmp[1] = product[15];
1061 tmp[2] = 0;
1062 tmp[3] = product[9];
1063 tmp[4] = product[10];
1064 tmp[5] = product[11];
1065 tmp[6] = 0;
1066 tmp[7] = product[13];
Manuel Pégourié-Gonnard129b42e2019-11-04 14:41:45 +01001067 carry -= uECC_vli_sub(result, result, tmp);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001068
1069 if (carry < 0) {
1070 do {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001071 carry += uECC_vli_add(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001072 }
1073 while (carry < 0);
1074 } else {
Piotr Nowicki1a9d33e2020-05-20 22:10:14 +02001075 while (carry ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001076 uECC_vli_cmp_unsafe(curve_p, result) != 1) {
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001077 carry -= uECC_vli_sub(result, result, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001078 }
1079 }
1080}
1081
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001082uECC_word_t EccPoint_isZero(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001083{
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001084 return uECC_vli_isZero(point);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001085}
1086
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001087void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001088{
1089 uECC_word_t t1[NUM_ECC_WORDS];
1090
Andrzej Kurek0919b142020-07-06 15:28:59 -04001091 uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001092 uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */
1093 uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */
1094 uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001095}
1096
1097/* P = (x1, y1) => 2P, (x2, y2) => P' */
1098static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
1099 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001100 const uECC_word_t * const initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001101{
1102 uECC_word_t z[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001103 if (initial_Z) {
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001104 uECC_vli_set(z, initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001105 } else {
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001106 uECC_vli_clear(z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001107 z[0] = 1;
1108 }
1109
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001110 uECC_vli_set(X2, X1);
1111 uECC_vli_set(Y2, Y1);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001112
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001113 apply_z(X1, Y1, z);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001114 double_jacobian_default(X1, Y1, z);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001115 apply_z(X2, Y2, z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001116}
1117
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001118static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1119 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001120 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001121{
1122 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1123 uECC_word_t t5[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001124
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001125 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001126 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001127 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1128 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001129 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001130 uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001131
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001132 uECC_vli_modSub(t5, t5, X1, curve_p); /* t5 = D - B */
1133 uECC_vli_modSub(t5, t5, X2, curve_p); /* t5 = D - B - C = x3 */
1134 uECC_vli_modSub(X2, X2, X1, curve_p); /* t3 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001135 uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001136 uECC_vli_modSub(X2, X1, t5, curve_p); /* t3 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001137 uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001138 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001139
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001140 uECC_vli_set(X2, t5);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001141}
1142
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001143void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001144 uECC_word_t * X2, uECC_word_t * Y2)
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001145{
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001146 XYcZ_add_rnd(X1, Y1, X2, Y2, NULL);
1147}
1148
Jarno Lamsa18987a42019-04-24 15:40:43 +03001149/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
1150 Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
1151 or P => P - Q, Q => P + Q
1152 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001153static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1,
1154 uECC_word_t * X2, uECC_word_t * Y2,
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001155 ecc_wait_state_t *s)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001156{
1157 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
1158 uECC_word_t t5[NUM_ECC_WORDS];
1159 uECC_word_t t6[NUM_ECC_WORDS];
1160 uECC_word_t t7[NUM_ECC_WORDS];
Jarno Lamsa18987a42019-04-24 15:40:43 +03001161
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001162 uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001163 uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001164 uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */
1165 uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001166 uECC_vli_modAdd(t5, Y2, Y1, curve_p); /* t5 = y2 + y1 */
1167 uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001168
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001169 uECC_vli_modSub(t6, X2, X1, curve_p); /* t6 = C - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001170 uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001171 uECC_vli_modAdd(t6, X1, X2, curve_p); /* t6 = B + C */
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001172 uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001173 uECC_vli_modSub(X2, X2, t6, curve_p); /* t3 = D - (B + C) = x3 */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001174
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001175 uECC_vli_modSub(t7, X1, X2, curve_p); /* t7 = B - x3 */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001176 uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001177 /* t4 = (y2 - y1)*(B - x3) - E = y3: */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001178 uECC_vli_modSub(Y2, Y2, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001179
Manuel Pégourié-Gonnardc78d86b2019-11-04 10:18:42 +01001180 uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001181 uECC_vli_modSub(t7, t7, t6, curve_p); /* t7 = F - (B + C) = x3' */
1182 uECC_vli_modSub(t6, t7, X1, curve_p); /* t6 = x3' - B */
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001183 uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001184 /* t2 = (y2+y1)*(x3' - B) - E = y3': */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001185 uECC_vli_modSub(Y1, t6, Y1, curve_p);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001186
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001187 uECC_vli_set(X1, t7);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001188}
1189
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001190static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
Jarno Lamsa18987a42019-04-24 15:40:43 +03001191 const uECC_word_t * scalar,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001192 const uECC_word_t * initial_Z)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001193{
1194 /* R0 and R1 */
1195 uECC_word_t Rx[2][NUM_ECC_WORDS];
1196 uECC_word_t Ry[2][NUM_ECC_WORDS];
1197 uECC_word_t z[NUM_ECC_WORDS];
1198 bitcount_t i;
1199 uECC_word_t nb;
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001200 const wordcount_t num_words = NUM_ECC_WORDS;
1201 const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001202 ecc_wait_state_t wait_state;
1203 ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001204
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001205 uECC_vli_set(Rx[1], point);
1206 uECC_vli_set(Ry[1], point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001207
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001208 XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001209
1210 for (i = num_bits - 2; i > 0; --i) {
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001211 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001212 nb = !uECC_vli_testBit(scalar, i);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001213 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
1214 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001215 }
1216
Manuel Pégourié-Gonnardd5e503e2019-10-31 12:53:44 +01001217 ecc_wait_state_reset(ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001218 nb = !uECC_vli_testBit(scalar, 0);
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001219 XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001220
1221 /* Find final 1/Z value. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001222 uECC_vli_modSub(z, Rx[1], Rx[0], curve_p); /* X1 - X0 */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001223 uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */
1224 uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001225 uECC_vli_modInv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0))*/
Jarno Lamsa18987a42019-04-24 15:40:43 +03001226 /* yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001227 uECC_vli_modMult_fast(z, z, point + num_words);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001228 /* Xb * yP / (xP * Yb * (X1 - X0)) */
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001229 uECC_vli_modMult_fast(z, z, Rx[1 - nb]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001230 /* End 1/Z calculation */
1231
Manuel Pégourié-Gonnard938f53f2019-10-29 11:23:43 +01001232 XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws);
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001233 apply_z(Rx[0], Ry[0], z);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001234
Manuel Pégourié-Gonnardcbbb0f02019-11-04 13:02:04 +01001235 uECC_vli_set(result, Rx[0]);
1236 uECC_vli_set(result + num_words, Ry[0]);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001237}
1238
Manuel Pégourié-Gonnard27926d62019-11-04 11:26:46 +01001239static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001240 uECC_word_t *k1)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001241{
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001242 bitcount_t num_n_bits = NUM_ECC_BITS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001243
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001244 uECC_word_t carry = uECC_vli_add(k0, k, curve_n) ||
Andrzej Kurek0919b142020-07-06 15:28:59 -04001245 uECC_vli_testBit(k0, num_n_bits);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001246
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001247 uECC_vli_add(k1, k0, curve_n);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001248
1249 return carry;
1250}
1251
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001252int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001253 const uECC_word_t * scalar)
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001254{
1255 uECC_word_t tmp[NUM_ECC_WORDS];
1256 uECC_word_t s[NUM_ECC_WORDS];
1257 uECC_word_t *k2[2] = {tmp, s};
Manuel Pégourié-Gonnard78a7e352019-11-04 12:31:06 +01001258 wordcount_t num_words = NUM_ECC_WORDS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001259 uECC_word_t carry;
1260 uECC_word_t *initial_Z = 0;
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001261 int r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001262 volatile int problem;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001263
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001264 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001265 problem = -1;
1266 problem = uECC_check_curve_integrity();
1267 if (problem != 0) {
1268 return UECC_FAULT_DETECTED;
1269 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001270 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001271 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001272 return UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001273 }
1274
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001275 /* Protects against invalid curve attacks */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001276 problem = -1;
1277 problem = uECC_valid_point(point);
1278 if (problem != 0) {
1279 /* invalid input, can happen without fault */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001280 return UECC_FAILURE;
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001281 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001282 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001283 if (problem != 0) {
1284 /* failure on second check means fault, though */
1285 return UECC_FAULT_DETECTED;
1286 }
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001287
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001288 /* Regularize the bitcount for the private key so that attackers cannot use a
1289 * side channel attack to learn the number of leading zeros. */
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001290 carry = regularize_k(scalar, tmp, s);
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001291
1292 /* If an RNG function was specified, get a random initial Z value to
Andrzej Kurek0919b142020-07-06 15:28:59 -04001293 * protect against side-channel attacks such as Template SPA */
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001294 if (g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001295 if (uECC_generate_random_int(k2[carry], curve_p, num_words) != UECC_SUCCESS) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001296 r = UECC_FAILURE;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001297 goto clear_and_out;
1298 }
1299 initial_Z = k2[carry];
1300 }
1301
Manuel Pégourié-Gonnard3645ac92019-11-04 11:39:18 +01001302 EccPoint_mult(result, point, k2[!carry], initial_Z);
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001303
Manuel Pégourié-Gonnarde7143322019-11-15 10:47:45 +01001304 /* Protect against fault injections that would make the resulting
1305 * point not lie on the intended curve */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001306 problem = -1;
1307 problem = uECC_valid_point(result);
1308 if (problem != 0) {
1309 r = UECC_FAULT_DETECTED;
1310 goto clear_and_out;
1311 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001312 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001313 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001314 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard41ab8cb2019-11-14 11:59:09 +01001315 goto clear_and_out;
1316 }
1317
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001318 /* Protect against faults modifying curve paremeters in flash */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001319 problem = -1;
1320 problem = uECC_check_curve_integrity();
1321 if (problem != 0) {
1322 r = UECC_FAULT_DETECTED;
1323 goto clear_and_out;
1324 }
Arto Kinnunenac6d2262020-01-09 10:11:20 +02001325 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001326 if (problem != 0) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001327 r = UECC_FAULT_DETECTED;
Manuel Pégourié-Gonnard2b909612019-11-21 13:37:00 +01001328 goto clear_and_out;
1329 }
1330
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001331 r = UECC_SUCCESS;
Manuel Pégourié-Gonnardef238282019-11-04 11:19:30 +01001332
1333clear_and_out:
1334 /* erasing temporary buffer used to store secret: */
1335 mbedtls_platform_zeroize(k2, sizeof(k2));
1336 mbedtls_platform_zeroize(tmp, sizeof(tmp));
1337 mbedtls_platform_zeroize(s, sizeof(s));
1338
1339 return r;
1340}
1341
Jarno Lamsa18987a42019-04-24 15:40:43 +03001342uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001343 uECC_word_t *private_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001344{
Manuel Pégourié-Gonnard1a533712019-11-21 12:00:43 +01001345 return EccPoint_mult_safer(result, curve_G, private_key);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001346}
1347
1348/* Converts an integer in uECC native format to big-endian bytes. */
1349void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001350 const unsigned int *native)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001351{
1352 wordcount_t i;
1353 for (i = 0; i < num_bytes; ++i) {
1354 unsigned b = num_bytes - 1 - i;
1355 bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
1356 }
1357}
1358
1359/* Converts big-endian bytes to an integer in uECC native format. */
1360void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001361 int num_bytes)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001362{
1363 wordcount_t i;
Manuel Pégourié-Gonnard94e48492019-11-04 12:47:28 +01001364 uECC_vli_clear(native);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001365 for (i = 0; i < num_bytes; ++i) {
1366 unsigned b = num_bytes - 1 - i;
1367 native[b / uECC_WORD_SIZE] |=
1368 (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
1369 }
1370}
1371
1372int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
Andrzej Kurek0919b142020-07-06 15:28:59 -04001373 wordcount_t num_words)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001374{
1375 uECC_word_t mask = (uECC_word_t)-1;
1376 uECC_word_t tries;
Manuel Pégourié-Gonnard2bf5a122019-11-04 12:56:59 +01001377 bitcount_t num_bits = uECC_vli_numBits(top);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001378
1379 if (!g_rng_function) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001380 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001381 }
1382
1383 for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
Andrzej Kurek090365f2020-06-08 11:00:51 -04001384 if (g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE) != num_words * uECC_WORD_SIZE) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001385 return UECC_FAILURE;
1386 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001387 random[num_words - 1] &=
Andrzej Kurek0919b142020-07-06 15:28:59 -04001388 mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001389 if (!uECC_vli_isZero(random) &&
Manuel Pégourié-Gonnard2cb3eea2019-11-04 14:43:35 +01001390 uECC_vli_cmp(top, random) == 1) {
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001391 return UECC_SUCCESS;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001392 }
1393 }
Andrzej Kurek3a0df032020-06-12 06:32:13 -04001394 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001395}
1396
1397
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001398int uECC_valid_point(const uECC_word_t *point)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001399{
1400 uECC_word_t tmp1[NUM_ECC_WORDS];
1401 uECC_word_t tmp2[NUM_ECC_WORDS];
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001402 wordcount_t num_words = NUM_ECC_WORDS;
Jarno Lamsa83d78812019-12-04 14:40:57 +02001403 volatile uECC_word_t diff = 0xffffffff;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001404
1405 /* The point at infinity is invalid. */
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001406 if (EccPoint_isZero(point)) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001407 return -1;
1408 }
1409
1410 /* x and y must be smaller than p. */
Manuel Pégourié-Gonnard4d8777c2019-11-21 10:02:58 +01001411 if (uECC_vli_cmp_unsafe(curve_p, point) != 1 ||
1412 uECC_vli_cmp_unsafe(curve_p, point + num_words) != 1) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001413 return -2;
1414 }
1415
Manuel Pégourié-Gonnardc3ec14c2019-11-04 12:12:00 +01001416 uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words);
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001417 x_side_default(tmp2, point); /* tmp2 = x^3 + ax + b */
Jarno Lamsa18987a42019-04-24 15:40:43 +03001418
1419 /* Make sure that y^2 == x^3 + ax + b */
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001420 diff = uECC_vli_equal(tmp1, tmp2);
1421 if (diff == 0) {
Andrzej Kurek0919b142020-07-06 15:28:59 -04001422 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001423 if (diff == 0) {
1424 return 0;
1425 }
1426 }
Jarno Lamsa18987a42019-04-24 15:40:43 +03001427
Manuel Pégourié-Gonnard5c3066a2019-11-27 12:27:48 +01001428 return -3;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001429}
1430
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001431int uECC_valid_public_key(const uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001432{
1433
1434 uECC_word_t _public[NUM_ECC_WORDS * 2];
1435
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001436 uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001437 uECC_vli_bytesToNative(
Manuel Pégourié-Gonnard17659332019-11-21 09:27:38 +01001438 _public + NUM_ECC_WORDS,
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001439 public_key + NUM_ECC_BYTES,
1440 NUM_ECC_BYTES);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001441
Manuel Pégourié-Gonnarda6115082019-11-21 10:29:14 +01001442 if (memcmp(_public, curve_G, NUM_ECC_WORDS * 2) == 0) {
Jarno Lamsa18987a42019-04-24 15:40:43 +03001443 return -4;
1444 }
1445
Manuel Pégourié-Gonnardbe5f8332019-11-21 11:02:38 +01001446 return uECC_valid_point(_public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001447}
1448
Andrzej Kurek0919b142020-07-06 15:28:59 -04001449int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key)
Jarno Lamsa18987a42019-04-24 15:40:43 +03001450{
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001451 int ret = UECC_FAULT_DETECTED;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001452 uECC_word_t _private[NUM_ECC_WORDS];
1453 uECC_word_t _public[NUM_ECC_WORDS * 2];
1454
1455 uECC_vli_bytesToNative(
1456 _private,
1457 private_key,
Manuel Pégourié-Gonnard30833f22019-11-21 09:46:52 +01001458 BITS_TO_BYTES(NUM_ECC_BITS));
Jarno Lamsa18987a42019-04-24 15:40:43 +03001459
1460 /* Make sure the private key is in the range [1, n-1]. */
Manuel Pégourié-Gonnardf3899fc2019-11-04 12:44:43 +01001461 if (uECC_vli_isZero(_private)) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001462 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001463 }
1464
Manuel Pégourié-Gonnard356d8592019-11-21 10:23:05 +01001465 if (uECC_vli_cmp(curve_n, _private) != 1) {
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001466 return UECC_FAILURE;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001467 }
1468
1469 /* Compute public key. */
Manuel Pégourié-Gonnard9d6a5352019-11-25 13:06:05 +01001470 ret = EccPoint_compute_public_key(_public, _private);
1471 if (ret != UECC_SUCCESS) {
1472 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001473 }
1474
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001475 uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public);
Jarno Lamsa18987a42019-04-24 15:40:43 +03001476 uECC_vli_nativeToBytes(
1477 public_key +
Manuel Pégourié-Gonnard72c17642019-11-21 09:34:09 +01001478 NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS);
Andrzej Kurekcf3e35c2020-07-15 22:32:08 -04001479
Andrzej Kurekfd56f402020-05-25 11:52:05 -04001480 return ret;
Jarno Lamsa18987a42019-04-24 15:40:43 +03001481}