blob: 050a497e1b8d80d738cf8110d13b3e6060550e23 [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;
Manuel Pégourié-Gonnarda90a95b2020-06-17 12:40:57 +0200324 uint8_t tmp[HASH_BLOCK_BYTES];
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200325
326 while( len_done < output_len )
327 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200328 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
Manuel Pégourié-Gonnarda90a95b2020-06-17 12:40:57 +0200349 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
350
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200351 return( 0 );
352}
353
354#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200355#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200356#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200357#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
358
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200359#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100360/*
361 * Maximum number of "basic operations" to be done in a row.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +0200362 *
363 * Default value 0 means that ECC operations will not yield.
364 * Note that regardless of the value of ecp_max_ops, always at
365 * least one step is performed before yielding.
366 *
367 * Setting ecp_max_ops=1 can be suitable for testing purposes
368 * as it will interrupt computation at all possible points.
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100369 */
370static unsigned ecp_max_ops = 0;
371
372/*
373 * Set ecp_max_ops
374 */
375void mbedtls_ecp_set_max_ops( unsigned max_ops )
376{
377 ecp_max_ops = max_ops;
378}
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100379
380/*
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200381 * Check if restart is enabled
382 */
Manuel Pégourié-Gonnardb843b152018-10-16 10:41:31 +0200383int mbedtls_ecp_restart_is_enabled( void )
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200384{
385 return( ecp_max_ops != 0 );
386}
387
388/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200389 * Restart sub-context for ecp_mul_comb()
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100390 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200391struct mbedtls_ecp_restart_mul
392{
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100393 mbedtls_ecp_point R; /* current intermediate result */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +0100394 size_t i; /* current index in various loops, 0 outside */
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100395 mbedtls_ecp_point *T; /* table for precomputed points */
396 unsigned char T_size; /* number of points in table T */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200397 enum { /* what were we doing last time we returned? */
398 ecp_rsm_init = 0, /* nothing so far, dummy initial state */
399 ecp_rsm_pre_dbl, /* precompute 2^n multiples */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100400 ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */
401 ecp_rsm_pre_add, /* precompute remaining points by adding */
402 ecp_rsm_pre_norm_add, /* normalize all precomputed points */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200403 ecp_rsm_comb_core, /* ecp_mul_comb_core() */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100404 ecp_rsm_final_norm, /* do the final normalization */
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100405 } state;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200406#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
407 ecp_drbg_context drbg_ctx;
408 unsigned char drbg_seeded;
409#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100410};
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100411
412/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200413 * Init restart_mul sub-context
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100414 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200415static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100416{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200417 mbedtls_ecp_point_init( &ctx->R );
418 ctx->i = 0;
419 ctx->T = NULL;
420 ctx->T_size = 0;
421 ctx->state = ecp_rsm_init;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200422#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
423 ecp_drbg_init( &ctx->drbg_ctx );
424 ctx->drbg_seeded = 0;
425#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100426}
427
428/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200429 * Free the components of a restart_mul sub-context
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100430 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200431static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100432{
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100433 unsigned char i;
434
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100435 if( ctx == NULL )
436 return;
Manuel Pégourié-Gonnard78d564a2017-03-14 11:48:38 +0100437
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100438 mbedtls_ecp_point_free( &ctx->R );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100439
Manuel Pégourié-Gonnard31f0ef72017-05-17 10:05:58 +0200440 if( ctx->T != NULL )
441 {
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100442 for( i = 0; i < ctx->T_size; i++ )
443 mbedtls_ecp_point_free( ctx->T + i );
444 mbedtls_free( ctx->T );
445 }
446
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200447#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
448 ecp_drbg_free( &ctx->drbg_ctx );
449#endif
450
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200451 ecp_restart_rsm_init( ctx );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100452}
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100453
454/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200455 * Restart context for ecp_muladd()
456 */
457struct mbedtls_ecp_restart_muladd
458{
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200459 mbedtls_ecp_point mP; /* mP value */
460 mbedtls_ecp_point R; /* R intermediate result */
461 enum { /* what should we do next? */
462 ecp_rsma_mul1 = 0, /* first multiplication */
463 ecp_rsma_mul2, /* second multiplication */
464 ecp_rsma_add, /* addition */
465 ecp_rsma_norm, /* normalization */
466 } state;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200467};
468
469/*
470 * Init restart_muladd sub-context
471 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200472static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200473{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200474 mbedtls_ecp_point_init( &ctx->mP );
475 mbedtls_ecp_point_init( &ctx->R );
476 ctx->state = ecp_rsma_mul1;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200477}
478
479/*
480 * Free the components of a restart_muladd sub-context
481 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200482static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200483{
484 if( ctx == NULL )
485 return;
486
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200487 mbedtls_ecp_point_free( &ctx->mP );
488 mbedtls_ecp_point_free( &ctx->R );
489
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200490 ecp_restart_ma_init( ctx );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200491}
492
493/*
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200494 * Initialize a restart context
495 */
496void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx )
497{
Hanno Becker80f71682018-12-18 23:44:43 +0000498 ECP_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200499 ctx->ops_done = 0;
500 ctx->depth = 0;
501 ctx->rsm = NULL;
502 ctx->ma = NULL;
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200503}
504
505/*
506 * Free the components of a restart context
507 */
508void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx )
509{
510 if( ctx == NULL )
511 return;
512
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200513 ecp_restart_rsm_free( ctx->rsm );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200514 mbedtls_free( ctx->rsm );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200515
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200516 ecp_restart_ma_free( ctx->ma );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200517 mbedtls_free( ctx->ma );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200518
519 mbedtls_ecp_restart_init( ctx );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200520}
521
522/*
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100523 * Check if we can do the next step
524 */
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +0200525int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
526 mbedtls_ecp_restart_ctx *rs_ctx,
527 unsigned ops )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100528{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000529 ECP_VALIDATE_RET( grp != NULL );
530
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200531 if( rs_ctx != NULL && ecp_max_ops != 0 )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100532 {
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100533 /* scale depending on curve size: the chosen reference is 256-bit,
534 * and multiplication is quadratic. Round to the closest integer. */
535 if( grp->pbits >= 512 )
536 ops *= 4;
537 else if( grp->pbits >= 384 )
538 ops *= 2;
539
Hanno Beckerb10c6602018-10-26 13:50:13 +0100540 /* Avoid infinite loops: always allow first step.
541 * Because of that, however, it's not generally true
542 * that ops_done <= ecp_max_ops, so the check
543 * ops_done > ecp_max_ops below is mandatory. */
544 if( ( rs_ctx->ops_done != 0 ) &&
545 ( rs_ctx->ops_done > ecp_max_ops ||
546 ops > ecp_max_ops - rs_ctx->ops_done ) )
547 {
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100548 return( MBEDTLS_ERR_ECP_IN_PROGRESS );
Hanno Beckerb10c6602018-10-26 13:50:13 +0100549 }
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100550
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100551 /* update running count */
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200552 rs_ctx->ops_done += ops;
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100553 }
554
555 return( 0 );
556}
557
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200558/* Call this when entering a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200559#define ECP_RS_ENTER( SUB ) do { \
560 /* reset ops count for this call if top-level */ \
561 if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \
562 rs_ctx->ops_done = 0; \
563 \
564 /* set up our own sub-context if needed */ \
565 if( mbedtls_ecp_restart_is_enabled() && \
566 rs_ctx != NULL && rs_ctx->SUB == NULL ) \
567 { \
568 rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
569 if( rs_ctx->SUB == NULL ) \
570 return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
571 \
572 ecp_restart_## SUB ##_init( rs_ctx->SUB ); \
573 } \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200574} while( 0 )
575
576/* Call this when leaving a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200577#define ECP_RS_LEAVE( SUB ) do { \
578 /* clear our sub-context when not in progress (done or error) */ \
579 if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
580 ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
581 { \
582 ecp_restart_## SUB ##_free( rs_ctx->SUB ); \
583 mbedtls_free( rs_ctx->SUB ); \
584 rs_ctx->SUB = NULL; \
585 } \
586 \
587 if( rs_ctx != NULL ) \
588 rs_ctx->depth--; \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200589} while( 0 )
590
591#else /* MBEDTLS_ECP_RESTARTABLE */
592
593#define ECP_RS_ENTER( sub ) (void) rs_ctx;
594#define ECP_RS_LEAVE( sub ) (void) rs_ctx;
595
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200596#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
599 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
600 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
601 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
602 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
603 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
604 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
605 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
606 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
607 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
608 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200609#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100610#endif
611
Nicholas Wilson08f3ef12015-11-10 13:10:01 +0000612#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
613 defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200614#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100615#endif
616
617/*
618 * Curve types: internal for now, might be exposed later
619 */
620typedef enum
621{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200622 ECP_TYPE_NONE = 0,
623 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
624 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100625} ecp_curve_type;
626
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100627/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200628 * List of supported curves:
629 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200630 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200631 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200632 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100633 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100634 * Curves are listed in order: largest curves first, and for a given size,
635 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200636 *
637 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200638 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200640{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
642 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200643#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200644#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
645 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100646#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
648 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200649#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
651 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100652#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
654 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200655#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
657 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100658#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
660 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100661#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
663 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200664#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
666 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100667#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
669 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100670#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
672 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100673#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200675};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100676
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200677#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
678 sizeof( ecp_supported_curves[0] )
679
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200681
682/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200683 * List of supported curves and associated info
684 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200686{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200687 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200688}
689
690/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100691 * List of supported curves, group ID only
692 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100694{
695 static int init_done = 0;
696
697 if( ! init_done )
698 {
699 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200700 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100701
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702 for( curve_info = mbedtls_ecp_curve_list();
703 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100704 curve_info++ )
705 {
706 ecp_supported_grp_id[i++] = curve_info->grp_id;
707 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100709
710 init_done = 1;
711 }
712
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200713 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100714}
715
716/*
717 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200718 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719const 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 +0200720{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200722
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200723 for( curve_info = mbedtls_ecp_curve_list();
724 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200725 curve_info++ )
726 {
727 if( curve_info->grp_id == grp_id )
728 return( curve_info );
729 }
730
731 return( NULL );
732}
733
734/*
735 * Get the curve info from the TLS identifier
736 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200738{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200740
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741 for( curve_info = mbedtls_ecp_curve_list();
742 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200743 curve_info++ )
744 {
745 if( curve_info->tls_id == tls_id )
746 return( curve_info );
747 }
748
749 return( NULL );
750}
751
752/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100753 * Get the curve info from the name
754 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200755const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100756{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200757 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100758
Hanno Beckerb7a04a72018-12-18 23:50:21 +0000759 if( name == NULL )
760 return( NULL );
761
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200762 for( curve_info = mbedtls_ecp_curve_list();
763 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100764 curve_info++ )
765 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200766 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100767 return( curve_info );
768 }
769
770 return( NULL );
771}
772
773/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100774 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100775 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200776static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100777{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100778 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200779 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100780
781 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200782 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100783 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200784 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100785}
786
787/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100788 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100789 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200790void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100791{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000792 ECP_VALIDATE( pt != NULL );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100793
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200794 mbedtls_mpi_init( &pt->X );
795 mbedtls_mpi_init( &pt->Y );
796 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100797}
798
799/*
800 * Initialize (the components of) a group
801 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200802void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100803{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000804 ECP_VALIDATE( grp != NULL );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100805
Manuel Pégourié-Gonnard95e2eca2018-06-20 10:29:47 +0200806 grp->id = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200807 mbedtls_mpi_init( &grp->P );
808 mbedtls_mpi_init( &grp->A );
809 mbedtls_mpi_init( &grp->B );
810 mbedtls_ecp_point_init( &grp->G );
811 mbedtls_mpi_init( &grp->N );
812 grp->pbits = 0;
813 grp->nbits = 0;
814 grp->h = 0;
815 grp->modp = NULL;
816 grp->t_pre = NULL;
817 grp->t_post = NULL;
818 grp->t_data = NULL;
819 grp->T = NULL;
820 grp->T_size = 0;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100821}
822
823/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200824 * Initialize (the components of) a key pair
825 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200826void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200827{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000828 ECP_VALIDATE( key != NULL );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200829
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200830 mbedtls_ecp_group_init( &key->grp );
831 mbedtls_mpi_init( &key->d );
832 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200833}
834
835/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100836 * Unallocate (the components of) a point
837 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200838void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100839{
840 if( pt == NULL )
841 return;
842
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200843 mbedtls_mpi_free( &( pt->X ) );
844 mbedtls_mpi_free( &( pt->Y ) );
845 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100846}
847
848/*
849 * Unallocate (the components of) a group
850 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200851void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100852{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200853 size_t i;
854
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100855 if( grp == NULL )
856 return;
857
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100858 if( grp->h != 1 )
859 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200860 mbedtls_mpi_free( &grp->P );
861 mbedtls_mpi_free( &grp->A );
862 mbedtls_mpi_free( &grp->B );
863 mbedtls_ecp_point_free( &grp->G );
864 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100865 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200866
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200867 if( grp->T != NULL )
868 {
869 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200870 mbedtls_ecp_point_free( &grp->T[i] );
871 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200872 }
873
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500874 mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100875}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100876
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100877/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200878 * Unallocate (the components of) a key pair
879 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200880void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200881{
Paul Bakker66d5d072014-06-17 16:39:18 +0200882 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200883 return;
884
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200885 mbedtls_ecp_group_free( &key->grp );
886 mbedtls_mpi_free( &key->d );
887 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200888}
889
890/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200891 * Copy the contents of a point
892 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200893int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200894{
895 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000896 ECP_VALIDATE_RET( P != NULL );
897 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200898
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
900 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
901 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200902
903cleanup:
904 return( ret );
905}
906
907/*
908 * Copy the contents of a group object
909 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200910int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200911{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000912 ECP_VALIDATE_RET( dst != NULL );
913 ECP_VALIDATE_RET( src != NULL );
914
915 return( mbedtls_ecp_group_load( dst, src->id ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200916}
917
918/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100919 * Set point to zero
920 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200921int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100922{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100923 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000924 ECP_VALIDATE_RET( pt != NULL );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100925
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200926 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
927 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
928 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100929
930cleanup:
931 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100932}
933
934/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100935 * Tell if a point is zero
936 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200937int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100938{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000939 ECP_VALIDATE_RET( pt != NULL );
940
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100942}
943
944/*
Brian J Murrayf343de12018-10-22 16:40:49 -0700945 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200946 */
947int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
948 const mbedtls_ecp_point *Q )
949{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000950 ECP_VALIDATE_RET( P != NULL );
951 ECP_VALIDATE_RET( Q != NULL );
952
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200953 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
954 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
955 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
956 {
957 return( 0 );
958 }
959
960 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
961}
962
963/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100964 * Import a non-zero point from ASCII strings
965 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200966int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100967 const char *x, const char *y )
968{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100969 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000970 ECP_VALIDATE_RET( P != NULL );
971 ECP_VALIDATE_RET( x != NULL );
972 ECP_VALIDATE_RET( y != NULL );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100973
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200974 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
975 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
976 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100977
978cleanup:
979 return( ret );
980}
981
982/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100983 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100984 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000985int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp,
986 const mbedtls_ecp_point *P,
987 int format, size_t *olen,
988 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100989{
Paul Bakkera280d0f2013-04-08 13:40:17 +0200990 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100991 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000992 ECP_VALIDATE_RET( grp != NULL );
993 ECP_VALIDATE_RET( P != NULL );
994 ECP_VALIDATE_RET( olen != NULL );
995 ECP_VALIDATE_RET( buf != NULL );
996 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
997 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100998
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100999 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001000 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001001 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001002 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001003 {
1004 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001005 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001006
1007 buf[0] = 0x00;
1008 *olen = 1;
1009
1010 return( 0 );
1011 }
1012
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001013 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001014
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001016 {
1017 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001018
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001019 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001020 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001021
1022 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001023 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
1024 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001025 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001026 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001027 {
1028 *olen = plen + 1;
1029
1030 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001031 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
1034 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001035 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001036
1037cleanup:
1038 return( ret );
1039}
1040
1041/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001042 * Import a point from unsigned binary data (SEC1 2.3.4)
1043 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001044int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
1045 mbedtls_ecp_point *pt,
1046 const unsigned char *buf, size_t ilen )
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001047{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001048 int ret;
1049 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001050 ECP_VALIDATE_RET( grp != NULL );
1051 ECP_VALIDATE_RET( pt != NULL );
1052 ECP_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001053
Paul Bakker82788fb2014-10-20 13:59:19 +02001054 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001055 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001056
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001057 if( buf[0] == 0x00 )
1058 {
1059 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001060 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001061 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001063 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001065 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001066
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001067 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001068 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001069
1070 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001071 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001072
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001073 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
1074 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
1075 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001076
1077cleanup:
1078 return( ret );
1079}
1080
1081/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001082 * Import a point from a TLS ECPoint record (RFC 4492)
1083 * struct {
1084 * opaque point <1..2^8-1>;
1085 * } ECPoint;
1086 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001087int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp,
1088 mbedtls_ecp_point *pt,
1089 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001090{
1091 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001092 const unsigned char *buf_start;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001093 ECP_VALIDATE_RET( grp != NULL );
1094 ECP_VALIDATE_RET( pt != NULL );
1095 ECP_VALIDATE_RET( buf != NULL );
1096 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001097
1098 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001099 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001100 */
1101 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001102 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001103
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001104 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001105 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001106 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001107
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001108 /*
1109 * Save buffer start for read_binary and update buf
1110 */
1111 buf_start = *buf;
1112 *buf += data_len;
1113
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001114 return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001115}
1116
1117/*
1118 * Export a point as a TLS ECPoint record (RFC 4492)
1119 * struct {
1120 * opaque point <1..2^8-1>;
1121 * } ECPoint;
1122 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001123int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001124 int format, size_t *olen,
1125 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001126{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001127 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001128 ECP_VALIDATE_RET( grp != NULL );
1129 ECP_VALIDATE_RET( pt != NULL );
1130 ECP_VALIDATE_RET( olen != NULL );
1131 ECP_VALIDATE_RET( buf != NULL );
1132 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
1133 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001134
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001135 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001136 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001137 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001138 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001139 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001140
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001142 olen, buf + 1, blen - 1) ) != 0 )
1143 return( ret );
1144
1145 /*
1146 * write length to the first byte and update total length
1147 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +02001148 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001149 ++*olen;
1150
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001151 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001152}
1153
1154/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001155 * Set a group from an ECParameters record (RFC 4492)
1156 */
Janos Follath89ac8c92018-10-30 11:24:05 +00001157int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp,
1158 const unsigned char **buf, size_t len )
1159{
1160 int ret;
1161 mbedtls_ecp_group_id grp_id;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001162 ECP_VALIDATE_RET( grp != NULL );
1163 ECP_VALIDATE_RET( buf != NULL );
1164 ECP_VALIDATE_RET( *buf != NULL );
Janos Follath89ac8c92018-10-30 11:24:05 +00001165
1166 if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 )
1167 return( ret );
1168
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001169 return( mbedtls_ecp_group_load( grp, grp_id ) );
Janos Follath89ac8c92018-10-30 11:24:05 +00001170}
1171
1172/*
1173 * Read a group id from an ECParameters record (RFC 4492) and convert it to
1174 * mbedtls_ecp_group_id.
1175 */
1176int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp,
1177 const unsigned char **buf, size_t len )
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001178{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001179 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001180 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001181 ECP_VALIDATE_RET( grp != NULL );
1182 ECP_VALIDATE_RET( buf != NULL );
1183 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001184
1185 /*
1186 * We expect at least three bytes (see below)
1187 */
1188 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001189 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001190
1191 /*
1192 * First byte is curve_type; only named_curve is handled
1193 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001194 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
1195 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001196
1197 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001198 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001199 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001200 tls_id = *(*buf)++;
1201 tls_id <<= 8;
1202 tls_id |= *(*buf)++;
1203
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001204 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
1205 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001206
Janos Follath89ac8c92018-10-30 11:24:05 +00001207 *grp = curve_info->grp_id;
1208
1209 return( 0 );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001210}
1211
1212/*
1213 * Write the ECParameters record corresponding to a group (RFC 4492)
1214 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001215int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001216 unsigned char *buf, size_t blen )
1217{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001218 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001219 ECP_VALIDATE_RET( grp != NULL );
1220 ECP_VALIDATE_RET( buf != NULL );
1221 ECP_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
1224 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001225
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001226 /*
1227 * We are going to write 3 bytes (see below)
1228 */
1229 *olen = 3;
1230 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001231 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001232
1233 /*
1234 * First byte is curve_type, always named_curve
1235 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001236 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001237
1238 /*
1239 * Next two bytes are the namedcurve value
1240 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001241 buf[0] = curve_info->tls_id >> 8;
1242 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001243
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001244 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +01001245}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001246
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001247/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001248 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
1249 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001250 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001251 * 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 +02001252 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001254{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001255 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001256
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001257 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001259
1260 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001261 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001262 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001263 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001265 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001267 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001268
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001269 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001270 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
1271 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001273 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001274 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001276
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001277cleanup:
1278 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001279}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001280
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +01001281/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001282 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001283 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001284 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001285 * 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 +01001286 * bring the result back to this range.
1287 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001288 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001289 */
1290
1291/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001292 * 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 +01001293 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001294#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01001295#define INC_MUL_COUNT mul_count++;
1296#else
1297#define INC_MUL_COUNT
1298#endif
1299
Hanno Beckerd6028a12018-10-15 12:01:35 +01001300#define MOD_MUL( N ) \
1301 do \
1302 { \
1303 MBEDTLS_MPI_CHK( ecp_modp( &(N), grp ) ); \
1304 INC_MUL_COUNT \
1305 } while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001306
1307/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001308 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +02001309 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001310 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001311#define MOD_SUB( N ) \
1312 while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \
1313 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001314
1315/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001316 * 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 +02001317 * We known P, N and the result are positive, so sub_abs is correct, and
1318 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001319 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001320#define MOD_ADD( N ) \
1321 while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \
1322 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001323
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001324#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001325/*
1326 * For curves in short Weierstrass form, we do all the internal operations in
1327 * Jacobian coordinates.
1328 *
1329 * For multiplication, we'll use a comb method with coutermeasueres against
1330 * SPA, hence timing attacks.
1331 */
1332
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001333/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001334 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001335 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001336 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001337static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001338{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001339 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001340 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001342 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001343 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001344
Janos Follathb0697532016-08-18 12:38:46 +01001345#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001346 if( mbedtls_internal_ecp_grp_capable( grp ) )
1347 return( mbedtls_internal_ecp_normalize_jac( grp, pt ) );
Janos Follath372697b2016-10-28 16:53:11 +01001348#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001349
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001350 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001351
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001352 /*
1353 * X = X / Z^2 mod p
1354 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001355 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
1356 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1357 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 +01001358
1359 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001360 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001361 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
1363 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 +01001364
1365 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001366 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001367 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001369
1370cleanup:
1371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001373
1374 return( ret );
1375}
1376
1377/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001378 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001379 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001380 * (See for example Cohen's "A Course in Computational Algebraic Number
1381 * Theory", Algorithm 10.3.4.)
1382 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001383 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001384 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001385 *
1386 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001387 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001388static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001389 mbedtls_ecp_point *T[], size_t T_size )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001390{
1391 int ret;
1392 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001394
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001395 if( T_size < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001396 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001397
Janos Follathb0697532016-08-18 12:38:46 +01001398#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001399 if( mbedtls_internal_ecp_grp_capable( grp ) )
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001400 return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) );
Janos Follathb0697532016-08-18 12:38:46 +01001401#endif
1402
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001403 if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001404 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001405
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02001406 for( i = 0; i < T_size; i++ )
1407 mbedtls_mpi_init( &c[i] );
1408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001409 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001410
1411 /*
1412 * c[i] = Z_0 * ... * Z_i
1413 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001415 for( i = 1; i < T_size; i++ )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001416 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001417 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001418 MOD_MUL( c[i] );
1419 }
1420
1421 /*
1422 * u = 1 / (Z_0 * ... * Z_n) mod P
1423 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001424 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001425
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001426 for( i = T_size - 1; ; i-- )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001427 {
1428 /*
1429 * Zi = 1 / Z_i mod p
1430 * u = 1 / (Z_0 * ... * Z_i) mod P
1431 */
1432 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001433 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001434 }
1435 else
1436 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001437 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1438 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001439 }
1440
1441 /*
1442 * proceed as in normalize()
1443 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001444 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1445 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1446 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1447 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 +01001448
1449 /*
1450 * Post-precessing: reclaim some memory by shrinking coordinates
1451 * - not storing Z (always 1)
1452 * - shrinking other coordinates, but still keeping the same number of
1453 * limbs as P, as otherwise it will too likely be regrown too fast.
1454 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001455 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1456 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1457 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001458
1459 if( i == 0 )
1460 break;
1461 }
1462
1463cleanup:
1464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001465 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001466 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001467 mbedtls_mpi_free( &c[i] );
1468 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001469
1470 return( ret );
1471}
1472
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001473/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001474 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1475 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1476 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1478 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001479 unsigned char inv )
1480{
1481 int ret;
1482 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001483 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001486
1487 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1489 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1490 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001491
1492cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001493 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001494
1495 return( ret );
1496}
1497
1498/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001499 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001500 *
Peter Dettmance661b22015-02-07 14:43:51 +07001501 * 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 +01001502 *
Peter Dettmance661b22015-02-07 14:43:51 +07001503 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1504 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1505 *
1506 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1507 *
1508 * Cost: 1D := 3M + 4S (A == 0)
1509 * 4M + 4S (A == -3)
1510 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001511 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001512static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1513 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001514{
1515 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001516 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001518#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001519 dbl_count++;
1520#endif
1521
Janos Follathb0697532016-08-18 12:38:46 +01001522#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001523 if( mbedtls_internal_ecp_grp_capable( grp ) )
1524 return( mbedtls_internal_ecp_double_jac( grp, R, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01001525#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001526
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001527 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 +01001528
1529 /* Special case for A = -3 */
1530 if( grp->A.p == NULL )
1531 {
Peter Dettmance661b22015-02-07 14:43:51 +07001532 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001533 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1534 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1535 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1536 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1537 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001538 }
1539 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001540 {
Peter Dettmance661b22015-02-07 14:43:51 +07001541 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001542 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1543 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001544
1545 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001546 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001547 {
1548 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001549 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1550 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1551 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1552 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001553 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001554 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001555
Peter Dettmance661b22015-02-07 14:43:51 +07001556 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001557 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1558 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1559 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1560 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001561
Peter Dettmance661b22015-02-07 14:43:51 +07001562 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001563 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1564 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001565
1566 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001567 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1568 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1569 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001570
1571 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001572 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1573 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1574 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001575
1576 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001577 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1578 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001579
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001580 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1581 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1582 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001583
1584cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001585 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 +02001586
1587 return( ret );
1588}
1589
1590/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001591 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001592 *
1593 * The coordinates of Q must be normalized (= affine),
1594 * but those of P don't need to. R is not normalized.
1595 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001596 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001597 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001598 * - at each step, P, Q and R are multiples of the base point, the factor
1599 * being less than its order, so none of them is zero;
1600 * - Q is an odd multiple of the base point, P an even multiple,
1601 * due to the choice of precomputed points in the modified comb method.
1602 * So branches for these cases do not leak secret information.
1603 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001604 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1605 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001606 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001607 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001608static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1609 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001610{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001611 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001612 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001613
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001614#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001615 add_count++;
1616#endif
1617
Janos Follathb0697532016-08-18 12:38:46 +01001618#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001619 if( mbedtls_internal_ecp_grp_capable( grp ) )
1620 return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) );
Janos Follath372697b2016-10-28 16:53:11 +01001621#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001622
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001623 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001624 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001625 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1627 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001629 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1630 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001631
1632 /*
1633 * Make sure Q coordinates are normalized
1634 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001635 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1636 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001638 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1639 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001640
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1642 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1643 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1644 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1645 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1646 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001647
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001648 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001649 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001650 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001652 {
1653 ret = ecp_double_jac( grp, R, P );
1654 goto cleanup;
1655 }
1656 else
1657 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001659 goto cleanup;
1660 }
1661 }
1662
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1664 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1665 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1666 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1667 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1668 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1669 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1670 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1671 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1672 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1673 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1674 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1677 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1678 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001679
1680cleanup:
1681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001682 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1683 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001684
1685 return( ret );
1686}
1687
1688/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001689 * Randomize jacobian coordinates:
1690 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001691 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001692 *
1693 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001694 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001695static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001696 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1697{
1698 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001699 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001700 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001701 int count = 0;
1702
Janos Follathb0697532016-08-18 12:38:46 +01001703#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001704 if( mbedtls_internal_ecp_grp_capable( grp ) )
1705 return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) );
Janos Follath372697b2016-10-28 16:53:11 +01001706#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001707
1708 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001709 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001710
1711 /* Generate l such that 1 < l < p */
1712 do
1713 {
Ron Eldorca6ff582017-01-12 14:50:50 +02001714 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001715
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001716 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1717 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001718
1719 if( count++ > 10 )
Jonas6645fd32020-05-08 16:57:18 +09001720 {
1721 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1722 goto cleanup;
1723 }
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001724 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001726
1727 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001728 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 +02001729
1730 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001731 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1732 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 +02001733
1734 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001735 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1736 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 +02001737
1738cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001739 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001740
1741 return( ret );
1742}
1743
1744/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001745 * Check and define parameters used by the comb method (see below for details)
1746 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001747#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1748#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001749#endif
1750
1751/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001752#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001753
1754/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001756
1757/*
1758 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001759 *
1760 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001761 * modified version that provides resistance to SPA by avoiding zero
1762 * digits in the representation as in [3]. We modify the method further by
1763 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001764 * representation uses one more K_i, due to carries, but saves on the size of
1765 * the precomputed table.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001766 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001767 * Summary of the comb method and its modifications:
1768 *
1769 * - The goal is to compute m*P for some w*d-bit integer m.
1770 *
1771 * - The basic comb method splits m into the w-bit integers
1772 * x[0] .. x[d-1] where x[i] consists of the bits in m whose
1773 * index has residue i modulo d, and computes m * P as
1774 * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where
1775 * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P.
1776 *
1777 * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by
1778 * .. + 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]] ..,
1779 * thereby successively converting it into a form where all summands
1780 * are nonzero, at the cost of negative summands. This is the basic idea of [3].
1781 *
1782 * - More generally, even if x[i+1] != 0, we can first transform the sum as
1783 * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] ..,
1784 * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]].
1785 * Performing and iterating this procedure for those x[i] that are even
1786 * (keeping track of carry), we can transform the original sum into one of the form
1787 * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]]
1788 * with all x'[i] odd. It is therefore only necessary to know S at odd indices,
1789 * which is why we are only computing half of it in the first place in
1790 * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb.
1791 *
1792 * - For the sake of compactness, only the seven low-order bits of x[i]
1793 * are used to represent its absolute value (K_i in the paper), and the msb
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001794 * 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 +02001795 * if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001796 *
1797 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001798 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001799 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001800 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001801 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1802 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001803 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01001804static void ecp_comb_recode_core( unsigned char x[], size_t d,
1805 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001806{
1807 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001808 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001809
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001810 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001811
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001812 /* First get the classical comb values (except for x_d = 0) */
1813 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001814 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001815 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001816
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001817 /* Now make sure x_1 .. x_d are odd */
1818 c = 0;
1819 for( i = 1; i <= d; i++ )
1820 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001821 /* Add carry and update it */
1822 cc = x[i] & c;
1823 x[i] = x[i] ^ c;
1824 c = cc;
1825
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001826 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001827 adjust = 1 - ( x[i] & 0x01 );
1828 c |= x[i] & ( x[i-1] * adjust );
1829 x[i] = x[i] ^ ( x[i-1] * adjust );
1830 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001831 }
1832}
1833
1834/*
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001835 * Precompute points for the adapted comb method
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001836 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001837 * Assumption: T must be able to hold 2^{w - 1} elements.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001838 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001839 * Operation: If i = i_{w-1} ... i_1 is the binary representation of i,
1840 * 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 +01001841 *
1842 * 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 +02001843 *
1844 * Note: Even comb values (those where P would be omitted from the
1845 * sum defining T[i] above) are not needed in our adaption
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001846 * the comb method. See ecp_comb_recode_core().
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001847 *
1848 * This function currently works in four steps:
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001849 * (1) [dbl] Computation of intermediate T[i] for 2-power values of i
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001850 * (2) [norm_dbl] Normalization of coordinates of these T[i]
1851 * (3) [add] Computation of all T[i]
1852 * (4) [norm_add] Normalization of all T[i]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001853 *
1854 * Step 1 can be interrupted but not the others; together with the final
1855 * coordinate normalization they are the largest steps done at once, depending
1856 * on the window size. Here are operation counts for P-256:
1857 *
1858 * step (2) (3) (4)
1859 * w = 5 142 165 208
1860 * w = 4 136 77 160
1861 * w = 3 130 33 136
1862 * w = 2 124 11 124
1863 *
1864 * So if ECC operations are blocking for too long even with a low max_ops
1865 * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order
1866 * to minimize maximum blocking time.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001867 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001868static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1869 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001870 unsigned char w, size_t d,
1871 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001872{
1873 int ret;
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001874 unsigned char i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001875 size_t j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001876 const unsigned char T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001878
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001879#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001880 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001881 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001882 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
1883 goto dbl;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001884 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl )
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001885 goto norm_dbl;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001886 if( rs_ctx->rsm->state == ecp_rsm_pre_add )
1887 goto add;
1888 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add )
1889 goto norm_add;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001890 }
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001891#else
1892 (void) rs_ctx;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001893#endif
1894
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001895#if defined(MBEDTLS_ECP_RESTARTABLE)
1896 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1897 {
1898 rs_ctx->rsm->state = ecp_rsm_pre_dbl;
1899
1900 /* initial state for the loop */
1901 rs_ctx->rsm->i = 0;
1902 }
1903
1904dbl:
1905#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001906 /*
1907 * Set T[0] = P and
1908 * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
1909 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001910 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001911
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001912#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001913 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
1914 j = rs_ctx->rsm->i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001915 else
1916#endif
1917 j = 0;
1918
1919 for( ; j < d * ( w - 1 ); j++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001920 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001921 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL );
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001922
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001923 i = 1U << ( j / d );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001924 cur = T + i;
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001925
1926 if( j % d == 0 )
1927 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
1928
1929 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001930 }
1931
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001932#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001933 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1934 rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl;
1935
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001936norm_dbl:
1937#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001938 /*
1939 * Normalize current elements in T. As T has holes,
1940 * use an auxiliary array of pointers to elements in T.
1941 */
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001942 j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001943 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001944 TT[j++] = T + i;
1945
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001946 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001947
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001948 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001949
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001950#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001951 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1952 rs_ctx->rsm->state = ecp_rsm_pre_add;
1953
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001954add:
1955#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001956 /*
1957 * Compute the remaining ones using the minimal number of additions
1958 * Be careful to update T[2^l] only after using it!
1959 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001960 MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001961
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001962 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001963 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001964 j = i;
1965 while( j-- )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001966 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001967 }
1968
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001969#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001970 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1971 rs_ctx->rsm->state = ecp_rsm_pre_norm_add;
1972
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001973norm_add:
1974#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001975 /*
Manuel Pégourié-Gonnarda966fde2018-10-23 10:41:11 +02001976 * Normalize final elements in T. Even though there are no holes now, we
1977 * still need the auxiliary array for homogeneity with the previous
1978 * call. Also, skip T[0] which is already normalised, being a copy of P.
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001979 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001980 for( j = 0; j + 1 < T_size; j++ )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001981 TT[j] = T + j + 1;
1982
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001983 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001984
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001985 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01001986
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001987cleanup:
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001988#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001989 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
1990 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001991 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001992 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001993 rs_ctx->rsm->i = j;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001994 }
1995#endif
Janos Follathb0697532016-08-18 12:38:46 +01001996
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001997 return( ret );
1998}
1999
2000/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01002001 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002002 *
2003 * See ecp_comb_recode_core() for background
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002004 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002006 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002007 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002008{
2009 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002010 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002011
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002012 /* Ignore the "sign" bit and scale down */
2013 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002014
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002015 /* Read the whole table to thwart cache-based timing attacks */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002016 for( j = 0; j < T_size; j++ )
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002017 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
2019 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002020 }
2021
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01002022 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002023 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002024
2025cleanup:
2026 return( ret );
2027}
2028
2029/*
2030 * Core multiplication algorithm for the (modified) comb method.
2031 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01002032 *
2033 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002034 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002035static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002036 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01002037 const unsigned char x[], size_t d,
2038 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002039 void *p_rng,
2040 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002041{
2042 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002043 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002044 size_t i;
2045
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002047
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002048#if !defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002049 (void) rs_ctx;
2050#endif
2051
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002052#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002053 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2054 rs_ctx->rsm->state != ecp_rsm_comb_core )
2055 {
2056 rs_ctx->rsm->i = 0;
2057 rs_ctx->rsm->state = ecp_rsm_comb_core;
2058 }
2059
2060 /* new 'if' instead of nested for the sake of the 'else' branch */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002061 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002062 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002063 /* restore current index (R already pointing to rs_ctx->rsm->R) */
2064 i = rs_ctx->rsm->i;
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002065 }
2066 else
2067#endif
2068 {
2069 /* Start with a non-zero point and randomize its coordinates */
2070 i = d;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002071 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) );
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002072 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002073#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002074 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002075#endif
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002076 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
2077 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002078
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002079 while( i != 0 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002080 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002081 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002082 --i;
2083
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002084 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002085 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002086 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002087 }
2088
2089cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002090
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002091 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002092
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002093#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002094 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2095 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002096 {
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002097 rs_ctx->rsm->i = i;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002098 /* no need to save R, already pointing to rs_ctx->rsm->R */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002099 }
2100#endif
2101
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002102 return( ret );
2103}
2104
2105/*
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002106 * Recode the scalar to get constant-time comb multiplication
2107 *
2108 * As the actual scalar recoding needs an odd scalar as a starting point,
2109 * this wrapper ensures that by replacing m by N - m if necessary, and
2110 * informs the caller that the result of multiplication will be negated.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002111 *
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002112 * This works because we only support large prime order for Short Weierstrass
2113 * curves, so N is always odd hence either m or N - m is.
2114 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002115 * See ecp_comb_recode_core() for background.
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002116 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002117static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp,
2118 const mbedtls_mpi *m,
2119 unsigned char k[COMB_MAX_D + 1],
2120 size_t d,
2121 unsigned char w,
2122 unsigned char *parity_trick )
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002123{
2124 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002125 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002126
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002127 mbedtls_mpi_init( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002128 mbedtls_mpi_init( &mm );
2129
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002130 /* N is always odd (see above), just make extra sure */
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002131 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
2132 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
2133
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002134 /* do we need the parity trick? */
2135 *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 );
2136
2137 /* execute parity fix in constant time */
2138 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002139 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002140 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) );
2141
2142 /* actual scalar recoding */
2143 ecp_comb_recode_core( k, d, w, &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002144
2145cleanup:
2146 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002147 mbedtls_mpi_free( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002148
2149 return( ret );
2150}
2151
2152/*
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002153 * Perform comb multiplication (for short Weierstrass curves)
2154 * once the auxiliary table has been pre-computed.
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002155 *
2156 * Scalar recoding may use a parity trick that makes us compute -m * P,
2157 * if that is the case we'll need to recover m * P at the end.
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002158 */
2159static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
2160 mbedtls_ecp_point *R,
2161 const mbedtls_mpi *m,
2162 const mbedtls_ecp_point *T,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002163 unsigned char T_size,
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002164 unsigned char w,
2165 size_t d,
2166 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002167 void *p_rng,
2168 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002169{
2170 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002171 unsigned char parity_trick;
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002172 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002173 mbedtls_ecp_point *RR = R;
2174
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002175#if defined(MBEDTLS_ECP_RESTARTABLE)
2176 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2177 {
2178 RR = &rs_ctx->rsm->R;
2179
2180 if( rs_ctx->rsm->state == ecp_rsm_final_norm )
2181 goto final_norm;
2182 }
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002183#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002184
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002185 MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w,
2186 &parity_trick ) );
2187 MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d,
2188 f_rng, p_rng, rs_ctx ) );
2189 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) );
2190
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002191#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002192 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002193 rs_ctx->rsm->state = ecp_rsm_final_norm;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002194
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002195final_norm:
Manuel Pégourié-Gonnard18b0b3c2020-06-08 09:53:20 +02002196 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002197#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002198 /*
2199 * Knowledge of the jacobian coordinates may leak the last few bits of the
2200 * scalar [1], and since our MPI implementation isn't constant-flow,
2201 * inversion (used for coordinate normalization) may leak the full value
2202 * of its input via side-channels [2].
2203 *
2204 * [1] https://eprint.iacr.org/2003/191
2205 * [2] https://eprint.iacr.org/2020/055
2206 *
2207 * Avoid the leak by randomizing coordinates before we normalize them.
2208 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002209#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002210 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002211#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002212 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) );
2213
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002214 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
2215
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002216#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard28d16282017-08-23 17:33:27 +02002217 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2218 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) );
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002219#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002220
2221cleanup:
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002222 return( ret );
2223}
2224
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002225/*
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002226 * Pick window size based on curve size and whether we optimize for base point
2227 */
2228static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
2229 unsigned char p_eq_g )
2230{
2231 unsigned char w;
2232
2233 /*
2234 * Minimize the number of multiplications, that is minimize
2235 * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
2236 * (see costs of the various parts, with 1S = 1M)
2237 */
2238 w = grp->nbits >= 384 ? 5 : 4;
2239
2240 /*
2241 * If P == G, pre-compute a bit more, since this may be re-used later.
2242 * Just adding one avoids upping the cost of the first mul too much,
2243 * and the memory cost too.
2244 */
2245 if( p_eq_g )
2246 w++;
2247
2248 /*
2249 * Make sure w is within bounds.
2250 * (The last test is useful only for very small curves in the test suite.)
2251 */
2252 if( w > MBEDTLS_ECP_WINDOW_SIZE )
2253 w = MBEDTLS_ECP_WINDOW_SIZE;
2254 if( w >= grp->nbits )
2255 w = 2;
2256
2257 return( w );
2258}
2259
2260/*
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002261 * Multiplication using the comb method - for curves in short Weierstrass form
2262 *
2263 * This function is mainly responsible for administrative work:
2264 * - managing the restart context if enabled
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002265 * - managing the table of precomputed points (passed between the below two
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002266 * functions): allocation, computation, ownership tranfer, freeing.
2267 *
2268 * It delegates the actual arithmetic work to:
2269 * ecp_precompute_comb() and ecp_mul_comb_with_precomp()
2270 *
2271 * See comments on ecp_comb_recode_core() regarding the computation strategy.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002272 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2274 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002275 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002276 void *p_rng,
2277 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002278{
2279 int ret;
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002280 unsigned char w, p_eq_g, i;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002281 size_t d;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002282 unsigned char T_size = 0, T_ok = 0;
2283 mbedtls_ecp_point *T = NULL;
2284#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2285 ecp_drbg_context drbg_ctx;
2286
2287 ecp_drbg_init( &drbg_ctx );
2288#endif
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002289
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002290 ECP_RS_ENTER( rsm );
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +01002291
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002292#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2293 if( f_rng == NULL )
2294 {
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002295 /* Adjust pointers */
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002296 f_rng = &ecp_drbg_random;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002297#if defined(MBEDTLS_ECP_RESTARTABLE)
2298 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2299 p_rng = &rs_ctx->rsm->drbg_ctx;
2300 else
2301#endif
2302 p_rng = &drbg_ctx;
2303
2304 /* Initialize internal DRBG if necessary */
2305#if defined(MBEDTLS_ECP_RESTARTABLE)
2306 if( rs_ctx == NULL || rs_ctx->rsm == NULL ||
2307 rs_ctx->rsm->drbg_seeded == 0 )
2308#endif
2309 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002310 const size_t m_len = ( grp->nbits + 7 ) / 8;
2311 MBEDTLS_MPI_CHK( ecp_drbg_seed( p_rng, m, m_len ) );
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002312 }
2313#if defined(MBEDTLS_ECP_RESTARTABLE)
2314 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2315 rs_ctx->rsm->drbg_seeded = 1;
2316#endif
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002317 }
2318#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2319
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002320 /* Is P the base point ? */
2321#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
2322 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
2323 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard196d1332017-08-28 13:14:27 +02002324#else
2325 p_eq_g = 0;
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002326#endif
2327
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002328 /* Pick window size and deduce related sizes */
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002329 w = ecp_pick_window_size( grp, p_eq_g );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002330 T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002331 d = ( grp->nbits + w - 1 ) / w;
2332
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002333 /* Pre-computed table: do we have it already for the base point? */
2334 if( p_eq_g && grp->T != NULL )
2335 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002336 /* second pointer to the same table, will be deleted on exit */
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002337 T = grp->T;
2338 T_ok = 1;
2339 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002340 else
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002341#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002342 /* Pre-computed table: do we have one in progress? complete? */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002343 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL )
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002344 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002345 /* transfer ownership of T from rsm to local function */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002346 T = rs_ctx->rsm->T;
2347 rs_ctx->rsm->T = NULL;
2348 rs_ctx->rsm->T_size = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002349
Manuel Pégourié-Gonnardb25cb602018-10-16 11:48:09 +02002350 /* This effectively jumps to the call to mul_comb_after_precomp() */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002351 T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002352 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002353 else
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002354#endif
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002355 /* Allocate table if we didn't have any */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002356 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002357 T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002358 if( T == NULL )
2359 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02002360 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002361 goto cleanup;
2362 }
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02002363
2364 for( i = 0; i < T_size; i++ )
2365 mbedtls_ecp_point_init( &T[i] );
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002366
2367 T_ok = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002368 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002369
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002370 /* Compute table (or finish computing it) if not done already */
2371 if( !T_ok )
2372 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002373 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002374
2375 if( p_eq_g )
2376 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002377 /* almost transfer ownership of T to the group, but keep a copy of
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02002378 * the pointer to use for calling the next function more easily */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002379 grp->T = T;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002380 grp->T_size = T_size;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002381 }
2382 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002383
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002384 /* Actual comb multiplication using precomputed points */
2385 MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002386 T, T_size, w, d,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002387 f_rng, p_rng, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002388
2389cleanup:
2390
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002391#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2392 ecp_drbg_free( &drbg_ctx );
2393#endif
2394
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002395 /* does T belong to the group? */
2396 if( T == grp->T )
2397 T = NULL;
2398
2399 /* does T belong to the restart context? */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002400#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002401 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 +01002402 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002403 /* transfer ownership of T from local function to rsm */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002404 rs_ctx->rsm->T_size = T_size;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002405 rs_ctx->rsm->T = T;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002406 T = NULL;
2407 }
2408#endif
2409
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002410 /* did T belong to us? then let's destroy it! */
2411 if( T != NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002412 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002413 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002414 mbedtls_ecp_point_free( &T[i] );
2415 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002416 }
2417
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002418 /* don't free R while in progress in case R == P */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002419#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002420 if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
2421#endif
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002422 /* prevent caller from using invalid value */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01002423 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002424 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002425
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002426 ECP_RS_LEAVE( rsm );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +01002427
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002428 return( ret );
2429}
2430
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002431#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002432
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002433#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002434/*
2435 * For Montgomery curves, we do all the internal arithmetic in projective
2436 * coordinates. Import/export of points uses only the x coordinates, which is
2437 * internaly represented as X / Z.
2438 *
2439 * For scalar multiplication, we'll use a Montgomery ladder.
2440 */
2441
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002442/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002443 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
2444 * Cost: 1M + 1I
2445 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002446static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002447{
2448 int ret;
2449
Janos Follathb0697532016-08-18 12:38:46 +01002450#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002451 if( mbedtls_internal_ecp_grp_capable( grp ) )
2452 return( mbedtls_internal_ecp_normalize_mxz( grp, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01002453#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002455 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
2456 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
2457 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002458
2459cleanup:
2460 return( ret );
2461}
2462
2463/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002464 * Randomize projective x/z coordinates:
2465 * (X, Z) -> (l X, l Z) for random l
2466 * This is sort of the reverse operation of ecp_normalize_mxz().
2467 *
2468 * This countermeasure was first suggested in [2].
2469 * Cost: 2M
2470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002471static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002472 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2473{
2474 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01002476 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002477 int count = 0;
2478
Janos Follathb0697532016-08-18 12:38:46 +01002479#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002480 if( mbedtls_internal_ecp_grp_capable( grp ) )
2481 return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
Janos Follath372697b2016-10-28 16:53:11 +01002482#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002483
2484 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002485 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002486
2487 /* Generate l such that 1 < l < p */
2488 do
2489 {
Ron Eldorca6ff582017-01-12 14:50:50 +02002490 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
2493 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002494
2495 if( count++ > 10 )
Jonas6645fd32020-05-08 16:57:18 +09002496 {
2497 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
2498 goto cleanup;
2499 }
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002500 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002503 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
2504 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 +01002505
2506cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002507 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002508
2509 return( ret );
2510}
2511
2512/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002513 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
2514 * for Montgomery curves in x/z coordinates.
2515 *
2516 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
2517 * with
2518 * d = X1
2519 * P = (X2, Z2)
2520 * Q = (X3, Z3)
2521 * R = (X4, Z4)
2522 * S = (X5, Z5)
2523 * and eliminating temporary variables tO, ..., t4.
2524 *
2525 * Cost: 5M + 4S
2526 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002527static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
2528 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
2529 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
2530 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002531{
2532 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002533 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002534
Janos Follathb0697532016-08-18 12:38:46 +01002535#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002536 if( mbedtls_internal_ecp_grp_capable( grp ) )
2537 return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) );
Janos Follath372697b2016-10-28 16:53:11 +01002538#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002540 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
2541 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
2542 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002544 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
2545 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
2546 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
2547 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
2548 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
2549 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
2550 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
2551 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
2552 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
2553 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
2554 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
2555 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
2556 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
2557 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
2558 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
2559 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
2560 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
2561 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 +01002562
2563cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002564 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
2565 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
2566 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002567
2568 return( ret );
2569}
2570
2571/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002572 * Multiplication with Montgomery ladder in x/z coordinates,
2573 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002574 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002575static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2576 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002577 int (*f_rng)(void *, unsigned char *, size_t),
2578 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002579{
2580 int ret;
2581 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002582 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002583 mbedtls_ecp_point RP;
2584 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002585#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2586 ecp_drbg_context drbg_ctx;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002587
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002588 ecp_drbg_init( &drbg_ctx );
2589#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002590 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002591
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002592#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2593 if( f_rng == NULL )
2594 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002595 const size_t m_len = ( grp->nbits + 7 ) / 8;
2596 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002597 f_rng = &ecp_drbg_random;
2598 p_rng = &drbg_ctx;
2599 }
2600#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2601
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002602 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002603 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
2604 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002605
2606 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002607 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
2608 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
2609 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002610
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01002611 /* RP.X might be sligtly larger than P, so reduce it */
2612 MOD_ADD( RP.X );
2613
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002614 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002615#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002616 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002617#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002618 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002619
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002620 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002621 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002622 while( i-- > 0 )
2623 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002624 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002625 /*
2626 * if (b) R = 2R + P else R = 2R,
2627 * which is:
2628 * if (b) double_add( RP, R, RP, R )
2629 * else double_add( R, RP, R, RP )
2630 * but using safe conditional swaps to avoid leaks
2631 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002632 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2633 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
2634 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
2635 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2636 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002637 }
2638
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002639 /*
2640 * Knowledge of the projective coordinates may leak the last few bits of the
2641 * scalar [1], and since our MPI implementation isn't constant-flow,
2642 * inversion (used for coordinate normalization) may leak the full value
2643 * of its input via side-channels [2].
2644 *
2645 * [1] https://eprint.iacr.org/2003/191
2646 * [2] https://eprint.iacr.org/2020/055
2647 *
2648 * Avoid the leak by randomizing coordinates before we normalize them.
2649 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002650#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002651 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002652#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002653 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
2654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002655 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002656
2657cleanup:
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002658#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2659 ecp_drbg_free( &drbg_ctx );
2660#endif
2661
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002662 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002663
2664 return( ret );
2665}
2666
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002667#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002668
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002669/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002670 * Restartable multiplication R = m * P
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002671 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002672int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002673 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002674 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
2675 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002676{
Janos Follathb0697532016-08-18 12:38:46 +01002677 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00002678#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2679 char is_grp_capable = 0;
2680#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002681 ECP_VALIDATE_RET( grp != NULL );
2682 ECP_VALIDATE_RET( R != NULL );
2683 ECP_VALIDATE_RET( m != NULL );
2684 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002685
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002686#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002687 /* reset ops count for this call if top-level */
2688 if( rs_ctx != NULL && rs_ctx->depth++ == 0 )
2689 rs_ctx->ops_done = 0;
2690#endif
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002691
Janos Follathc44ab972016-11-18 16:38:23 +00002692#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002693 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
Janos Follathc44ab972016-11-18 16:38:23 +00002694 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathc44ab972016-11-18 16:38:23 +00002695#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002696
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002697#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002698 /* skip argument check when restarting */
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002699 if( rs_ctx == NULL || rs_ctx->rsm == NULL )
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002700#endif
2701 {
Manuel Pégourié-Gonnard5314f232017-04-21 12:36:59 +02002702 /* check_privkey is free */
2703 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
2704
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002705 /* Common sanity checks */
2706 MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) );
2707 MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002708 }
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002709
2710 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002711#if defined(ECP_MONTGOMERY)
2712 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002713 MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
Janos Follath430d3372016-11-03 14:25:37 +00002714#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002715#if defined(ECP_SHORTWEIERSTRASS)
2716 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002717 MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) );
Janos Follath430d3372016-11-03 14:25:37 +00002718#endif
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002719
Janos Follath6c8ccd52016-11-29 15:37:09 +00002720cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002721
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002722#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002723 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002724 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002725#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002726
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002727#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002728 if( rs_ctx != NULL )
2729 rs_ctx->depth--;
2730#endif
2731
Janos Follathb0697532016-08-18 12:38:46 +01002732 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002733}
2734
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002735/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002736 * Multiplication R = m * P
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002737 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002738int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002739 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002740 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002741{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002742 ECP_VALIDATE_RET( grp != NULL );
2743 ECP_VALIDATE_RET( R != NULL );
2744 ECP_VALIDATE_RET( m != NULL );
2745 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002746 return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002747}
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002748
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002749#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002750/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002751 * Check that an affine point is valid as a public key,
2752 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002753 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002754static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002755{
2756 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002757 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002758
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002759 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002760 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2761 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2762 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2763 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2764 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002765
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002766 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002767
2768 /*
2769 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002770 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002771 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002772 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2773 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002774
2775 /* Special case for A = -3 */
2776 if( grp->A.p == NULL )
2777 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002778 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002779 }
2780 else
2781 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002782 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002783 }
2784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002785 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2786 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002787
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002788 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2789 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002790
2791cleanup:
2792
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002793 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002794
2795 return( ret );
2796}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002797#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002798
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002799/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002800 * R = m * P with shortcuts for m == 1 and m == -1
2801 * NOT constant-time - ONLY for short Weierstrass!
2802 */
2803static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2804 mbedtls_ecp_point *R,
2805 const mbedtls_mpi *m,
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002806 const mbedtls_ecp_point *P,
2807 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002808{
2809 int ret;
2810
2811 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2812 {
2813 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2814 }
2815 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2816 {
2817 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2818 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2819 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2820 }
2821 else
2822 {
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002823 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P,
2824 NULL, NULL, rs_ctx ) );
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002825 }
2826
2827cleanup:
2828 return( ret );
2829}
2830
2831/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002832 * Restartable linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002833 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002834 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002835int mbedtls_ecp_muladd_restartable(
2836 mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002837 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002838 const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
2839 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002840{
2841 int ret;
2842 mbedtls_ecp_point mP;
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002843 mbedtls_ecp_point *pmP = &mP;
2844 mbedtls_ecp_point *pR = R;
Janos Follathc44ab972016-11-18 16:38:23 +00002845#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2846 char is_grp_capable = 0;
2847#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002848 ECP_VALIDATE_RET( grp != NULL );
2849 ECP_VALIDATE_RET( R != NULL );
2850 ECP_VALIDATE_RET( m != NULL );
2851 ECP_VALIDATE_RET( P != NULL );
2852 ECP_VALIDATE_RET( n != NULL );
2853 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002854
2855 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2856 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2857
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002858 mbedtls_ecp_point_init( &mP );
2859
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002860 ECP_RS_ENTER( ma );
2861
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002862#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002863 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2864 {
2865 /* redirect intermediate results to restart context */
2866 pmP = &rs_ctx->ma->mP;
2867 pR = &rs_ctx->ma->R;
2868
2869 /* jump to next operation */
2870 if( rs_ctx->ma->state == ecp_rsma_mul2 )
2871 goto mul2;
2872 if( rs_ctx->ma->state == ecp_rsma_add )
2873 goto add;
2874 if( rs_ctx->ma->state == ecp_rsma_norm )
2875 goto norm;
2876 }
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002877#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002878
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002879 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002880#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002881 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002882 rs_ctx->ma->state = ecp_rsma_mul2;
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002883
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002884mul2:
2885#endif
2886 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) );
Janos Follathaf6f2692018-12-07 09:55:24 +00002887
2888#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2889 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
2890 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
2891#endif /* MBEDTLS_ECP_INTERNAL_ALT */
2892
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002893#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002894 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002895 rs_ctx->ma->state = ecp_rsma_add;
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002896
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002897add:
2898#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002899 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002900 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002901#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002902 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002903 rs_ctx->ma->state = ecp_rsma_norm;
Janos Follath430d3372016-11-03 14:25:37 +00002904
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002905norm:
2906#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002907 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002908 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) );
2909
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002910#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002911 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2912 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) );
2913#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002914
2915cleanup:
Janos Follathc44ab972016-11-18 16:38:23 +00002916#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002917 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002918 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002919#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002920
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002921 mbedtls_ecp_point_free( &mP );
2922
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002923 ECP_RS_LEAVE( ma );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002924
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002925 return( ret );
2926}
2927
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002928/*
2929 * Linear combination
2930 * NOT constant-time
2931 */
2932int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2933 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2934 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2935{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002936 ECP_VALIDATE_RET( grp != NULL );
2937 ECP_VALIDATE_RET( R != NULL );
2938 ECP_VALIDATE_RET( m != NULL );
2939 ECP_VALIDATE_RET( P != NULL );
2940 ECP_VALIDATE_RET( n != NULL );
2941 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002942 return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) );
2943}
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002944
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002945#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002946/*
2947 * Check validity of a public key for Montgomery curves with x-only schemes
2948 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002949static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002950{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002951 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00002952 /* Allow any public value, if it's too big then we'll just reduce it mod p
2953 * (RFC 7748 sec. 5 para. 3). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002954 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
2955 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002956
2957 return( 0 );
2958}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002959#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002960
2961/*
2962 * Check that a point is valid as a public key
2963 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002964int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp,
2965 const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002966{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002967 ECP_VALIDATE_RET( grp != NULL );
2968 ECP_VALIDATE_RET( pt != NULL );
2969
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002970 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002971 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
2972 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002973
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002974#if defined(ECP_MONTGOMERY)
2975 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002976 return( ecp_check_pubkey_mx( grp, pt ) );
2977#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002978#if defined(ECP_SHORTWEIERSTRASS)
2979 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002980 return( ecp_check_pubkey_sw( grp, pt ) );
2981#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002982 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002983}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002984
2985/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002986 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002987 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002988int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp,
2989 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002990{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002991 ECP_VALIDATE_RET( grp != NULL );
2992 ECP_VALIDATE_RET( d != NULL );
2993
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002994#if defined(ECP_MONTGOMERY)
2995 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002996 {
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00002997 /* see RFC 7748 sec. 5 para. 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002998 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
2999 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02003000 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003001 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003002
3003 /* see [Curve25519] page 5 */
3004 if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 )
3005 return( MBEDTLS_ERR_ECP_INVALID_KEY );
3006
3007 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003008 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003009#endif /* ECP_MONTGOMERY */
3010#if defined(ECP_SHORTWEIERSTRASS)
3011 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003012 {
3013 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003014 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
3015 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
3016 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003017 else
3018 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003019 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003020#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003021
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003022 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003023}
3024
3025/*
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003026 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003027 */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003028int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
3029 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003030 int (*f_rng)(void *, unsigned char *, size_t),
3031 void *p_rng )
3032{
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003033 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003034 size_t n_size;
3035
3036 ECP_VALIDATE_RET( grp != NULL );
3037 ECP_VALIDATE_RET( d != NULL );
3038 ECP_VALIDATE_RET( f_rng != NULL );
3039
3040 n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003041
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003042#if defined(ECP_MONTGOMERY)
3043 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003044 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003045 /* [M225] page 5 */
3046 size_t b;
3047
Janos Follath98e28a72016-05-31 14:03:54 +01003048 do {
3049 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
3050 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003051
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003052 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02003053 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003054 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003055 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003056 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003057 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003058
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003059 /* Make sure the last two bits are unset for Curve448, three bits for
3060 Curve25519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003061 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
3062 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003063 if( grp->nbits == 254 )
3064 {
3065 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
3066 }
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003067 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003068#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003069
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003070#if defined(ECP_SHORTWEIERSTRASS)
3071 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003072 {
3073 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003074 int count = 0;
Janos Follath867a3ab2019-10-11 14:21:53 +01003075 unsigned cmp = 0;
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01003076
3077 /*
3078 * Match the procedure given in RFC 6979 (deterministic ECDSA):
3079 * - use the same byte ordering;
3080 * - keep the leftmost nbits bits of the generated octet string;
3081 * - try until result is in the desired range.
3082 * This also avoids any biais, which is especially important for ECDSA.
3083 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003084 do
3085 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01003086 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003087 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003088
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01003089 /*
3090 * Each try has at worst a probability 1/2 of failing (the msb has
3091 * a probability 1/2 of being 0, and then the result will be < N),
3092 * so after 30 tries failure probability is a most 2**(-30).
3093 *
3094 * For most curves, 1 try is enough with overwhelming probability,
3095 * since N starts with a lot of 1s in binary, but some curves
3096 * such as secp224k1 are actually very close to the worst case.
3097 */
Manuel Pégourié-Gonnard67543962017-04-21 13:19:43 +02003098 if( ++count > 30 )
3099 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
Janos Follath4c3408b2019-09-16 14:27:39 +01003100
Janos Follath867a3ab2019-10-11 14:21:53 +01003101 ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
Janos Follath4c3408b2019-09-16 14:27:39 +01003102 if( ret != 0 )
3103 {
3104 goto cleanup;
3105 }
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003106 }
Janos Follath867a3ab2019-10-11 14:21:53 +01003107 while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003108 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003109#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003110
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003111cleanup:
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003112 return( ret );
3113}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003114
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003115/*
3116 * Generate a keypair with configurable base point
3117 */
3118int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
3119 const mbedtls_ecp_point *G,
3120 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3121 int (*f_rng)(void *, unsigned char *, size_t),
3122 void *p_rng )
3123{
3124 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003125 ECP_VALIDATE_RET( grp != NULL );
3126 ECP_VALIDATE_RET( d != NULL );
3127 ECP_VALIDATE_RET( G != NULL );
3128 ECP_VALIDATE_RET( Q != NULL );
3129 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003130
3131 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
3132 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
3133
3134cleanup:
3135 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003136}
3137
3138/*
3139 * Generate key pair, wrapper for conventional base point
3140 */
3141int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
3142 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3143 int (*f_rng)(void *, unsigned char *, size_t),
3144 void *p_rng )
3145{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003146 ECP_VALIDATE_RET( grp != NULL );
3147 ECP_VALIDATE_RET( d != NULL );
3148 ECP_VALIDATE_RET( Q != NULL );
3149 ECP_VALIDATE_RET( f_rng != NULL );
3150
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003151 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003152}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01003153
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003154/*
3155 * Generate a keypair, prettier wrapper
3156 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003157int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003158 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
3159{
3160 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003161 ECP_VALIDATE_RET( key != NULL );
3162 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003163
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003164 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003165 return( ret );
3166
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003167 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003168}
3169
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003170/*
3171 * Check a public-private key pair
3172 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003173int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003174{
3175 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003176 mbedtls_ecp_point Q;
3177 mbedtls_ecp_group grp;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003178 ECP_VALIDATE_RET( pub != NULL );
3179 ECP_VALIDATE_RET( prv != NULL );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003181 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003182 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003183 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
3184 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
3185 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003186 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003187 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003188 }
3189
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003190 mbedtls_ecp_point_init( &Q );
3191 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003193 /* mbedtls_ecp_mul() needs a non-const group... */
3194 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003195
3196 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003197 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003199 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
3200 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
3201 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003203 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003204 goto cleanup;
3205 }
3206
3207cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003208 mbedtls_ecp_point_free( &Q );
3209 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003210
3211 return( ret );
3212}
3213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003214#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003215
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003216#if defined(ECP_ONE_STEP_KDF)
3217/*
3218 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
3219 * but unofficial ones can be found at:
3220 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
3221 *
3222 * We only use the ones with empty fixedInfo, and for brevity's sake, only
3223 * 32-bytes output (with SHA-1 that's more than one block, with SHA-256
3224 * exactly one block, and with SHA-512 less than one block).
3225 */
3226#if defined(MBEDTLS_SHA512_C)
3227
3228static const uint8_t test_kdf_z[16] = {
3229 0xeb, 0xf3, 0x19, 0x67, 0x1e, 0xac, 0xcc, 0x6f,
3230 0xc5, 0xc0, 0x5d, 0x95, 0x8d, 0x17, 0x15, 0x94,
3231};
3232static const uint8_t test_kdf_out[32] = {
3233 0xa9, 0x48, 0x85, 0x67, 0x54, 0x7c, 0x2a, 0x8e,
3234 0x9e, 0xd1, 0x67, 0x76, 0xe3, 0x1c, 0x03, 0x92,
3235 0x41, 0x77, 0x2a, 0x9e, 0xc7, 0xcc, 0xd7, 0x1f,
3236 0xda, 0x12, 0xe9, 0xba, 0xc9, 0xb2, 0x17, 0x24,
3237};
3238
3239#elif defined(MBEDTLS_SHA256_C)
3240
3241static const uint8_t test_kdf_z[16] = {
3242 0x0d, 0x5e, 0xc8, 0x9a, 0x68, 0xb1, 0xa7, 0xa0,
3243 0xdf, 0x95, 0x24, 0x54, 0x3f, 0x4d, 0x70, 0xef,
3244};
3245static const uint8_t test_kdf_out[32] = {
3246 0x77, 0xbc, 0x94, 0x9e, 0xa0, 0xd3, 0xdd, 0x5c,
3247 0x8e, 0xb7, 0xeb, 0x84, 0x05, 0x40, 0x60, 0xfa,
3248 0x96, 0x6e, 0x7e, 0xcd, 0x73, 0x9f, 0xa1, 0xe6,
3249 0x34, 0x3f, 0x6d, 0x82, 0x16, 0x22, 0xb4, 0x45,
3250};
3251
3252#elif defined(MBEDTLS_SHA1_C)
3253
3254static const uint8_t test_kdf_z[16] = {
3255 0x4e, 0x1e, 0x70, 0xc9, 0x88, 0x68, 0x19, 0xa3,
3256 0x1b, 0xc2, 0x9a, 0x53, 0x79, 0x11, 0xad, 0xd9,
3257};
3258static const uint8_t test_kdf_out[32] = {
3259 0xdd, 0xbf, 0xc4, 0x40, 0x44, 0x9a, 0xab, 0x41,
3260 0x31, 0xc6, 0xd8, 0xae, 0xc0, 0x8c, 0xe1, 0x49,
3261 0x6f, 0x27, 0x02, 0x24, 0x1d, 0x0e, 0x27, 0xcc,
3262 0x15, 0x5c, 0x5c, 0x7c, 0x3c, 0xda, 0x75, 0xb5,
3263};
3264
3265#else
3266#error "Need at least one of SHA-512, SHA-256 or SHA-1"
3267#endif
3268
3269static int ecp_kdf_self_test( void )
3270{
3271 int ret;
3272 ecp_drbg_context kdf_ctx;
3273 mbedtls_mpi scalar;
3274 uint8_t out[sizeof( test_kdf_out )];
3275
3276 ecp_drbg_init( &kdf_ctx );
3277 mbedtls_mpi_init( &scalar );
3278 memset( out, 0, sizeof( out ) );
3279
3280 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
3281 test_kdf_z, sizeof( test_kdf_z ) ) );
3282
3283 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
3284 &scalar, sizeof( test_kdf_z ) ) );
3285
3286 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
3287
3288 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
3289 ret = -1;
3290
3291cleanup:
3292 ecp_drbg_free( &kdf_ctx );
3293 mbedtls_mpi_free( &scalar );
3294
3295 return( ret );
3296}
3297#endif /* ECP_ONE_STEP_KDF */
3298
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01003299/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003300 * Checkup routine
3301 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003302int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003303{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003304 int ret;
3305 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003306 mbedtls_ecp_group grp;
3307 mbedtls_ecp_point R, P;
3308 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003309 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003310 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02003311 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003312 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003313 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003314 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003315 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003316 "400000000000000000000000000000000000000000000000", /* one and zeros */
3317 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
3318 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003319 };
3320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003321 mbedtls_ecp_group_init( &grp );
3322 mbedtls_ecp_point_init( &R );
3323 mbedtls_ecp_point_init( &P );
3324 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003325
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003326 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003327#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003328 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02003329#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003330 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003331#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003332
3333 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003334 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003335
3336 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003337 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
3338 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003339
3340 add_count = 0;
3341 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003342 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003343 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3344 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003345
3346 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3347 {
3348 add_c_prev = add_count;
3349 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003350 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003351 add_count = 0;
3352 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003353 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003355 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3356 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003357
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003358 if( add_count != add_c_prev ||
3359 dbl_count != dbl_c_prev ||
3360 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003361 {
3362 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003363 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003364
3365 ret = 1;
3366 goto cleanup;
3367 }
3368 }
3369
3370 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003371 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003372
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003373 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003374 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003375 /* We computed P = 2G last time, use it */
3376
3377 add_count = 0;
3378 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003379 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003380 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3381 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003382
3383 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3384 {
3385 add_c_prev = add_count;
3386 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003387 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003388 add_count = 0;
3389 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003390 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003392 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3393 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003394
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003395 if( add_count != add_c_prev ||
3396 dbl_count != dbl_c_prev ||
3397 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003398 {
3399 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003400 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003401
3402 ret = 1;
3403 goto cleanup;
3404 }
3405 }
3406
3407 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003408 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003409
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003410#if defined(ECP_ONE_STEP_KDF)
3411 if( verbose != 0 )
3412 mbedtls_printf( " ECP test #3 (internal KDF): " );
3413
3414 ret = ecp_kdf_self_test();
3415 if( ret != 0 )
3416 {
3417 if( verbose != 0 )
3418 mbedtls_printf( "failed\n" );
3419
3420 ret = 1;
3421 goto cleanup;
3422 }
3423
3424 if( verbose != 0 )
3425 mbedtls_printf( "passed\n" );
3426#endif /* ECP_ONE_STEP_KDF */
3427
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003428cleanup:
3429
3430 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003431 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003433 mbedtls_ecp_group_free( &grp );
3434 mbedtls_ecp_point_free( &R );
3435 mbedtls_ecp_point_free( &P );
3436 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003437
3438 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003439 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003440
3441 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003442}
3443
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003444#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003445
Janos Follathb0697532016-08-18 12:38:46 +01003446#endif /* !MBEDTLS_ECP_ALT */
3447
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003448#endif /* MBEDTLS_ECP_C */