blob: 91fbe3b9fda26775336a73429951655121e6e0f7 [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 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010020 */
21
22/*
23 * References:
24 *
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +010025 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +010026 * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +010027 * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +010028 * RFC 4492 for the related TLS structures and constants
Nicholas Wilson08f3ef12015-11-10 13:10:01 +000029 * RFC 7748 for the Curve448 and Curve25519 curve definitions
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020030 *
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +020031 * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +010032 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020033 * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020034 * for elliptic curve cryptosystems. In : Cryptographic Hardware and
35 * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
36 * <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010037 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020038 * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010039 * render ECC resistant against Side Channel Attacks. IACR Cryptology
40 * ePrint Archive, 2004, vol. 2004, p. 342.
41 * <http://eprint.iacr.org/2004/342.pdf>
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010042 */
43
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000045#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020046#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020048#endif
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010049
Janos Follath683c5822018-12-07 12:09:25 +000050/**
51 * \brief Function level alternative implementation.
52 *
53 * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to
54 * replace certain functions in this module. The alternative implementations are
55 * typically hardware accelerators and need to activate the hardware before the
56 * computation starts and deactivate it after it finishes. The
57 * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve
58 * this purpose.
59 *
60 * To preserve the correct functionality the following conditions must hold:
61 *
62 * - The alternative implementation must be activated by
63 * mbedtls_internal_ecp_init() before any of the replaceable functions is
64 * called.
65 * - mbedtls_internal_ecp_free() must \b only be called when the alternative
66 * implementation is activated.
67 * - mbedtls_internal_ecp_init() must \b not be called when the alternative
68 * implementation is activated.
69 * - Public functions must not return while the alternative implementation is
70 * activated.
71 * - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and
72 * before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) )
73 * \endcode ensures that the alternative implementation supports the current
74 * group.
75 */
76#if defined(MBEDTLS_ECP_INTERNAL_ALT)
77#endif
78
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020079#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010080
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000081#include "mbedtls/ecp.h"
Janos Follath430d3372016-11-03 14:25:37 +000082#include "mbedtls/threading.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050083#include "mbedtls/platform_util.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020084
Rich Evans00ab4702015-02-06 13:43:58 +000085#include <string.h>
86
Janos Follathb0697532016-08-18 12:38:46 +010087#if !defined(MBEDTLS_ECP_ALT)
88
Hanno Becker4f8e8e52018-12-14 15:08:03 +000089/* Parameter validation macros based on platform_util.h */
90#define ECP_VALIDATE_RET( cond ) \
91 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
92#define ECP_VALIDATE( cond ) \
93 MBEDTLS_INTERNAL_VALIDATE( cond )
94
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020095#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000096#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020097#else
Rich Evans00ab4702015-02-06 13:43:58 +000098#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000099#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200101#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +0200103#endif
104
Janos Follath47d28f02016-11-01 13:22:05 +0000105#include "mbedtls/ecp_internal.h"
Janos Follathb0697532016-08-18 12:38:46 +0100106
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200107#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200108#if defined(MBEDTLS_HMAC_DRBG_C)
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200109#include "mbedtls/hmac_drbg.h"
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200110#elif defined(MBEDTLS_CTR_DRBG_C)
111#include "mbedtls/ctr_drbg.h"
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200112#elif defined(MBEDTLS_SHA512_C)
113#include "mbedtls/sha512.h"
114#elif defined(MBEDTLS_SHA256_C)
115#include "mbedtls/sha256.h"
116#elif defined(MBEDTLS_SHA1_C)
117#include "mbedtls/sha1.h"
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200118#else
119#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
120#endif
121#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
122
Manuel Pégourié-Gonnard0223ab92015-10-05 11:40:01 +0100123#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
124 !defined(inline) && !defined(__cplusplus)
Paul Bakker6a6087e2013-10-28 18:53:08 +0100125#define inline __inline
Manuel Pégourié-Gonnard20af64d2015-07-07 18:33:39 +0200126#endif
Paul Bakker6a6087e2013-10-28 18:53:08 +0100127
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100129/*
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100130 * Counts of point addition and doubling, and field multiplications.
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +0200131 * Used to test resistance of point multiplication to simple timing attacks.
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100132 */
Manuel Pégourié-Gonnard43863ee2013-12-01 16:51:27 +0100133static unsigned long add_count, dbl_count, mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100134#endif
135
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200136#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
137/*
138 * Currently ecp_mul() takes a RNG function as an argument, used for
Manuel Pégourié-Gonnard0defc572020-06-10 09:18:25 +0200139 * side-channel protection, but it can be NULL. The initial reasoning was
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200140 * that people will pass non-NULL RNG when they care about side-channels, but
141 * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with
142 * no opportunity for the user to do anything about it.
143 *
144 * The obvious strategies for addressing that include:
145 * - change those APIs so that they take RNG arguments;
146 * - require a global RNG to be available to all crypto modules.
147 *
148 * Unfortunately those would break compatibility. So what we do instead is
149 * have our own internal DRBG instance, seeded from the secret scalar.
150 *
151 * The following is a light-weight abstraction layer for doing that with
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200152 * HMAC_DRBG (first choice) or CTR_DRBG.
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200153 */
154
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200155#if defined(MBEDTLS_HMAC_DRBG_C)
156
157/* DRBG context type */
158typedef mbedtls_hmac_drbg_context ecp_drbg_context;
159
160/* DRBG context init */
161static inline void ecp_drbg_init( ecp_drbg_context *ctx )
162{
163 mbedtls_hmac_drbg_init( ctx );
164}
165
166/* DRBG context free */
167static inline void ecp_drbg_free( ecp_drbg_context *ctx )
168{
169 mbedtls_hmac_drbg_free( ctx );
170}
171
172/* DRBG function */
173static inline int ecp_drbg_random( void *p_rng,
174 unsigned char *output, size_t output_len )
175{
176 return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) );
177}
178
179/* DRBG context seeding */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200180static int ecp_drbg_seed( ecp_drbg_context *ctx,
181 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200182{
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200183 int ret;
184 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200185 /* The list starts with strong hashes */
186 const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
187 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
188
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200189 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
190 secret_bytes, secret_len ) );
191
192 ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len );
193
194cleanup:
195 mbedtls_platform_zeroize( secret_bytes, secret_len );
196
197 return( ret );
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200198}
199
200#elif defined(MBEDTLS_CTR_DRBG_C)
201
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200202/* DRBG context type */
203typedef mbedtls_ctr_drbg_context ecp_drbg_context;
204
205/* DRBG context init */
206static inline void ecp_drbg_init( ecp_drbg_context *ctx )
207{
208 mbedtls_ctr_drbg_init( ctx );
209}
210
211/* DRBG context free */
212static inline void ecp_drbg_free( ecp_drbg_context *ctx )
213{
214 mbedtls_ctr_drbg_free( ctx );
215}
216
217/* DRBG function */
218static inline int ecp_drbg_random( void *p_rng,
219 unsigned char *output, size_t output_len )
220{
221 return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
222}
223
224/*
225 * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
226 * we need to pass an entropy function when seeding. So we use a dummy
227 * function for that, and pass the actual entropy as customisation string.
228 * (During seeding of CTR_DRBG the entropy input and customisation string are
229 * concatenated before being used to update the secret state.)
230 */
231static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
232{
233 (void) ctx;
234 memset( out, 0, len );
235 return( 0 );
236}
237
238/* DRBG context seeding */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200239static int ecp_drbg_seed( ecp_drbg_context *ctx,
240 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200241{
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200242 int ret;
243 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200244
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200245 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
246 secret_bytes, secret_len ) );
247
248 ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
249 secret_bytes, secret_len );
250
251cleanup:
252 mbedtls_platform_zeroize( secret_bytes, secret_len );
253
254 return( ret );
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200255}
256
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200257#elif defined(MBEDTLS_SHA512_C) || \
258 defined(MBEDTLS_SHA256_C) || \
259 defined(MBEDTLS_SHA1_C)
260
261/* This will be used in the self-test function */
262#define ECP_ONE_STEP_KDF
263
264/*
265 * We need to expand secret data (the scalar) into a longer stream of bytes.
266 *
267 * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash
268 * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for
269 * convenience, this is not a full-fledged DRBG, but we don't need one here.)
270 *
271 * We need a basic hash abstraction layer to use whatever SHA is available.
272 */
273#if defined(MBEDTLS_SHA512_C)
274
275#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 );
276#define HASH_BLOCK_BYTES ( 512 / 8 )
277
278#elif defined(MBEDTLS_SHA256_C)
279
280#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 );
281#define HASH_BLOCK_BYTES ( 256 / 8 )
282
283#else // from a previous #if we know that SHA-1 is available if SHA-2 isn't
284
285#define HASH_FUNC mbedtls_sha1_ret
286#define HASH_BLOCK_BYTES ( 160 / 8 )
287
288#endif /* SHA512/SHA256/SHA1 abstraction */
289
290/*
291 * State consists of a 32-bit counter plus the secret value.
292 *
293 * We stored them concatenated in a single buffer as that's what will get
294 * passed to the hash function.
295 */
296typedef struct {
297 size_t total_len;
298 uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES];
299} ecp_drbg_context;
300
301static void ecp_drbg_init( ecp_drbg_context *ctx )
302{
303 memset( ctx, 0, sizeof( ecp_drbg_context ) );
304}
305
306static void ecp_drbg_free( ecp_drbg_context *ctx )
307{
308 mbedtls_platform_zeroize( ctx, sizeof( ecp_drbg_context ) );
309}
310
311static int ecp_drbg_seed( ecp_drbg_context *ctx,
312 const mbedtls_mpi *secret, size_t secret_len )
313{
314 ctx->total_len = 4 + secret_len;
315 memset( ctx->buf, 0, 4);
316 return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) );
317}
318
319static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
320{
321 ecp_drbg_context *ctx = p_rng;
322 int ret;
323 size_t len_done = 0;
324
325 while( len_done < output_len )
326 {
327 uint8_t tmp[HASH_BLOCK_BYTES];
328 uint8_t use_len;
329
330 /* We don't need to draw more that 255 blocks, so don't bother with
331 * carry propagation and just return an error instead. */
332 ctx->buf[3] += 1;
333 if( ctx->buf[3] == 0 )
334 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
335
336 ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
337 if( ret != 0 )
338 return( ret );
339
340 if( output_len - len_done > HASH_BLOCK_BYTES )
341 use_len = HASH_BLOCK_BYTES;
342 else
343 use_len = output_len - len_done;
344
345 memcpy( output + len_done, tmp, use_len );
346 len_done += use_len;
347 }
348
349 return( 0 );
350}
351
352#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200353#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200354#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200355#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
356
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200357#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100358/*
359 * Maximum number of "basic operations" to be done in a row.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +0200360 *
361 * Default value 0 means that ECC operations will not yield.
362 * Note that regardless of the value of ecp_max_ops, always at
363 * least one step is performed before yielding.
364 *
365 * Setting ecp_max_ops=1 can be suitable for testing purposes
366 * as it will interrupt computation at all possible points.
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100367 */
368static unsigned ecp_max_ops = 0;
369
370/*
371 * Set ecp_max_ops
372 */
373void mbedtls_ecp_set_max_ops( unsigned max_ops )
374{
375 ecp_max_ops = max_ops;
376}
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100377
378/*
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200379 * Check if restart is enabled
380 */
Manuel Pégourié-Gonnardb843b152018-10-16 10:41:31 +0200381int mbedtls_ecp_restart_is_enabled( void )
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200382{
383 return( ecp_max_ops != 0 );
384}
385
386/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200387 * Restart sub-context for ecp_mul_comb()
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100388 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200389struct mbedtls_ecp_restart_mul
390{
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100391 mbedtls_ecp_point R; /* current intermediate result */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +0100392 size_t i; /* current index in various loops, 0 outside */
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100393 mbedtls_ecp_point *T; /* table for precomputed points */
394 unsigned char T_size; /* number of points in table T */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200395 enum { /* what were we doing last time we returned? */
396 ecp_rsm_init = 0, /* nothing so far, dummy initial state */
397 ecp_rsm_pre_dbl, /* precompute 2^n multiples */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100398 ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */
399 ecp_rsm_pre_add, /* precompute remaining points by adding */
400 ecp_rsm_pre_norm_add, /* normalize all precomputed points */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200401 ecp_rsm_comb_core, /* ecp_mul_comb_core() */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100402 ecp_rsm_final_norm, /* do the final normalization */
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100403 } state;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200404#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
405 ecp_drbg_context drbg_ctx;
406 unsigned char drbg_seeded;
407#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100408};
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100409
410/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200411 * Init restart_mul sub-context
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100412 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200413static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100414{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200415 mbedtls_ecp_point_init( &ctx->R );
416 ctx->i = 0;
417 ctx->T = NULL;
418 ctx->T_size = 0;
419 ctx->state = ecp_rsm_init;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200420#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
421 ecp_drbg_init( &ctx->drbg_ctx );
422 ctx->drbg_seeded = 0;
423#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100424}
425
426/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200427 * Free the components of a restart_mul sub-context
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100428 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200429static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100430{
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100431 unsigned char i;
432
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100433 if( ctx == NULL )
434 return;
Manuel Pégourié-Gonnard78d564a2017-03-14 11:48:38 +0100435
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100436 mbedtls_ecp_point_free( &ctx->R );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100437
Manuel Pégourié-Gonnard31f0ef72017-05-17 10:05:58 +0200438 if( ctx->T != NULL )
439 {
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100440 for( i = 0; i < ctx->T_size; i++ )
441 mbedtls_ecp_point_free( ctx->T + i );
442 mbedtls_free( ctx->T );
443 }
444
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200445#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
446 ecp_drbg_free( &ctx->drbg_ctx );
447#endif
448
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200449 ecp_restart_rsm_init( ctx );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100450}
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100451
452/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200453 * Restart context for ecp_muladd()
454 */
455struct mbedtls_ecp_restart_muladd
456{
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200457 mbedtls_ecp_point mP; /* mP value */
458 mbedtls_ecp_point R; /* R intermediate result */
459 enum { /* what should we do next? */
460 ecp_rsma_mul1 = 0, /* first multiplication */
461 ecp_rsma_mul2, /* second multiplication */
462 ecp_rsma_add, /* addition */
463 ecp_rsma_norm, /* normalization */
464 } state;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200465};
466
467/*
468 * Init restart_muladd sub-context
469 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200470static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200471{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200472 mbedtls_ecp_point_init( &ctx->mP );
473 mbedtls_ecp_point_init( &ctx->R );
474 ctx->state = ecp_rsma_mul1;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200475}
476
477/*
478 * Free the components of a restart_muladd sub-context
479 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200480static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200481{
482 if( ctx == NULL )
483 return;
484
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200485 mbedtls_ecp_point_free( &ctx->mP );
486 mbedtls_ecp_point_free( &ctx->R );
487
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200488 ecp_restart_ma_init( ctx );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200489}
490
491/*
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200492 * Initialize a restart context
493 */
494void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx )
495{
Hanno Becker80f71682018-12-18 23:44:43 +0000496 ECP_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200497 ctx->ops_done = 0;
498 ctx->depth = 0;
499 ctx->rsm = NULL;
500 ctx->ma = NULL;
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200501}
502
503/*
504 * Free the components of a restart context
505 */
506void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx )
507{
508 if( ctx == NULL )
509 return;
510
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200511 ecp_restart_rsm_free( ctx->rsm );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200512 mbedtls_free( ctx->rsm );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200513
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200514 ecp_restart_ma_free( ctx->ma );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200515 mbedtls_free( ctx->ma );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200516
517 mbedtls_ecp_restart_init( ctx );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200518}
519
520/*
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100521 * Check if we can do the next step
522 */
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +0200523int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
524 mbedtls_ecp_restart_ctx *rs_ctx,
525 unsigned ops )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100526{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000527 ECP_VALIDATE_RET( grp != NULL );
528
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200529 if( rs_ctx != NULL && ecp_max_ops != 0 )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100530 {
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100531 /* scale depending on curve size: the chosen reference is 256-bit,
532 * and multiplication is quadratic. Round to the closest integer. */
533 if( grp->pbits >= 512 )
534 ops *= 4;
535 else if( grp->pbits >= 384 )
536 ops *= 2;
537
Hanno Beckerb10c6602018-10-26 13:50:13 +0100538 /* Avoid infinite loops: always allow first step.
539 * Because of that, however, it's not generally true
540 * that ops_done <= ecp_max_ops, so the check
541 * ops_done > ecp_max_ops below is mandatory. */
542 if( ( rs_ctx->ops_done != 0 ) &&
543 ( rs_ctx->ops_done > ecp_max_ops ||
544 ops > ecp_max_ops - rs_ctx->ops_done ) )
545 {
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100546 return( MBEDTLS_ERR_ECP_IN_PROGRESS );
Hanno Beckerb10c6602018-10-26 13:50:13 +0100547 }
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100548
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100549 /* update running count */
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200550 rs_ctx->ops_done += ops;
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100551 }
552
553 return( 0 );
554}
555
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200556/* Call this when entering a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200557#define ECP_RS_ENTER( SUB ) do { \
558 /* reset ops count for this call if top-level */ \
559 if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \
560 rs_ctx->ops_done = 0; \
561 \
562 /* set up our own sub-context if needed */ \
563 if( mbedtls_ecp_restart_is_enabled() && \
564 rs_ctx != NULL && rs_ctx->SUB == NULL ) \
565 { \
566 rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
567 if( rs_ctx->SUB == NULL ) \
568 return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
569 \
570 ecp_restart_## SUB ##_init( rs_ctx->SUB ); \
571 } \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200572} while( 0 )
573
574/* Call this when leaving a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200575#define ECP_RS_LEAVE( SUB ) do { \
576 /* clear our sub-context when not in progress (done or error) */ \
577 if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
578 ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
579 { \
580 ecp_restart_## SUB ##_free( rs_ctx->SUB ); \
581 mbedtls_free( rs_ctx->SUB ); \
582 rs_ctx->SUB = NULL; \
583 } \
584 \
585 if( rs_ctx != NULL ) \
586 rs_ctx->depth--; \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200587} while( 0 )
588
589#else /* MBEDTLS_ECP_RESTARTABLE */
590
591#define ECP_RS_ENTER( sub ) (void) rs_ctx;
592#define ECP_RS_LEAVE( sub ) (void) rs_ctx;
593
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200594#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
597 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
598 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
599 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
600 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
601 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
602 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
603 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
604 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
605 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
606 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200607#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100608#endif
609
Nicholas Wilson08f3ef12015-11-10 13:10:01 +0000610#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
611 defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200612#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100613#endif
614
615/*
616 * Curve types: internal for now, might be exposed later
617 */
618typedef enum
619{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200620 ECP_TYPE_NONE = 0,
621 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
622 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100623} ecp_curve_type;
624
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100625/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200626 * List of supported curves:
627 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200628 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200629 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200630 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100631 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100632 * Curves are listed in order: largest curves first, and for a given size,
633 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200634 *
635 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200636 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200638{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
640 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200641#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
643 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100644#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
646 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200647#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200648#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
649 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100650#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
652 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200653#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
655 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100656#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
658 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100659#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
661 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200662#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200663#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
664 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100665#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
667 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100668#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
670 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100671#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200673};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100674
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200675#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
676 sizeof( ecp_supported_curves[0] )
677
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200679
680/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200681 * List of supported curves and associated info
682 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200684{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200685 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200686}
687
688/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100689 * List of supported curves, group ID only
690 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100692{
693 static int init_done = 0;
694
695 if( ! init_done )
696 {
697 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100699
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200700 for( curve_info = mbedtls_ecp_curve_list();
701 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100702 curve_info++ )
703 {
704 ecp_supported_grp_id[i++] = curve_info->grp_id;
705 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100707
708 init_done = 1;
709 }
710
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200711 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100712}
713
714/*
715 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200716 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200717const 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 +0200718{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 for( curve_info = mbedtls_ecp_curve_list();
722 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200723 curve_info++ )
724 {
725 if( curve_info->grp_id == grp_id )
726 return( curve_info );
727 }
728
729 return( NULL );
730}
731
732/*
733 * Get the curve info from the TLS identifier
734 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200735const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200736{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200738
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 for( curve_info = mbedtls_ecp_curve_list();
740 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200741 curve_info++ )
742 {
743 if( curve_info->tls_id == tls_id )
744 return( curve_info );
745 }
746
747 return( NULL );
748}
749
750/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100751 * Get the curve info from the name
752 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200753const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100754{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200755 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100756
Hanno Beckerb7a04a72018-12-18 23:50:21 +0000757 if( name == NULL )
758 return( NULL );
759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200760 for( curve_info = mbedtls_ecp_curve_list();
761 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100762 curve_info++ )
763 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200764 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100765 return( curve_info );
766 }
767
768 return( NULL );
769}
770
771/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100772 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100773 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200774static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100775{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100776 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200777 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100778
779 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200780 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100781 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200782 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100783}
784
785/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100786 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100787 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200788void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100789{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000790 ECP_VALIDATE( pt != NULL );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100791
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200792 mbedtls_mpi_init( &pt->X );
793 mbedtls_mpi_init( &pt->Y );
794 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100795}
796
797/*
798 * Initialize (the components of) a group
799 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200800void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100801{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000802 ECP_VALIDATE( grp != NULL );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100803
Manuel Pégourié-Gonnard95e2eca2018-06-20 10:29:47 +0200804 grp->id = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200805 mbedtls_mpi_init( &grp->P );
806 mbedtls_mpi_init( &grp->A );
807 mbedtls_mpi_init( &grp->B );
808 mbedtls_ecp_point_init( &grp->G );
809 mbedtls_mpi_init( &grp->N );
810 grp->pbits = 0;
811 grp->nbits = 0;
812 grp->h = 0;
813 grp->modp = NULL;
814 grp->t_pre = NULL;
815 grp->t_post = NULL;
816 grp->t_data = NULL;
817 grp->T = NULL;
818 grp->T_size = 0;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100819}
820
821/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200822 * Initialize (the components of) a key pair
823 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200824void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200825{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000826 ECP_VALIDATE( key != NULL );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200827
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200828 mbedtls_ecp_group_init( &key->grp );
829 mbedtls_mpi_init( &key->d );
830 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200831}
832
833/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100834 * Unallocate (the components of) a point
835 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200836void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100837{
838 if( pt == NULL )
839 return;
840
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841 mbedtls_mpi_free( &( pt->X ) );
842 mbedtls_mpi_free( &( pt->Y ) );
843 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100844}
845
846/*
847 * Unallocate (the components of) a group
848 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200849void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100850{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200851 size_t i;
852
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100853 if( grp == NULL )
854 return;
855
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100856 if( grp->h != 1 )
857 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858 mbedtls_mpi_free( &grp->P );
859 mbedtls_mpi_free( &grp->A );
860 mbedtls_mpi_free( &grp->B );
861 mbedtls_ecp_point_free( &grp->G );
862 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100863 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200864
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200865 if( grp->T != NULL )
866 {
867 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200868 mbedtls_ecp_point_free( &grp->T[i] );
869 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200870 }
871
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500872 mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100873}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100874
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100875/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200876 * Unallocate (the components of) a key pair
877 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200878void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200879{
Paul Bakker66d5d072014-06-17 16:39:18 +0200880 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200881 return;
882
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200883 mbedtls_ecp_group_free( &key->grp );
884 mbedtls_mpi_free( &key->d );
885 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200886}
887
888/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200889 * Copy the contents of a point
890 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200891int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200892{
893 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000894 ECP_VALIDATE_RET( P != NULL );
895 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200896
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200897 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
898 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
899 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200900
901cleanup:
902 return( ret );
903}
904
905/*
906 * Copy the contents of a group object
907 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200908int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200909{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000910 ECP_VALIDATE_RET( dst != NULL );
911 ECP_VALIDATE_RET( src != NULL );
912
913 return( mbedtls_ecp_group_load( dst, src->id ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200914}
915
916/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100917 * Set point to zero
918 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100920{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100921 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000922 ECP_VALIDATE_RET( pt != NULL );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100923
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200924 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
925 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
926 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100927
928cleanup:
929 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100930}
931
932/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100933 * Tell if a point is zero
934 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200935int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100936{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000937 ECP_VALIDATE_RET( pt != NULL );
938
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100940}
941
942/*
Brian J Murrayf343de12018-10-22 16:40:49 -0700943 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200944 */
945int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
946 const mbedtls_ecp_point *Q )
947{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000948 ECP_VALIDATE_RET( P != NULL );
949 ECP_VALIDATE_RET( Q != NULL );
950
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200951 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
952 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
953 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
954 {
955 return( 0 );
956 }
957
958 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
959}
960
961/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100962 * Import a non-zero point from ASCII strings
963 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200964int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100965 const char *x, const char *y )
966{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100967 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000968 ECP_VALIDATE_RET( P != NULL );
969 ECP_VALIDATE_RET( x != NULL );
970 ECP_VALIDATE_RET( y != NULL );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100971
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200972 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
973 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
974 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100975
976cleanup:
977 return( ret );
978}
979
980/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100981 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100982 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000983int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp,
984 const mbedtls_ecp_point *P,
985 int format, size_t *olen,
986 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100987{
Paul Bakkera280d0f2013-04-08 13:40:17 +0200988 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100989 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000990 ECP_VALIDATE_RET( grp != NULL );
991 ECP_VALIDATE_RET( P != NULL );
992 ECP_VALIDATE_RET( olen != NULL );
993 ECP_VALIDATE_RET( buf != NULL );
994 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
995 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100996
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100997 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100998 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100999 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001000 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001001 {
1002 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001003 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001004
1005 buf[0] = 0x00;
1006 *olen = 1;
1007
1008 return( 0 );
1009 }
1010
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001012
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001013 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001014 {
1015 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001016
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001017 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001018 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001019
1020 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001021 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
1022 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001023 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001025 {
1026 *olen = plen + 1;
1027
1028 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001029 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001030
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001031 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
1032 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001033 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001034
1035cleanup:
1036 return( ret );
1037}
1038
1039/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001040 * Import a point from unsigned binary data (SEC1 2.3.4)
1041 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001042int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
1043 mbedtls_ecp_point *pt,
1044 const unsigned char *buf, size_t ilen )
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001045{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001046 int ret;
1047 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001048 ECP_VALIDATE_RET( grp != NULL );
1049 ECP_VALIDATE_RET( pt != NULL );
1050 ECP_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001051
Paul Bakker82788fb2014-10-20 13:59:19 +02001052 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001053 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001054
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001055 if( buf[0] == 0x00 )
1056 {
1057 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001058 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001059 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001060 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001061 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001062
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001063 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001064
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001065 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001067
1068 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001069 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001071 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
1072 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
1073 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001074
1075cleanup:
1076 return( ret );
1077}
1078
1079/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001080 * Import a point from a TLS ECPoint record (RFC 4492)
1081 * struct {
1082 * opaque point <1..2^8-1>;
1083 * } ECPoint;
1084 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001085int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp,
1086 mbedtls_ecp_point *pt,
1087 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001088{
1089 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001090 const unsigned char *buf_start;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001091 ECP_VALIDATE_RET( grp != NULL );
1092 ECP_VALIDATE_RET( pt != NULL );
1093 ECP_VALIDATE_RET( buf != NULL );
1094 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001095
1096 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001097 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001098 */
1099 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001100 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001101
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001102 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001103 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001104 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001105
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001106 /*
1107 * Save buffer start for read_binary and update buf
1108 */
1109 buf_start = *buf;
1110 *buf += data_len;
1111
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001112 return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001113}
1114
1115/*
1116 * Export a point as a TLS ECPoint record (RFC 4492)
1117 * struct {
1118 * opaque point <1..2^8-1>;
1119 * } ECPoint;
1120 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001121int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001122 int format, size_t *olen,
1123 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001124{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001125 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001126 ECP_VALIDATE_RET( grp != NULL );
1127 ECP_VALIDATE_RET( pt != NULL );
1128 ECP_VALIDATE_RET( olen != NULL );
1129 ECP_VALIDATE_RET( buf != NULL );
1130 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
1131 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001132
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001133 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001134 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001135 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001136 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001137 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001139 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001140 olen, buf + 1, blen - 1) ) != 0 )
1141 return( ret );
1142
1143 /*
1144 * write length to the first byte and update total length
1145 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +02001146 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001147 ++*olen;
1148
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001149 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001150}
1151
1152/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001153 * Set a group from an ECParameters record (RFC 4492)
1154 */
Janos Follath89ac8c92018-10-30 11:24:05 +00001155int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp,
1156 const unsigned char **buf, size_t len )
1157{
1158 int ret;
1159 mbedtls_ecp_group_id grp_id;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001160 ECP_VALIDATE_RET( grp != NULL );
1161 ECP_VALIDATE_RET( buf != NULL );
1162 ECP_VALIDATE_RET( *buf != NULL );
Janos Follath89ac8c92018-10-30 11:24:05 +00001163
1164 if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 )
1165 return( ret );
1166
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001167 return( mbedtls_ecp_group_load( grp, grp_id ) );
Janos Follath89ac8c92018-10-30 11:24:05 +00001168}
1169
1170/*
1171 * Read a group id from an ECParameters record (RFC 4492) and convert it to
1172 * mbedtls_ecp_group_id.
1173 */
1174int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp,
1175 const unsigned char **buf, size_t len )
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001176{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001177 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001178 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001179 ECP_VALIDATE_RET( grp != NULL );
1180 ECP_VALIDATE_RET( buf != NULL );
1181 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001182
1183 /*
1184 * We expect at least three bytes (see below)
1185 */
1186 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001187 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001188
1189 /*
1190 * First byte is curve_type; only named_curve is handled
1191 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001192 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
1193 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001194
1195 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001196 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001197 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001198 tls_id = *(*buf)++;
1199 tls_id <<= 8;
1200 tls_id |= *(*buf)++;
1201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001202 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
1203 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001204
Janos Follath89ac8c92018-10-30 11:24:05 +00001205 *grp = curve_info->grp_id;
1206
1207 return( 0 );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001208}
1209
1210/*
1211 * Write the ECParameters record corresponding to a group (RFC 4492)
1212 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001213int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001214 unsigned char *buf, size_t blen )
1215{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001217 ECP_VALIDATE_RET( grp != NULL );
1218 ECP_VALIDATE_RET( buf != NULL );
1219 ECP_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001220
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001221 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
1222 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001223
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001224 /*
1225 * We are going to write 3 bytes (see below)
1226 */
1227 *olen = 3;
1228 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001229 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001230
1231 /*
1232 * First byte is curve_type, always named_curve
1233 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001234 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001235
1236 /*
1237 * Next two bytes are the namedcurve value
1238 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001239 buf[0] = curve_info->tls_id >> 8;
1240 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001241
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001242 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +01001243}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001244
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001245/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001246 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
1247 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001248 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001249 * 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 +02001250 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001251static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001252{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001253 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001254
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001255 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001256 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001257
1258 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001260 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001261 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001262 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001263 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001264
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001265 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001266
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001267 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001268 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
1269 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001271 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001272 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001273 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001274
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001275cleanup:
1276 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001277}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001278
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +01001279/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001280 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001281 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001282 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001283 * 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 +01001284 * bring the result back to this range.
1285 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001286 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001287 */
1288
1289/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001290 * 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 +01001291 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001292#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01001293#define INC_MUL_COUNT mul_count++;
1294#else
1295#define INC_MUL_COUNT
1296#endif
1297
Hanno Beckerd6028a12018-10-15 12:01:35 +01001298#define MOD_MUL( N ) \
1299 do \
1300 { \
1301 MBEDTLS_MPI_CHK( ecp_modp( &(N), grp ) ); \
1302 INC_MUL_COUNT \
1303 } while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001304
1305/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001306 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +02001307 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001308 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001309#define MOD_SUB( N ) \
1310 while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \
1311 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001312
1313/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001314 * 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 +02001315 * We known P, N and the result are positive, so sub_abs is correct, and
1316 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001317 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001318#define MOD_ADD( N ) \
1319 while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \
1320 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001321
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001322#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001323/*
1324 * For curves in short Weierstrass form, we do all the internal operations in
1325 * Jacobian coordinates.
1326 *
1327 * For multiplication, we'll use a comb method with coutermeasueres against
1328 * SPA, hence timing attacks.
1329 */
1330
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001331/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001332 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001333 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001334 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001335static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001336{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001337 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001338 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001340 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001341 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001342
Janos Follathb0697532016-08-18 12:38:46 +01001343#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001344 if( mbedtls_internal_ecp_grp_capable( grp ) )
1345 return( mbedtls_internal_ecp_normalize_jac( grp, pt ) );
Janos Follath372697b2016-10-28 16:53:11 +01001346#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001348 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001349
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001350 /*
1351 * X = X / Z^2 mod p
1352 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001353 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
1354 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1355 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 +01001356
1357 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001358 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001359 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001360 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
1361 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 +01001362
1363 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001364 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001365 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001367
1368cleanup:
1369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001371
1372 return( ret );
1373}
1374
1375/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001376 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001377 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001378 * (See for example Cohen's "A Course in Computational Algebraic Number
1379 * Theory", Algorithm 10.3.4.)
1380 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001381 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001382 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001383 *
1384 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001385 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001386static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001387 mbedtls_ecp_point *T[], size_t T_size )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001388{
1389 int ret;
1390 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001392
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001393 if( T_size < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001394 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001395
Janos Follathb0697532016-08-18 12:38:46 +01001396#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001397 if( mbedtls_internal_ecp_grp_capable( grp ) )
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001398 return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) );
Janos Follathb0697532016-08-18 12:38:46 +01001399#endif
1400
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001401 if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001402 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001403
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02001404 for( i = 0; i < T_size; i++ )
1405 mbedtls_mpi_init( &c[i] );
1406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001407 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001408
1409 /*
1410 * c[i] = Z_0 * ... * Z_i
1411 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001412 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001413 for( i = 1; i < T_size; i++ )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001414 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001415 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001416 MOD_MUL( c[i] );
1417 }
1418
1419 /*
1420 * u = 1 / (Z_0 * ... * Z_n) mod P
1421 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001422 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001423
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001424 for( i = T_size - 1; ; i-- )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001425 {
1426 /*
1427 * Zi = 1 / Z_i mod p
1428 * u = 1 / (Z_0 * ... * Z_i) mod P
1429 */
1430 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001431 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001432 }
1433 else
1434 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001435 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1436 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001437 }
1438
1439 /*
1440 * proceed as in normalize()
1441 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001442 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1443 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1444 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1445 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 +01001446
1447 /*
1448 * Post-precessing: reclaim some memory by shrinking coordinates
1449 * - not storing Z (always 1)
1450 * - shrinking other coordinates, but still keeping the same number of
1451 * limbs as P, as otherwise it will too likely be regrown too fast.
1452 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001453 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1454 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1455 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001456
1457 if( i == 0 )
1458 break;
1459 }
1460
1461cleanup:
1462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001463 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001464 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001465 mbedtls_mpi_free( &c[i] );
1466 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001467
1468 return( ret );
1469}
1470
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001471/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001472 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1473 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1474 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001475static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1476 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001477 unsigned char inv )
1478{
1479 int ret;
1480 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001481 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001483 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001484
1485 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1487 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1488 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001489
1490cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001491 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001492
1493 return( ret );
1494}
1495
1496/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001497 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001498 *
Peter Dettmance661b22015-02-07 14:43:51 +07001499 * 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 +01001500 *
Peter Dettmance661b22015-02-07 14:43:51 +07001501 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1502 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1503 *
1504 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1505 *
1506 * Cost: 1D := 3M + 4S (A == 0)
1507 * 4M + 4S (A == -3)
1508 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001509 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001510static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1511 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001512{
1513 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001514 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001516#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001517 dbl_count++;
1518#endif
1519
Janos Follathb0697532016-08-18 12:38:46 +01001520#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001521 if( mbedtls_internal_ecp_grp_capable( grp ) )
1522 return( mbedtls_internal_ecp_double_jac( grp, R, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01001523#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001524
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001525 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 +01001526
1527 /* Special case for A = -3 */
1528 if( grp->A.p == NULL )
1529 {
Peter Dettmance661b22015-02-07 14:43:51 +07001530 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001531 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1532 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1533 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1534 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1535 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001536 }
1537 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001538 {
Peter Dettmance661b22015-02-07 14:43:51 +07001539 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001540 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1541 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001542
1543 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001544 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001545 {
1546 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001547 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1548 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1549 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1550 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001551 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001552 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001553
Peter Dettmance661b22015-02-07 14:43:51 +07001554 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001555 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1556 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1557 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1558 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001559
Peter Dettmance661b22015-02-07 14:43:51 +07001560 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001561 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1562 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001563
1564 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001565 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1566 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1567 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001568
1569 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001570 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1571 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1572 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001573
1574 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001575 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1576 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001577
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001578 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1579 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1580 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001581
1582cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001583 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 +02001584
1585 return( ret );
1586}
1587
1588/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001589 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001590 *
1591 * The coordinates of Q must be normalized (= affine),
1592 * but those of P don't need to. R is not normalized.
1593 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001594 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001595 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001596 * - at each step, P, Q and R are multiples of the base point, the factor
1597 * being less than its order, so none of them is zero;
1598 * - Q is an odd multiple of the base point, P an even multiple,
1599 * due to the choice of precomputed points in the modified comb method.
1600 * So branches for these cases do not leak secret information.
1601 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001602 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1603 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001604 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001605 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001606static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1607 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001608{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001609 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001610 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001612#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001613 add_count++;
1614#endif
1615
Janos Follathb0697532016-08-18 12:38:46 +01001616#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001617 if( mbedtls_internal_ecp_grp_capable( grp ) )
1618 return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) );
Janos Follath372697b2016-10-28 16:53:11 +01001619#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001620
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001621 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001622 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001623 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001624 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1625 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001627 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1628 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001629
1630 /*
1631 * Make sure Q coordinates are normalized
1632 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001633 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1634 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1637 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001638
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001639 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1640 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1641 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1642 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1643 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1644 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001645
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001646 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001647 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001648 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001649 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001650 {
1651 ret = ecp_double_jac( grp, R, P );
1652 goto cleanup;
1653 }
1654 else
1655 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001656 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001657 goto cleanup;
1658 }
1659 }
1660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1662 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1663 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1664 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1665 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1666 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1667 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1668 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1669 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1670 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1671 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1672 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1675 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1676 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001677
1678cleanup:
1679
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001680 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1681 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001682
1683 return( ret );
1684}
1685
1686/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001687 * Randomize jacobian coordinates:
1688 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001689 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001690 *
1691 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001692 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001693static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001694 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1695{
1696 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001697 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001698 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001699 int count = 0;
1700
Janos Follathb0697532016-08-18 12:38:46 +01001701#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001702 if( mbedtls_internal_ecp_grp_capable( grp ) )
1703 return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) );
Janos Follath372697b2016-10-28 16:53:11 +01001704#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001705
1706 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001707 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001708
1709 /* Generate l such that 1 < l < p */
1710 do
1711 {
Ron Eldorca6ff582017-01-12 14:50:50 +02001712 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001714 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1715 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001716
1717 if( count++ > 10 )
Jonas6645fd32020-05-08 16:57:18 +09001718 {
1719 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1720 goto cleanup;
1721 }
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001722 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001723 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001724
1725 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001726 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 +02001727
1728 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001729 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1730 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 +02001731
1732 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001733 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1734 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 +02001735
1736cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001737 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001738
1739 return( ret );
1740}
1741
1742/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001743 * Check and define parameters used by the comb method (see below for details)
1744 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001745#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1746#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001747#endif
1748
1749/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001750#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001751
1752/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001753#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001754
1755/*
1756 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001757 *
1758 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001759 * modified version that provides resistance to SPA by avoiding zero
1760 * digits in the representation as in [3]. We modify the method further by
1761 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001762 * representation uses one more K_i, due to carries, but saves on the size of
1763 * the precomputed table.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001764 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001765 * Summary of the comb method and its modifications:
1766 *
1767 * - The goal is to compute m*P for some w*d-bit integer m.
1768 *
1769 * - The basic comb method splits m into the w-bit integers
1770 * x[0] .. x[d-1] where x[i] consists of the bits in m whose
1771 * index has residue i modulo d, and computes m * P as
1772 * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where
1773 * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P.
1774 *
1775 * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by
1776 * .. + 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]] ..,
1777 * thereby successively converting it into a form where all summands
1778 * are nonzero, at the cost of negative summands. This is the basic idea of [3].
1779 *
1780 * - More generally, even if x[i+1] != 0, we can first transform the sum as
1781 * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] ..,
1782 * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]].
1783 * Performing and iterating this procedure for those x[i] that are even
1784 * (keeping track of carry), we can transform the original sum into one of the form
1785 * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]]
1786 * with all x'[i] odd. It is therefore only necessary to know S at odd indices,
1787 * which is why we are only computing half of it in the first place in
1788 * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb.
1789 *
1790 * - For the sake of compactness, only the seven low-order bits of x[i]
1791 * are used to represent its absolute value (K_i in the paper), and the msb
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001792 * 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 +02001793 * if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001794 *
1795 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001796 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001797 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001798 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001799 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1800 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001801 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01001802static void ecp_comb_recode_core( unsigned char x[], size_t d,
1803 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001804{
1805 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001806 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001807
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001808 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001809
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001810 /* First get the classical comb values (except for x_d = 0) */
1811 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001812 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001813 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001814
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001815 /* Now make sure x_1 .. x_d are odd */
1816 c = 0;
1817 for( i = 1; i <= d; i++ )
1818 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001819 /* Add carry and update it */
1820 cc = x[i] & c;
1821 x[i] = x[i] ^ c;
1822 c = cc;
1823
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001824 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001825 adjust = 1 - ( x[i] & 0x01 );
1826 c |= x[i] & ( x[i-1] * adjust );
1827 x[i] = x[i] ^ ( x[i-1] * adjust );
1828 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001829 }
1830}
1831
1832/*
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001833 * Precompute points for the adapted comb method
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001834 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001835 * Assumption: T must be able to hold 2^{w - 1} elements.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001836 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001837 * Operation: If i = i_{w-1} ... i_1 is the binary representation of i,
1838 * 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 +01001839 *
1840 * 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 +02001841 *
1842 * Note: Even comb values (those where P would be omitted from the
1843 * sum defining T[i] above) are not needed in our adaption
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001844 * the comb method. See ecp_comb_recode_core().
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001845 *
1846 * This function currently works in four steps:
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001847 * (1) [dbl] Computation of intermediate T[i] for 2-power values of i
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001848 * (2) [norm_dbl] Normalization of coordinates of these T[i]
1849 * (3) [add] Computation of all T[i]
1850 * (4) [norm_add] Normalization of all T[i]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001851 *
1852 * Step 1 can be interrupted but not the others; together with the final
1853 * coordinate normalization they are the largest steps done at once, depending
1854 * on the window size. Here are operation counts for P-256:
1855 *
1856 * step (2) (3) (4)
1857 * w = 5 142 165 208
1858 * w = 4 136 77 160
1859 * w = 3 130 33 136
1860 * w = 2 124 11 124
1861 *
1862 * So if ECC operations are blocking for too long even with a low max_ops
1863 * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order
1864 * to minimize maximum blocking time.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001865 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001866static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1867 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001868 unsigned char w, size_t d,
1869 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001870{
1871 int ret;
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001872 unsigned char i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001873 size_t j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001874 const unsigned char T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001875 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001876
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001877#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001878 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001879 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001880 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
1881 goto dbl;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001882 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl )
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001883 goto norm_dbl;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001884 if( rs_ctx->rsm->state == ecp_rsm_pre_add )
1885 goto add;
1886 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add )
1887 goto norm_add;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001888 }
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001889#else
1890 (void) rs_ctx;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001891#endif
1892
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001893#if defined(MBEDTLS_ECP_RESTARTABLE)
1894 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1895 {
1896 rs_ctx->rsm->state = ecp_rsm_pre_dbl;
1897
1898 /* initial state for the loop */
1899 rs_ctx->rsm->i = 0;
1900 }
1901
1902dbl:
1903#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001904 /*
1905 * Set T[0] = P and
1906 * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
1907 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001908 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001909
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001910#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001911 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
1912 j = rs_ctx->rsm->i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001913 else
1914#endif
1915 j = 0;
1916
1917 for( ; j < d * ( w - 1 ); j++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001918 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001919 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL );
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001920
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001921 i = 1U << ( j / d );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001922 cur = T + i;
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001923
1924 if( j % d == 0 )
1925 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
1926
1927 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001928 }
1929
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001930#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001931 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1932 rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl;
1933
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001934norm_dbl:
1935#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001936 /*
1937 * Normalize current elements in T. As T has holes,
1938 * use an auxiliary array of pointers to elements in T.
1939 */
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001940 j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001941 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001942 TT[j++] = T + i;
1943
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001944 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001945
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001946 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001947
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001948#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001949 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1950 rs_ctx->rsm->state = ecp_rsm_pre_add;
1951
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001952add:
1953#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001954 /*
1955 * Compute the remaining ones using the minimal number of additions
1956 * Be careful to update T[2^l] only after using it!
1957 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001958 MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001959
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001960 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001961 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001962 j = i;
1963 while( j-- )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001964 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001965 }
1966
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001967#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001968 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1969 rs_ctx->rsm->state = ecp_rsm_pre_norm_add;
1970
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001971norm_add:
1972#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001973 /*
Manuel Pégourié-Gonnarda966fde2018-10-23 10:41:11 +02001974 * Normalize final elements in T. Even though there are no holes now, we
1975 * still need the auxiliary array for homogeneity with the previous
1976 * call. Also, skip T[0] which is already normalised, being a copy of P.
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001977 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001978 for( j = 0; j + 1 < T_size; j++ )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001979 TT[j] = T + j + 1;
1980
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001981 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001982
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001983 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01001984
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001985cleanup:
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001986#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001987 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
1988 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001989 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001990 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001991 rs_ctx->rsm->i = j;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001992 }
1993#endif
Janos Follathb0697532016-08-18 12:38:46 +01001994
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001995 return( ret );
1996}
1997
1998/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001999 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002000 *
2001 * See ecp_comb_recode_core() for background
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002002 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002003static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002004 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002005 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002006{
2007 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002008 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002009
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002010 /* Ignore the "sign" bit and scale down */
2011 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002012
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002013 /* Read the whole table to thwart cache-based timing attacks */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002014 for( j = 0; j < T_size; j++ )
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002015 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
2017 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002018 }
2019
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01002020 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002021 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002022
2023cleanup:
2024 return( ret );
2025}
2026
2027/*
2028 * Core multiplication algorithm for the (modified) comb method.
2029 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01002030 *
2031 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002032 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002034 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01002035 const unsigned char x[], size_t d,
2036 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002037 void *p_rng,
2038 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002039{
2040 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002041 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002042 size_t i;
2043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002044 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002045
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002046#if !defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002047 (void) rs_ctx;
2048#endif
2049
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002050#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002051 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2052 rs_ctx->rsm->state != ecp_rsm_comb_core )
2053 {
2054 rs_ctx->rsm->i = 0;
2055 rs_ctx->rsm->state = ecp_rsm_comb_core;
2056 }
2057
2058 /* new 'if' instead of nested for the sake of the 'else' branch */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002059 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002060 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002061 /* restore current index (R already pointing to rs_ctx->rsm->R) */
2062 i = rs_ctx->rsm->i;
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002063 }
2064 else
2065#endif
2066 {
2067 /* Start with a non-zero point and randomize its coordinates */
2068 i = d;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002069 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) );
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002070 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002071#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002072 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002073#endif
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002074 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
2075 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002076
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002077 while( i != 0 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002078 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002079 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002080 --i;
2081
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002083 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002084 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002085 }
2086
2087cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002088
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002089 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002090
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002091#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002092 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2093 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002094 {
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002095 rs_ctx->rsm->i = i;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002096 /* no need to save R, already pointing to rs_ctx->rsm->R */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002097 }
2098#endif
2099
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002100 return( ret );
2101}
2102
2103/*
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002104 * Recode the scalar to get constant-time comb multiplication
2105 *
2106 * As the actual scalar recoding needs an odd scalar as a starting point,
2107 * this wrapper ensures that by replacing m by N - m if necessary, and
2108 * informs the caller that the result of multiplication will be negated.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002109 *
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002110 * This works because we only support large prime order for Short Weierstrass
2111 * curves, so N is always odd hence either m or N - m is.
2112 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002113 * See ecp_comb_recode_core() for background.
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002114 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002115static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp,
2116 const mbedtls_mpi *m,
2117 unsigned char k[COMB_MAX_D + 1],
2118 size_t d,
2119 unsigned char w,
2120 unsigned char *parity_trick )
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002121{
2122 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002123 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002124
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002125 mbedtls_mpi_init( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002126 mbedtls_mpi_init( &mm );
2127
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002128 /* N is always odd (see above), just make extra sure */
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002129 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
2130 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
2131
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002132 /* do we need the parity trick? */
2133 *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 );
2134
2135 /* execute parity fix in constant time */
2136 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002137 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002138 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) );
2139
2140 /* actual scalar recoding */
2141 ecp_comb_recode_core( k, d, w, &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002142
2143cleanup:
2144 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002145 mbedtls_mpi_free( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002146
2147 return( ret );
2148}
2149
2150/*
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002151 * Perform comb multiplication (for short Weierstrass curves)
2152 * once the auxiliary table has been pre-computed.
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002153 *
2154 * Scalar recoding may use a parity trick that makes us compute -m * P,
2155 * if that is the case we'll need to recover m * P at the end.
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002156 */
2157static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
2158 mbedtls_ecp_point *R,
2159 const mbedtls_mpi *m,
2160 const mbedtls_ecp_point *T,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002161 unsigned char T_size,
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002162 unsigned char w,
2163 size_t d,
2164 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002165 void *p_rng,
2166 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002167{
2168 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002169 unsigned char parity_trick;
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002170 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002171 mbedtls_ecp_point *RR = R;
2172
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002173#if defined(MBEDTLS_ECP_RESTARTABLE)
2174 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2175 {
2176 RR = &rs_ctx->rsm->R;
2177
2178 if( rs_ctx->rsm->state == ecp_rsm_final_norm )
2179 goto final_norm;
2180 }
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002181#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002182
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002183 MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w,
2184 &parity_trick ) );
2185 MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d,
2186 f_rng, p_rng, rs_ctx ) );
2187 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) );
2188
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002189#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002190 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002191 rs_ctx->rsm->state = ecp_rsm_final_norm;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002192
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002193final_norm:
Manuel Pégourié-Gonnard18b0b3c2020-06-08 09:53:20 +02002194 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002195#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002196 /*
2197 * Knowledge of the jacobian coordinates may leak the last few bits of the
2198 * scalar [1], and since our MPI implementation isn't constant-flow,
2199 * inversion (used for coordinate normalization) may leak the full value
2200 * of its input via side-channels [2].
2201 *
2202 * [1] https://eprint.iacr.org/2003/191
2203 * [2] https://eprint.iacr.org/2020/055
2204 *
2205 * Avoid the leak by randomizing coordinates before we normalize them.
2206 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002207#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002208 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002209#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002210 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) );
2211
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002212 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
2213
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002214#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard28d16282017-08-23 17:33:27 +02002215 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2216 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) );
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002217#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002218
2219cleanup:
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002220 return( ret );
2221}
2222
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002223/*
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002224 * Pick window size based on curve size and whether we optimize for base point
2225 */
2226static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
2227 unsigned char p_eq_g )
2228{
2229 unsigned char w;
2230
2231 /*
2232 * Minimize the number of multiplications, that is minimize
2233 * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
2234 * (see costs of the various parts, with 1S = 1M)
2235 */
2236 w = grp->nbits >= 384 ? 5 : 4;
2237
2238 /*
2239 * If P == G, pre-compute a bit more, since this may be re-used later.
2240 * Just adding one avoids upping the cost of the first mul too much,
2241 * and the memory cost too.
2242 */
2243 if( p_eq_g )
2244 w++;
2245
2246 /*
2247 * Make sure w is within bounds.
2248 * (The last test is useful only for very small curves in the test suite.)
2249 */
2250 if( w > MBEDTLS_ECP_WINDOW_SIZE )
2251 w = MBEDTLS_ECP_WINDOW_SIZE;
2252 if( w >= grp->nbits )
2253 w = 2;
2254
2255 return( w );
2256}
2257
2258/*
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002259 * Multiplication using the comb method - for curves in short Weierstrass form
2260 *
2261 * This function is mainly responsible for administrative work:
2262 * - managing the restart context if enabled
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002263 * - managing the table of precomputed points (passed between the below two
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002264 * functions): allocation, computation, ownership tranfer, freeing.
2265 *
2266 * It delegates the actual arithmetic work to:
2267 * ecp_precompute_comb() and ecp_mul_comb_with_precomp()
2268 *
2269 * See comments on ecp_comb_recode_core() regarding the computation strategy.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002270 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2272 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002273 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002274 void *p_rng,
2275 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002276{
2277 int ret;
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002278 unsigned char w, p_eq_g, i;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002279 size_t d;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002280 unsigned char T_size = 0, T_ok = 0;
2281 mbedtls_ecp_point *T = NULL;
2282#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2283 ecp_drbg_context drbg_ctx;
2284
2285 ecp_drbg_init( &drbg_ctx );
2286#endif
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002287
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002288 ECP_RS_ENTER( rsm );
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +01002289
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002290#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2291 if( f_rng == NULL )
2292 {
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002293 /* Adjust pointers */
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002294 f_rng = &ecp_drbg_random;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002295#if defined(MBEDTLS_ECP_RESTARTABLE)
2296 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2297 p_rng = &rs_ctx->rsm->drbg_ctx;
2298 else
2299#endif
2300 p_rng = &drbg_ctx;
2301
2302 /* Initialize internal DRBG if necessary */
2303#if defined(MBEDTLS_ECP_RESTARTABLE)
2304 if( rs_ctx == NULL || rs_ctx->rsm == NULL ||
2305 rs_ctx->rsm->drbg_seeded == 0 )
2306#endif
2307 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002308 const size_t m_len = ( grp->nbits + 7 ) / 8;
2309 MBEDTLS_MPI_CHK( ecp_drbg_seed( p_rng, m, m_len ) );
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002310 }
2311#if defined(MBEDTLS_ECP_RESTARTABLE)
2312 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2313 rs_ctx->rsm->drbg_seeded = 1;
2314#endif
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002315 }
2316#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2317
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002318 /* Is P the base point ? */
2319#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
2320 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
2321 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard196d1332017-08-28 13:14:27 +02002322#else
2323 p_eq_g = 0;
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002324#endif
2325
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002326 /* Pick window size and deduce related sizes */
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002327 w = ecp_pick_window_size( grp, p_eq_g );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002328 T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002329 d = ( grp->nbits + w - 1 ) / w;
2330
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002331 /* Pre-computed table: do we have it already for the base point? */
2332 if( p_eq_g && grp->T != NULL )
2333 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002334 /* second pointer to the same table, will be deleted on exit */
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002335 T = grp->T;
2336 T_ok = 1;
2337 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002338 else
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002339#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002340 /* Pre-computed table: do we have one in progress? complete? */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002341 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL )
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002342 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002343 /* transfer ownership of T from rsm to local function */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002344 T = rs_ctx->rsm->T;
2345 rs_ctx->rsm->T = NULL;
2346 rs_ctx->rsm->T_size = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002347
Manuel Pégourié-Gonnardb25cb602018-10-16 11:48:09 +02002348 /* This effectively jumps to the call to mul_comb_after_precomp() */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002349 T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002350 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002351 else
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002352#endif
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002353 /* Allocate table if we didn't have any */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002354 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002355 T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002356 if( T == NULL )
2357 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02002358 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002359 goto cleanup;
2360 }
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02002361
2362 for( i = 0; i < T_size; i++ )
2363 mbedtls_ecp_point_init( &T[i] );
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002364
2365 T_ok = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002366 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002367
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002368 /* Compute table (or finish computing it) if not done already */
2369 if( !T_ok )
2370 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002371 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002372
2373 if( p_eq_g )
2374 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002375 /* almost transfer ownership of T to the group, but keep a copy of
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02002376 * the pointer to use for calling the next function more easily */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002377 grp->T = T;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002378 grp->T_size = T_size;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002379 }
2380 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002381
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002382 /* Actual comb multiplication using precomputed points */
2383 MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002384 T, T_size, w, d,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002385 f_rng, p_rng, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002386
2387cleanup:
2388
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002389#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2390 ecp_drbg_free( &drbg_ctx );
2391#endif
2392
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002393 /* does T belong to the group? */
2394 if( T == grp->T )
2395 T = NULL;
2396
2397 /* does T belong to the restart context? */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002398#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002399 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 +01002400 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002401 /* transfer ownership of T from local function to rsm */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002402 rs_ctx->rsm->T_size = T_size;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002403 rs_ctx->rsm->T = T;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002404 T = NULL;
2405 }
2406#endif
2407
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002408 /* did T belong to us? then let's destroy it! */
2409 if( T != NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002410 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002411 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412 mbedtls_ecp_point_free( &T[i] );
2413 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002414 }
2415
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002416 /* don't free R while in progress in case R == P */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002417#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002418 if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
2419#endif
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002420 /* prevent caller from using invalid value */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01002421 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002422 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002423
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002424 ECP_RS_LEAVE( rsm );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +01002425
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002426 return( ret );
2427}
2428
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002429#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002430
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002431#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002432/*
2433 * For Montgomery curves, we do all the internal arithmetic in projective
2434 * coordinates. Import/export of points uses only the x coordinates, which is
2435 * internaly represented as X / Z.
2436 *
2437 * For scalar multiplication, we'll use a Montgomery ladder.
2438 */
2439
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002440/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002441 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
2442 * Cost: 1M + 1I
2443 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002444static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002445{
2446 int ret;
2447
Janos Follathb0697532016-08-18 12:38:46 +01002448#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002449 if( mbedtls_internal_ecp_grp_capable( grp ) )
2450 return( mbedtls_internal_ecp_normalize_mxz( grp, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01002451#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002453 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
2454 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
2455 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002456
2457cleanup:
2458 return( ret );
2459}
2460
2461/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002462 * Randomize projective x/z coordinates:
2463 * (X, Z) -> (l X, l Z) for random l
2464 * This is sort of the reverse operation of ecp_normalize_mxz().
2465 *
2466 * This countermeasure was first suggested in [2].
2467 * Cost: 2M
2468 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002469static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002470 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2471{
2472 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01002474 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002475 int count = 0;
2476
Janos Follathb0697532016-08-18 12:38:46 +01002477#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002478 if( mbedtls_internal_ecp_grp_capable( grp ) )
2479 return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
Janos Follath372697b2016-10-28 16:53:11 +01002480#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002481
2482 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002483 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002484
2485 /* Generate l such that 1 < l < p */
2486 do
2487 {
Ron Eldorca6ff582017-01-12 14:50:50 +02002488 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002489
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002490 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
2491 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002492
2493 if( count++ > 10 )
Jonas6645fd32020-05-08 16:57:18 +09002494 {
2495 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
2496 goto cleanup;
2497 }
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002498 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002499 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
2502 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 +01002503
2504cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002505 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002506
2507 return( ret );
2508}
2509
2510/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002511 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
2512 * for Montgomery curves in x/z coordinates.
2513 *
2514 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
2515 * with
2516 * d = X1
2517 * P = (X2, Z2)
2518 * Q = (X3, Z3)
2519 * R = (X4, Z4)
2520 * S = (X5, Z5)
2521 * and eliminating temporary variables tO, ..., t4.
2522 *
2523 * Cost: 5M + 4S
2524 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
2526 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
2527 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
2528 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002529{
2530 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002531 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002532
Janos Follathb0697532016-08-18 12:38:46 +01002533#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002534 if( mbedtls_internal_ecp_grp_capable( grp ) )
2535 return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) );
Janos Follath372697b2016-10-28 16:53:11 +01002536#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002537
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002538 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
2539 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
2540 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002542 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
2543 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
2544 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
2545 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
2546 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
2547 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
2548 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
2549 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
2550 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
2551 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
2552 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
2553 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
2554 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
2555 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
2556 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
2557 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
2558 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
2559 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 +01002560
2561cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
2563 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
2564 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002565
2566 return( ret );
2567}
2568
2569/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002570 * Multiplication with Montgomery ladder in x/z coordinates,
2571 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002572 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002573static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2574 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002575 int (*f_rng)(void *, unsigned char *, size_t),
2576 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002577{
2578 int ret;
2579 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002580 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002581 mbedtls_ecp_point RP;
2582 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002583#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2584 ecp_drbg_context drbg_ctx;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002585
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002586 ecp_drbg_init( &drbg_ctx );
2587#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002588 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002589
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002590#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2591 if( f_rng == NULL )
2592 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002593 const size_t m_len = ( grp->nbits + 7 ) / 8;
2594 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002595 f_rng = &ecp_drbg_random;
2596 p_rng = &drbg_ctx;
2597 }
2598#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2599
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002600 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002601 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
2602 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002603
2604 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002605 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
2606 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
2607 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002608
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01002609 /* RP.X might be sligtly larger than P, so reduce it */
2610 MOD_ADD( RP.X );
2611
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002612 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002613#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002614 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002615#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002616 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002617
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002618 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002619 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002620 while( i-- > 0 )
2621 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002622 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002623 /*
2624 * if (b) R = 2R + P else R = 2R,
2625 * which is:
2626 * if (b) double_add( RP, R, RP, R )
2627 * else double_add( R, RP, R, RP )
2628 * but using safe conditional swaps to avoid leaks
2629 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002630 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2631 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
2632 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
2633 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2634 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002635 }
2636
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002637 /*
2638 * Knowledge of the projective coordinates may leak the last few bits of the
2639 * scalar [1], and since our MPI implementation isn't constant-flow,
2640 * inversion (used for coordinate normalization) may leak the full value
2641 * of its input via side-channels [2].
2642 *
2643 * [1] https://eprint.iacr.org/2003/191
2644 * [2] https://eprint.iacr.org/2020/055
2645 *
2646 * Avoid the leak by randomizing coordinates before we normalize them.
2647 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002648#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002649 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002650#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002651 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
2652
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002653 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002654
2655cleanup:
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002656#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2657 ecp_drbg_free( &drbg_ctx );
2658#endif
2659
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002660 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002661
2662 return( ret );
2663}
2664
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002665#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002666
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002667/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002668 * Restartable multiplication R = m * P
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002669 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002670int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002671 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002672 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
2673 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002674{
Janos Follathb0697532016-08-18 12:38:46 +01002675 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00002676#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2677 char is_grp_capable = 0;
2678#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002679 ECP_VALIDATE_RET( grp != NULL );
2680 ECP_VALIDATE_RET( R != NULL );
2681 ECP_VALIDATE_RET( m != NULL );
2682 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002683
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002684#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002685 /* reset ops count for this call if top-level */
2686 if( rs_ctx != NULL && rs_ctx->depth++ == 0 )
2687 rs_ctx->ops_done = 0;
2688#endif
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002689
Janos Follathc44ab972016-11-18 16:38:23 +00002690#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002691 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
Janos Follathc44ab972016-11-18 16:38:23 +00002692 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathc44ab972016-11-18 16:38:23 +00002693#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002694
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002695#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002696 /* skip argument check when restarting */
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002697 if( rs_ctx == NULL || rs_ctx->rsm == NULL )
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002698#endif
2699 {
Manuel Pégourié-Gonnard5314f232017-04-21 12:36:59 +02002700 /* check_privkey is free */
2701 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
2702
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002703 /* Common sanity checks */
2704 MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) );
2705 MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002706 }
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002707
2708 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002709#if defined(ECP_MONTGOMERY)
2710 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002711 MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
Janos Follath430d3372016-11-03 14:25:37 +00002712#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002713#if defined(ECP_SHORTWEIERSTRASS)
2714 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002715 MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) );
Janos Follath430d3372016-11-03 14:25:37 +00002716#endif
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002717
Janos Follath6c8ccd52016-11-29 15:37:09 +00002718cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002719
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002720#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002721 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002722 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002723#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002724
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002725#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002726 if( rs_ctx != NULL )
2727 rs_ctx->depth--;
2728#endif
2729
Janos Follathb0697532016-08-18 12:38:46 +01002730 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002731}
2732
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002733/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002734 * Multiplication R = m * P
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002735 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002736int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002737 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002738 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002739{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002740 ECP_VALIDATE_RET( grp != NULL );
2741 ECP_VALIDATE_RET( R != NULL );
2742 ECP_VALIDATE_RET( m != NULL );
2743 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002744 return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002745}
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002746
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002747#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002748/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002749 * Check that an affine point is valid as a public key,
2750 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002751 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002752static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002753{
2754 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002755 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002756
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002757 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002758 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2759 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2760 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2761 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2762 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002763
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002764 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002765
2766 /*
2767 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002768 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002769 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002770 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2771 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002772
2773 /* Special case for A = -3 */
2774 if( grp->A.p == NULL )
2775 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002776 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002777 }
2778 else
2779 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002780 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002781 }
2782
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002783 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2784 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002785
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002786 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2787 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002788
2789cleanup:
2790
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002791 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002792
2793 return( ret );
2794}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002795#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002796
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002797/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002798 * R = m * P with shortcuts for m == 1 and m == -1
2799 * NOT constant-time - ONLY for short Weierstrass!
2800 */
2801static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2802 mbedtls_ecp_point *R,
2803 const mbedtls_mpi *m,
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002804 const mbedtls_ecp_point *P,
2805 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002806{
2807 int ret;
2808
2809 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2810 {
2811 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2812 }
2813 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2814 {
2815 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2816 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2817 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2818 }
2819 else
2820 {
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002821 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P,
2822 NULL, NULL, rs_ctx ) );
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002823 }
2824
2825cleanup:
2826 return( ret );
2827}
2828
2829/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002830 * Restartable linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002831 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002832 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002833int mbedtls_ecp_muladd_restartable(
2834 mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002835 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002836 const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
2837 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002838{
2839 int ret;
2840 mbedtls_ecp_point mP;
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002841 mbedtls_ecp_point *pmP = &mP;
2842 mbedtls_ecp_point *pR = R;
Janos Follathc44ab972016-11-18 16:38:23 +00002843#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2844 char is_grp_capable = 0;
2845#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002846 ECP_VALIDATE_RET( grp != NULL );
2847 ECP_VALIDATE_RET( R != NULL );
2848 ECP_VALIDATE_RET( m != NULL );
2849 ECP_VALIDATE_RET( P != NULL );
2850 ECP_VALIDATE_RET( n != NULL );
2851 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002852
2853 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2854 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2855
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002856 mbedtls_ecp_point_init( &mP );
2857
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002858 ECP_RS_ENTER( ma );
2859
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002860#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002861 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2862 {
2863 /* redirect intermediate results to restart context */
2864 pmP = &rs_ctx->ma->mP;
2865 pR = &rs_ctx->ma->R;
2866
2867 /* jump to next operation */
2868 if( rs_ctx->ma->state == ecp_rsma_mul2 )
2869 goto mul2;
2870 if( rs_ctx->ma->state == ecp_rsma_add )
2871 goto add;
2872 if( rs_ctx->ma->state == ecp_rsma_norm )
2873 goto norm;
2874 }
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002875#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002876
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002877 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002878#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002879 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002880 rs_ctx->ma->state = ecp_rsma_mul2;
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002881
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002882mul2:
2883#endif
2884 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) );
Janos Follathaf6f2692018-12-07 09:55:24 +00002885
2886#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2887 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
2888 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
2889#endif /* MBEDTLS_ECP_INTERNAL_ALT */
2890
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002891#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002892 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002893 rs_ctx->ma->state = ecp_rsma_add;
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002894
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002895add:
2896#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002897 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002898 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002899#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002900 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002901 rs_ctx->ma->state = ecp_rsma_norm;
Janos Follath430d3372016-11-03 14:25:37 +00002902
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002903norm:
2904#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002905 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002906 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) );
2907
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002908#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002909 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2910 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) );
2911#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002912
2913cleanup:
Janos Follathc44ab972016-11-18 16:38:23 +00002914#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002915 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002916 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002917#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002918
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002919 mbedtls_ecp_point_free( &mP );
2920
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002921 ECP_RS_LEAVE( ma );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002922
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002923 return( ret );
2924}
2925
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002926/*
2927 * Linear combination
2928 * NOT constant-time
2929 */
2930int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2931 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2932 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2933{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002934 ECP_VALIDATE_RET( grp != NULL );
2935 ECP_VALIDATE_RET( R != NULL );
2936 ECP_VALIDATE_RET( m != NULL );
2937 ECP_VALIDATE_RET( P != NULL );
2938 ECP_VALIDATE_RET( n != NULL );
2939 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002940 return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) );
2941}
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002942
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002943#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002944/*
2945 * Check validity of a public key for Montgomery curves with x-only schemes
2946 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002947static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002948{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002949 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00002950 /* Allow any public value, if it's too big then we'll just reduce it mod p
2951 * (RFC 7748 sec. 5 para. 3). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002952 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
2953 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002954
2955 return( 0 );
2956}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002957#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002958
2959/*
2960 * Check that a point is valid as a public key
2961 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002962int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp,
2963 const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002964{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002965 ECP_VALIDATE_RET( grp != NULL );
2966 ECP_VALIDATE_RET( pt != NULL );
2967
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002968 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002969 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
2970 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002971
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002972#if defined(ECP_MONTGOMERY)
2973 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002974 return( ecp_check_pubkey_mx( grp, pt ) );
2975#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002976#if defined(ECP_SHORTWEIERSTRASS)
2977 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002978 return( ecp_check_pubkey_sw( grp, pt ) );
2979#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002980 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002981}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002982
2983/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002984 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002985 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002986int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp,
2987 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002988{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002989 ECP_VALIDATE_RET( grp != NULL );
2990 ECP_VALIDATE_RET( d != NULL );
2991
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002992#if defined(ECP_MONTGOMERY)
2993 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002994 {
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00002995 /* see RFC 7748 sec. 5 para. 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002996 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
2997 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002998 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002999 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003000
3001 /* see [Curve25519] page 5 */
3002 if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 )
3003 return( MBEDTLS_ERR_ECP_INVALID_KEY );
3004
3005 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003006 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003007#endif /* ECP_MONTGOMERY */
3008#if defined(ECP_SHORTWEIERSTRASS)
3009 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003010 {
3011 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003012 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
3013 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
3014 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003015 else
3016 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003017 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003018#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003019
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003020 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003021}
3022
3023/*
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003024 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003025 */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003026int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
3027 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003028 int (*f_rng)(void *, unsigned char *, size_t),
3029 void *p_rng )
3030{
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003031 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003032 size_t n_size;
3033
3034 ECP_VALIDATE_RET( grp != NULL );
3035 ECP_VALIDATE_RET( d != NULL );
3036 ECP_VALIDATE_RET( f_rng != NULL );
3037
3038 n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003039
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003040#if defined(ECP_MONTGOMERY)
3041 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003042 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003043 /* [M225] page 5 */
3044 size_t b;
3045
Janos Follath98e28a72016-05-31 14:03:54 +01003046 do {
3047 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
3048 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003049
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003050 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02003051 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003052 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003053 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003054 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003055 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003056
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003057 /* Make sure the last two bits are unset for Curve448, three bits for
3058 Curve25519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003059 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
3060 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003061 if( grp->nbits == 254 )
3062 {
3063 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
3064 }
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003065 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003066#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003067
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003068#if defined(ECP_SHORTWEIERSTRASS)
3069 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003070 {
3071 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003072 int count = 0;
Janos Follath867a3ab2019-10-11 14:21:53 +01003073 unsigned cmp = 0;
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01003074
3075 /*
3076 * Match the procedure given in RFC 6979 (deterministic ECDSA):
3077 * - use the same byte ordering;
3078 * - keep the leftmost nbits bits of the generated octet string;
3079 * - try until result is in the desired range.
3080 * This also avoids any biais, which is especially important for ECDSA.
3081 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003082 do
3083 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01003084 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003085 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003086
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01003087 /*
3088 * Each try has at worst a probability 1/2 of failing (the msb has
3089 * a probability 1/2 of being 0, and then the result will be < N),
3090 * so after 30 tries failure probability is a most 2**(-30).
3091 *
3092 * For most curves, 1 try is enough with overwhelming probability,
3093 * since N starts with a lot of 1s in binary, but some curves
3094 * such as secp224k1 are actually very close to the worst case.
3095 */
Manuel Pégourié-Gonnard67543962017-04-21 13:19:43 +02003096 if( ++count > 30 )
3097 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
Janos Follath4c3408b2019-09-16 14:27:39 +01003098
Janos Follath867a3ab2019-10-11 14:21:53 +01003099 ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
Janos Follath4c3408b2019-09-16 14:27:39 +01003100 if( ret != 0 )
3101 {
3102 goto cleanup;
3103 }
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003104 }
Janos Follath867a3ab2019-10-11 14:21:53 +01003105 while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003106 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003107#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003108
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003109cleanup:
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003110 return( ret );
3111}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003112
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003113/*
3114 * Generate a keypair with configurable base point
3115 */
3116int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
3117 const mbedtls_ecp_point *G,
3118 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3119 int (*f_rng)(void *, unsigned char *, size_t),
3120 void *p_rng )
3121{
3122 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003123 ECP_VALIDATE_RET( grp != NULL );
3124 ECP_VALIDATE_RET( d != NULL );
3125 ECP_VALIDATE_RET( G != NULL );
3126 ECP_VALIDATE_RET( Q != NULL );
3127 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003128
3129 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
3130 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
3131
3132cleanup:
3133 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003134}
3135
3136/*
3137 * Generate key pair, wrapper for conventional base point
3138 */
3139int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
3140 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3141 int (*f_rng)(void *, unsigned char *, size_t),
3142 void *p_rng )
3143{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003144 ECP_VALIDATE_RET( grp != NULL );
3145 ECP_VALIDATE_RET( d != NULL );
3146 ECP_VALIDATE_RET( Q != NULL );
3147 ECP_VALIDATE_RET( f_rng != NULL );
3148
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003149 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003150}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01003151
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003152/*
3153 * Generate a keypair, prettier wrapper
3154 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003155int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003156 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
3157{
3158 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003159 ECP_VALIDATE_RET( key != NULL );
3160 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003161
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003162 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003163 return( ret );
3164
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003165 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003166}
3167
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003168/*
3169 * Check a public-private key pair
3170 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003171int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003172{
3173 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003174 mbedtls_ecp_point Q;
3175 mbedtls_ecp_group grp;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003176 ECP_VALIDATE_RET( pub != NULL );
3177 ECP_VALIDATE_RET( prv != NULL );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003179 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003180 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003181 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
3182 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
3183 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003184 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003185 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003186 }
3187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003188 mbedtls_ecp_point_init( &Q );
3189 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003191 /* mbedtls_ecp_mul() needs a non-const group... */
3192 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003193
3194 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003195 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003197 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
3198 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
3199 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003200 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003201 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003202 goto cleanup;
3203 }
3204
3205cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003206 mbedtls_ecp_point_free( &Q );
3207 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003208
3209 return( ret );
3210}
3211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003212#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003213
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003214#if defined(ECP_ONE_STEP_KDF)
3215/*
3216 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
3217 * but unofficial ones can be found at:
3218 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
3219 *
3220 * We only use the ones with empty fixedInfo, and for brevity's sake, only
3221 * 32-bytes output (with SHA-1 that's more than one block, with SHA-256
3222 * exactly one block, and with SHA-512 less than one block).
3223 */
3224#if defined(MBEDTLS_SHA512_C)
3225
3226static const uint8_t test_kdf_z[16] = {
3227 0xeb, 0xf3, 0x19, 0x67, 0x1e, 0xac, 0xcc, 0x6f,
3228 0xc5, 0xc0, 0x5d, 0x95, 0x8d, 0x17, 0x15, 0x94,
3229};
3230static const uint8_t test_kdf_out[32] = {
3231 0xa9, 0x48, 0x85, 0x67, 0x54, 0x7c, 0x2a, 0x8e,
3232 0x9e, 0xd1, 0x67, 0x76, 0xe3, 0x1c, 0x03, 0x92,
3233 0x41, 0x77, 0x2a, 0x9e, 0xc7, 0xcc, 0xd7, 0x1f,
3234 0xda, 0x12, 0xe9, 0xba, 0xc9, 0xb2, 0x17, 0x24,
3235};
3236
3237#elif defined(MBEDTLS_SHA256_C)
3238
3239static const uint8_t test_kdf_z[16] = {
3240 0x0d, 0x5e, 0xc8, 0x9a, 0x68, 0xb1, 0xa7, 0xa0,
3241 0xdf, 0x95, 0x24, 0x54, 0x3f, 0x4d, 0x70, 0xef,
3242};
3243static const uint8_t test_kdf_out[32] = {
3244 0x77, 0xbc, 0x94, 0x9e, 0xa0, 0xd3, 0xdd, 0x5c,
3245 0x8e, 0xb7, 0xeb, 0x84, 0x05, 0x40, 0x60, 0xfa,
3246 0x96, 0x6e, 0x7e, 0xcd, 0x73, 0x9f, 0xa1, 0xe6,
3247 0x34, 0x3f, 0x6d, 0x82, 0x16, 0x22, 0xb4, 0x45,
3248};
3249
3250#elif defined(MBEDTLS_SHA1_C)
3251
3252static const uint8_t test_kdf_z[16] = {
3253 0x4e, 0x1e, 0x70, 0xc9, 0x88, 0x68, 0x19, 0xa3,
3254 0x1b, 0xc2, 0x9a, 0x53, 0x79, 0x11, 0xad, 0xd9,
3255};
3256static const uint8_t test_kdf_out[32] = {
3257 0xdd, 0xbf, 0xc4, 0x40, 0x44, 0x9a, 0xab, 0x41,
3258 0x31, 0xc6, 0xd8, 0xae, 0xc0, 0x8c, 0xe1, 0x49,
3259 0x6f, 0x27, 0x02, 0x24, 0x1d, 0x0e, 0x27, 0xcc,
3260 0x15, 0x5c, 0x5c, 0x7c, 0x3c, 0xda, 0x75, 0xb5,
3261};
3262
3263#else
3264#error "Need at least one of SHA-512, SHA-256 or SHA-1"
3265#endif
3266
3267static int ecp_kdf_self_test( void )
3268{
3269 int ret;
3270 ecp_drbg_context kdf_ctx;
3271 mbedtls_mpi scalar;
3272 uint8_t out[sizeof( test_kdf_out )];
3273
3274 ecp_drbg_init( &kdf_ctx );
3275 mbedtls_mpi_init( &scalar );
3276 memset( out, 0, sizeof( out ) );
3277
3278 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
3279 test_kdf_z, sizeof( test_kdf_z ) ) );
3280
3281 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
3282 &scalar, sizeof( test_kdf_z ) ) );
3283
3284 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
3285
3286 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
3287 ret = -1;
3288
3289cleanup:
3290 ecp_drbg_free( &kdf_ctx );
3291 mbedtls_mpi_free( &scalar );
3292
3293 return( ret );
3294}
3295#endif /* ECP_ONE_STEP_KDF */
3296
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01003297/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003298 * Checkup routine
3299 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003300int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003301{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003302 int ret;
3303 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003304 mbedtls_ecp_group grp;
3305 mbedtls_ecp_point R, P;
3306 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003307 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003308 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02003309 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003310 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003311 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003312 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003313 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003314 "400000000000000000000000000000000000000000000000", /* one and zeros */
3315 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
3316 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003317 };
3318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003319 mbedtls_ecp_group_init( &grp );
3320 mbedtls_ecp_point_init( &R );
3321 mbedtls_ecp_point_init( &P );
3322 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003323
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003324 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003325#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003326 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02003327#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003328 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003329#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003330
3331 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003332 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003333
3334 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003335 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
3336 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003337
3338 add_count = 0;
3339 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003340 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003341 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3342 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003343
3344 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3345 {
3346 add_c_prev = add_count;
3347 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003348 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003349 add_count = 0;
3350 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003351 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003353 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3354 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003355
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003356 if( add_count != add_c_prev ||
3357 dbl_count != dbl_c_prev ||
3358 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003359 {
3360 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003361 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003362
3363 ret = 1;
3364 goto cleanup;
3365 }
3366 }
3367
3368 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003369 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003370
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003371 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003372 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003373 /* We computed P = 2G last time, use it */
3374
3375 add_count = 0;
3376 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003377 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003378 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3379 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003380
3381 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3382 {
3383 add_c_prev = add_count;
3384 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003385 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003386 add_count = 0;
3387 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003388 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003390 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3391 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003392
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003393 if( add_count != add_c_prev ||
3394 dbl_count != dbl_c_prev ||
3395 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003396 {
3397 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003398 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003399
3400 ret = 1;
3401 goto cleanup;
3402 }
3403 }
3404
3405 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003406 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003407
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003408#if defined(ECP_ONE_STEP_KDF)
3409 if( verbose != 0 )
3410 mbedtls_printf( " ECP test #3 (internal KDF): " );
3411
3412 ret = ecp_kdf_self_test();
3413 if( ret != 0 )
3414 {
3415 if( verbose != 0 )
3416 mbedtls_printf( "failed\n" );
3417
3418 ret = 1;
3419 goto cleanup;
3420 }
3421
3422 if( verbose != 0 )
3423 mbedtls_printf( "passed\n" );
3424#endif /* ECP_ONE_STEP_KDF */
3425
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003426cleanup:
3427
3428 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003429 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003431 mbedtls_ecp_group_free( &grp );
3432 mbedtls_ecp_point_free( &R );
3433 mbedtls_ecp_point_free( &P );
3434 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003435
3436 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003437 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003438
3439 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003440}
3441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003442#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003443
Janos Follathb0697532016-08-18 12:38:46 +01003444#endif /* !MBEDTLS_ECP_ALT */
3445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003446#endif /* MBEDTLS_ECP_C */