blob: 5927abcc5080e5ec5c594f94cc25307ef67d6d54 [file] [log] [blame]
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01001/*
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +01002 * Elliptic curves over GF(p): generic functions
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003 *
Bence Szépkútia2947ac2020-08-19 16:37:36 +02004 * Copyright The Mbed TLS Contributors
Bence Szépkútif744bd72020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010024 *
Bence Szépkútif744bd72020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010045 */
46
47/*
48 * References:
49 *
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +010050 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +010051 * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +010052 * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +010053 * RFC 4492 for the related TLS structures and constants
Nicholas Wilson08f3ef12015-11-10 13:10:01 +000054 * RFC 7748 for the Curve448 and Curve25519 curve definitions
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020055 *
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +020056 * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +010057 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020058 * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020059 * for elliptic curve cryptosystems. In : Cryptographic Hardware and
60 * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
61 * <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010062 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020063 * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010064 * render ECC resistant against Side Channel Attacks. IACR Cryptology
65 * ePrint Archive, 2004, vol. 2004, p. 342.
66 * <http://eprint.iacr.org/2004/342.pdf>
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010067 */
68
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000070#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020071#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020073#endif
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010074
Janos Follath683c5822018-12-07 12:09:25 +000075/**
76 * \brief Function level alternative implementation.
77 *
78 * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to
79 * replace certain functions in this module. The alternative implementations are
80 * typically hardware accelerators and need to activate the hardware before the
81 * computation starts and deactivate it after it finishes. The
82 * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve
83 * this purpose.
84 *
85 * To preserve the correct functionality the following conditions must hold:
86 *
87 * - The alternative implementation must be activated by
88 * mbedtls_internal_ecp_init() before any of the replaceable functions is
89 * called.
90 * - mbedtls_internal_ecp_free() must \b only be called when the alternative
91 * implementation is activated.
92 * - mbedtls_internal_ecp_init() must \b not be called when the alternative
93 * implementation is activated.
94 * - Public functions must not return while the alternative implementation is
95 * activated.
96 * - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and
97 * before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) )
98 * \endcode ensures that the alternative implementation supports the current
99 * group.
100 */
101#if defined(MBEDTLS_ECP_INTERNAL_ALT)
102#endif
103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100105
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +0000106#include "mbedtls/ecp.h"
Janos Follath430d3372016-11-03 14:25:37 +0000107#include "mbedtls/threading.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500108#include "mbedtls/platform_util.h"
Paul Bakker6e339b52013-07-03 13:37:05 +0200109
Rich Evans00ab4702015-02-06 13:43:58 +0000110#include <string.h>
111
Janos Follathb0697532016-08-18 12:38:46 +0100112#if !defined(MBEDTLS_ECP_ALT)
113
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000114/* Parameter validation macros based on platform_util.h */
115#define ECP_VALIDATE_RET( cond ) \
116 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
117#define ECP_VALIDATE( cond ) \
118 MBEDTLS_INTERNAL_VALIDATE( cond )
119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +0000121#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +0200122#else
Rich Evans00ab4702015-02-06 13:43:58 +0000123#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +0000124#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200126#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +0200128#endif
129
Janos Follath47d28f02016-11-01 13:22:05 +0000130#include "mbedtls/ecp_internal.h"
Janos Follathb0697532016-08-18 12:38:46 +0100131
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200132#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200133#if defined(MBEDTLS_HMAC_DRBG_C)
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200134#include "mbedtls/hmac_drbg.h"
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200135#elif defined(MBEDTLS_CTR_DRBG_C)
136#include "mbedtls/ctr_drbg.h"
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200137#elif defined(MBEDTLS_SHA512_C)
138#include "mbedtls/sha512.h"
139#elif defined(MBEDTLS_SHA256_C)
140#include "mbedtls/sha256.h"
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200141#else
142#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
143#endif
144#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
145
Manuel Pégourié-Gonnard0223ab92015-10-05 11:40:01 +0100146#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
147 !defined(inline) && !defined(__cplusplus)
Paul Bakker6a6087e2013-10-28 18:53:08 +0100148#define inline __inline
Manuel Pégourié-Gonnard20af64d2015-07-07 18:33:39 +0200149#endif
Paul Bakker6a6087e2013-10-28 18:53:08 +0100150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100152/*
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100153 * Counts of point addition and doubling, and field multiplications.
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +0200154 * Used to test resistance of point multiplication to simple timing attacks.
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100155 */
Manuel Pégourié-Gonnard43863ee2013-12-01 16:51:27 +0100156static unsigned long add_count, dbl_count, mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100157#endif
158
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200159#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
160/*
161 * Currently ecp_mul() takes a RNG function as an argument, used for
Manuel Pégourié-Gonnard0defc572020-06-10 09:18:25 +0200162 * side-channel protection, but it can be NULL. The initial reasoning was
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200163 * that people will pass non-NULL RNG when they care about side-channels, but
164 * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with
165 * no opportunity for the user to do anything about it.
166 *
167 * The obvious strategies for addressing that include:
168 * - change those APIs so that they take RNG arguments;
169 * - require a global RNG to be available to all crypto modules.
170 *
171 * Unfortunately those would break compatibility. So what we do instead is
172 * have our own internal DRBG instance, seeded from the secret scalar.
173 *
174 * The following is a light-weight abstraction layer for doing that with
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200175 * HMAC_DRBG (first choice) or CTR_DRBG.
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200176 */
177
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200178#if defined(MBEDTLS_HMAC_DRBG_C)
179
180/* DRBG context type */
181typedef mbedtls_hmac_drbg_context ecp_drbg_context;
182
183/* DRBG context init */
184static inline void ecp_drbg_init( ecp_drbg_context *ctx )
185{
186 mbedtls_hmac_drbg_init( ctx );
187}
188
189/* DRBG context free */
190static inline void ecp_drbg_free( ecp_drbg_context *ctx )
191{
192 mbedtls_hmac_drbg_free( ctx );
193}
194
195/* DRBG function */
196static inline int ecp_drbg_random( void *p_rng,
197 unsigned char *output, size_t output_len )
198{
199 return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) );
200}
201
202/* DRBG context seeding */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200203static int ecp_drbg_seed( ecp_drbg_context *ctx,
204 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200205{
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200206 int ret;
207 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200208 /* The list starts with strong hashes */
209 const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
210 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
211
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200212 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
213 secret_bytes, secret_len ) );
214
215 ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len );
216
217cleanup:
218 mbedtls_platform_zeroize( secret_bytes, secret_len );
219
220 return( ret );
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200221}
222
223#elif defined(MBEDTLS_CTR_DRBG_C)
224
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200225/* DRBG context type */
226typedef mbedtls_ctr_drbg_context ecp_drbg_context;
227
228/* DRBG context init */
229static inline void ecp_drbg_init( ecp_drbg_context *ctx )
230{
231 mbedtls_ctr_drbg_init( ctx );
232}
233
234/* DRBG context free */
235static inline void ecp_drbg_free( ecp_drbg_context *ctx )
236{
237 mbedtls_ctr_drbg_free( ctx );
238}
239
240/* DRBG function */
241static inline int ecp_drbg_random( void *p_rng,
242 unsigned char *output, size_t output_len )
243{
244 return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
245}
246
247/*
248 * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
249 * we need to pass an entropy function when seeding. So we use a dummy
250 * function for that, and pass the actual entropy as customisation string.
251 * (During seeding of CTR_DRBG the entropy input and customisation string are
252 * concatenated before being used to update the secret state.)
253 */
254static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
255{
256 (void) ctx;
257 memset( out, 0, len );
258 return( 0 );
259}
260
261/* DRBG context seeding */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200262static int ecp_drbg_seed( ecp_drbg_context *ctx,
263 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200264{
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200265 int ret;
266 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200267
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200268 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
269 secret_bytes, secret_len ) );
270
271 ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
272 secret_bytes, secret_len );
273
274cleanup:
275 mbedtls_platform_zeroize( secret_bytes, secret_len );
276
277 return( ret );
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200278}
279
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200280#elif defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA256_C)
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200281
282/* This will be used in the self-test function */
283#define ECP_ONE_STEP_KDF
284
285/*
286 * We need to expand secret data (the scalar) into a longer stream of bytes.
287 *
288 * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash
289 * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for
290 * convenience, this is not a full-fledged DRBG, but we don't need one here.)
291 *
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200292 * We need a basic hash abstraction layer to use whatever SHA-2 is available.
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200293 */
294#if defined(MBEDTLS_SHA512_C)
295
296#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 );
297#define HASH_BLOCK_BYTES ( 512 / 8 )
298
299#elif defined(MBEDTLS_SHA256_C)
300
301#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 );
302#define HASH_BLOCK_BYTES ( 256 / 8 )
303
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200304#endif /* SHA512/SHA256 abstraction */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200305
306/*
307 * State consists of a 32-bit counter plus the secret value.
308 *
309 * We stored them concatenated in a single buffer as that's what will get
310 * passed to the hash function.
311 */
312typedef struct {
313 size_t total_len;
314 uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES];
315} ecp_drbg_context;
316
317static void ecp_drbg_init( ecp_drbg_context *ctx )
318{
319 memset( ctx, 0, sizeof( ecp_drbg_context ) );
320}
321
322static void ecp_drbg_free( ecp_drbg_context *ctx )
323{
324 mbedtls_platform_zeroize( ctx, sizeof( ecp_drbg_context ) );
325}
326
327static int ecp_drbg_seed( ecp_drbg_context *ctx,
328 const mbedtls_mpi *secret, size_t secret_len )
329{
330 ctx->total_len = 4 + secret_len;
331 memset( ctx->buf, 0, 4);
332 return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) );
333}
334
335static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
336{
337 ecp_drbg_context *ctx = p_rng;
338 int ret;
339 size_t len_done = 0;
Manuel Pégourié-Gonnarda90a95b2020-06-17 12:40:57 +0200340 uint8_t tmp[HASH_BLOCK_BYTES];
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200341
342 while( len_done < output_len )
343 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200344 uint8_t use_len;
345
Manuel Pégourié-Gonnard7d7c0042020-06-17 12:57:33 +0200346 /* This function is only called for coordinate randomisation, which
347 * happens only twice in a scalar multiplication. Each time needs a
348 * random value in the range [2, p-1], and gets it by drawing len(p)
349 * bytes from this function, and retrying up to 10 times if unlucky.
350 *
351 * So for the largest curve, each scalar multiplication draws at most
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200352 * 20 * 66 bytes. The minimum block size is 32 (SHA-256), so with
353 * rounding that means a most 20 * 3 blocks.
Manuel Pégourié-Gonnard7d7c0042020-06-17 12:57:33 +0200354 *
355 * Since we don't need to draw more that 255 blocks, don't bother
356 * with carry propagation and just return an error instead. We can
357 * change that it we even need to draw more blinding values.
358 */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200359 ctx->buf[3] += 1;
360 if( ctx->buf[3] == 0 )
361 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
362
363 ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
364 if( ret != 0 )
365 return( ret );
366
367 if( output_len - len_done > HASH_BLOCK_BYTES )
368 use_len = HASH_BLOCK_BYTES;
369 else
370 use_len = output_len - len_done;
371
372 memcpy( output + len_done, tmp, use_len );
373 len_done += use_len;
374 }
375
Manuel Pégourié-Gonnarda90a95b2020-06-17 12:40:57 +0200376 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
377
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200378 return( 0 );
379}
380
381#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200382#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200383#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200384#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
385
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200386#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100387/*
388 * Maximum number of "basic operations" to be done in a row.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +0200389 *
390 * Default value 0 means that ECC operations will not yield.
391 * Note that regardless of the value of ecp_max_ops, always at
392 * least one step is performed before yielding.
393 *
394 * Setting ecp_max_ops=1 can be suitable for testing purposes
395 * as it will interrupt computation at all possible points.
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100396 */
397static unsigned ecp_max_ops = 0;
398
399/*
400 * Set ecp_max_ops
401 */
402void mbedtls_ecp_set_max_ops( unsigned max_ops )
403{
404 ecp_max_ops = max_ops;
405}
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100406
407/*
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200408 * Check if restart is enabled
409 */
Manuel Pégourié-Gonnardb843b152018-10-16 10:41:31 +0200410int mbedtls_ecp_restart_is_enabled( void )
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200411{
412 return( ecp_max_ops != 0 );
413}
414
415/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200416 * Restart sub-context for ecp_mul_comb()
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100417 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200418struct mbedtls_ecp_restart_mul
419{
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100420 mbedtls_ecp_point R; /* current intermediate result */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +0100421 size_t i; /* current index in various loops, 0 outside */
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100422 mbedtls_ecp_point *T; /* table for precomputed points */
423 unsigned char T_size; /* number of points in table T */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200424 enum { /* what were we doing last time we returned? */
425 ecp_rsm_init = 0, /* nothing so far, dummy initial state */
426 ecp_rsm_pre_dbl, /* precompute 2^n multiples */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100427 ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */
428 ecp_rsm_pre_add, /* precompute remaining points by adding */
429 ecp_rsm_pre_norm_add, /* normalize all precomputed points */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200430 ecp_rsm_comb_core, /* ecp_mul_comb_core() */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100431 ecp_rsm_final_norm, /* do the final normalization */
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100432 } state;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200433#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
434 ecp_drbg_context drbg_ctx;
435 unsigned char drbg_seeded;
436#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100437};
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100438
439/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200440 * Init restart_mul sub-context
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100441 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200442static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100443{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200444 mbedtls_ecp_point_init( &ctx->R );
445 ctx->i = 0;
446 ctx->T = NULL;
447 ctx->T_size = 0;
448 ctx->state = ecp_rsm_init;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200449#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
450 ecp_drbg_init( &ctx->drbg_ctx );
451 ctx->drbg_seeded = 0;
452#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100453}
454
455/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200456 * Free the components of a restart_mul sub-context
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100457 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200458static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100459{
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100460 unsigned char i;
461
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100462 if( ctx == NULL )
463 return;
Manuel Pégourié-Gonnard78d564a2017-03-14 11:48:38 +0100464
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100465 mbedtls_ecp_point_free( &ctx->R );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100466
Manuel Pégourié-Gonnard31f0ef72017-05-17 10:05:58 +0200467 if( ctx->T != NULL )
468 {
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100469 for( i = 0; i < ctx->T_size; i++ )
470 mbedtls_ecp_point_free( ctx->T + i );
471 mbedtls_free( ctx->T );
472 }
473
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200474#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
475 ecp_drbg_free( &ctx->drbg_ctx );
476#endif
477
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200478 ecp_restart_rsm_init( ctx );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100479}
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100480
481/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200482 * Restart context for ecp_muladd()
483 */
484struct mbedtls_ecp_restart_muladd
485{
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200486 mbedtls_ecp_point mP; /* mP value */
487 mbedtls_ecp_point R; /* R intermediate result */
488 enum { /* what should we do next? */
489 ecp_rsma_mul1 = 0, /* first multiplication */
490 ecp_rsma_mul2, /* second multiplication */
491 ecp_rsma_add, /* addition */
492 ecp_rsma_norm, /* normalization */
493 } state;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200494};
495
496/*
497 * Init restart_muladd sub-context
498 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200499static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200500{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200501 mbedtls_ecp_point_init( &ctx->mP );
502 mbedtls_ecp_point_init( &ctx->R );
503 ctx->state = ecp_rsma_mul1;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200504}
505
506/*
507 * Free the components of a restart_muladd sub-context
508 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200509static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200510{
511 if( ctx == NULL )
512 return;
513
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200514 mbedtls_ecp_point_free( &ctx->mP );
515 mbedtls_ecp_point_free( &ctx->R );
516
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200517 ecp_restart_ma_init( ctx );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200518}
519
520/*
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200521 * Initialize a restart context
522 */
523void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx )
524{
Hanno Becker80f71682018-12-18 23:44:43 +0000525 ECP_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200526 ctx->ops_done = 0;
527 ctx->depth = 0;
528 ctx->rsm = NULL;
529 ctx->ma = NULL;
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200530}
531
532/*
533 * Free the components of a restart context
534 */
535void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx )
536{
537 if( ctx == NULL )
538 return;
539
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200540 ecp_restart_rsm_free( ctx->rsm );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200541 mbedtls_free( ctx->rsm );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200542
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200543 ecp_restart_ma_free( ctx->ma );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200544 mbedtls_free( ctx->ma );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200545
546 mbedtls_ecp_restart_init( ctx );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200547}
548
549/*
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100550 * Check if we can do the next step
551 */
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +0200552int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
553 mbedtls_ecp_restart_ctx *rs_ctx,
554 unsigned ops )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100555{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000556 ECP_VALIDATE_RET( grp != NULL );
557
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200558 if( rs_ctx != NULL && ecp_max_ops != 0 )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100559 {
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100560 /* scale depending on curve size: the chosen reference is 256-bit,
561 * and multiplication is quadratic. Round to the closest integer. */
562 if( grp->pbits >= 512 )
563 ops *= 4;
564 else if( grp->pbits >= 384 )
565 ops *= 2;
566
Hanno Beckerb10c6602018-10-26 13:50:13 +0100567 /* Avoid infinite loops: always allow first step.
568 * Because of that, however, it's not generally true
569 * that ops_done <= ecp_max_ops, so the check
570 * ops_done > ecp_max_ops below is mandatory. */
571 if( ( rs_ctx->ops_done != 0 ) &&
572 ( rs_ctx->ops_done > ecp_max_ops ||
573 ops > ecp_max_ops - rs_ctx->ops_done ) )
574 {
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100575 return( MBEDTLS_ERR_ECP_IN_PROGRESS );
Hanno Beckerb10c6602018-10-26 13:50:13 +0100576 }
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100577
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100578 /* update running count */
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200579 rs_ctx->ops_done += ops;
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100580 }
581
582 return( 0 );
583}
584
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200585/* Call this when entering a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200586#define ECP_RS_ENTER( SUB ) do { \
587 /* reset ops count for this call if top-level */ \
588 if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \
589 rs_ctx->ops_done = 0; \
590 \
591 /* set up our own sub-context if needed */ \
592 if( mbedtls_ecp_restart_is_enabled() && \
593 rs_ctx != NULL && rs_ctx->SUB == NULL ) \
594 { \
595 rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
596 if( rs_ctx->SUB == NULL ) \
597 return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
598 \
599 ecp_restart_## SUB ##_init( rs_ctx->SUB ); \
600 } \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200601} while( 0 )
602
603/* Call this when leaving a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200604#define ECP_RS_LEAVE( SUB ) do { \
605 /* clear our sub-context when not in progress (done or error) */ \
606 if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
607 ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
608 { \
609 ecp_restart_## SUB ##_free( rs_ctx->SUB ); \
610 mbedtls_free( rs_ctx->SUB ); \
611 rs_ctx->SUB = NULL; \
612 } \
613 \
614 if( rs_ctx != NULL ) \
615 rs_ctx->depth--; \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200616} while( 0 )
617
618#else /* MBEDTLS_ECP_RESTARTABLE */
619
620#define ECP_RS_ENTER( sub ) (void) rs_ctx;
621#define ECP_RS_LEAVE( sub ) (void) rs_ctx;
622
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200623#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
626 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
627 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
628 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
629 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
630 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
631 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
632 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
633 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
634 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
635 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200636#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100637#endif
638
Nicholas Wilson08f3ef12015-11-10 13:10:01 +0000639#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
640 defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200641#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100642#endif
643
644/*
645 * Curve types: internal for now, might be exposed later
646 */
647typedef enum
648{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200649 ECP_TYPE_NONE = 0,
650 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
651 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100652} ecp_curve_type;
653
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100654/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200655 * List of supported curves:
656 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200657 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200658 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200659 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100660 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100661 * Curves are listed in order: largest curves first, and for a given size,
662 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200663 *
664 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200665 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200667{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
669 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200670#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
672 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100673#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
675 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200676#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200677#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
678 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100679#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
681 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200682#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
684 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100685#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
687 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100688#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
690 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200691#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
693 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100694#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
696 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100697#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
699 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100700#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200702};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100703
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200704#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
705 sizeof( ecp_supported_curves[0] )
706
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200708
709/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200710 * List of supported curves and associated info
711 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200713{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200714 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200715}
716
717/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100718 * List of supported curves, group ID only
719 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200720const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100721{
722 static int init_done = 0;
723
724 if( ! init_done )
725 {
726 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200727 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100728
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200729 for( curve_info = mbedtls_ecp_curve_list();
730 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100731 curve_info++ )
732 {
733 ecp_supported_grp_id[i++] = curve_info->grp_id;
734 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200735 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100736
737 init_done = 1;
738 }
739
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200740 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100741}
742
743/*
744 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200745 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200746const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200747{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200748 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200749
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750 for( curve_info = mbedtls_ecp_curve_list();
751 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200752 curve_info++ )
753 {
754 if( curve_info->grp_id == grp_id )
755 return( curve_info );
756 }
757
758 return( NULL );
759}
760
761/*
762 * Get the curve info from the TLS identifier
763 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200764const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200765{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200766 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200767
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200768 for( curve_info = mbedtls_ecp_curve_list();
769 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200770 curve_info++ )
771 {
772 if( curve_info->tls_id == tls_id )
773 return( curve_info );
774 }
775
776 return( NULL );
777}
778
779/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100780 * Get the curve info from the name
781 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200782const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100783{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200784 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100785
Hanno Beckerb7a04a72018-12-18 23:50:21 +0000786 if( name == NULL )
787 return( NULL );
788
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200789 for( curve_info = mbedtls_ecp_curve_list();
790 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100791 curve_info++ )
792 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200793 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100794 return( curve_info );
795 }
796
797 return( NULL );
798}
799
800/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100801 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100802 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200803static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100804{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100805 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200806 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100807
808 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200809 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100810 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200811 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100812}
813
814/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100815 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100816 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200817void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100818{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000819 ECP_VALIDATE( pt != NULL );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100820
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200821 mbedtls_mpi_init( &pt->X );
822 mbedtls_mpi_init( &pt->Y );
823 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100824}
825
826/*
827 * Initialize (the components of) a group
828 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200829void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100830{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000831 ECP_VALIDATE( grp != NULL );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100832
Manuel Pégourié-Gonnard95e2eca2018-06-20 10:29:47 +0200833 grp->id = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200834 mbedtls_mpi_init( &grp->P );
835 mbedtls_mpi_init( &grp->A );
836 mbedtls_mpi_init( &grp->B );
837 mbedtls_ecp_point_init( &grp->G );
838 mbedtls_mpi_init( &grp->N );
839 grp->pbits = 0;
840 grp->nbits = 0;
841 grp->h = 0;
842 grp->modp = NULL;
843 grp->t_pre = NULL;
844 grp->t_post = NULL;
845 grp->t_data = NULL;
846 grp->T = NULL;
847 grp->T_size = 0;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100848}
849
850/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200851 * Initialize (the components of) a key pair
852 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200853void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200854{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000855 ECP_VALIDATE( key != NULL );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200856
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857 mbedtls_ecp_group_init( &key->grp );
858 mbedtls_mpi_init( &key->d );
859 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200860}
861
862/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100863 * Unallocate (the components of) a point
864 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200865void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100866{
867 if( pt == NULL )
868 return;
869
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200870 mbedtls_mpi_free( &( pt->X ) );
871 mbedtls_mpi_free( &( pt->Y ) );
872 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100873}
874
875/*
876 * Unallocate (the components of) a group
877 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200878void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100879{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200880 size_t i;
881
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100882 if( grp == NULL )
883 return;
884
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100885 if( grp->h != 1 )
886 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200887 mbedtls_mpi_free( &grp->P );
888 mbedtls_mpi_free( &grp->A );
889 mbedtls_mpi_free( &grp->B );
890 mbedtls_ecp_point_free( &grp->G );
891 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100892 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200893
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200894 if( grp->T != NULL )
895 {
896 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200897 mbedtls_ecp_point_free( &grp->T[i] );
898 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200899 }
900
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500901 mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100902}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100903
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100904/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200905 * Unallocate (the components of) a key pair
906 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200907void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200908{
Paul Bakker66d5d072014-06-17 16:39:18 +0200909 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200910 return;
911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200912 mbedtls_ecp_group_free( &key->grp );
913 mbedtls_mpi_free( &key->d );
914 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200915}
916
917/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200918 * Copy the contents of a point
919 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200920int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200921{
922 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000923 ECP_VALIDATE_RET( P != NULL );
924 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200925
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200926 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
927 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
928 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200929
930cleanup:
931 return( ret );
932}
933
934/*
935 * Copy the contents of a group object
936 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200937int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200938{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000939 ECP_VALIDATE_RET( dst != NULL );
940 ECP_VALIDATE_RET( src != NULL );
941
942 return( mbedtls_ecp_group_load( dst, src->id ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200943}
944
945/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100946 * Set point to zero
947 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200948int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100949{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100950 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000951 ECP_VALIDATE_RET( pt != NULL );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100952
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200953 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
954 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
955 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100956
957cleanup:
958 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100959}
960
961/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100962 * Tell if a point is zero
963 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200964int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100965{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000966 ECP_VALIDATE_RET( pt != NULL );
967
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100969}
970
971/*
Brian J Murrayf343de12018-10-22 16:40:49 -0700972 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200973 */
974int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
975 const mbedtls_ecp_point *Q )
976{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000977 ECP_VALIDATE_RET( P != NULL );
978 ECP_VALIDATE_RET( Q != NULL );
979
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200980 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
981 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
982 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
983 {
984 return( 0 );
985 }
986
987 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
988}
989
990/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100991 * Import a non-zero point from ASCII strings
992 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200993int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100994 const char *x, const char *y )
995{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100996 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000997 ECP_VALIDATE_RET( P != NULL );
998 ECP_VALIDATE_RET( x != NULL );
999 ECP_VALIDATE_RET( y != NULL );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +01001000
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001001 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
1002 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
1003 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +01001004
1005cleanup:
1006 return( ret );
1007}
1008
1009/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001010 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001011 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001012int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp,
1013 const mbedtls_ecp_point *P,
1014 int format, size_t *olen,
1015 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001016{
Paul Bakkera280d0f2013-04-08 13:40:17 +02001017 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001018 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001019 ECP_VALIDATE_RET( grp != NULL );
1020 ECP_VALIDATE_RET( P != NULL );
1021 ECP_VALIDATE_RET( olen != NULL );
1022 ECP_VALIDATE_RET( buf != NULL );
1023 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
1024 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001025
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001026 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001027 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001028 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001029 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001030 {
1031 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001032 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001033
1034 buf[0] = 0x00;
1035 *olen = 1;
1036
1037 return( 0 );
1038 }
1039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001040 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001041
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001043 {
1044 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001045
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001046 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001047 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001048
1049 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
1051 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001052 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001053 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001054 {
1055 *olen = plen + 1;
1056
1057 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001058 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001060 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
1061 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001062 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001063
1064cleanup:
1065 return( ret );
1066}
1067
1068/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001069 * Import a point from unsigned binary data (SEC1 2.3.4)
1070 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001071int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
1072 mbedtls_ecp_point *pt,
1073 const unsigned char *buf, size_t ilen )
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001074{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001075 int ret;
1076 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001077 ECP_VALIDATE_RET( grp != NULL );
1078 ECP_VALIDATE_RET( pt != NULL );
1079 ECP_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001080
Paul Bakker82788fb2014-10-20 13:59:19 +02001081 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001082 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001083
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001084 if( buf[0] == 0x00 )
1085 {
1086 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001087 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001088 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001089 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001090 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001091
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001092 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001093
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001094 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001095 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001096
1097 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001098 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001099
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001100 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
1101 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
1102 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001103
1104cleanup:
1105 return( ret );
1106}
1107
1108/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001109 * Import a point from a TLS ECPoint record (RFC 4492)
1110 * struct {
1111 * opaque point <1..2^8-1>;
1112 * } ECPoint;
1113 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001114int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp,
1115 mbedtls_ecp_point *pt,
1116 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001117{
1118 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001119 const unsigned char *buf_start;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001120 ECP_VALIDATE_RET( grp != NULL );
1121 ECP_VALIDATE_RET( pt != NULL );
1122 ECP_VALIDATE_RET( buf != NULL );
1123 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001124
1125 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001126 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001127 */
1128 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001129 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001130
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001131 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001132 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001133 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001134
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001135 /*
1136 * Save buffer start for read_binary and update buf
1137 */
1138 buf_start = *buf;
1139 *buf += data_len;
1140
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001141 return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001142}
1143
1144/*
1145 * Export a point as a TLS ECPoint record (RFC 4492)
1146 * struct {
1147 * opaque point <1..2^8-1>;
1148 * } ECPoint;
1149 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001150int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001151 int format, size_t *olen,
1152 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001153{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001154 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001155 ECP_VALIDATE_RET( grp != NULL );
1156 ECP_VALIDATE_RET( pt != NULL );
1157 ECP_VALIDATE_RET( olen != NULL );
1158 ECP_VALIDATE_RET( buf != NULL );
1159 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
1160 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001161
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001162 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001163 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001164 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001165 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001166 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001168 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001169 olen, buf + 1, blen - 1) ) != 0 )
1170 return( ret );
1171
1172 /*
1173 * write length to the first byte and update total length
1174 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +02001175 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001176 ++*olen;
1177
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001178 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001179}
1180
1181/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001182 * Set a group from an ECParameters record (RFC 4492)
1183 */
Janos Follath89ac8c92018-10-30 11:24:05 +00001184int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp,
1185 const unsigned char **buf, size_t len )
1186{
1187 int ret;
1188 mbedtls_ecp_group_id grp_id;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001189 ECP_VALIDATE_RET( grp != NULL );
1190 ECP_VALIDATE_RET( buf != NULL );
1191 ECP_VALIDATE_RET( *buf != NULL );
Janos Follath89ac8c92018-10-30 11:24:05 +00001192
1193 if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 )
1194 return( ret );
1195
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001196 return( mbedtls_ecp_group_load( grp, grp_id ) );
Janos Follath89ac8c92018-10-30 11:24:05 +00001197}
1198
1199/*
1200 * Read a group id from an ECParameters record (RFC 4492) and convert it to
1201 * mbedtls_ecp_group_id.
1202 */
1203int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp,
1204 const unsigned char **buf, size_t len )
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001205{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001206 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001208 ECP_VALIDATE_RET( grp != NULL );
1209 ECP_VALIDATE_RET( buf != NULL );
1210 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001211
1212 /*
1213 * We expect at least three bytes (see below)
1214 */
1215 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001217
1218 /*
1219 * First byte is curve_type; only named_curve is handled
1220 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001221 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
1222 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001223
1224 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001225 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001226 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001227 tls_id = *(*buf)++;
1228 tls_id <<= 8;
1229 tls_id |= *(*buf)++;
1230
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001231 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
1232 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001233
Janos Follath89ac8c92018-10-30 11:24:05 +00001234 *grp = curve_info->grp_id;
1235
1236 return( 0 );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001237}
1238
1239/*
1240 * Write the ECParameters record corresponding to a group (RFC 4492)
1241 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001242int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001243 unsigned char *buf, size_t blen )
1244{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001245 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001246 ECP_VALIDATE_RET( grp != NULL );
1247 ECP_VALIDATE_RET( buf != NULL );
1248 ECP_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001249
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001250 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
1251 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001252
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001253 /*
1254 * We are going to write 3 bytes (see below)
1255 */
1256 *olen = 3;
1257 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001259
1260 /*
1261 * First byte is curve_type, always named_curve
1262 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001263 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001264
1265 /*
1266 * Next two bytes are the namedcurve value
1267 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001268 buf[0] = curve_info->tls_id >> 8;
1269 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001270
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001271 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +01001272}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001273
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001274/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
1276 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001277 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001278 * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf.
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001279 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001280static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001281{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001282 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001283
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001284 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001285 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001286
1287 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001288 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001289 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001290 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001291 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001292 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001294 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001295
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001296 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001297 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
1298 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001300 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001301 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001302 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001303
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001304cleanup:
1305 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001306}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001307
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +01001308/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001309 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001310 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001311 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001312 * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001313 * bring the result back to this range.
1314 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001315 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001316 */
1317
1318/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319 * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001320 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01001322#define INC_MUL_COUNT mul_count++;
1323#else
1324#define INC_MUL_COUNT
1325#endif
1326
Hanno Beckerd6028a12018-10-15 12:01:35 +01001327#define MOD_MUL( N ) \
1328 do \
1329 { \
1330 MBEDTLS_MPI_CHK( ecp_modp( &(N), grp ) ); \
1331 INC_MUL_COUNT \
1332 } while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001333
1334/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001335 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +02001336 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001337 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001338#define MOD_SUB( N ) \
1339 while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \
1340 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001341
1342/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001343 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int.
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +02001344 * We known P, N and the result are positive, so sub_abs is correct, and
1345 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001346 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001347#define MOD_ADD( N ) \
1348 while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \
1349 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001350
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001351#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001352/*
1353 * For curves in short Weierstrass form, we do all the internal operations in
1354 * Jacobian coordinates.
1355 *
1356 * For multiplication, we'll use a comb method with coutermeasueres against
1357 * SPA, hence timing attacks.
1358 */
1359
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001360/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001361 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001362 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001363 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001364static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001365{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001366 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001367 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001370 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001371
Janos Follathb0697532016-08-18 12:38:46 +01001372#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001373 if( mbedtls_internal_ecp_grp_capable( grp ) )
1374 return( mbedtls_internal_ecp_normalize_jac( grp, pt ) );
Janos Follath372697b2016-10-28 16:53:11 +01001375#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001376
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001377 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001378
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001379 /*
1380 * X = X / Z^2 mod p
1381 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
1383 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1384 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001385
1386 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001387 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001388 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001389 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
1390 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001391
1392 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001393 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001394 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001396
1397cleanup:
1398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001400
1401 return( ret );
1402}
1403
1404/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001405 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001406 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001407 * (See for example Cohen's "A Course in Computational Algebraic Number
1408 * Theory", Algorithm 10.3.4.)
1409 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001410 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001411 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001412 *
1413 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001414 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001415static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001416 mbedtls_ecp_point *T[], size_t T_size )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001417{
1418 int ret;
1419 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001420 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001421
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001422 if( T_size < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001423 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001424
Janos Follathb0697532016-08-18 12:38:46 +01001425#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001426 if( mbedtls_internal_ecp_grp_capable( grp ) )
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001427 return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) );
Janos Follathb0697532016-08-18 12:38:46 +01001428#endif
1429
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001430 if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001431 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001432
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02001433 for( i = 0; i < T_size; i++ )
1434 mbedtls_mpi_init( &c[i] );
1435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001436 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001437
1438 /*
1439 * c[i] = Z_0 * ... * Z_i
1440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001441 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001442 for( i = 1; i < T_size; i++ )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001443 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001444 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001445 MOD_MUL( c[i] );
1446 }
1447
1448 /*
1449 * u = 1 / (Z_0 * ... * Z_n) mod P
1450 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001451 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001452
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001453 for( i = T_size - 1; ; i-- )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001454 {
1455 /*
1456 * Zi = 1 / Z_i mod p
1457 * u = 1 / (Z_0 * ... * Z_i) mod P
1458 */
1459 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001460 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001461 }
1462 else
1463 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001464 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1465 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001466 }
1467
1468 /*
1469 * proceed as in normalize()
1470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1472 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1473 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1474 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi ) ); MOD_MUL( T[i]->Y );
Manuel Pégourié-Gonnard1f789b82013-12-30 17:31:56 +01001475
1476 /*
1477 * Post-precessing: reclaim some memory by shrinking coordinates
1478 * - not storing Z (always 1)
1479 * - shrinking other coordinates, but still keeping the same number of
1480 * limbs as P, as otherwise it will too likely be regrown too fast.
1481 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001482 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1483 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1484 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001485
1486 if( i == 0 )
1487 break;
1488 }
1489
1490cleanup:
1491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001492 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001493 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 mbedtls_mpi_free( &c[i] );
1495 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001496
1497 return( ret );
1498}
1499
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001500/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001501 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1502 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1503 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001504static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1505 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001506 unsigned char inv )
1507{
1508 int ret;
1509 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001510 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001512 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001513
1514 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001515 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1516 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1517 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001518
1519cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001521
1522 return( ret );
1523}
1524
1525/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001526 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001527 *
Peter Dettmance661b22015-02-07 14:43:51 +07001528 * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 .
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001529 *
Peter Dettmance661b22015-02-07 14:43:51 +07001530 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1531 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1532 *
1533 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1534 *
1535 * Cost: 1D := 3M + 4S (A == 0)
1536 * 4M + 4S (A == -3)
1537 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001538 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1540 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001541{
1542 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001543 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001546 dbl_count++;
1547#endif
1548
Janos Follathb0697532016-08-18 12:38:46 +01001549#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001550 if( mbedtls_internal_ecp_grp_capable( grp ) )
1551 return( mbedtls_internal_ecp_double_jac( grp, R, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01001552#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001553
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001554 mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001555
1556 /* Special case for A = -3 */
1557 if( grp->A.p == NULL )
1558 {
Peter Dettmance661b22015-02-07 14:43:51 +07001559 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001560 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1561 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1562 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1563 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1564 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001565 }
1566 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001567 {
Peter Dettmance661b22015-02-07 14:43:51 +07001568 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001569 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1570 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001571
1572 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001573 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001574 {
1575 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001576 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1577 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1578 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1579 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001580 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001581 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001582
Peter Dettmance661b22015-02-07 14:43:51 +07001583 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001584 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1585 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1586 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1587 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001588
Peter Dettmance661b22015-02-07 14:43:51 +07001589 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001590 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1591 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001592
1593 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001594 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1595 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1596 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001597
1598 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001599 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1600 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1601 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001602
1603 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001604 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1605 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001606
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001607 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1608 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1609 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001610
1611cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001612 mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001613
1614 return( ret );
1615}
1616
1617/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001618 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001619 *
1620 * The coordinates of Q must be normalized (= affine),
1621 * but those of P don't need to. R is not normalized.
1622 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001623 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001624 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001625 * - at each step, P, Q and R are multiples of the base point, the factor
1626 * being less than its order, so none of them is zero;
1627 * - Q is an odd multiple of the base point, P an even multiple,
1628 * due to the choice of precomputed points in the modified comb method.
1629 * So branches for these cases do not leak secret information.
1630 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001631 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1632 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001633 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001634 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001635static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1636 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001637{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001638 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001639 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001640
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001642 add_count++;
1643#endif
1644
Janos Follathb0697532016-08-18 12:38:46 +01001645#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001646 if( mbedtls_internal_ecp_grp_capable( grp ) )
1647 return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) );
Janos Follath372697b2016-10-28 16:53:11 +01001648#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001649
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001650 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001651 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001652 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001653 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1654 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001655
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001656 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1657 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001658
1659 /*
1660 * Make sure Q coordinates are normalized
1661 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001662 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1663 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001664
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001665 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1666 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1669 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1670 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1671 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1672 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1673 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001674
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001675 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001677 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001678 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001679 {
1680 ret = ecp_double_jac( grp, R, P );
1681 goto cleanup;
1682 }
1683 else
1684 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001685 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001686 goto cleanup;
1687 }
1688 }
1689
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001690 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1691 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1692 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1693 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1694 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1695 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1696 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1697 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1698 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1699 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1700 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1701 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001703 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1704 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1705 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001706
1707cleanup:
1708
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001709 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1710 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001711
1712 return( ret );
1713}
1714
1715/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001716 * Randomize jacobian coordinates:
1717 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001718 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001719 *
1720 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001721 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001722static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001723 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1724{
1725 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001726 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001727 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001728 int count = 0;
1729
Janos Follathb0697532016-08-18 12:38:46 +01001730#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001731 if( mbedtls_internal_ecp_grp_capable( grp ) )
1732 return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) );
Janos Follath372697b2016-10-28 16:53:11 +01001733#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001734
1735 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001736 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001737
1738 /* Generate l such that 1 < l < p */
1739 do
1740 {
Ronald Cron2e0969a2021-06-10 17:24:02 +02001741 if( count++ > 30 )
Jonas6645fd32020-05-08 16:57:18 +09001742 {
1743 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1744 goto cleanup;
1745 }
Ronald Cron2e0969a2021-06-10 17:24:02 +02001746
1747 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
1748 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, ( p_size * 8 ) - grp->pbits ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001749 }
Ronald Cron2e0969a2021-06-10 17:24:02 +02001750 while( ( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ) ||
1751 ( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001752
1753 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001754 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001755
1756 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001757 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1758 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001759
1760 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001761 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1762 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001763
1764cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001765 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001766
1767 return( ret );
1768}
1769
1770/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001771 * Check and define parameters used by the comb method (see below for details)
1772 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001773#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1774#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001775#endif
1776
1777/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001778#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001779
1780/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001781#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001782
1783/*
1784 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001785 *
1786 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001787 * modified version that provides resistance to SPA by avoiding zero
1788 * digits in the representation as in [3]. We modify the method further by
1789 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001790 * representation uses one more K_i, due to carries, but saves on the size of
1791 * the precomputed table.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001792 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001793 * Summary of the comb method and its modifications:
1794 *
1795 * - The goal is to compute m*P for some w*d-bit integer m.
1796 *
1797 * - The basic comb method splits m into the w-bit integers
1798 * x[0] .. x[d-1] where x[i] consists of the bits in m whose
1799 * index has residue i modulo d, and computes m * P as
1800 * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where
1801 * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P.
1802 *
1803 * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by
1804 * .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] ..,
1805 * thereby successively converting it into a form where all summands
1806 * are nonzero, at the cost of negative summands. This is the basic idea of [3].
1807 *
1808 * - More generally, even if x[i+1] != 0, we can first transform the sum as
1809 * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] ..,
1810 * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]].
1811 * Performing and iterating this procedure for those x[i] that are even
1812 * (keeping track of carry), we can transform the original sum into one of the form
1813 * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]]
1814 * with all x'[i] odd. It is therefore only necessary to know S at odd indices,
1815 * which is why we are only computing half of it in the first place in
1816 * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb.
1817 *
1818 * - For the sake of compactness, only the seven low-order bits of x[i]
1819 * are used to represent its absolute value (K_i in the paper), and the msb
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001820 * of x[i] encodes the sign (s_i in the paper): it is set if and only if
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001821 * if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001822 *
1823 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001824 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001825 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001826 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001827 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1828 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001829 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01001830static void ecp_comb_recode_core( unsigned char x[], size_t d,
1831 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001832{
1833 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001834 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001835
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001836 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001837
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001838 /* First get the classical comb values (except for x_d = 0) */
1839 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001840 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001842
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001843 /* Now make sure x_1 .. x_d are odd */
1844 c = 0;
1845 for( i = 1; i <= d; i++ )
1846 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001847 /* Add carry and update it */
1848 cc = x[i] & c;
1849 x[i] = x[i] ^ c;
1850 c = cc;
1851
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001852 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001853 adjust = 1 - ( x[i] & 0x01 );
1854 c |= x[i] & ( x[i-1] * adjust );
1855 x[i] = x[i] ^ ( x[i-1] * adjust );
1856 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001857 }
1858}
1859
1860/*
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001861 * Precompute points for the adapted comb method
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001862 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001863 * Assumption: T must be able to hold 2^{w - 1} elements.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001864 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001865 * Operation: If i = i_{w-1} ... i_1 is the binary representation of i,
1866 * sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001867 *
1868 * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1)
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001869 *
1870 * Note: Even comb values (those where P would be omitted from the
1871 * sum defining T[i] above) are not needed in our adaption
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001872 * the comb method. See ecp_comb_recode_core().
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001873 *
1874 * This function currently works in four steps:
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001875 * (1) [dbl] Computation of intermediate T[i] for 2-power values of i
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001876 * (2) [norm_dbl] Normalization of coordinates of these T[i]
1877 * (3) [add] Computation of all T[i]
1878 * (4) [norm_add] Normalization of all T[i]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001879 *
1880 * Step 1 can be interrupted but not the others; together with the final
1881 * coordinate normalization they are the largest steps done at once, depending
1882 * on the window size. Here are operation counts for P-256:
1883 *
1884 * step (2) (3) (4)
1885 * w = 5 142 165 208
1886 * w = 4 136 77 160
1887 * w = 3 130 33 136
1888 * w = 2 124 11 124
1889 *
1890 * So if ECC operations are blocking for too long even with a low max_ops
1891 * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order
1892 * to minimize maximum blocking time.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001893 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1895 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001896 unsigned char w, size_t d,
1897 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001898{
1899 int ret;
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001900 unsigned char i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001901 size_t j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001902 const unsigned char T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001903 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001904
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001905#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001906 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001907 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001908 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
1909 goto dbl;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001910 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl )
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001911 goto norm_dbl;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001912 if( rs_ctx->rsm->state == ecp_rsm_pre_add )
1913 goto add;
1914 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add )
1915 goto norm_add;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001916 }
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001917#else
1918 (void) rs_ctx;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001919#endif
1920
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001921#if defined(MBEDTLS_ECP_RESTARTABLE)
1922 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1923 {
1924 rs_ctx->rsm->state = ecp_rsm_pre_dbl;
1925
1926 /* initial state for the loop */
1927 rs_ctx->rsm->i = 0;
1928 }
1929
1930dbl:
1931#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001932 /*
1933 * Set T[0] = P and
1934 * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
1935 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001936 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001937
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001938#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001939 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
1940 j = rs_ctx->rsm->i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001941 else
1942#endif
1943 j = 0;
1944
1945 for( ; j < d * ( w - 1 ); j++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001946 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001947 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL );
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001948
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001949 i = 1U << ( j / d );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001950 cur = T + i;
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001951
1952 if( j % d == 0 )
1953 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
1954
1955 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001956 }
1957
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001958#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001959 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1960 rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl;
1961
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001962norm_dbl:
1963#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001964 /*
1965 * Normalize current elements in T. As T has holes,
1966 * use an auxiliary array of pointers to elements in T.
1967 */
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001968 j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001969 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001970 TT[j++] = T + i;
1971
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001972 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001973
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001974 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001975
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001976#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001977 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1978 rs_ctx->rsm->state = ecp_rsm_pre_add;
1979
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001980add:
1981#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001982 /*
1983 * Compute the remaining ones using the minimal number of additions
1984 * Be careful to update T[2^l] only after using it!
1985 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001986 MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001987
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001988 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001989 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001990 j = i;
1991 while( j-- )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001992 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001993 }
1994
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001995#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001996 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1997 rs_ctx->rsm->state = ecp_rsm_pre_norm_add;
1998
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001999norm_add:
2000#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02002001 /*
Manuel Pégourié-Gonnarda966fde2018-10-23 10:41:11 +02002002 * Normalize final elements in T. Even though there are no holes now, we
2003 * still need the auxiliary array for homogeneity with the previous
2004 * call. Also, skip T[0] which is already normalised, being a copy of P.
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02002005 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002006 for( j = 0; j + 1 < T_size; j++ )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01002007 TT[j] = T + j + 1;
2008
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002009 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01002010
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01002011 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01002012
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002013cleanup:
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002014#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002015 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2016 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01002017 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002018 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002019 rs_ctx->rsm->i = j;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01002020 }
2021#endif
Janos Follathb0697532016-08-18 12:38:46 +01002022
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002023 return( ret );
2024}
2025
2026/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01002027 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002028 *
2029 * See ecp_comb_recode_core() for background
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002030 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002031static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002032 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002033 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002034{
2035 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002036 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002037
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002038 /* Ignore the "sign" bit and scale down */
2039 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002040
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002041 /* Read the whole table to thwart cache-based timing attacks */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002042 for( j = 0; j < T_size; j++ )
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002043 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
2045 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002046 }
2047
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01002048 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002050
2051cleanup:
2052 return( ret );
2053}
2054
2055/*
2056 * Core multiplication algorithm for the (modified) comb method.
2057 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01002058 *
2059 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002060 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002062 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01002063 const unsigned char x[], size_t d,
2064 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002065 void *p_rng,
2066 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002067{
2068 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002069 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002070 size_t i;
2071
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002073
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002074#if !defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002075 (void) rs_ctx;
2076#endif
2077
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002078#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002079 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2080 rs_ctx->rsm->state != ecp_rsm_comb_core )
2081 {
2082 rs_ctx->rsm->i = 0;
2083 rs_ctx->rsm->state = ecp_rsm_comb_core;
2084 }
2085
2086 /* new 'if' instead of nested for the sake of the 'else' branch */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002087 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002088 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002089 /* restore current index (R already pointing to rs_ctx->rsm->R) */
2090 i = rs_ctx->rsm->i;
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002091 }
2092 else
2093#endif
2094 {
2095 /* Start with a non-zero point and randomize its coordinates */
2096 i = d;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002097 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) );
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002098 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002099#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002100 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002101#endif
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002102 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
2103 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002104
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002105 while( i != 0 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002106 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002107 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002108 --i;
2109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002110 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002111 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002112 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002113 }
2114
2115cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002116
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002117 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002118
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002119#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002120 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2121 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002122 {
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002123 rs_ctx->rsm->i = i;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002124 /* no need to save R, already pointing to rs_ctx->rsm->R */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002125 }
2126#endif
2127
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002128 return( ret );
2129}
2130
2131/*
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002132 * Recode the scalar to get constant-time comb multiplication
2133 *
2134 * As the actual scalar recoding needs an odd scalar as a starting point,
2135 * this wrapper ensures that by replacing m by N - m if necessary, and
2136 * informs the caller that the result of multiplication will be negated.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002137 *
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002138 * This works because we only support large prime order for Short Weierstrass
2139 * curves, so N is always odd hence either m or N - m is.
2140 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002141 * See ecp_comb_recode_core() for background.
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002142 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002143static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp,
2144 const mbedtls_mpi *m,
2145 unsigned char k[COMB_MAX_D + 1],
2146 size_t d,
2147 unsigned char w,
2148 unsigned char *parity_trick )
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002149{
2150 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002151 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002152
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002153 mbedtls_mpi_init( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002154 mbedtls_mpi_init( &mm );
2155
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002156 /* N is always odd (see above), just make extra sure */
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002157 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
2158 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
2159
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002160 /* do we need the parity trick? */
2161 *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 );
2162
2163 /* execute parity fix in constant time */
2164 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002165 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002166 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) );
2167
2168 /* actual scalar recoding */
2169 ecp_comb_recode_core( k, d, w, &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002170
2171cleanup:
2172 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002173 mbedtls_mpi_free( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002174
2175 return( ret );
2176}
2177
2178/*
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002179 * Perform comb multiplication (for short Weierstrass curves)
2180 * once the auxiliary table has been pre-computed.
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002181 *
2182 * Scalar recoding may use a parity trick that makes us compute -m * P,
2183 * if that is the case we'll need to recover m * P at the end.
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002184 */
2185static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
2186 mbedtls_ecp_point *R,
2187 const mbedtls_mpi *m,
2188 const mbedtls_ecp_point *T,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002189 unsigned char T_size,
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002190 unsigned char w,
2191 size_t d,
2192 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002193 void *p_rng,
2194 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002195{
2196 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002197 unsigned char parity_trick;
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002198 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002199 mbedtls_ecp_point *RR = R;
2200
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002201#if defined(MBEDTLS_ECP_RESTARTABLE)
2202 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2203 {
2204 RR = &rs_ctx->rsm->R;
2205
2206 if( rs_ctx->rsm->state == ecp_rsm_final_norm )
2207 goto final_norm;
2208 }
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002209#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002210
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002211 MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w,
2212 &parity_trick ) );
2213 MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d,
2214 f_rng, p_rng, rs_ctx ) );
2215 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) );
2216
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002217#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002218 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002219 rs_ctx->rsm->state = ecp_rsm_final_norm;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002220
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002221final_norm:
Manuel Pégourié-Gonnard18b0b3c2020-06-08 09:53:20 +02002222 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002223#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002224 /*
2225 * Knowledge of the jacobian coordinates may leak the last few bits of the
2226 * scalar [1], and since our MPI implementation isn't constant-flow,
2227 * inversion (used for coordinate normalization) may leak the full value
2228 * of its input via side-channels [2].
2229 *
2230 * [1] https://eprint.iacr.org/2003/191
2231 * [2] https://eprint.iacr.org/2020/055
2232 *
2233 * Avoid the leak by randomizing coordinates before we normalize them.
2234 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002235#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002236 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002237#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002238 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) );
2239
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002240 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
2241
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002242#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard28d16282017-08-23 17:33:27 +02002243 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2244 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) );
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002245#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002246
2247cleanup:
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002248 return( ret );
2249}
2250
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002251/*
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002252 * Pick window size based on curve size and whether we optimize for base point
2253 */
2254static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
2255 unsigned char p_eq_g )
2256{
2257 unsigned char w;
2258
2259 /*
2260 * Minimize the number of multiplications, that is minimize
2261 * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
2262 * (see costs of the various parts, with 1S = 1M)
2263 */
2264 w = grp->nbits >= 384 ? 5 : 4;
2265
2266 /*
2267 * If P == G, pre-compute a bit more, since this may be re-used later.
2268 * Just adding one avoids upping the cost of the first mul too much,
2269 * and the memory cost too.
2270 */
2271 if( p_eq_g )
2272 w++;
2273
2274 /*
2275 * Make sure w is within bounds.
2276 * (The last test is useful only for very small curves in the test suite.)
2277 */
2278 if( w > MBEDTLS_ECP_WINDOW_SIZE )
2279 w = MBEDTLS_ECP_WINDOW_SIZE;
2280 if( w >= grp->nbits )
2281 w = 2;
2282
2283 return( w );
2284}
2285
2286/*
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002287 * Multiplication using the comb method - for curves in short Weierstrass form
2288 *
2289 * This function is mainly responsible for administrative work:
2290 * - managing the restart context if enabled
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002291 * - managing the table of precomputed points (passed between the below two
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002292 * functions): allocation, computation, ownership tranfer, freeing.
2293 *
2294 * It delegates the actual arithmetic work to:
2295 * ecp_precompute_comb() and ecp_mul_comb_with_precomp()
2296 *
2297 * See comments on ecp_comb_recode_core() regarding the computation strategy.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002298 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2300 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002301 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002302 void *p_rng,
2303 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002304{
2305 int ret;
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002306 unsigned char w, p_eq_g, i;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002307 size_t d;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002308 unsigned char T_size = 0, T_ok = 0;
2309 mbedtls_ecp_point *T = NULL;
2310#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2311 ecp_drbg_context drbg_ctx;
2312
2313 ecp_drbg_init( &drbg_ctx );
2314#endif
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002315
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002316 ECP_RS_ENTER( rsm );
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +01002317
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002318#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2319 if( f_rng == NULL )
2320 {
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002321 /* Adjust pointers */
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002322 f_rng = &ecp_drbg_random;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002323#if defined(MBEDTLS_ECP_RESTARTABLE)
2324 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2325 p_rng = &rs_ctx->rsm->drbg_ctx;
2326 else
2327#endif
2328 p_rng = &drbg_ctx;
2329
2330 /* Initialize internal DRBG if necessary */
2331#if defined(MBEDTLS_ECP_RESTARTABLE)
2332 if( rs_ctx == NULL || rs_ctx->rsm == NULL ||
2333 rs_ctx->rsm->drbg_seeded == 0 )
2334#endif
2335 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002336 const size_t m_len = ( grp->nbits + 7 ) / 8;
2337 MBEDTLS_MPI_CHK( ecp_drbg_seed( p_rng, m, m_len ) );
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002338 }
2339#if defined(MBEDTLS_ECP_RESTARTABLE)
2340 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2341 rs_ctx->rsm->drbg_seeded = 1;
2342#endif
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002343 }
2344#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2345
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002346 /* Is P the base point ? */
2347#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
2348 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
2349 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard196d1332017-08-28 13:14:27 +02002350#else
2351 p_eq_g = 0;
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002352#endif
2353
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002354 /* Pick window size and deduce related sizes */
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002355 w = ecp_pick_window_size( grp, p_eq_g );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002356 T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002357 d = ( grp->nbits + w - 1 ) / w;
2358
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002359 /* Pre-computed table: do we have it already for the base point? */
2360 if( p_eq_g && grp->T != NULL )
2361 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002362 /* second pointer to the same table, will be deleted on exit */
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002363 T = grp->T;
2364 T_ok = 1;
2365 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002366 else
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002367#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002368 /* Pre-computed table: do we have one in progress? complete? */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002369 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL )
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002370 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002371 /* transfer ownership of T from rsm to local function */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002372 T = rs_ctx->rsm->T;
2373 rs_ctx->rsm->T = NULL;
2374 rs_ctx->rsm->T_size = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002375
Manuel Pégourié-Gonnardb25cb602018-10-16 11:48:09 +02002376 /* This effectively jumps to the call to mul_comb_after_precomp() */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002377 T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002378 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002379 else
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002380#endif
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002381 /* Allocate table if we didn't have any */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002382 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002383 T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002384 if( T == NULL )
2385 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02002386 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002387 goto cleanup;
2388 }
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02002389
2390 for( i = 0; i < T_size; i++ )
2391 mbedtls_ecp_point_init( &T[i] );
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002392
2393 T_ok = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002394 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002395
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002396 /* Compute table (or finish computing it) if not done already */
2397 if( !T_ok )
2398 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002399 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002400
2401 if( p_eq_g )
2402 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002403 /* almost transfer ownership of T to the group, but keep a copy of
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02002404 * the pointer to use for calling the next function more easily */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002405 grp->T = T;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002406 grp->T_size = T_size;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002407 }
2408 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002409
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002410 /* Actual comb multiplication using precomputed points */
2411 MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002412 T, T_size, w, d,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002413 f_rng, p_rng, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002414
2415cleanup:
2416
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002417#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2418 ecp_drbg_free( &drbg_ctx );
2419#endif
2420
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002421 /* does T belong to the group? */
2422 if( T == grp->T )
2423 T = NULL;
2424
2425 /* does T belong to the restart context? */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002426#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002427 if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL )
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002428 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002429 /* transfer ownership of T from local function to rsm */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002430 rs_ctx->rsm->T_size = T_size;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002431 rs_ctx->rsm->T = T;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002432 T = NULL;
2433 }
2434#endif
2435
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002436 /* did T belong to us? then let's destroy it! */
2437 if( T != NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002438 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002439 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440 mbedtls_ecp_point_free( &T[i] );
2441 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002442 }
2443
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002444 /* don't free R while in progress in case R == P */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002445#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002446 if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
2447#endif
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002448 /* prevent caller from using invalid value */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01002449 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002450 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002451
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002452 ECP_RS_LEAVE( rsm );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +01002453
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002454 return( ret );
2455}
2456
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002457#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002458
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002459#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002460/*
2461 * For Montgomery curves, we do all the internal arithmetic in projective
2462 * coordinates. Import/export of points uses only the x coordinates, which is
2463 * internaly represented as X / Z.
2464 *
2465 * For scalar multiplication, we'll use a Montgomery ladder.
2466 */
2467
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002468/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002469 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
2470 * Cost: 1M + 1I
2471 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002472static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002473{
2474 int ret;
2475
Janos Follathb0697532016-08-18 12:38:46 +01002476#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002477 if( mbedtls_internal_ecp_grp_capable( grp ) )
2478 return( mbedtls_internal_ecp_normalize_mxz( grp, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01002479#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002481 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
2482 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
2483 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002484
2485cleanup:
2486 return( ret );
2487}
2488
2489/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002490 * Randomize projective x/z coordinates:
2491 * (X, Z) -> (l X, l Z) for random l
2492 * This is sort of the reverse operation of ecp_normalize_mxz().
2493 *
2494 * This countermeasure was first suggested in [2].
2495 * Cost: 2M
2496 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002497static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002498 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2499{
2500 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01002502 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002503 int count = 0;
2504
Janos Follathb0697532016-08-18 12:38:46 +01002505#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002506 if( mbedtls_internal_ecp_grp_capable( grp ) )
Steven Cooreman4a5ed022021-03-11 13:18:29 +01002507 return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ) );
Janos Follath372697b2016-10-28 16:53:11 +01002508#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002509
2510 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002511 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002512
2513 /* Generate l such that 1 < l < p */
2514 do
2515 {
Ronald Cron2e0969a2021-06-10 17:24:02 +02002516 if( count++ > 30 )
Jonas6645fd32020-05-08 16:57:18 +09002517 {
2518 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
2519 goto cleanup;
2520 }
Ronald Cron2e0969a2021-06-10 17:24:02 +02002521
2522 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
2523 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, ( p_size * 8 ) - grp->pbits ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002524 }
Ronald Cron2e0969a2021-06-10 17:24:02 +02002525 while( ( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ) ||
2526 ( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002528 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
2529 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002530
2531cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002532 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002533
2534 return( ret );
2535}
2536
2537/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002538 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
2539 * for Montgomery curves in x/z coordinates.
2540 *
2541 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
2542 * with
2543 * d = X1
2544 * P = (X2, Z2)
2545 * Q = (X3, Z3)
2546 * R = (X4, Z4)
2547 * S = (X5, Z5)
2548 * and eliminating temporary variables tO, ..., t4.
2549 *
2550 * Cost: 5M + 4S
2551 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002552static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
2553 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
2554 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
2555 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002556{
2557 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002558 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002559
Janos Follathb0697532016-08-18 12:38:46 +01002560#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002561 if( mbedtls_internal_ecp_grp_capable( grp ) )
2562 return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) );
Janos Follath372697b2016-10-28 16:53:11 +01002563#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002565 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
2566 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
2567 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002568
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002569 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
2570 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
2571 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
2572 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
2573 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
2574 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
2575 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
2576 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
2577 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
2578 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
2579 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
2580 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
2581 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
2582 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
2583 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
2584 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
2585 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
2586 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &E, &R->Z ) ); MOD_MUL( R->Z );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002587
2588cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002589 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
2590 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
2591 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002592
2593 return( ret );
2594}
2595
2596/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002597 * Multiplication with Montgomery ladder in x/z coordinates,
2598 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002599 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002600static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2601 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002602 int (*f_rng)(void *, unsigned char *, size_t),
2603 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002604{
2605 int ret;
2606 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002607 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002608 mbedtls_ecp_point RP;
2609 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002610#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2611 ecp_drbg_context drbg_ctx;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002612
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002613 ecp_drbg_init( &drbg_ctx );
2614#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002615 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002616
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002617#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2618 if( f_rng == NULL )
2619 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002620 const size_t m_len = ( grp->nbits + 7 ) / 8;
2621 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002622 f_rng = &ecp_drbg_random;
2623 p_rng = &drbg_ctx;
2624 }
2625#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2626
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002627 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002628 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
2629 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002630
2631 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002632 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
2633 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
2634 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002635
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01002636 /* RP.X might be sligtly larger than P, so reduce it */
2637 MOD_ADD( RP.X );
2638
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002639 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002640#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002641 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002642#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002643 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002644
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002645 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002646 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002647 while( i-- > 0 )
2648 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002649 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002650 /*
2651 * if (b) R = 2R + P else R = 2R,
2652 * which is:
2653 * if (b) double_add( RP, R, RP, R )
2654 * else double_add( R, RP, R, RP )
2655 * but using safe conditional swaps to avoid leaks
2656 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002657 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2658 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
2659 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
2660 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2661 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002662 }
2663
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002664 /*
2665 * Knowledge of the projective coordinates may leak the last few bits of the
2666 * scalar [1], and since our MPI implementation isn't constant-flow,
2667 * inversion (used for coordinate normalization) may leak the full value
2668 * of its input via side-channels [2].
2669 *
2670 * [1] https://eprint.iacr.org/2003/191
2671 * [2] https://eprint.iacr.org/2020/055
2672 *
2673 * Avoid the leak by randomizing coordinates before we normalize them.
2674 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002675#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002676 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002677#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002678 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
2679
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002680 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002681
2682cleanup:
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002683#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2684 ecp_drbg_free( &drbg_ctx );
2685#endif
2686
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002687 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002688
2689 return( ret );
2690}
2691
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002692#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002693
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002694/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002695 * Restartable multiplication R = m * P
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002696 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002697int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002698 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002699 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
2700 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002701{
Janos Follathb0697532016-08-18 12:38:46 +01002702 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00002703#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2704 char is_grp_capable = 0;
2705#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002706 ECP_VALIDATE_RET( grp != NULL );
2707 ECP_VALIDATE_RET( R != NULL );
2708 ECP_VALIDATE_RET( m != NULL );
2709 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002710
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002711#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002712 /* reset ops count for this call if top-level */
2713 if( rs_ctx != NULL && rs_ctx->depth++ == 0 )
2714 rs_ctx->ops_done = 0;
2715#endif
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002716
Janos Follathc44ab972016-11-18 16:38:23 +00002717#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002718 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
Janos Follathc44ab972016-11-18 16:38:23 +00002719 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathc44ab972016-11-18 16:38:23 +00002720#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002721
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002722#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002723 /* skip argument check when restarting */
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002724 if( rs_ctx == NULL || rs_ctx->rsm == NULL )
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002725#endif
2726 {
Manuel Pégourié-Gonnard5314f232017-04-21 12:36:59 +02002727 /* check_privkey is free */
2728 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
2729
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002730 /* Common sanity checks */
2731 MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) );
2732 MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002733 }
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002734
2735 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002736#if defined(ECP_MONTGOMERY)
2737 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002738 MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
Janos Follath430d3372016-11-03 14:25:37 +00002739#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002740#if defined(ECP_SHORTWEIERSTRASS)
2741 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002742 MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) );
Janos Follath430d3372016-11-03 14:25:37 +00002743#endif
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002744
Janos Follath6c8ccd52016-11-29 15:37:09 +00002745cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002746
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002747#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002748 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002749 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002750#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002751
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002752#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002753 if( rs_ctx != NULL )
2754 rs_ctx->depth--;
2755#endif
2756
Janos Follathb0697532016-08-18 12:38:46 +01002757 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002758}
2759
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002760/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002761 * Multiplication R = m * P
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002762 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002763int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002764 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002765 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002766{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002767 ECP_VALIDATE_RET( grp != NULL );
2768 ECP_VALIDATE_RET( R != NULL );
2769 ECP_VALIDATE_RET( m != NULL );
2770 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002771 return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002772}
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002773
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002774#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002775/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002776 * Check that an affine point is valid as a public key,
2777 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002778 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002779static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002780{
2781 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002782 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002783
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002784 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002785 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2786 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2787 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2788 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2789 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002790
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002791 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002792
2793 /*
2794 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002795 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002796 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002797 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2798 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002799
2800 /* Special case for A = -3 */
2801 if( grp->A.p == NULL )
2802 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002803 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002804 }
2805 else
2806 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002807 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002808 }
2809
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002810 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2811 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002812
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002813 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2814 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002815
2816cleanup:
2817
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002818 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002819
2820 return( ret );
2821}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002822#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002823
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002824/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002825 * R = m * P with shortcuts for m == 1 and m == -1
2826 * NOT constant-time - ONLY for short Weierstrass!
2827 */
2828static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2829 mbedtls_ecp_point *R,
2830 const mbedtls_mpi *m,
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002831 const mbedtls_ecp_point *P,
2832 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002833{
2834 int ret;
2835
2836 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2837 {
2838 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2839 }
2840 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2841 {
2842 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2843 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2844 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2845 }
2846 else
2847 {
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002848 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P,
2849 NULL, NULL, rs_ctx ) );
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002850 }
2851
2852cleanup:
2853 return( ret );
2854}
2855
2856/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002857 * Restartable linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002858 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002859 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002860int mbedtls_ecp_muladd_restartable(
2861 mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002862 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002863 const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
2864 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002865{
2866 int ret;
2867 mbedtls_ecp_point mP;
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002868 mbedtls_ecp_point *pmP = &mP;
2869 mbedtls_ecp_point *pR = R;
Janos Follathc44ab972016-11-18 16:38:23 +00002870#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2871 char is_grp_capable = 0;
2872#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002873 ECP_VALIDATE_RET( grp != NULL );
2874 ECP_VALIDATE_RET( R != NULL );
2875 ECP_VALIDATE_RET( m != NULL );
2876 ECP_VALIDATE_RET( P != NULL );
2877 ECP_VALIDATE_RET( n != NULL );
2878 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002879
2880 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2881 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2882
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002883 mbedtls_ecp_point_init( &mP );
2884
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002885 ECP_RS_ENTER( ma );
2886
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002887#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002888 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2889 {
2890 /* redirect intermediate results to restart context */
2891 pmP = &rs_ctx->ma->mP;
2892 pR = &rs_ctx->ma->R;
2893
2894 /* jump to next operation */
2895 if( rs_ctx->ma->state == ecp_rsma_mul2 )
2896 goto mul2;
2897 if( rs_ctx->ma->state == ecp_rsma_add )
2898 goto add;
2899 if( rs_ctx->ma->state == ecp_rsma_norm )
2900 goto norm;
2901 }
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002902#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002903
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002904 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002905#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002906 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002907 rs_ctx->ma->state = ecp_rsma_mul2;
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002908
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002909mul2:
2910#endif
2911 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) );
Janos Follathaf6f2692018-12-07 09:55:24 +00002912
2913#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2914 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
2915 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
2916#endif /* MBEDTLS_ECP_INTERNAL_ALT */
2917
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002918#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002919 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002920 rs_ctx->ma->state = ecp_rsma_add;
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002921
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002922add:
2923#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002924 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002925 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002926#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002927 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002928 rs_ctx->ma->state = ecp_rsma_norm;
Janos Follath430d3372016-11-03 14:25:37 +00002929
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002930norm:
2931#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002932 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002933 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) );
2934
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002935#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002936 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2937 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) );
2938#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002939
2940cleanup:
Janos Follathc44ab972016-11-18 16:38:23 +00002941#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002942 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002943 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002944#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002945
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002946 mbedtls_ecp_point_free( &mP );
2947
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002948 ECP_RS_LEAVE( ma );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002949
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002950 return( ret );
2951}
2952
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002953/*
2954 * Linear combination
2955 * NOT constant-time
2956 */
2957int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2958 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2959 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2960{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002961 ECP_VALIDATE_RET( grp != NULL );
2962 ECP_VALIDATE_RET( R != NULL );
2963 ECP_VALIDATE_RET( m != NULL );
2964 ECP_VALIDATE_RET( P != NULL );
2965 ECP_VALIDATE_RET( n != NULL );
2966 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002967 return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) );
2968}
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002969
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002970#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02002971#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
Manuel Pégourié-Gonnard9f12b112021-06-23 12:53:18 +02002972/* Duplicated macros from ecp_curves.c */
2973#if defined(MBEDTLS_HAVE_INT32)
2974#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
2975 BYTES_TO_T_UINT_4( a, b, c, d ), \
2976 BYTES_TO_T_UINT_4( e, f, g, h )
2977#else /* 64-bits */
2978#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
2979 ( (mbedtls_mpi_uint) (a) << 0 ) | \
2980 ( (mbedtls_mpi_uint) (b) << 8 ) | \
2981 ( (mbedtls_mpi_uint) (c) << 16 ) | \
2982 ( (mbedtls_mpi_uint) (d) << 24 ) | \
2983 ( (mbedtls_mpi_uint) (e) << 32 ) | \
2984 ( (mbedtls_mpi_uint) (f) << 40 ) | \
2985 ( (mbedtls_mpi_uint) (g) << 48 ) | \
2986 ( (mbedtls_mpi_uint) (h) << 56 )
2987#endif /* bits in mbedtls_mpi_uint */
2988#define ECP_MPI_INIT(s, n, p) {s, (n), (mbedtls_mpi_uint *)(p)}
2989#define ECP_MPI_INIT_ARRAY(x) \
2990 ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x)
2991/*
2992 * Constants for the two points other than 0, 1, -1 (mod p) in
2993 * https://cr.yp.to/ecdh.html#validate
2994 * See ecp_check_pubkey_x25519().
2995 */
2996static const mbedtls_mpi_uint x25519_bad_point_1[] = {
2997 BYTES_TO_T_UINT_8( 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae ),
2998 BYTES_TO_T_UINT_8( 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a ),
2999 BYTES_TO_T_UINT_8( 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd ),
3000 BYTES_TO_T_UINT_8( 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 ),
3001};
3002static const mbedtls_mpi_uint x25519_bad_point_2[] = {
3003 BYTES_TO_T_UINT_8( 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24 ),
3004 BYTES_TO_T_UINT_8( 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b ),
3005 BYTES_TO_T_UINT_8( 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86 ),
3006 BYTES_TO_T_UINT_8( 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 ),
3007};
3008static const mbedtls_mpi ecp_x25519_bad_point_1 = ECP_MPI_INIT_ARRAY(
3009 x25519_bad_point_1 );
3010static const mbedtls_mpi ecp_x25519_bad_point_2 = ECP_MPI_INIT_ARRAY(
3011 x25519_bad_point_2 );
Manuel Pégourié-Gonnard6ec15352021-06-23 12:25:48 +02003012
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003013/*
3014 * Check that the input point is not one of the low-order points.
3015 * This is recommended by the "May the Fourth" paper:
3016 * https://eprint.iacr.org/2017/806.pdf
3017 * Those points are never sent by an honest peer.
3018 */
3019static int ecp_check_pubkey_x25519( const mbedtls_mpi *X, const mbedtls_mpi *P )
3020{
3021 int ret;
Manuel Pégourié-Gonnard6ec15352021-06-23 12:25:48 +02003022 mbedtls_mpi XmP;
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003023
3024 mbedtls_mpi_init( &XmP );
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003025
3026 /* Reduce X mod P so that we only need to check values less than P.
3027 * We know X < 2^256 so we can proceed by subtraction. */
3028 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &XmP, X ) );
3029 while( mbedtls_mpi_cmp_mpi( &XmP, P ) >= 0 )
3030 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &XmP, &XmP, P ) );
3031
3032 /* Check against the known bad values that are less than P in the
3033 * following list: https://cr.yp.to/ecdh.html#validate */
3034 if( mbedtls_mpi_cmp_int( &XmP, 1 ) <= 0 ) /* takes care of 0 and 1 */
3035 return( MBEDTLS_ERR_ECP_INVALID_KEY );
3036
Manuel Pégourié-Gonnard9f12b112021-06-23 12:53:18 +02003037 if( mbedtls_mpi_cmp_mpi( &XmP, &ecp_x25519_bad_point_1 ) == 0 )
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003038 return( MBEDTLS_ERR_ECP_INVALID_KEY );
3039
Manuel Pégourié-Gonnard9f12b112021-06-23 12:53:18 +02003040 if( mbedtls_mpi_cmp_mpi( &XmP, &ecp_x25519_bad_point_2 ) == 0 )
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003041 return( MBEDTLS_ERR_ECP_INVALID_KEY );
3042
Manuel Pégourié-Gonnard6ec15352021-06-23 12:25:48 +02003043 /* Final check: check if XmP + 1 is P (final because it changes XmP!) */
3044 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &XmP, &XmP, 1 ) );
3045 if( mbedtls_mpi_cmp_mpi( &XmP, P ) == 0 )
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003046 return( MBEDTLS_ERR_ECP_INVALID_KEY );
3047
3048 ret = 0;
3049
3050cleanup:
3051 mbedtls_mpi_free( &XmP );
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003052
3053 return( ret );
3054}
3055#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
3056
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003057/*
3058 * Check validity of a public key for Montgomery curves with x-only schemes
3059 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003060static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003061{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02003062 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003063 /* Allow any public value, if it's too big then we'll just reduce it mod p
3064 * (RFC 7748 sec. 5 para. 3). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003065 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
3066 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003067
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003068 /* Implicit in all standards (as they don't consider negative numbers):
3069 * X must be non-negative. This is normally ensured by the way it's
3070 * encoded for transmission, but let's be extra sure. */
3071 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 )
3072 return( MBEDTLS_ERR_ECP_INVALID_KEY );
3073
3074#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
3075 if( grp->id == MBEDTLS_ECP_DP_CURVE25519 )
3076 return( ecp_check_pubkey_x25519( &pt->X, &grp->P ) );
3077#endif
3078
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003079 return( 0 );
3080}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003081#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003082
3083/*
3084 * Check that a point is valid as a public key
3085 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003086int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp,
3087 const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003088{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003089 ECP_VALIDATE_RET( grp != NULL );
3090 ECP_VALIDATE_RET( pt != NULL );
3091
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003092 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003093 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
3094 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003095
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003096#if defined(ECP_MONTGOMERY)
3097 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003098 return( ecp_check_pubkey_mx( grp, pt ) );
3099#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003100#if defined(ECP_SHORTWEIERSTRASS)
3101 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003102 return( ecp_check_pubkey_sw( grp, pt ) );
3103#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003104 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003105}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003106
3107/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003108 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003109 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003110int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp,
3111 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003112{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003113 ECP_VALIDATE_RET( grp != NULL );
3114 ECP_VALIDATE_RET( d != NULL );
3115
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003116#if defined(ECP_MONTGOMERY)
3117 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003118 {
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003119 /* see RFC 7748 sec. 5 para. 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003120 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
3121 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02003122 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003123 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003124
3125 /* see [Curve25519] page 5 */
3126 if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 )
3127 return( MBEDTLS_ERR_ECP_INVALID_KEY );
3128
3129 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003130 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003131#endif /* ECP_MONTGOMERY */
3132#if defined(ECP_SHORTWEIERSTRASS)
3133 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003134 {
3135 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003136 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
3137 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
3138 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003139 else
3140 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003141 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003142#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003144 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003145}
3146
3147/*
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003148 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003149 */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003150int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
3151 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003152 int (*f_rng)(void *, unsigned char *, size_t),
3153 void *p_rng )
3154{
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003155 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003156 size_t n_size;
Manuel Pégourié-Gonnardac127672021-06-01 12:06:57 +02003157#if defined(ECP_SHORTWEIERSTRASS)
3158 mbedtls_mpi one;
3159
3160 mbedtls_mpi_init( &one );
3161#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003162
3163 ECP_VALIDATE_RET( grp != NULL );
3164 ECP_VALIDATE_RET( d != NULL );
3165 ECP_VALIDATE_RET( f_rng != NULL );
3166
3167 n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003168
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003169#if defined(ECP_MONTGOMERY)
3170 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003171 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003172 /* [M225] page 5 */
3173 size_t b;
3174
Janos Follath98e28a72016-05-31 14:03:54 +01003175 do {
3176 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
3177 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003178
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003179 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02003180 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003181 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003182 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003183 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003184 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003185
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003186 /* Make sure the last two bits are unset for Curve448, three bits for
3187 Curve25519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003188 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
3189 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003190 if( grp->nbits == 254 )
3191 {
3192 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
3193 }
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003194 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003195#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003196
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003197#if defined(ECP_SHORTWEIERSTRASS)
3198 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003199 {
3200 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003201 int count = 0;
Manuel Pégourié-Gonnardac127672021-06-01 12:06:57 +02003202 unsigned lt_lower = 1, lt_upper = 0;
3203
3204 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &one, grp->N.n ) );
3205 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01003206
3207 /*
3208 * Match the procedure given in RFC 6979 (deterministic ECDSA):
3209 * - use the same byte ordering;
3210 * - keep the leftmost nbits bits of the generated octet string;
3211 * - try until result is in the desired range.
3212 * This also avoids any biais, which is especially important for ECDSA.
3213 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003214 do
3215 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01003216 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003217 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003218
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01003219 /*
3220 * Each try has at worst a probability 1/2 of failing (the msb has
3221 * a probability 1/2 of being 0, and then the result will be < N),
3222 * so after 30 tries failure probability is a most 2**(-30).
3223 *
3224 * For most curves, 1 try is enough with overwhelming probability,
3225 * since N starts with a lot of 1s in binary, but some curves
3226 * such as secp224k1 are actually very close to the worst case.
3227 */
Manuel Pégourié-Gonnard67543962017-04-21 13:19:43 +02003228 if( ++count > 30 )
Janos Follath4c3408b2019-09-16 14:27:39 +01003229 {
Manuel Pégourié-Gonnardac127672021-06-01 12:06:57 +02003230 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
Janos Follath4c3408b2019-09-16 14:27:39 +01003231 goto cleanup;
3232 }
Manuel Pégourié-Gonnardac127672021-06-01 12:06:57 +02003233
3234 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( d, &grp->N, &lt_upper ) );
3235 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( d, &one, &lt_lower ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003236 }
Manuel Pégourié-Gonnardac127672021-06-01 12:06:57 +02003237 while( lt_lower != 0 || lt_upper == 0 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003238 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003239#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003240
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003241cleanup:
Manuel Pégourié-Gonnardac127672021-06-01 12:06:57 +02003242#if defined(ECP_SHORTWEIERSTRASS)
3243 mbedtls_mpi_free( &one );
3244#endif
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003245 return( ret );
3246}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003247
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003248/*
3249 * Generate a keypair with configurable base point
3250 */
3251int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
3252 const mbedtls_ecp_point *G,
3253 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3254 int (*f_rng)(void *, unsigned char *, size_t),
3255 void *p_rng )
3256{
3257 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003258 ECP_VALIDATE_RET( grp != NULL );
3259 ECP_VALIDATE_RET( d != NULL );
3260 ECP_VALIDATE_RET( G != NULL );
3261 ECP_VALIDATE_RET( Q != NULL );
3262 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003263
3264 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
3265 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
3266
3267cleanup:
3268 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003269}
3270
3271/*
3272 * Generate key pair, wrapper for conventional base point
3273 */
3274int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
3275 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3276 int (*f_rng)(void *, unsigned char *, size_t),
3277 void *p_rng )
3278{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003279 ECP_VALIDATE_RET( grp != NULL );
3280 ECP_VALIDATE_RET( d != NULL );
3281 ECP_VALIDATE_RET( Q != NULL );
3282 ECP_VALIDATE_RET( f_rng != NULL );
3283
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003284 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003285}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01003286
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003287/*
3288 * Generate a keypair, prettier wrapper
3289 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003290int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003291 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
3292{
3293 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003294 ECP_VALIDATE_RET( key != NULL );
3295 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003296
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003297 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003298 return( ret );
3299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003300 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003301}
3302
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003303/*
3304 * Check a public-private key pair
3305 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003306int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003307{
3308 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003309 mbedtls_ecp_point Q;
3310 mbedtls_ecp_group grp;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003311 ECP_VALIDATE_RET( pub != NULL );
3312 ECP_VALIDATE_RET( prv != NULL );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003313
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003314 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003315 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003316 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
3317 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
3318 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003319 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003320 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003321 }
3322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003323 mbedtls_ecp_point_init( &Q );
3324 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003326 /* mbedtls_ecp_mul() needs a non-const group... */
3327 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003328
3329 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003330 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003332 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
3333 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
3334 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003335 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003336 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003337 goto cleanup;
3338 }
3339
3340cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003341 mbedtls_ecp_point_free( &Q );
3342 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003343
3344 return( ret );
3345}
3346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003347#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003348
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003349#if defined(ECP_ONE_STEP_KDF)
3350/*
3351 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
3352 * but unofficial ones can be found at:
3353 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
3354 *
3355 * We only use the ones with empty fixedInfo, and for brevity's sake, only
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003356 * 40-bytes output (with SHA-256 that's more than one block, and with SHA-512
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +02003357 * less than one block).
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003358 */
3359#if defined(MBEDTLS_SHA512_C)
3360
3361static const uint8_t test_kdf_z[16] = {
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003362 0x3b, 0xa9, 0x79, 0xe9, 0xbc, 0x5e, 0x3e, 0xc7,
3363 0x61, 0x30, 0x36, 0xb6, 0xf5, 0x1c, 0xd5, 0xaa,
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003364};
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003365static const uint8_t test_kdf_out[40] = {
3366 0x3e, 0xf6, 0xda, 0xf9, 0x51, 0x60, 0x70, 0x5f,
3367 0xdf, 0x21, 0xcd, 0xab, 0xac, 0x25, 0x7b, 0x05,
3368 0xfe, 0xc1, 0xab, 0x7c, 0xc9, 0x68, 0x43, 0x25,
3369 0x8a, 0xfc, 0x40, 0x6e, 0x5b, 0xf7, 0x98, 0x27,
3370 0x10, 0xfa, 0x7b, 0x93, 0x52, 0xd4, 0x16, 0xaa,
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003371};
3372
3373#elif defined(MBEDTLS_SHA256_C)
3374
3375static const uint8_t test_kdf_z[16] = {
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003376 0xc8, 0x3e, 0x35, 0x8e, 0x99, 0xa6, 0x89, 0xc6,
3377 0x7d, 0xb4, 0xfe, 0x39, 0xcf, 0x8f, 0x26, 0xe1,
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003378};
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003379static const uint8_t test_kdf_out[40] = {
3380 0x7d, 0xf6, 0x41, 0xf8, 0x3c, 0x47, 0xdc, 0x28,
3381 0x5f, 0x7f, 0xaa, 0xde, 0x05, 0x64, 0xd6, 0x25,
3382 0x00, 0x6a, 0x47, 0xd9, 0x1e, 0xa4, 0xa0, 0x8c,
3383 0xd7, 0xf7, 0x0c, 0x99, 0xaa, 0xa0, 0x72, 0x66,
3384 0x69, 0x0e, 0x25, 0xaa, 0xa1, 0x63, 0x14, 0x79,
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003385};
3386
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003387#endif
3388
3389static int ecp_kdf_self_test( void )
3390{
3391 int ret;
3392 ecp_drbg_context kdf_ctx;
3393 mbedtls_mpi scalar;
3394 uint8_t out[sizeof( test_kdf_out )];
3395
3396 ecp_drbg_init( &kdf_ctx );
3397 mbedtls_mpi_init( &scalar );
3398 memset( out, 0, sizeof( out ) );
3399
3400 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
3401 test_kdf_z, sizeof( test_kdf_z ) ) );
3402
3403 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
3404 &scalar, sizeof( test_kdf_z ) ) );
3405
3406 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
3407
3408 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
3409 ret = -1;
3410
3411cleanup:
3412 ecp_drbg_free( &kdf_ctx );
3413 mbedtls_mpi_free( &scalar );
3414
3415 return( ret );
3416}
3417#endif /* ECP_ONE_STEP_KDF */
3418
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01003419/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003420 * Checkup routine
3421 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003422int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003423{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003424 int ret;
3425 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003426 mbedtls_ecp_group grp;
3427 mbedtls_ecp_point R, P;
3428 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003429 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003430 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02003431 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003432 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003433 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003434 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003435 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003436 "400000000000000000000000000000000000000000000000", /* one and zeros */
3437 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
3438 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003439 };
3440
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003441 mbedtls_ecp_group_init( &grp );
3442 mbedtls_ecp_point_init( &R );
3443 mbedtls_ecp_point_init( &P );
3444 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003445
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003446 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003447#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003448 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02003449#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003450 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003451#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003452
3453 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003454 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003455
3456 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003457 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
3458 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003459
3460 add_count = 0;
3461 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003462 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003463 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3464 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003465
3466 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3467 {
3468 add_c_prev = add_count;
3469 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003470 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003471 add_count = 0;
3472 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003473 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003475 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3476 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003477
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003478 if( add_count != add_c_prev ||
3479 dbl_count != dbl_c_prev ||
3480 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003481 {
3482 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003483 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003484
3485 ret = 1;
3486 goto cleanup;
3487 }
3488 }
3489
3490 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003491 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003492
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003493 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003494 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003495 /* We computed P = 2G last time, use it */
3496
3497 add_count = 0;
3498 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003499 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003500 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3501 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003502
3503 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3504 {
3505 add_c_prev = add_count;
3506 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003507 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003508 add_count = 0;
3509 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003510 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003512 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3513 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003514
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003515 if( add_count != add_c_prev ||
3516 dbl_count != dbl_c_prev ||
3517 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003518 {
3519 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003520 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003521
3522 ret = 1;
3523 goto cleanup;
3524 }
3525 }
3526
3527 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003528 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003529
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003530#if defined(ECP_ONE_STEP_KDF)
3531 if( verbose != 0 )
3532 mbedtls_printf( " ECP test #3 (internal KDF): " );
3533
3534 ret = ecp_kdf_self_test();
3535 if( ret != 0 )
3536 {
3537 if( verbose != 0 )
3538 mbedtls_printf( "failed\n" );
3539
3540 ret = 1;
3541 goto cleanup;
3542 }
3543
3544 if( verbose != 0 )
3545 mbedtls_printf( "passed\n" );
3546#endif /* ECP_ONE_STEP_KDF */
3547
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003548cleanup:
3549
3550 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003551 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003553 mbedtls_ecp_group_free( &grp );
3554 mbedtls_ecp_point_free( &R );
3555 mbedtls_ecp_point_free( &P );
3556 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003557
3558 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003559 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003560
3561 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003562}
3563
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003564#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003565
Janos Follathb0697532016-08-18 12:38:46 +01003566#endif /* !MBEDTLS_ECP_ALT */
3567
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003568#endif /* MBEDTLS_ECP_C */