blob: cb21f363d463a33c169cb8f454e1ef47ab066d82 [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"
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200116#else
117#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
118#endif
119#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
120
Manuel Pégourié-Gonnard0223ab92015-10-05 11:40:01 +0100121#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
122 !defined(inline) && !defined(__cplusplus)
Paul Bakker6a6087e2013-10-28 18:53:08 +0100123#define inline __inline
Manuel Pégourié-Gonnard20af64d2015-07-07 18:33:39 +0200124#endif
Paul Bakker6a6087e2013-10-28 18:53:08 +0100125
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200126#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100127/*
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100128 * Counts of point addition and doubling, and field multiplications.
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +0200129 * Used to test resistance of point multiplication to simple timing attacks.
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100130 */
Manuel Pégourié-Gonnard43863ee2013-12-01 16:51:27 +0100131static unsigned long add_count, dbl_count, mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100132#endif
133
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200134#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
135/*
136 * Currently ecp_mul() takes a RNG function as an argument, used for
Manuel Pégourié-Gonnard0defc572020-06-10 09:18:25 +0200137 * side-channel protection, but it can be NULL. The initial reasoning was
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200138 * that people will pass non-NULL RNG when they care about side-channels, but
139 * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with
140 * no opportunity for the user to do anything about it.
141 *
142 * The obvious strategies for addressing that include:
143 * - change those APIs so that they take RNG arguments;
144 * - require a global RNG to be available to all crypto modules.
145 *
146 * Unfortunately those would break compatibility. So what we do instead is
147 * have our own internal DRBG instance, seeded from the secret scalar.
148 *
149 * The following is a light-weight abstraction layer for doing that with
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200150 * HMAC_DRBG (first choice) or CTR_DRBG.
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200151 */
152
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200153#if defined(MBEDTLS_HMAC_DRBG_C)
154
155/* DRBG context type */
156typedef mbedtls_hmac_drbg_context ecp_drbg_context;
157
158/* DRBG context init */
159static inline void ecp_drbg_init( ecp_drbg_context *ctx )
160{
161 mbedtls_hmac_drbg_init( ctx );
162}
163
164/* DRBG context free */
165static inline void ecp_drbg_free( ecp_drbg_context *ctx )
166{
167 mbedtls_hmac_drbg_free( ctx );
168}
169
170/* DRBG function */
171static inline int ecp_drbg_random( void *p_rng,
172 unsigned char *output, size_t output_len )
173{
174 return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) );
175}
176
177/* DRBG context seeding */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200178static int ecp_drbg_seed( ecp_drbg_context *ctx,
179 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200180{
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200181 int ret;
182 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200183 /* The list starts with strong hashes */
184 const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
185 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
186
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200187 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
188 secret_bytes, secret_len ) );
189
190 ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len );
191
192cleanup:
193 mbedtls_platform_zeroize( secret_bytes, secret_len );
194
195 return( ret );
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200196}
197
198#elif defined(MBEDTLS_CTR_DRBG_C)
199
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200200/* DRBG context type */
201typedef mbedtls_ctr_drbg_context ecp_drbg_context;
202
203/* DRBG context init */
204static inline void ecp_drbg_init( ecp_drbg_context *ctx )
205{
206 mbedtls_ctr_drbg_init( ctx );
207}
208
209/* DRBG context free */
210static inline void ecp_drbg_free( ecp_drbg_context *ctx )
211{
212 mbedtls_ctr_drbg_free( ctx );
213}
214
215/* DRBG function */
216static inline int ecp_drbg_random( void *p_rng,
217 unsigned char *output, size_t output_len )
218{
219 return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
220}
221
222/*
223 * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
224 * we need to pass an entropy function when seeding. So we use a dummy
225 * function for that, and pass the actual entropy as customisation string.
226 * (During seeding of CTR_DRBG the entropy input and customisation string are
227 * concatenated before being used to update the secret state.)
228 */
229static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
230{
231 (void) ctx;
232 memset( out, 0, len );
233 return( 0 );
234}
235
236/* DRBG context seeding */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200237static int ecp_drbg_seed( ecp_drbg_context *ctx,
238 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200239{
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200240 int ret;
241 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200242
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200243 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
244 secret_bytes, secret_len ) );
245
246 ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
247 secret_bytes, secret_len );
248
249cleanup:
250 mbedtls_platform_zeroize( secret_bytes, secret_len );
251
252 return( ret );
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200253}
254
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200255#elif defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA256_C)
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200256
257/* This will be used in the self-test function */
258#define ECP_ONE_STEP_KDF
259
260/*
261 * We need to expand secret data (the scalar) into a longer stream of bytes.
262 *
263 * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash
264 * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for
265 * convenience, this is not a full-fledged DRBG, but we don't need one here.)
266 *
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200267 * We need a basic hash abstraction layer to use whatever SHA-2 is available.
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200268 */
269#if defined(MBEDTLS_SHA512_C)
270
271#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 );
272#define HASH_BLOCK_BYTES ( 512 / 8 )
273
274#elif defined(MBEDTLS_SHA256_C)
275
276#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 );
277#define HASH_BLOCK_BYTES ( 256 / 8 )
278
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200279#endif /* SHA512/SHA256 abstraction */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200280
281/*
282 * State consists of a 32-bit counter plus the secret value.
283 *
284 * We stored them concatenated in a single buffer as that's what will get
285 * passed to the hash function.
286 */
287typedef struct {
288 size_t total_len;
289 uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES];
290} ecp_drbg_context;
291
292static void ecp_drbg_init( ecp_drbg_context *ctx )
293{
294 memset( ctx, 0, sizeof( ecp_drbg_context ) );
295}
296
297static void ecp_drbg_free( ecp_drbg_context *ctx )
298{
299 mbedtls_platform_zeroize( ctx, sizeof( ecp_drbg_context ) );
300}
301
302static int ecp_drbg_seed( ecp_drbg_context *ctx,
303 const mbedtls_mpi *secret, size_t secret_len )
304{
305 ctx->total_len = 4 + secret_len;
306 memset( ctx->buf, 0, 4);
307 return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) );
308}
309
310static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
311{
312 ecp_drbg_context *ctx = p_rng;
313 int ret;
314 size_t len_done = 0;
Manuel Pégourié-Gonnarda90a95b2020-06-17 12:40:57 +0200315 uint8_t tmp[HASH_BLOCK_BYTES];
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200316
317 while( len_done < output_len )
318 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200319 uint8_t use_len;
320
Manuel Pégourié-Gonnard7d7c0042020-06-17 12:57:33 +0200321 /* This function is only called for coordinate randomisation, which
322 * happens only twice in a scalar multiplication. Each time needs a
323 * random value in the range [2, p-1], and gets it by drawing len(p)
324 * bytes from this function, and retrying up to 10 times if unlucky.
325 *
326 * So for the largest curve, each scalar multiplication draws at most
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200327 * 20 * 66 bytes. The minimum block size is 32 (SHA-256), so with
328 * rounding that means a most 20 * 3 blocks.
Manuel Pégourié-Gonnard7d7c0042020-06-17 12:57:33 +0200329 *
330 * Since we don't need to draw more that 255 blocks, don't bother
331 * with carry propagation and just return an error instead. We can
332 * change that it we even need to draw more blinding values.
333 */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200334 ctx->buf[3] += 1;
335 if( ctx->buf[3] == 0 )
336 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
337
338 ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
339 if( ret != 0 )
340 return( ret );
341
342 if( output_len - len_done > HASH_BLOCK_BYTES )
343 use_len = HASH_BLOCK_BYTES;
344 else
345 use_len = output_len - len_done;
346
347 memcpy( output + len_done, tmp, use_len );
348 len_done += use_len;
349 }
350
Manuel Pégourié-Gonnarda90a95b2020-06-17 12:40:57 +0200351 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
352
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200353 return( 0 );
354}
355
356#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200357#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200358#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200359#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
360
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200361#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100362/*
363 * Maximum number of "basic operations" to be done in a row.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +0200364 *
365 * Default value 0 means that ECC operations will not yield.
366 * Note that regardless of the value of ecp_max_ops, always at
367 * least one step is performed before yielding.
368 *
369 * Setting ecp_max_ops=1 can be suitable for testing purposes
370 * as it will interrupt computation at all possible points.
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100371 */
372static unsigned ecp_max_ops = 0;
373
374/*
375 * Set ecp_max_ops
376 */
377void mbedtls_ecp_set_max_ops( unsigned max_ops )
378{
379 ecp_max_ops = max_ops;
380}
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100381
382/*
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200383 * Check if restart is enabled
384 */
Manuel Pégourié-Gonnardb843b152018-10-16 10:41:31 +0200385int mbedtls_ecp_restart_is_enabled( void )
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200386{
387 return( ecp_max_ops != 0 );
388}
389
390/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200391 * Restart sub-context for ecp_mul_comb()
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100392 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200393struct mbedtls_ecp_restart_mul
394{
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100395 mbedtls_ecp_point R; /* current intermediate result */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +0100396 size_t i; /* current index in various loops, 0 outside */
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100397 mbedtls_ecp_point *T; /* table for precomputed points */
398 unsigned char T_size; /* number of points in table T */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200399 enum { /* what were we doing last time we returned? */
400 ecp_rsm_init = 0, /* nothing so far, dummy initial state */
401 ecp_rsm_pre_dbl, /* precompute 2^n multiples */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100402 ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */
403 ecp_rsm_pre_add, /* precompute remaining points by adding */
404 ecp_rsm_pre_norm_add, /* normalize all precomputed points */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200405 ecp_rsm_comb_core, /* ecp_mul_comb_core() */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100406 ecp_rsm_final_norm, /* do the final normalization */
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100407 } state;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200408#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
409 ecp_drbg_context drbg_ctx;
410 unsigned char drbg_seeded;
411#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100412};
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100413
414/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200415 * Init restart_mul sub-context
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100416 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200417static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100418{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200419 mbedtls_ecp_point_init( &ctx->R );
420 ctx->i = 0;
421 ctx->T = NULL;
422 ctx->T_size = 0;
423 ctx->state = ecp_rsm_init;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200424#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
425 ecp_drbg_init( &ctx->drbg_ctx );
426 ctx->drbg_seeded = 0;
427#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100428}
429
430/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200431 * Free the components of a restart_mul sub-context
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100432 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200433static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100434{
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100435 unsigned char i;
436
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100437 if( ctx == NULL )
438 return;
Manuel Pégourié-Gonnard78d564a2017-03-14 11:48:38 +0100439
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100440 mbedtls_ecp_point_free( &ctx->R );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100441
Manuel Pégourié-Gonnard31f0ef72017-05-17 10:05:58 +0200442 if( ctx->T != NULL )
443 {
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100444 for( i = 0; i < ctx->T_size; i++ )
445 mbedtls_ecp_point_free( ctx->T + i );
446 mbedtls_free( ctx->T );
447 }
448
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200449#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
450 ecp_drbg_free( &ctx->drbg_ctx );
451#endif
452
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200453 ecp_restart_rsm_init( ctx );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100454}
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100455
456/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200457 * Restart context for ecp_muladd()
458 */
459struct mbedtls_ecp_restart_muladd
460{
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200461 mbedtls_ecp_point mP; /* mP value */
462 mbedtls_ecp_point R; /* R intermediate result */
463 enum { /* what should we do next? */
464 ecp_rsma_mul1 = 0, /* first multiplication */
465 ecp_rsma_mul2, /* second multiplication */
466 ecp_rsma_add, /* addition */
467 ecp_rsma_norm, /* normalization */
468 } state;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200469};
470
471/*
472 * Init restart_muladd sub-context
473 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200474static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200475{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200476 mbedtls_ecp_point_init( &ctx->mP );
477 mbedtls_ecp_point_init( &ctx->R );
478 ctx->state = ecp_rsma_mul1;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200479}
480
481/*
482 * Free the components of a restart_muladd sub-context
483 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200484static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200485{
486 if( ctx == NULL )
487 return;
488
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200489 mbedtls_ecp_point_free( &ctx->mP );
490 mbedtls_ecp_point_free( &ctx->R );
491
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200492 ecp_restart_ma_init( ctx );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200493}
494
495/*
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200496 * Initialize a restart context
497 */
498void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx )
499{
Hanno Becker80f71682018-12-18 23:44:43 +0000500 ECP_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200501 ctx->ops_done = 0;
502 ctx->depth = 0;
503 ctx->rsm = NULL;
504 ctx->ma = NULL;
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200505}
506
507/*
508 * Free the components of a restart context
509 */
510void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx )
511{
512 if( ctx == NULL )
513 return;
514
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200515 ecp_restart_rsm_free( ctx->rsm );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200516 mbedtls_free( ctx->rsm );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200517
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200518 ecp_restart_ma_free( ctx->ma );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200519 mbedtls_free( ctx->ma );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200520
521 mbedtls_ecp_restart_init( ctx );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200522}
523
524/*
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100525 * Check if we can do the next step
526 */
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +0200527int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
528 mbedtls_ecp_restart_ctx *rs_ctx,
529 unsigned ops )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100530{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000531 ECP_VALIDATE_RET( grp != NULL );
532
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200533 if( rs_ctx != NULL && ecp_max_ops != 0 )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100534 {
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100535 /* scale depending on curve size: the chosen reference is 256-bit,
536 * and multiplication is quadratic. Round to the closest integer. */
537 if( grp->pbits >= 512 )
538 ops *= 4;
539 else if( grp->pbits >= 384 )
540 ops *= 2;
541
Hanno Beckerb10c6602018-10-26 13:50:13 +0100542 /* Avoid infinite loops: always allow first step.
543 * Because of that, however, it's not generally true
544 * that ops_done <= ecp_max_ops, so the check
545 * ops_done > ecp_max_ops below is mandatory. */
546 if( ( rs_ctx->ops_done != 0 ) &&
547 ( rs_ctx->ops_done > ecp_max_ops ||
548 ops > ecp_max_ops - rs_ctx->ops_done ) )
549 {
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100550 return( MBEDTLS_ERR_ECP_IN_PROGRESS );
Hanno Beckerb10c6602018-10-26 13:50:13 +0100551 }
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100552
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100553 /* update running count */
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200554 rs_ctx->ops_done += ops;
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100555 }
556
557 return( 0 );
558}
559
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200560/* Call this when entering a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200561#define ECP_RS_ENTER( SUB ) do { \
562 /* reset ops count for this call if top-level */ \
563 if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \
564 rs_ctx->ops_done = 0; \
565 \
566 /* set up our own sub-context if needed */ \
567 if( mbedtls_ecp_restart_is_enabled() && \
568 rs_ctx != NULL && rs_ctx->SUB == NULL ) \
569 { \
570 rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
571 if( rs_ctx->SUB == NULL ) \
572 return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
573 \
574 ecp_restart_## SUB ##_init( rs_ctx->SUB ); \
575 } \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200576} while( 0 )
577
578/* Call this when leaving a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200579#define ECP_RS_LEAVE( SUB ) do { \
580 /* clear our sub-context when not in progress (done or error) */ \
581 if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
582 ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
583 { \
584 ecp_restart_## SUB ##_free( rs_ctx->SUB ); \
585 mbedtls_free( rs_ctx->SUB ); \
586 rs_ctx->SUB = NULL; \
587 } \
588 \
589 if( rs_ctx != NULL ) \
590 rs_ctx->depth--; \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200591} while( 0 )
592
593#else /* MBEDTLS_ECP_RESTARTABLE */
594
595#define ECP_RS_ENTER( sub ) (void) rs_ctx;
596#define ECP_RS_LEAVE( sub ) (void) rs_ctx;
597
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200598#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
601 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
602 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
603 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
604 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
605 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
606 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
607 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
608 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
609 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
610 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200611#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100612#endif
613
Nicholas Wilson08f3ef12015-11-10 13:10:01 +0000614#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
615 defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200616#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100617#endif
618
619/*
620 * Curve types: internal for now, might be exposed later
621 */
622typedef enum
623{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200624 ECP_TYPE_NONE = 0,
625 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
626 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100627} ecp_curve_type;
628
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100629/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200630 * List of supported curves:
631 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200632 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200633 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200634 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100635 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100636 * Curves are listed in order: largest curves first, and for a given size,
637 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200638 *
639 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200640 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200642{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200643#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
644 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200645#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
647 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100648#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
650 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200651#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200652#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
653 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100654#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
656 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200657#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
659 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100660#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
662 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100663#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200664#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
665 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200666#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
668 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100669#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
671 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100672#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
674 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100675#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200677};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100678
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200679#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
680 sizeof( ecp_supported_curves[0] )
681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200683
684/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200685 * List of supported curves and associated info
686 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200688{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200689 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200690}
691
692/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100693 * List of supported curves, group ID only
694 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100696{
697 static int init_done = 0;
698
699 if( ! init_done )
700 {
701 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100703
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200704 for( curve_info = mbedtls_ecp_curve_list();
705 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100706 curve_info++ )
707 {
708 ecp_supported_grp_id[i++] = curve_info->grp_id;
709 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100711
712 init_done = 1;
713 }
714
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200715 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100716}
717
718/*
719 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200720 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721const 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 +0200722{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200723 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200724
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200725 for( curve_info = mbedtls_ecp_curve_list();
726 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200727 curve_info++ )
728 {
729 if( curve_info->grp_id == grp_id )
730 return( curve_info );
731 }
732
733 return( NULL );
734}
735
736/*
737 * Get the curve info from the TLS identifier
738 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200740{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 for( curve_info = mbedtls_ecp_curve_list();
744 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200745 curve_info++ )
746 {
747 if( curve_info->tls_id == tls_id )
748 return( curve_info );
749 }
750
751 return( NULL );
752}
753
754/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100755 * Get the curve info from the name
756 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200757const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100758{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200759 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100760
Hanno Beckerb7a04a72018-12-18 23:50:21 +0000761 if( name == NULL )
762 return( NULL );
763
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200764 for( curve_info = mbedtls_ecp_curve_list();
765 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100766 curve_info++ )
767 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200768 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100769 return( curve_info );
770 }
771
772 return( NULL );
773}
774
775/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100776 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100777 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100779{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100780 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200781 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100782
783 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200784 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100785 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200786 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100787}
788
789/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100790 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100791 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200792void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100793{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000794 ECP_VALIDATE( pt != NULL );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100795
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200796 mbedtls_mpi_init( &pt->X );
797 mbedtls_mpi_init( &pt->Y );
798 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100799}
800
801/*
802 * Initialize (the components of) a group
803 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200804void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100805{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000806 ECP_VALIDATE( grp != NULL );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100807
Manuel Pégourié-Gonnard95e2eca2018-06-20 10:29:47 +0200808 grp->id = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200809 mbedtls_mpi_init( &grp->P );
810 mbedtls_mpi_init( &grp->A );
811 mbedtls_mpi_init( &grp->B );
812 mbedtls_ecp_point_init( &grp->G );
813 mbedtls_mpi_init( &grp->N );
814 grp->pbits = 0;
815 grp->nbits = 0;
816 grp->h = 0;
817 grp->modp = NULL;
818 grp->t_pre = NULL;
819 grp->t_post = NULL;
820 grp->t_data = NULL;
821 grp->T = NULL;
822 grp->T_size = 0;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100823}
824
825/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200826 * Initialize (the components of) a key pair
827 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200828void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200829{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000830 ECP_VALIDATE( key != NULL );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200831
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200832 mbedtls_ecp_group_init( &key->grp );
833 mbedtls_mpi_init( &key->d );
834 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200835}
836
837/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100838 * Unallocate (the components of) a point
839 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100841{
842 if( pt == NULL )
843 return;
844
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200845 mbedtls_mpi_free( &( pt->X ) );
846 mbedtls_mpi_free( &( pt->Y ) );
847 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100848}
849
850/*
851 * Unallocate (the components of) a group
852 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200853void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100854{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200855 size_t i;
856
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100857 if( grp == NULL )
858 return;
859
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100860 if( grp->h != 1 )
861 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200862 mbedtls_mpi_free( &grp->P );
863 mbedtls_mpi_free( &grp->A );
864 mbedtls_mpi_free( &grp->B );
865 mbedtls_ecp_point_free( &grp->G );
866 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100867 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200868
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200869 if( grp->T != NULL )
870 {
871 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200872 mbedtls_ecp_point_free( &grp->T[i] );
873 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200874 }
875
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500876 mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100877}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100878
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100879/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200880 * Unallocate (the components of) a key pair
881 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200883{
Paul Bakker66d5d072014-06-17 16:39:18 +0200884 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200885 return;
886
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200887 mbedtls_ecp_group_free( &key->grp );
888 mbedtls_mpi_free( &key->d );
889 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200890}
891
892/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200893 * Copy the contents of a point
894 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200895int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200896{
897 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000898 ECP_VALIDATE_RET( P != NULL );
899 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200900
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200901 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
902 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
903 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200904
905cleanup:
906 return( ret );
907}
908
909/*
910 * Copy the contents of a group object
911 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200912int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200913{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000914 ECP_VALIDATE_RET( dst != NULL );
915 ECP_VALIDATE_RET( src != NULL );
916
917 return( mbedtls_ecp_group_load( dst, src->id ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200918}
919
920/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100921 * Set point to zero
922 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200923int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100924{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100925 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000926 ECP_VALIDATE_RET( pt != NULL );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100927
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200928 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
929 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
930 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100931
932cleanup:
933 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100934}
935
936/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100937 * Tell if a point is zero
938 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100940{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000941 ECP_VALIDATE_RET( pt != NULL );
942
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200943 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100944}
945
946/*
Brian J Murrayf343de12018-10-22 16:40:49 -0700947 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200948 */
949int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
950 const mbedtls_ecp_point *Q )
951{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000952 ECP_VALIDATE_RET( P != NULL );
953 ECP_VALIDATE_RET( Q != NULL );
954
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200955 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
956 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
957 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
958 {
959 return( 0 );
960 }
961
962 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
963}
964
965/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100966 * Import a non-zero point from ASCII strings
967 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100969 const char *x, const char *y )
970{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100971 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000972 ECP_VALIDATE_RET( P != NULL );
973 ECP_VALIDATE_RET( x != NULL );
974 ECP_VALIDATE_RET( y != NULL );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100975
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200976 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
977 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
978 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100979
980cleanup:
981 return( ret );
982}
983
984/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100985 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100986 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000987int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp,
988 const mbedtls_ecp_point *P,
989 int format, size_t *olen,
990 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100991{
Paul Bakkera280d0f2013-04-08 13:40:17 +0200992 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100993 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000994 ECP_VALIDATE_RET( grp != NULL );
995 ECP_VALIDATE_RET( P != NULL );
996 ECP_VALIDATE_RET( olen != NULL );
997 ECP_VALIDATE_RET( buf != NULL );
998 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
999 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001000
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001001 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001002 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001003 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001004 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001005 {
1006 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001008
1009 buf[0] = 0x00;
1010 *olen = 1;
1011
1012 return( 0 );
1013 }
1014
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001016
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001018 {
1019 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001020
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001021 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001022 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001023
1024 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001025 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
1026 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001027 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001028 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001029 {
1030 *olen = plen + 1;
1031
1032 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001035 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
1036 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001037 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001038
1039cleanup:
1040 return( ret );
1041}
1042
1043/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001044 * Import a point from unsigned binary data (SEC1 2.3.4)
1045 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001046int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
1047 mbedtls_ecp_point *pt,
1048 const unsigned char *buf, size_t ilen )
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001049{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001050 int ret;
1051 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001052 ECP_VALIDATE_RET( grp != NULL );
1053 ECP_VALIDATE_RET( pt != NULL );
1054 ECP_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001055
Paul Bakker82788fb2014-10-20 13:59:19 +02001056 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001057 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001058
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001059 if( buf[0] == 0x00 )
1060 {
1061 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001063 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001064 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001065 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001066
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001067 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001068
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001069 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001070 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001071
1072 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001073 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001074
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001075 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
1076 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
1077 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001078
1079cleanup:
1080 return( ret );
1081}
1082
1083/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001084 * Import a point from a TLS ECPoint record (RFC 4492)
1085 * struct {
1086 * opaque point <1..2^8-1>;
1087 * } ECPoint;
1088 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001089int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp,
1090 mbedtls_ecp_point *pt,
1091 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001092{
1093 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001094 const unsigned char *buf_start;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001095 ECP_VALIDATE_RET( grp != NULL );
1096 ECP_VALIDATE_RET( pt != NULL );
1097 ECP_VALIDATE_RET( buf != NULL );
1098 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001099
1100 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001101 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001102 */
1103 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001104 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001105
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001106 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001107 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001108 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001109
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001110 /*
1111 * Save buffer start for read_binary and update buf
1112 */
1113 buf_start = *buf;
1114 *buf += data_len;
1115
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001116 return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001117}
1118
1119/*
1120 * Export a point as a TLS ECPoint record (RFC 4492)
1121 * struct {
1122 * opaque point <1..2^8-1>;
1123 * } ECPoint;
1124 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001126 int format, size_t *olen,
1127 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001128{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001129 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001130 ECP_VALIDATE_RET( grp != NULL );
1131 ECP_VALIDATE_RET( pt != NULL );
1132 ECP_VALIDATE_RET( olen != NULL );
1133 ECP_VALIDATE_RET( buf != NULL );
1134 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
1135 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001136
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001137 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001138 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001139 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001140 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001142
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001144 olen, buf + 1, blen - 1) ) != 0 )
1145 return( ret );
1146
1147 /*
1148 * write length to the first byte and update total length
1149 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +02001150 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001151 ++*olen;
1152
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001153 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001154}
1155
1156/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001157 * Set a group from an ECParameters record (RFC 4492)
1158 */
Janos Follath89ac8c92018-10-30 11:24:05 +00001159int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp,
1160 const unsigned char **buf, size_t len )
1161{
1162 int ret;
1163 mbedtls_ecp_group_id grp_id;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001164 ECP_VALIDATE_RET( grp != NULL );
1165 ECP_VALIDATE_RET( buf != NULL );
1166 ECP_VALIDATE_RET( *buf != NULL );
Janos Follath89ac8c92018-10-30 11:24:05 +00001167
1168 if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 )
1169 return( ret );
1170
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001171 return( mbedtls_ecp_group_load( grp, grp_id ) );
Janos Follath89ac8c92018-10-30 11:24:05 +00001172}
1173
1174/*
1175 * Read a group id from an ECParameters record (RFC 4492) and convert it to
1176 * mbedtls_ecp_group_id.
1177 */
1178int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp,
1179 const unsigned char **buf, size_t len )
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001180{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001181 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001182 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001183 ECP_VALIDATE_RET( grp != NULL );
1184 ECP_VALIDATE_RET( buf != NULL );
1185 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001186
1187 /*
1188 * We expect at least three bytes (see below)
1189 */
1190 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001191 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001192
1193 /*
1194 * First byte is curve_type; only named_curve is handled
1195 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
1197 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001198
1199 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001200 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001201 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001202 tls_id = *(*buf)++;
1203 tls_id <<= 8;
1204 tls_id |= *(*buf)++;
1205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001206 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
1207 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001208
Janos Follath89ac8c92018-10-30 11:24:05 +00001209 *grp = curve_info->grp_id;
1210
1211 return( 0 );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001212}
1213
1214/*
1215 * Write the ECParameters record corresponding to a group (RFC 4492)
1216 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001217int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001218 unsigned char *buf, size_t blen )
1219{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001220 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001221 ECP_VALIDATE_RET( grp != NULL );
1222 ECP_VALIDATE_RET( buf != NULL );
1223 ECP_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001225 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
1226 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001227
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001228 /*
1229 * We are going to write 3 bytes (see below)
1230 */
1231 *olen = 3;
1232 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001233 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001234
1235 /*
1236 * First byte is curve_type, always named_curve
1237 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001238 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001239
1240 /*
1241 * Next two bytes are the namedcurve value
1242 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001243 buf[0] = curve_info->tls_id >> 8;
1244 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001245
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001246 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +01001247}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001248
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001249/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001250 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
1251 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001252 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253 * 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 +02001254 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001255static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001256{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001257 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001258
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001259 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001261
1262 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001263 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001264 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001265 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001266 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001267 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001269 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001270
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001271 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001272 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
1273 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001274
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001276 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001277 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001278
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001279cleanup:
1280 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001281}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001282
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +01001283/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001284 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001285 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001286 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001287 * 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 +01001288 * bring the result back to this range.
1289 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001290 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001291 */
1292
1293/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001294 * 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 +01001295 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001296#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01001297#define INC_MUL_COUNT mul_count++;
1298#else
1299#define INC_MUL_COUNT
1300#endif
1301
Hanno Beckerd6028a12018-10-15 12:01:35 +01001302#define MOD_MUL( N ) \
1303 do \
1304 { \
1305 MBEDTLS_MPI_CHK( ecp_modp( &(N), grp ) ); \
1306 INC_MUL_COUNT \
1307 } while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001308
1309/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001310 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +02001311 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001312 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001313#define MOD_SUB( N ) \
1314 while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \
1315 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001316
1317/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001318 * 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 +02001319 * We known P, N and the result are positive, so sub_abs is correct, and
1320 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001321 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001322#define MOD_ADD( N ) \
1323 while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \
1324 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001325
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001326#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001327/*
1328 * For curves in short Weierstrass form, we do all the internal operations in
1329 * Jacobian coordinates.
1330 *
1331 * For multiplication, we'll use a comb method with coutermeasueres against
1332 * SPA, hence timing attacks.
1333 */
1334
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001335/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001336 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001337 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001338 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001339static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001340{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001341 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001342 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001345 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001346
Janos Follathb0697532016-08-18 12:38:46 +01001347#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001348 if( mbedtls_internal_ecp_grp_capable( grp ) )
1349 return( mbedtls_internal_ecp_normalize_jac( grp, pt ) );
Janos Follath372697b2016-10-28 16:53:11 +01001350#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001352 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001353
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001354 /*
1355 * X = X / Z^2 mod p
1356 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
1358 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1359 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 +01001360
1361 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001362 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001363 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001364 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
1365 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 +01001366
1367 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001368 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001369 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001371
1372cleanup:
1373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001375
1376 return( ret );
1377}
1378
1379/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001380 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001381 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001382 * (See for example Cohen's "A Course in Computational Algebraic Number
1383 * Theory", Algorithm 10.3.4.)
1384 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001385 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001386 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001387 *
1388 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001389 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001391 mbedtls_ecp_point *T[], size_t T_size )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001392{
1393 int ret;
1394 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001396
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001397 if( T_size < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001398 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001399
Janos Follathb0697532016-08-18 12:38:46 +01001400#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001401 if( mbedtls_internal_ecp_grp_capable( grp ) )
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001402 return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) );
Janos Follathb0697532016-08-18 12:38:46 +01001403#endif
1404
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001405 if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001406 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001407
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02001408 for( i = 0; i < T_size; i++ )
1409 mbedtls_mpi_init( &c[i] );
1410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001411 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001412
1413 /*
1414 * c[i] = Z_0 * ... * Z_i
1415 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001417 for( i = 1; i < T_size; i++ )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001418 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001419 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001420 MOD_MUL( c[i] );
1421 }
1422
1423 /*
1424 * u = 1 / (Z_0 * ... * Z_n) mod P
1425 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001426 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001427
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001428 for( i = T_size - 1; ; i-- )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001429 {
1430 /*
1431 * Zi = 1 / Z_i mod p
1432 * u = 1 / (Z_0 * ... * Z_i) mod P
1433 */
1434 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001435 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001436 }
1437 else
1438 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001439 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1440 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001441 }
1442
1443 /*
1444 * proceed as in normalize()
1445 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1447 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1448 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1449 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 +01001450
1451 /*
1452 * Post-precessing: reclaim some memory by shrinking coordinates
1453 * - not storing Z (always 1)
1454 * - shrinking other coordinates, but still keeping the same number of
1455 * limbs as P, as otherwise it will too likely be regrown too fast.
1456 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001457 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1458 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1459 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001460
1461 if( i == 0 )
1462 break;
1463 }
1464
1465cleanup:
1466
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001467 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001468 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001469 mbedtls_mpi_free( &c[i] );
1470 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001471
1472 return( ret );
1473}
1474
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001475/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001476 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1477 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1478 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001479static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1480 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001481 unsigned char inv )
1482{
1483 int ret;
1484 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001485 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001487 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001488
1489 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001490 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1491 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1492 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001493
1494cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001495 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001496
1497 return( ret );
1498}
1499
1500/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001501 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001502 *
Peter Dettmance661b22015-02-07 14:43:51 +07001503 * 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 +01001504 *
Peter Dettmance661b22015-02-07 14:43:51 +07001505 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1506 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1507 *
1508 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1509 *
1510 * Cost: 1D := 3M + 4S (A == 0)
1511 * 4M + 4S (A == -3)
1512 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001513 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1515 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001516{
1517 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001518 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001519
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001521 dbl_count++;
1522#endif
1523
Janos Follathb0697532016-08-18 12:38:46 +01001524#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001525 if( mbedtls_internal_ecp_grp_capable( grp ) )
1526 return( mbedtls_internal_ecp_double_jac( grp, R, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01001527#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001528
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001529 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 +01001530
1531 /* Special case for A = -3 */
1532 if( grp->A.p == NULL )
1533 {
Peter Dettmance661b22015-02-07 14:43:51 +07001534 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001535 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1536 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1537 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1538 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1539 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001540 }
1541 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001542 {
Peter Dettmance661b22015-02-07 14:43:51 +07001543 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001544 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1545 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001546
1547 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001548 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001549 {
1550 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001551 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1552 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1553 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1554 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001555 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001556 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001557
Peter Dettmance661b22015-02-07 14:43:51 +07001558 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001559 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1560 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1561 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1562 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001563
Peter Dettmance661b22015-02-07 14:43:51 +07001564 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001565 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1566 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001567
1568 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001569 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1570 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1571 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001572
1573 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001574 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1575 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1576 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001577
1578 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001579 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1580 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001581
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001582 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1583 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1584 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001585
1586cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001587 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 +02001588
1589 return( ret );
1590}
1591
1592/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001593 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001594 *
1595 * The coordinates of Q must be normalized (= affine),
1596 * but those of P don't need to. R is not normalized.
1597 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001598 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001599 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001600 * - at each step, P, Q and R are multiples of the base point, the factor
1601 * being less than its order, so none of them is zero;
1602 * - Q is an odd multiple of the base point, P an even multiple,
1603 * due to the choice of precomputed points in the modified comb method.
1604 * So branches for these cases do not leak secret information.
1605 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001606 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1607 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001608 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001609 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001610static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1611 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001612{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001613 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001614 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001615
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001616#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001617 add_count++;
1618#endif
1619
Janos Follathb0697532016-08-18 12:38:46 +01001620#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001621 if( mbedtls_internal_ecp_grp_capable( grp ) )
1622 return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) );
Janos Follath372697b2016-10-28 16:53:11 +01001623#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001624
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001625 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001626 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001627 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001628 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1629 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1632 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001633
1634 /*
1635 * Make sure Q coordinates are normalized
1636 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001637 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1638 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001639
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1641 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001642
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001643 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1644 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1645 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1646 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1647 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1648 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001649
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001650 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001651 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001652 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001653 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001654 {
1655 ret = ecp_double_jac( grp, R, P );
1656 goto cleanup;
1657 }
1658 else
1659 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001660 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001661 goto cleanup;
1662 }
1663 }
1664
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001665 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1666 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1667 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1668 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1669 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1670 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1671 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1672 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1673 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1674 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1675 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1676 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001677
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001678 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1679 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1680 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001681
1682cleanup:
1683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001684 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1685 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001686
1687 return( ret );
1688}
1689
1690/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001691 * Randomize jacobian coordinates:
1692 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001693 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001694 *
1695 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001696 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001697static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001698 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1699{
1700 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001701 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001702 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001703 int count = 0;
1704
Janos Follathb0697532016-08-18 12:38:46 +01001705#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001706 if( mbedtls_internal_ecp_grp_capable( grp ) )
1707 return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) );
Janos Follath372697b2016-10-28 16:53:11 +01001708#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001709
1710 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001711 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001712
1713 /* Generate l such that 1 < l < p */
1714 do
1715 {
Ron Eldorca6ff582017-01-12 14:50:50 +02001716 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001717
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001718 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1719 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001720
1721 if( count++ > 10 )
Jonas6645fd32020-05-08 16:57:18 +09001722 {
1723 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1724 goto cleanup;
1725 }
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001726 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001727 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001728
1729 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730 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 +02001731
1732 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001733 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1734 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 +02001735
1736 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001737 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1738 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 +02001739
1740cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001741 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001742
1743 return( ret );
1744}
1745
1746/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001747 * Check and define parameters used by the comb method (see below for details)
1748 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001749#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1750#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001751#endif
1752
1753/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001754#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001755
1756/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001757#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001758
1759/*
1760 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001761 *
1762 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001763 * modified version that provides resistance to SPA by avoiding zero
1764 * digits in the representation as in [3]. We modify the method further by
1765 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001766 * representation uses one more K_i, due to carries, but saves on the size of
1767 * the precomputed table.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001768 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001769 * Summary of the comb method and its modifications:
1770 *
1771 * - The goal is to compute m*P for some w*d-bit integer m.
1772 *
1773 * - The basic comb method splits m into the w-bit integers
1774 * x[0] .. x[d-1] where x[i] consists of the bits in m whose
1775 * index has residue i modulo d, and computes m * P as
1776 * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where
1777 * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P.
1778 *
1779 * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by
1780 * .. + 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]] ..,
1781 * thereby successively converting it into a form where all summands
1782 * are nonzero, at the cost of negative summands. This is the basic idea of [3].
1783 *
1784 * - More generally, even if x[i+1] != 0, we can first transform the sum as
1785 * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] ..,
1786 * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]].
1787 * Performing and iterating this procedure for those x[i] that are even
1788 * (keeping track of carry), we can transform the original sum into one of the form
1789 * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]]
1790 * with all x'[i] odd. It is therefore only necessary to know S at odd indices,
1791 * which is why we are only computing half of it in the first place in
1792 * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb.
1793 *
1794 * - For the sake of compactness, only the seven low-order bits of x[i]
1795 * are used to represent its absolute value (K_i in the paper), and the msb
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001796 * 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 +02001797 * if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001798 *
1799 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001800 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001801 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001802 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001803 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1804 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001805 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01001806static void ecp_comb_recode_core( unsigned char x[], size_t d,
1807 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001808{
1809 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001810 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001811
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001812 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001813
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001814 /* First get the classical comb values (except for x_d = 0) */
1815 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001816 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001817 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001818
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001819 /* Now make sure x_1 .. x_d are odd */
1820 c = 0;
1821 for( i = 1; i <= d; i++ )
1822 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001823 /* Add carry and update it */
1824 cc = x[i] & c;
1825 x[i] = x[i] ^ c;
1826 c = cc;
1827
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001828 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001829 adjust = 1 - ( x[i] & 0x01 );
1830 c |= x[i] & ( x[i-1] * adjust );
1831 x[i] = x[i] ^ ( x[i-1] * adjust );
1832 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001833 }
1834}
1835
1836/*
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001837 * Precompute points for the adapted comb method
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001838 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001839 * Assumption: T must be able to hold 2^{w - 1} elements.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001840 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001841 * Operation: If i = i_{w-1} ... i_1 is the binary representation of i,
1842 * 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 +01001843 *
1844 * 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 +02001845 *
1846 * Note: Even comb values (those where P would be omitted from the
1847 * sum defining T[i] above) are not needed in our adaption
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001848 * the comb method. See ecp_comb_recode_core().
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001849 *
1850 * This function currently works in four steps:
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001851 * (1) [dbl] Computation of intermediate T[i] for 2-power values of i
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001852 * (2) [norm_dbl] Normalization of coordinates of these T[i]
1853 * (3) [add] Computation of all T[i]
1854 * (4) [norm_add] Normalization of all T[i]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001855 *
1856 * Step 1 can be interrupted but not the others; together with the final
1857 * coordinate normalization they are the largest steps done at once, depending
1858 * on the window size. Here are operation counts for P-256:
1859 *
1860 * step (2) (3) (4)
1861 * w = 5 142 165 208
1862 * w = 4 136 77 160
1863 * w = 3 130 33 136
1864 * w = 2 124 11 124
1865 *
1866 * So if ECC operations are blocking for too long even with a low max_ops
1867 * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order
1868 * to minimize maximum blocking time.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001869 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001870static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1871 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001872 unsigned char w, size_t d,
1873 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001874{
1875 int ret;
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001876 unsigned char i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001877 size_t j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001878 const unsigned char T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001880
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001881#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001882 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001883 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001884 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
1885 goto dbl;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001886 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl )
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001887 goto norm_dbl;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001888 if( rs_ctx->rsm->state == ecp_rsm_pre_add )
1889 goto add;
1890 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add )
1891 goto norm_add;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001892 }
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001893#else
1894 (void) rs_ctx;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001895#endif
1896
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001897#if defined(MBEDTLS_ECP_RESTARTABLE)
1898 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1899 {
1900 rs_ctx->rsm->state = ecp_rsm_pre_dbl;
1901
1902 /* initial state for the loop */
1903 rs_ctx->rsm->i = 0;
1904 }
1905
1906dbl:
1907#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001908 /*
1909 * Set T[0] = P and
1910 * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
1911 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001912 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001913
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001914#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001915 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
1916 j = rs_ctx->rsm->i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001917 else
1918#endif
1919 j = 0;
1920
1921 for( ; j < d * ( w - 1 ); j++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001922 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001923 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL );
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001924
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001925 i = 1U << ( j / d );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001926 cur = T + i;
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001927
1928 if( j % d == 0 )
1929 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
1930
1931 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001932 }
1933
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001934#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001935 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1936 rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl;
1937
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001938norm_dbl:
1939#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001940 /*
1941 * Normalize current elements in T. As T has holes,
1942 * use an auxiliary array of pointers to elements in T.
1943 */
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001944 j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001945 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001946 TT[j++] = T + i;
1947
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001948 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001949
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001950 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001951
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001952#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001953 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1954 rs_ctx->rsm->state = ecp_rsm_pre_add;
1955
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001956add:
1957#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001958 /*
1959 * Compute the remaining ones using the minimal number of additions
1960 * Be careful to update T[2^l] only after using it!
1961 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001962 MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001963
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001964 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001965 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001966 j = i;
1967 while( j-- )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001968 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001969 }
1970
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001971#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001972 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1973 rs_ctx->rsm->state = ecp_rsm_pre_norm_add;
1974
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001975norm_add:
1976#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001977 /*
Manuel Pégourié-Gonnarda966fde2018-10-23 10:41:11 +02001978 * Normalize final elements in T. Even though there are no holes now, we
1979 * still need the auxiliary array for homogeneity with the previous
1980 * call. Also, skip T[0] which is already normalised, being a copy of P.
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001981 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001982 for( j = 0; j + 1 < T_size; j++ )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001983 TT[j] = T + j + 1;
1984
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001985 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001986
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001987 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01001988
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001989cleanup:
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001990#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001991 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
1992 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001993 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001994 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001995 rs_ctx->rsm->i = j;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001996 }
1997#endif
Janos Follathb0697532016-08-18 12:38:46 +01001998
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001999 return( ret );
2000}
2001
2002/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01002003 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002004 *
2005 * See ecp_comb_recode_core() for background
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002006 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002007static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002008 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002009 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002010{
2011 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002012 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002013
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002014 /* Ignore the "sign" bit and scale down */
2015 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002016
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002017 /* Read the whole table to thwart cache-based timing attacks */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002018 for( j = 0; j < T_size; j++ )
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002019 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002020 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
2021 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002022 }
2023
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01002024 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002025 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002026
2027cleanup:
2028 return( ret );
2029}
2030
2031/*
2032 * Core multiplication algorithm for the (modified) comb method.
2033 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01002034 *
2035 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002036 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002037static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002038 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01002039 const unsigned char x[], size_t d,
2040 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002041 void *p_rng,
2042 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002043{
2044 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002046 size_t i;
2047
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002049
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002050#if !defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002051 (void) rs_ctx;
2052#endif
2053
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002054#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002055 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2056 rs_ctx->rsm->state != ecp_rsm_comb_core )
2057 {
2058 rs_ctx->rsm->i = 0;
2059 rs_ctx->rsm->state = ecp_rsm_comb_core;
2060 }
2061
2062 /* new 'if' instead of nested for the sake of the 'else' branch */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002063 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002064 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002065 /* restore current index (R already pointing to rs_ctx->rsm->R) */
2066 i = rs_ctx->rsm->i;
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002067 }
2068 else
2069#endif
2070 {
2071 /* Start with a non-zero point and randomize its coordinates */
2072 i = d;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002073 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) );
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002074 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002075#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002076 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002077#endif
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002078 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
2079 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002080
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002081 while( i != 0 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002082 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002083 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002084 --i;
2085
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002086 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002087 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002088 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002089 }
2090
2091cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002092
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002093 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002094
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002095#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002096 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2097 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002098 {
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002099 rs_ctx->rsm->i = i;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002100 /* no need to save R, already pointing to rs_ctx->rsm->R */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002101 }
2102#endif
2103
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002104 return( ret );
2105}
2106
2107/*
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002108 * Recode the scalar to get constant-time comb multiplication
2109 *
2110 * As the actual scalar recoding needs an odd scalar as a starting point,
2111 * this wrapper ensures that by replacing m by N - m if necessary, and
2112 * informs the caller that the result of multiplication will be negated.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002113 *
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002114 * This works because we only support large prime order for Short Weierstrass
2115 * curves, so N is always odd hence either m or N - m is.
2116 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002117 * See ecp_comb_recode_core() for background.
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002118 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002119static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp,
2120 const mbedtls_mpi *m,
2121 unsigned char k[COMB_MAX_D + 1],
2122 size_t d,
2123 unsigned char w,
2124 unsigned char *parity_trick )
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002125{
2126 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002127 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002128
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002129 mbedtls_mpi_init( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002130 mbedtls_mpi_init( &mm );
2131
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002132 /* N is always odd (see above), just make extra sure */
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002133 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
2134 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
2135
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002136 /* do we need the parity trick? */
2137 *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 );
2138
2139 /* execute parity fix in constant time */
2140 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002141 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002142 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) );
2143
2144 /* actual scalar recoding */
2145 ecp_comb_recode_core( k, d, w, &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002146
2147cleanup:
2148 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002149 mbedtls_mpi_free( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002150
2151 return( ret );
2152}
2153
2154/*
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002155 * Perform comb multiplication (for short Weierstrass curves)
2156 * once the auxiliary table has been pre-computed.
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002157 *
2158 * Scalar recoding may use a parity trick that makes us compute -m * P,
2159 * if that is the case we'll need to recover m * P at the end.
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002160 */
2161static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
2162 mbedtls_ecp_point *R,
2163 const mbedtls_mpi *m,
2164 const mbedtls_ecp_point *T,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002165 unsigned char T_size,
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002166 unsigned char w,
2167 size_t d,
2168 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002169 void *p_rng,
2170 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002171{
2172 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002173 unsigned char parity_trick;
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002174 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002175 mbedtls_ecp_point *RR = R;
2176
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002177#if defined(MBEDTLS_ECP_RESTARTABLE)
2178 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2179 {
2180 RR = &rs_ctx->rsm->R;
2181
2182 if( rs_ctx->rsm->state == ecp_rsm_final_norm )
2183 goto final_norm;
2184 }
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002185#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002186
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002187 MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w,
2188 &parity_trick ) );
2189 MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d,
2190 f_rng, p_rng, rs_ctx ) );
2191 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) );
2192
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002193#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002194 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002195 rs_ctx->rsm->state = ecp_rsm_final_norm;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002196
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002197final_norm:
Manuel Pégourié-Gonnard18b0b3c2020-06-08 09:53:20 +02002198 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002199#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002200 /*
2201 * Knowledge of the jacobian coordinates may leak the last few bits of the
2202 * scalar [1], and since our MPI implementation isn't constant-flow,
2203 * inversion (used for coordinate normalization) may leak the full value
2204 * of its input via side-channels [2].
2205 *
2206 * [1] https://eprint.iacr.org/2003/191
2207 * [2] https://eprint.iacr.org/2020/055
2208 *
2209 * Avoid the leak by randomizing coordinates before we normalize them.
2210 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002211#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002212 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002213#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002214 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) );
2215
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002216 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
2217
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002218#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard28d16282017-08-23 17:33:27 +02002219 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2220 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) );
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002221#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002222
2223cleanup:
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002224 return( ret );
2225}
2226
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002227/*
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002228 * Pick window size based on curve size and whether we optimize for base point
2229 */
2230static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
2231 unsigned char p_eq_g )
2232{
2233 unsigned char w;
2234
2235 /*
2236 * Minimize the number of multiplications, that is minimize
2237 * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
2238 * (see costs of the various parts, with 1S = 1M)
2239 */
2240 w = grp->nbits >= 384 ? 5 : 4;
2241
2242 /*
2243 * If P == G, pre-compute a bit more, since this may be re-used later.
2244 * Just adding one avoids upping the cost of the first mul too much,
2245 * and the memory cost too.
2246 */
2247 if( p_eq_g )
2248 w++;
2249
2250 /*
2251 * Make sure w is within bounds.
2252 * (The last test is useful only for very small curves in the test suite.)
2253 */
2254 if( w > MBEDTLS_ECP_WINDOW_SIZE )
2255 w = MBEDTLS_ECP_WINDOW_SIZE;
2256 if( w >= grp->nbits )
2257 w = 2;
2258
2259 return( w );
2260}
2261
2262/*
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002263 * Multiplication using the comb method - for curves in short Weierstrass form
2264 *
2265 * This function is mainly responsible for administrative work:
2266 * - managing the restart context if enabled
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002267 * - managing the table of precomputed points (passed between the below two
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002268 * functions): allocation, computation, ownership tranfer, freeing.
2269 *
2270 * It delegates the actual arithmetic work to:
2271 * ecp_precompute_comb() and ecp_mul_comb_with_precomp()
2272 *
2273 * See comments on ecp_comb_recode_core() regarding the computation strategy.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002274 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2276 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002277 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002278 void *p_rng,
2279 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002280{
2281 int ret;
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002282 unsigned char w, p_eq_g, i;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002283 size_t d;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002284 unsigned char T_size = 0, T_ok = 0;
2285 mbedtls_ecp_point *T = NULL;
2286#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2287 ecp_drbg_context drbg_ctx;
2288
2289 ecp_drbg_init( &drbg_ctx );
2290#endif
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002291
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002292 ECP_RS_ENTER( rsm );
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +01002293
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002294#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2295 if( f_rng == NULL )
2296 {
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002297 /* Adjust pointers */
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002298 f_rng = &ecp_drbg_random;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002299#if defined(MBEDTLS_ECP_RESTARTABLE)
2300 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2301 p_rng = &rs_ctx->rsm->drbg_ctx;
2302 else
2303#endif
2304 p_rng = &drbg_ctx;
2305
2306 /* Initialize internal DRBG if necessary */
2307#if defined(MBEDTLS_ECP_RESTARTABLE)
2308 if( rs_ctx == NULL || rs_ctx->rsm == NULL ||
2309 rs_ctx->rsm->drbg_seeded == 0 )
2310#endif
2311 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002312 const size_t m_len = ( grp->nbits + 7 ) / 8;
2313 MBEDTLS_MPI_CHK( ecp_drbg_seed( p_rng, m, m_len ) );
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002314 }
2315#if defined(MBEDTLS_ECP_RESTARTABLE)
2316 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2317 rs_ctx->rsm->drbg_seeded = 1;
2318#endif
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002319 }
2320#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2321
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002322 /* Is P the base point ? */
2323#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
2324 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
2325 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard196d1332017-08-28 13:14:27 +02002326#else
2327 p_eq_g = 0;
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002328#endif
2329
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002330 /* Pick window size and deduce related sizes */
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002331 w = ecp_pick_window_size( grp, p_eq_g );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002332 T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002333 d = ( grp->nbits + w - 1 ) / w;
2334
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002335 /* Pre-computed table: do we have it already for the base point? */
2336 if( p_eq_g && grp->T != NULL )
2337 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002338 /* second pointer to the same table, will be deleted on exit */
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002339 T = grp->T;
2340 T_ok = 1;
2341 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002342 else
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002343#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002344 /* Pre-computed table: do we have one in progress? complete? */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002345 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL )
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002346 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002347 /* transfer ownership of T from rsm to local function */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002348 T = rs_ctx->rsm->T;
2349 rs_ctx->rsm->T = NULL;
2350 rs_ctx->rsm->T_size = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002351
Manuel Pégourié-Gonnardb25cb602018-10-16 11:48:09 +02002352 /* This effectively jumps to the call to mul_comb_after_precomp() */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002353 T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002354 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002355 else
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002356#endif
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002357 /* Allocate table if we didn't have any */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002358 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002359 T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002360 if( T == NULL )
2361 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02002362 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002363 goto cleanup;
2364 }
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02002365
2366 for( i = 0; i < T_size; i++ )
2367 mbedtls_ecp_point_init( &T[i] );
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002368
2369 T_ok = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002370 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002371
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002372 /* Compute table (or finish computing it) if not done already */
2373 if( !T_ok )
2374 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002375 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002376
2377 if( p_eq_g )
2378 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002379 /* almost transfer ownership of T to the group, but keep a copy of
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02002380 * the pointer to use for calling the next function more easily */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002381 grp->T = T;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002382 grp->T_size = T_size;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002383 }
2384 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002385
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002386 /* Actual comb multiplication using precomputed points */
2387 MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002388 T, T_size, w, d,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002389 f_rng, p_rng, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002390
2391cleanup:
2392
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002393#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2394 ecp_drbg_free( &drbg_ctx );
2395#endif
2396
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002397 /* does T belong to the group? */
2398 if( T == grp->T )
2399 T = NULL;
2400
2401 /* does T belong to the restart context? */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002402#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002403 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 +01002404 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002405 /* transfer ownership of T from local function to rsm */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002406 rs_ctx->rsm->T_size = T_size;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002407 rs_ctx->rsm->T = T;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002408 T = NULL;
2409 }
2410#endif
2411
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002412 /* did T belong to us? then let's destroy it! */
2413 if( T != NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002414 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002415 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002416 mbedtls_ecp_point_free( &T[i] );
2417 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002418 }
2419
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002420 /* don't free R while in progress in case R == P */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002421#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002422 if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
2423#endif
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002424 /* prevent caller from using invalid value */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01002425 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002426 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002427
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002428 ECP_RS_LEAVE( rsm );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +01002429
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002430 return( ret );
2431}
2432
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002433#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002434
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002435#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002436/*
2437 * For Montgomery curves, we do all the internal arithmetic in projective
2438 * coordinates. Import/export of points uses only the x coordinates, which is
2439 * internaly represented as X / Z.
2440 *
2441 * For scalar multiplication, we'll use a Montgomery ladder.
2442 */
2443
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002444/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002445 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
2446 * Cost: 1M + 1I
2447 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002448static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002449{
2450 int ret;
2451
Janos Follathb0697532016-08-18 12:38:46 +01002452#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002453 if( mbedtls_internal_ecp_grp_capable( grp ) )
2454 return( mbedtls_internal_ecp_normalize_mxz( grp, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01002455#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002457 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
2458 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
2459 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002460
2461cleanup:
2462 return( ret );
2463}
2464
2465/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002466 * Randomize projective x/z coordinates:
2467 * (X, Z) -> (l X, l Z) for random l
2468 * This is sort of the reverse operation of ecp_normalize_mxz().
2469 *
2470 * This countermeasure was first suggested in [2].
2471 * Cost: 2M
2472 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002474 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2475{
2476 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002477 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01002478 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002479 int count = 0;
2480
Janos Follathb0697532016-08-18 12:38:46 +01002481#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002482 if( mbedtls_internal_ecp_grp_capable( grp ) )
2483 return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
Janos Follath372697b2016-10-28 16:53:11 +01002484#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002485
2486 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002487 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002488
2489 /* Generate l such that 1 < l < p */
2490 do
2491 {
Ron Eldorca6ff582017-01-12 14:50:50 +02002492 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002494 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
2495 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002496
2497 if( count++ > 10 )
Jonas6645fd32020-05-08 16:57:18 +09002498 {
2499 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
2500 goto cleanup;
2501 }
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002502 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002503 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002504
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002505 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
2506 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 +01002507
2508cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002509 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002510
2511 return( ret );
2512}
2513
2514/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002515 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
2516 * for Montgomery curves in x/z coordinates.
2517 *
2518 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
2519 * with
2520 * d = X1
2521 * P = (X2, Z2)
2522 * Q = (X3, Z3)
2523 * R = (X4, Z4)
2524 * S = (X5, Z5)
2525 * and eliminating temporary variables tO, ..., t4.
2526 *
2527 * Cost: 5M + 4S
2528 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002529static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
2530 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
2531 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
2532 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002533{
2534 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002535 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002536
Janos Follathb0697532016-08-18 12:38:46 +01002537#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002538 if( mbedtls_internal_ecp_grp_capable( grp ) )
2539 return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) );
Janos Follath372697b2016-10-28 16:53:11 +01002540#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002542 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
2543 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
2544 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002546 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
2547 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
2548 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
2549 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
2550 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
2551 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
2552 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
2553 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
2554 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
2555 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
2556 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
2557 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
2558 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
2559 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
2560 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
2561 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
2562 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
2563 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 +01002564
2565cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002566 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
2567 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
2568 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002569
2570 return( ret );
2571}
2572
2573/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002574 * Multiplication with Montgomery ladder in x/z coordinates,
2575 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002576 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2578 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002579 int (*f_rng)(void *, unsigned char *, size_t),
2580 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002581{
2582 int ret;
2583 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002584 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002585 mbedtls_ecp_point RP;
2586 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002587#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2588 ecp_drbg_context drbg_ctx;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002589
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002590 ecp_drbg_init( &drbg_ctx );
2591#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002592 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002593
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002594#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2595 if( f_rng == NULL )
2596 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002597 const size_t m_len = ( grp->nbits + 7 ) / 8;
2598 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002599 f_rng = &ecp_drbg_random;
2600 p_rng = &drbg_ctx;
2601 }
2602#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2603
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002604 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002605 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
2606 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002607
2608 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002609 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
2610 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
2611 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002612
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01002613 /* RP.X might be sligtly larger than P, so reduce it */
2614 MOD_ADD( RP.X );
2615
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002616 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002617#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002618 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002619#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002620 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002621
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002622 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002623 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002624 while( i-- > 0 )
2625 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002626 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002627 /*
2628 * if (b) R = 2R + P else R = 2R,
2629 * which is:
2630 * if (b) double_add( RP, R, RP, R )
2631 * else double_add( R, RP, R, RP )
2632 * but using safe conditional swaps to avoid leaks
2633 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002634 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2635 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
2636 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
2637 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2638 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002639 }
2640
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002641 /*
2642 * Knowledge of the projective coordinates may leak the last few bits of the
2643 * scalar [1], and since our MPI implementation isn't constant-flow,
2644 * inversion (used for coordinate normalization) may leak the full value
2645 * of its input via side-channels [2].
2646 *
2647 * [1] https://eprint.iacr.org/2003/191
2648 * [2] https://eprint.iacr.org/2020/055
2649 *
2650 * Avoid the leak by randomizing coordinates before we normalize them.
2651 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002652#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002653 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002654#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002655 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
2656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002657 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002658
2659cleanup:
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002660#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2661 ecp_drbg_free( &drbg_ctx );
2662#endif
2663
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002664 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002665
2666 return( ret );
2667}
2668
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002669#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002670
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002671/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002672 * Restartable multiplication R = m * P
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002673 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002674int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002675 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002676 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
2677 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002678{
Janos Follathb0697532016-08-18 12:38:46 +01002679 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00002680#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2681 char is_grp_capable = 0;
2682#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002683 ECP_VALIDATE_RET( grp != NULL );
2684 ECP_VALIDATE_RET( R != NULL );
2685 ECP_VALIDATE_RET( m != NULL );
2686 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002687
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002688#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002689 /* reset ops count for this call if top-level */
2690 if( rs_ctx != NULL && rs_ctx->depth++ == 0 )
2691 rs_ctx->ops_done = 0;
2692#endif
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002693
Janos Follathc44ab972016-11-18 16:38:23 +00002694#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002695 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
Janos Follathc44ab972016-11-18 16:38:23 +00002696 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathc44ab972016-11-18 16:38:23 +00002697#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002698
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002699#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002700 /* skip argument check when restarting */
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002701 if( rs_ctx == NULL || rs_ctx->rsm == NULL )
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002702#endif
2703 {
Manuel Pégourié-Gonnard5314f232017-04-21 12:36:59 +02002704 /* check_privkey is free */
2705 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
2706
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002707 /* Common sanity checks */
2708 MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) );
2709 MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002710 }
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002711
2712 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002713#if defined(ECP_MONTGOMERY)
2714 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002715 MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
Janos Follath430d3372016-11-03 14:25:37 +00002716#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002717#if defined(ECP_SHORTWEIERSTRASS)
2718 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002719 MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) );
Janos Follath430d3372016-11-03 14:25:37 +00002720#endif
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002721
Janos Follath6c8ccd52016-11-29 15:37:09 +00002722cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002723
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002724#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002725 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002726 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002727#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002728
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002729#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002730 if( rs_ctx != NULL )
2731 rs_ctx->depth--;
2732#endif
2733
Janos Follathb0697532016-08-18 12:38:46 +01002734 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002735}
2736
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002737/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002738 * Multiplication R = m * P
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002739 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002740int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002741 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002742 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002743{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002744 ECP_VALIDATE_RET( grp != NULL );
2745 ECP_VALIDATE_RET( R != NULL );
2746 ECP_VALIDATE_RET( m != NULL );
2747 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002748 return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002749}
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002750
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002751#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002752/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002753 * Check that an affine point is valid as a public key,
2754 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002755 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002756static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002757{
2758 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002759 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002760
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002761 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002762 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2763 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2764 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2765 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2766 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002767
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002768 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002769
2770 /*
2771 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002772 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002773 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002774 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2775 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002776
2777 /* Special case for A = -3 */
2778 if( grp->A.p == NULL )
2779 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002780 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002781 }
2782 else
2783 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002784 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002785 }
2786
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002787 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2788 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002789
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002790 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2791 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002792
2793cleanup:
2794
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002795 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002796
2797 return( ret );
2798}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002799#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002800
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002801/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002802 * R = m * P with shortcuts for m == 1 and m == -1
2803 * NOT constant-time - ONLY for short Weierstrass!
2804 */
2805static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2806 mbedtls_ecp_point *R,
2807 const mbedtls_mpi *m,
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002808 const mbedtls_ecp_point *P,
2809 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002810{
2811 int ret;
2812
2813 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2814 {
2815 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2816 }
2817 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2818 {
2819 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2820 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2821 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2822 }
2823 else
2824 {
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002825 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P,
2826 NULL, NULL, rs_ctx ) );
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002827 }
2828
2829cleanup:
2830 return( ret );
2831}
2832
2833/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002834 * Restartable linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002835 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002836 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002837int mbedtls_ecp_muladd_restartable(
2838 mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002839 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002840 const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
2841 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002842{
2843 int ret;
2844 mbedtls_ecp_point mP;
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002845 mbedtls_ecp_point *pmP = &mP;
2846 mbedtls_ecp_point *pR = R;
Janos Follathc44ab972016-11-18 16:38:23 +00002847#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2848 char is_grp_capable = 0;
2849#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002850 ECP_VALIDATE_RET( grp != NULL );
2851 ECP_VALIDATE_RET( R != NULL );
2852 ECP_VALIDATE_RET( m != NULL );
2853 ECP_VALIDATE_RET( P != NULL );
2854 ECP_VALIDATE_RET( n != NULL );
2855 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002856
2857 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2858 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2859
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002860 mbedtls_ecp_point_init( &mP );
2861
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002862 ECP_RS_ENTER( ma );
2863
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002864#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002865 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2866 {
2867 /* redirect intermediate results to restart context */
2868 pmP = &rs_ctx->ma->mP;
2869 pR = &rs_ctx->ma->R;
2870
2871 /* jump to next operation */
2872 if( rs_ctx->ma->state == ecp_rsma_mul2 )
2873 goto mul2;
2874 if( rs_ctx->ma->state == ecp_rsma_add )
2875 goto add;
2876 if( rs_ctx->ma->state == ecp_rsma_norm )
2877 goto norm;
2878 }
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002879#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002880
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002881 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002882#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002883 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002884 rs_ctx->ma->state = ecp_rsma_mul2;
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002885
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002886mul2:
2887#endif
2888 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) );
Janos Follathaf6f2692018-12-07 09:55:24 +00002889
2890#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2891 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
2892 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
2893#endif /* MBEDTLS_ECP_INTERNAL_ALT */
2894
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002895#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002896 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002897 rs_ctx->ma->state = ecp_rsma_add;
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002898
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002899add:
2900#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002901 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002902 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002903#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002904 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002905 rs_ctx->ma->state = ecp_rsma_norm;
Janos Follath430d3372016-11-03 14:25:37 +00002906
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002907norm:
2908#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002909 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002910 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) );
2911
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002912#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002913 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2914 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) );
2915#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002916
2917cleanup:
Janos Follathc44ab972016-11-18 16:38:23 +00002918#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002919 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002920 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002921#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002922
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002923 mbedtls_ecp_point_free( &mP );
2924
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002925 ECP_RS_LEAVE( ma );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002926
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002927 return( ret );
2928}
2929
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002930/*
2931 * Linear combination
2932 * NOT constant-time
2933 */
2934int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2935 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2936 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2937{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002938 ECP_VALIDATE_RET( grp != NULL );
2939 ECP_VALIDATE_RET( R != NULL );
2940 ECP_VALIDATE_RET( m != NULL );
2941 ECP_VALIDATE_RET( P != NULL );
2942 ECP_VALIDATE_RET( n != NULL );
2943 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002944 return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) );
2945}
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002946
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002947#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002948/*
2949 * Check validity of a public key for Montgomery curves with x-only schemes
2950 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002951static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002952{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002953 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00002954 /* Allow any public value, if it's too big then we'll just reduce it mod p
2955 * (RFC 7748 sec. 5 para. 3). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002956 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
2957 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002958
2959 return( 0 );
2960}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002961#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002962
2963/*
2964 * Check that a point is valid as a public key
2965 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002966int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp,
2967 const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002968{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002969 ECP_VALIDATE_RET( grp != NULL );
2970 ECP_VALIDATE_RET( pt != NULL );
2971
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002972 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002973 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
2974 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002975
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002976#if defined(ECP_MONTGOMERY)
2977 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002978 return( ecp_check_pubkey_mx( grp, pt ) );
2979#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002980#if defined(ECP_SHORTWEIERSTRASS)
2981 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002982 return( ecp_check_pubkey_sw( grp, pt ) );
2983#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002984 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002985}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002986
2987/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002988 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002989 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002990int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp,
2991 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002992{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002993 ECP_VALIDATE_RET( grp != NULL );
2994 ECP_VALIDATE_RET( d != NULL );
2995
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002996#if defined(ECP_MONTGOMERY)
2997 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002998 {
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00002999 /* see RFC 7748 sec. 5 para. 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003000 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
3001 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02003002 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003003 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003004
3005 /* see [Curve25519] page 5 */
3006 if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 )
3007 return( MBEDTLS_ERR_ECP_INVALID_KEY );
3008
3009 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003010 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003011#endif /* ECP_MONTGOMERY */
3012#if defined(ECP_SHORTWEIERSTRASS)
3013 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003014 {
3015 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003016 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
3017 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
3018 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003019 else
3020 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003021 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003022#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003024 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003025}
3026
3027/*
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003028 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003029 */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003030int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
3031 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003032 int (*f_rng)(void *, unsigned char *, size_t),
3033 void *p_rng )
3034{
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003035 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003036 size_t n_size;
3037
3038 ECP_VALIDATE_RET( grp != NULL );
3039 ECP_VALIDATE_RET( d != NULL );
3040 ECP_VALIDATE_RET( f_rng != NULL );
3041
3042 n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003043
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003044#if defined(ECP_MONTGOMERY)
3045 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003046 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003047 /* [M225] page 5 */
3048 size_t b;
3049
Janos Follath98e28a72016-05-31 14:03:54 +01003050 do {
3051 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
3052 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003053
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003054 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02003055 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003056 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003057 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003058 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003059 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003060
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003061 /* Make sure the last two bits are unset for Curve448, three bits for
3062 Curve25519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003063 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
3064 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003065 if( grp->nbits == 254 )
3066 {
3067 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
3068 }
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003069 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003070#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003071
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003072#if defined(ECP_SHORTWEIERSTRASS)
3073 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003074 {
3075 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003076 int count = 0;
Janos Follath867a3ab2019-10-11 14:21:53 +01003077 unsigned cmp = 0;
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01003078
3079 /*
3080 * Match the procedure given in RFC 6979 (deterministic ECDSA):
3081 * - use the same byte ordering;
3082 * - keep the leftmost nbits bits of the generated octet string;
3083 * - try until result is in the desired range.
3084 * This also avoids any biais, which is especially important for ECDSA.
3085 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003086 do
3087 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01003088 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003089 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003090
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01003091 /*
3092 * Each try has at worst a probability 1/2 of failing (the msb has
3093 * a probability 1/2 of being 0, and then the result will be < N),
3094 * so after 30 tries failure probability is a most 2**(-30).
3095 *
3096 * For most curves, 1 try is enough with overwhelming probability,
3097 * since N starts with a lot of 1s in binary, but some curves
3098 * such as secp224k1 are actually very close to the worst case.
3099 */
Manuel Pégourié-Gonnard67543962017-04-21 13:19:43 +02003100 if( ++count > 30 )
3101 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
Janos Follath4c3408b2019-09-16 14:27:39 +01003102
Janos Follath867a3ab2019-10-11 14:21:53 +01003103 ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
Janos Follath4c3408b2019-09-16 14:27:39 +01003104 if( ret != 0 )
3105 {
3106 goto cleanup;
3107 }
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003108 }
Janos Follath867a3ab2019-10-11 14:21:53 +01003109 while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003110 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003111#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003112
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003113cleanup:
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003114 return( ret );
3115}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003116
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003117/*
3118 * Generate a keypair with configurable base point
3119 */
3120int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
3121 const mbedtls_ecp_point *G,
3122 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3123 int (*f_rng)(void *, unsigned char *, size_t),
3124 void *p_rng )
3125{
3126 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003127 ECP_VALIDATE_RET( grp != NULL );
3128 ECP_VALIDATE_RET( d != NULL );
3129 ECP_VALIDATE_RET( G != NULL );
3130 ECP_VALIDATE_RET( Q != NULL );
3131 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003132
3133 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
3134 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
3135
3136cleanup:
3137 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003138}
3139
3140/*
3141 * Generate key pair, wrapper for conventional base point
3142 */
3143int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
3144 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3145 int (*f_rng)(void *, unsigned char *, size_t),
3146 void *p_rng )
3147{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003148 ECP_VALIDATE_RET( grp != NULL );
3149 ECP_VALIDATE_RET( d != NULL );
3150 ECP_VALIDATE_RET( Q != NULL );
3151 ECP_VALIDATE_RET( f_rng != NULL );
3152
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003153 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003154}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01003155
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003156/*
3157 * Generate a keypair, prettier wrapper
3158 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003159int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003160 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
3161{
3162 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003163 ECP_VALIDATE_RET( key != NULL );
3164 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003165
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003166 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003167 return( ret );
3168
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003169 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003170}
3171
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003172/*
3173 * Check a public-private key pair
3174 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003175int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003176{
3177 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003178 mbedtls_ecp_point Q;
3179 mbedtls_ecp_group grp;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003180 ECP_VALIDATE_RET( pub != NULL );
3181 ECP_VALIDATE_RET( prv != NULL );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003182
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003183 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003184 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003185 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
3186 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
3187 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003188 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003189 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003190 }
3191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003192 mbedtls_ecp_point_init( &Q );
3193 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003195 /* mbedtls_ecp_mul() needs a non-const group... */
3196 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003197
3198 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003199 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003201 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
3202 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
3203 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003204 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003205 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003206 goto cleanup;
3207 }
3208
3209cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003210 mbedtls_ecp_point_free( &Q );
3211 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003212
3213 return( ret );
3214}
3215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003216#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003217
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003218#if defined(ECP_ONE_STEP_KDF)
3219/*
3220 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
3221 * but unofficial ones can be found at:
3222 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
3223 *
3224 * We only use the ones with empty fixedInfo, and for brevity's sake, only
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +02003225 * 32-bytes output (with SHA-256 that's exactly one block, and with SHA-512
3226 * less than one block).
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003227 */
3228#if defined(MBEDTLS_SHA512_C)
3229
3230static const uint8_t test_kdf_z[16] = {
3231 0xeb, 0xf3, 0x19, 0x67, 0x1e, 0xac, 0xcc, 0x6f,
3232 0xc5, 0xc0, 0x5d, 0x95, 0x8d, 0x17, 0x15, 0x94,
3233};
3234static const uint8_t test_kdf_out[32] = {
3235 0xa9, 0x48, 0x85, 0x67, 0x54, 0x7c, 0x2a, 0x8e,
3236 0x9e, 0xd1, 0x67, 0x76, 0xe3, 0x1c, 0x03, 0x92,
3237 0x41, 0x77, 0x2a, 0x9e, 0xc7, 0xcc, 0xd7, 0x1f,
3238 0xda, 0x12, 0xe9, 0xba, 0xc9, 0xb2, 0x17, 0x24,
3239};
3240
3241#elif defined(MBEDTLS_SHA256_C)
3242
3243static const uint8_t test_kdf_z[16] = {
3244 0x0d, 0x5e, 0xc8, 0x9a, 0x68, 0xb1, 0xa7, 0xa0,
3245 0xdf, 0x95, 0x24, 0x54, 0x3f, 0x4d, 0x70, 0xef,
3246};
3247static const uint8_t test_kdf_out[32] = {
3248 0x77, 0xbc, 0x94, 0x9e, 0xa0, 0xd3, 0xdd, 0x5c,
3249 0x8e, 0xb7, 0xeb, 0x84, 0x05, 0x40, 0x60, 0xfa,
3250 0x96, 0x6e, 0x7e, 0xcd, 0x73, 0x9f, 0xa1, 0xe6,
3251 0x34, 0x3f, 0x6d, 0x82, 0x16, 0x22, 0xb4, 0x45,
3252};
3253
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003254#endif
3255
3256static int ecp_kdf_self_test( void )
3257{
3258 int ret;
3259 ecp_drbg_context kdf_ctx;
3260 mbedtls_mpi scalar;
3261 uint8_t out[sizeof( test_kdf_out )];
3262
3263 ecp_drbg_init( &kdf_ctx );
3264 mbedtls_mpi_init( &scalar );
3265 memset( out, 0, sizeof( out ) );
3266
3267 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
3268 test_kdf_z, sizeof( test_kdf_z ) ) );
3269
3270 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
3271 &scalar, sizeof( test_kdf_z ) ) );
3272
3273 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
3274
3275 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
3276 ret = -1;
3277
3278cleanup:
3279 ecp_drbg_free( &kdf_ctx );
3280 mbedtls_mpi_free( &scalar );
3281
3282 return( ret );
3283}
3284#endif /* ECP_ONE_STEP_KDF */
3285
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01003286/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003287 * Checkup routine
3288 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003289int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003290{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003291 int ret;
3292 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003293 mbedtls_ecp_group grp;
3294 mbedtls_ecp_point R, P;
3295 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003296 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003297 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02003298 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003299 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003300 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003301 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003302 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003303 "400000000000000000000000000000000000000000000000", /* one and zeros */
3304 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
3305 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003306 };
3307
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003308 mbedtls_ecp_group_init( &grp );
3309 mbedtls_ecp_point_init( &R );
3310 mbedtls_ecp_point_init( &P );
3311 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003312
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003313 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003314#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003315 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02003316#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003317 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003318#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003319
3320 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003321 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003322
3323 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003324 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
3325 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003326
3327 add_count = 0;
3328 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003329 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003330 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3331 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003332
3333 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3334 {
3335 add_c_prev = add_count;
3336 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003337 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003338 add_count = 0;
3339 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003340 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003342 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3343 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003344
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003345 if( add_count != add_c_prev ||
3346 dbl_count != dbl_c_prev ||
3347 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003348 {
3349 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003350 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003351
3352 ret = 1;
3353 goto cleanup;
3354 }
3355 }
3356
3357 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003358 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003359
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003360 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003361 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003362 /* We computed P = 2G last time, use it */
3363
3364 add_count = 0;
3365 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003366 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003367 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3368 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003369
3370 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3371 {
3372 add_c_prev = add_count;
3373 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003374 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003375 add_count = 0;
3376 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003377 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003379 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3380 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003381
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003382 if( add_count != add_c_prev ||
3383 dbl_count != dbl_c_prev ||
3384 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003385 {
3386 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003387 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003388
3389 ret = 1;
3390 goto cleanup;
3391 }
3392 }
3393
3394 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003395 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003396
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003397#if defined(ECP_ONE_STEP_KDF)
3398 if( verbose != 0 )
3399 mbedtls_printf( " ECP test #3 (internal KDF): " );
3400
3401 ret = ecp_kdf_self_test();
3402 if( ret != 0 )
3403 {
3404 if( verbose != 0 )
3405 mbedtls_printf( "failed\n" );
3406
3407 ret = 1;
3408 goto cleanup;
3409 }
3410
3411 if( verbose != 0 )
3412 mbedtls_printf( "passed\n" );
3413#endif /* ECP_ONE_STEP_KDF */
3414
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003415cleanup:
3416
3417 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003418 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003419
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003420 mbedtls_ecp_group_free( &grp );
3421 mbedtls_ecp_point_free( &R );
3422 mbedtls_ecp_point_free( &P );
3423 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003424
3425 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003426 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003427
3428 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003429}
3430
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003431#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003432
Janos Follathb0697532016-08-18 12:38:46 +01003433#endif /* !MBEDTLS_ECP_ALT */
3434
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003435#endif /* MBEDTLS_ECP_C */